🌟
Laravel-echo-serverで遊ぶ over Apache
Laravel-echo-serverとは
- Nodejs with socket.ioで作られたLaravel用 WebScoketサーバー
- Laravel-echoとセットで利用する
- 半リアルタイム通信のLaravel+Livewireとは違いリアルタイム通信
但し
How does that work?
The client will try to establish a WebSocket connection if possible, and will fall back on HTTP long polling if not.
前提
- Laravel+Livewireで遊ぶ為の環境構築済み
- Redisサーバーが稼働している
- Let's Encryptをまたはオレオレ証明書を使用
- ポート8880は80、8883は443に読み替える事[1]
https対応
1. オレオレ証明書の作成
command
mkdir /etc/httpd/conf.d/ssl \
&& cd /etc/httpd/conf.d/ssl \
&& echo 'subjectAltName = DNS:localhost, IP:127.0.0.1' > SAN.txt \
&& openssl genrsa -out server.key 2048 \
&& openssl req -new -key server.key -out server.csr -subj "/C=JP/ST=Saitama/O=lfz/CN=localhost" \
&& openssl x509 -req -in server.csr -days 3650 -sha256 -extfile SAN.txt -signkey server.key -out server.crt
2. apacheの設定
command
[root@0117bc9732cb conf.d]# dnf install mod_ssl
/etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/httpd/conf.d/ssl/server.crt
SSLCertificateKeyFile /etc/httpd/conf.d/ssl/server.key
/etc/httpd/conf.d/laravel.conf
<VirtualHost *:80>
DocumentRoot /var/www/lfz-app/public
ServerName localhost
RewriteEngine on
DirectoryIndex index.html index.php
<Directory "/var/www/lfz-app">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /var/www/lfz-app/public
ServerName localhost
DirectoryIndex index.html index.php
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
#RewriteCond %{QUERY_STRING} ^((?!X-Atmosphere-Transport=websocket).)*$ [NC]
RewriteRule /(.*) ws://127.0.0.1:6001/$1 [P,L]
ProxyPass /socket.io http://127.0.0.1:6001/socket.io
ProxyPassReverse /socket.io http://127.0.0.1:6001/socket.io
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCertificateFile /etc/httpd/conf.d/ssl/server.crt
SSLCertificateKeyFile /etc/httpd/conf.d/ssl/server.key
<Directory "/var/www/lfz-app">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
3. apache再起動
command
[root@0117bc9732cb lfz-app]# systemctl restart httpd
- https接続の確認
https://localhost:8883/
Laravel-echo-serverの準備
1. laravel-echo-serverのインストール
command
[root@0117bc9732cb lfz-app]# cd /var/www/lfz-app/
[root@0117bc9732cb lfz-app]# npm install -g laravel-echo-server
2. 設定ファイルの作成
command
[root@3fade56e48d9 lfz-app]# laravel-echo-server init
? Do you want to run this server in development mode? Yes
? Which port would you like to serve from? 6001
? Which database would you like to use to store presence channel members? redis
? Enter the host of your Laravel authentication server. https://localhost
? Will you be serving on http or https? http
? Do you want to generate a client ID/Key for HTTP API? No
? Do you want to setup cross domain access to the API? No
? What do you want this config to be saved as? laravel-echo-server.json
Configuration file saved. Run laravel-echo-server start to run server.
Laravel echoの準備
1. クライアント用ライブラリインストール
command
[root@0117bc9732cb lfz-app]# npm install --save-dev socket.io-client@2 laravel-echo
参考にするのは
ではなく2. .envの修正
- .envの修正
.env
APP_NAME=lfz
BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
3. configの修正
config/app.php
174 // App\Providers\BroadcastServiceProvider::class,
↓コメントアウト解除
174 App\Providers\BroadcastServiceProvider::class,
4. envの反映(キャッシュしてない場合は不要)
command
[root@3fade56e48d9 lfz-app]# php artisan cache:clear
Application cache cleared!
[root@3fade56e48d9 lfz-app]# php artisan config:cache
Configuration cache cleared!
Configuration cached successfully!
5. クライアント用javascriptの作成
resources/js/bootstrap.js
import Echo from 'laravel-echo';
// window.Pusher = require('pusher-js');
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: 'https://localhost:8883',
forceTLS: true
});
window.Echo.channel('lfz_database_public-echo-channel')
.listen('RealtimeEcho', (e) => {
console.log(e);
});
6. assetsコンパイル
[root@3fade56e48d9 lfz-app]# npm run dev
7. blade修正
resources/views/welcome.blade.php
<!--追加-->
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="{{ mix('js/app.js') }}"></script>
ブロードキャストする為のイベント作成
1. イベント作成
command
[root@3fade56e48d9 /]# cd /var/www/lfz-app/
[root@3fade56e48d9 lfz-app]# php artisan make:event RealtimeEcho
Event created successfully.
app/Events/RealtimeEcho.php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Redis;
class RealtimeEcho implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(){
//
}
public function broadcastOn(){
return new Channel('public-echo-channel');
}
public function broadcastWith(){
return ['count' => Redis::get('count')
,'static' => 'STATIC STRING'
];
}
}
2. イベントを叩きつける為のURL用意
routes/web.php
use Illuminate\Support\Facades\Redis;
Route::get('/realtimeecho', function(){
(function($count){
echo $count;
is_null($count) ? Redis::set('count', 0) : Redis::set('count', $count+1);
})(Redis::get('count'));
broadcast(new \App\Events\RealtimeEcho);
});
laravel-echo-serverの稼働
command
[root@3fade56e48d9 lfz-app]# cd /var/www/lfz-app/
[root@3fade56e48d9 lfz-app]# laravel-echo-server start
L A R A V E L E C H O S E R V E R
version 1.6.2
⚠ Starting server in DEV mode...
✔ Running at localhost on port 6001
✔ Channels are ready.
✔ Listening for http events...
✔ Listening for redis events...
Server ready!
動作チェック
1. Socket通信している画面を開く
- https://localhost:8883/
- developer toolsを開き、consoleタブをオープン
2. イベントを叩きつける
https://localhost:8883/realtimeechoを開いてF5連打
log
{count: "3", static: "STATIC STRING", socket: null} app.js:1957
{count: "4", static: "STATIC STRING", socket: null} app.js:1957
{count: "5", static: "STATIC STRING", socket: null} app.js:1957
{count: "6", static: "STATIC STRING", socket: null} app.js:1957
という感じのログが出ればOK
これで定番のリアルタイムチャットとかを作れます
-
本記事の環境はdockerコンテナを利用している為ポートフォワードしています ↩︎
-
dockerコンテナだから ↩︎
Discussion