ผมเคยเจอคำถามและได้รับอีเมลบ่อยๆ ว่า “สามารถใช้ PHP กับ Node.js ได้หรือเปล่า?” คุยกันถึงรายละเอียดแล้วก็พบอีกว่าส่วนใหญ่พัฒนาเว็บด้วย PHP รันบน Apache web server กันอยู่แล้วแต่ต้องการใช้งาน WebSocket ซึ่งเขียนด้วย Node.js
ถามว่าใช้งานด้วยกันได้ไหม? ทำได้ครับแต่ต้องใช้กำลังภายในกันนิดนึง
ผมเคยเขียนถึงไปแล้ว ว่าถ้าจะใช้งาน WebSocket แบบเนียนๆ เสมือนรันบน web server เดียวกัน (ไม่ต้องระบุ port) ก็ต้องทำ reverse proxy และอาจจะต้องเพิ่ม software อื่นๆ เข้ามาใน stack ด้วยเพราะ Apache 2.2 ลงไปยังไม่รองรับ WebSocket แต่ใน Apache 2.4 สามารถใช้งานได้แล้วครับ ซึ่งวิธีทำก็ไม่ยุ่งยากเลยเหมือนทำ reverse proxy ทั่วไป แต่เพิ่มขั้นตอนนิดหน่อยตามนี้ครับ
Enable modules ที่จำเป็น
ขั้นตอนแรกก็ enable modules ที่ต้องใช้งานก่อนซึ่งก็คือ proxy , proxy_http และที่สำคัญเลยคือ proxy_wstunnel เราจะใช้ module นี้ในการคุยกันระหว่าง client-server ผ่าน WebSocket
$sudo a2enmod proxy proxy_http proxy_wstunnel
enable แล้วโปรแกรมจะแนะนำให้ restart ยังไม่ต้อง restart ก็ได้นะครับเพราะเราจะ config เพิ่มอีกค่อย restart ทีเดียวเลย
Config Apache 2.4 ให้รองรับ WebSocket
ให้ cd เข้าไปไดเรกทอรีที่เก็บไฟล์ config ของคุณครับ อย่างเช่นผมใช้ Ubuntu ก็จะอยู่ที่ /etc/apache2/site-enabled/ เปิดไฟล์ config virtual host ที่ต้องการขึ้นมาได้เลย (ถ้าใช้ default ก็เปิดไฟล์ 000-default.conf )
$sudo vim domainname.conf
เพิ่ม directive นี้เข้าไปก่อนครับ (แต่ละอันหมายความว่ายังไงไปอ่าน document กันเองนะครับ ในที่นี้ผมขอข้ามไปละกัน)
ProxyRequests Off ProxyVia Off <Proxy> Order deny,allow Allow from all </Proxy>
สมมุติว่าเรารัน Node.js app โดยใช้ transports: [‘websocket’] ไว้ที่ port 10001 ก็เพิ่ม ProxyPass และ ReverseProxy ตามนี้
ProxyPass /socket.io/1/websocket ws://localhost:10001/socket.io/1/websocket ProxyPassReverse /socket.io/1/websocket ws://localhost:10001/socket.io/1/websocket
2 บรรทัดข้างบนคือบอกว่าถ้าเจอ /socket.io/1/websocket จะเปลี่ยนไปคุยกันด้วย WebSocket protocol แทน
แต่…ช้าก่อน ยังไม่จบครับ เราต้องทำ reverse proxy ไป HTTP protocol เพื่อให้ client สามารถเรียกไฟล์ socket.io.js ได้ก่อน โดยเพิ่ม 2 บรรทัดนี้เข้าไป
ProxyPass /ws http://localhost:10001 ProxyPassReverse /ws http://localhost:10001
เวลาเรียก socket.io.js ในหน้า HTML ก็ระบุเป็นแบบนี้
<script src="/ws/socket.io/socket.io.js"></script>
เสร็จแล้ว save และ ต้อง restart Apache ให้อ่าน config ใหม่ก่อนนะครับถึงจะใช้งานได้
$sudo service apache2 restart
ลองเข้าเว็บเปิด debugger คลิกแท็บ Networks ดูครับ ถ้าไม่มี error อะไรก็น่าจะใช้งานได้แล้ว ถ้ายังใช้งานไม่ได้ก็ลองปรับเปลี่ยน path ต่างๆ ดูเพราะส่วนมากปัญหาที่เจอก็เรื่อง path นี่แหละ
ลองทำดูนะครับ
ผม config ตามนี้แล้วอ่ะครับแต่มันกลับขึ้นว่า WebSocket is closed before the connection is established.
ผม config ตัว Transfer เป็น websocket ในฝั่ง clients แล้วนะครับ มันขึ้น pending แล้วสักพักก็ finshed แล้วก็ connect ใหม่เรื่อยๆ มันต้องแก้อย่างไงครับ ขอบคุณครับ server เป็น debian8 Apache 2.4.^
บทความนี้อาจจะ outdate ไปแล้วครับเพราะ Socket.io ก็เปลี่ยนไปเยอะมาก