1+ /*
2+ * @Author : csxiaoyao
3+ * @Date : 2018-04-18 17:53:40
4+ * @Last Modified by: csxiaoyao
5+ * @Last Modified time: 2018-04-18 23:18:48
6+ */
7+
8+ const url = require ( 'url' ) ;
9+ const ws = require ( 'ws' ) ;
10+ const Cookies = require ( 'cookies' ) ;
11+ const Koa = require ( 'koa' ) ;
12+ const bodyParser = require ( 'koa-bodyparser' ) ;
13+ const controller = require ( './controller' ) ;
14+
15+ const WebSocketServer = ws . Server ;
16+
17+ const app = new Koa ( ) ;
18+
19+ // log request URL:
20+ app . use ( async ( ctx , next ) => {
21+ console . log ( `Process ${ ctx . request . method } ${ ctx . request . url } ...` ) ;
22+ await next ( ) ;
23+ } ) ;
24+
25+ // parse user from cookie:
26+ app . use ( async ( ctx , next ) => {
27+ ctx . state . user = parseUser ( ctx . cookies . get ( 'name' ) || '' ) ;
28+ await next ( ) ;
29+ } ) ;
30+
31+ // parse request body:
32+ app . use ( bodyParser ( ) ) ;
33+
34+ // add controller middleware:
35+ app . use ( controller ( ) ) ;
36+
37+ let server = app . listen ( 3000 ) ;
38+
39+ function parseUser ( obj ) {
40+ if ( ! obj ) {
41+ return ;
42+ }
43+ console . log ( 'try parse: ' + obj ) ;
44+ let s = '' ;
45+ if ( typeof obj === 'string' ) {
46+ s = obj ;
47+ } else if ( obj . headers ) {
48+ let cookies = new Cookies ( obj , null ) ;
49+ s = cookies . get ( 'name' ) ;
50+ }
51+ if ( s ) {
52+ try {
53+ let user = JSON . parse ( Buffer . from ( s , 'base64' ) . toString ( ) ) ;
54+ console . log ( `User: ${ user . name } , ID: ${ user . id } ` ) ;
55+ return user ;
56+ } catch ( e ) {
57+ // ignore
58+ }
59+ }
60+ }
61+
62+ function createWebSocketServer ( server , onConnection , onMessage , onClose , onError ) {
63+ let wss = new WebSocketServer ( {
64+ server : server
65+ } ) ;
66+ wss . broadcast = function broadcast ( data ) {
67+ wss . clients . forEach ( function each ( client ) {
68+ client . send ( data ) ;
69+ } ) ;
70+ } ;
71+ onConnection = onConnection || function ( ) {
72+ console . log ( '[WebSocket] connected.' ) ;
73+ } ;
74+ onMessage = onMessage || function ( msg ) {
75+ console . log ( '[WebSocket] message received: ' + msg ) ;
76+ } ;
77+ onClose = onClose || function ( code , message ) {
78+ console . log ( `[WebSocket] closed: ${ code } - ${ message } ` ) ;
79+ } ;
80+ onError = onError || function ( err ) {
81+ console . log ( '[WebSocket] error: ' + err ) ;
82+ } ;
83+ wss . on ( 'connection' , function ( ws , req ) {
84+ ws . upgradeReq = req ;
85+ let location = url . parse ( ws . upgradeReq . url , true ) ;
86+ console . log ( '[WebSocketServer] connection: ' + location . href ) ;
87+ ws . on ( 'message' , onMessage ) ;
88+ ws . on ( 'close' , onClose ) ;
89+ ws . on ( 'error' , onError ) ;
90+ if ( location . pathname !== '/ws/chat' ) {
91+ // close ws:
92+ ws . close ( 4000 , 'Invalid URL' ) ;
93+ }
94+ // check user:
95+ let user = parseUser ( ws . upgradeReq ) ;
96+ if ( ! user ) {
97+ ws . close ( 4001 , 'Invalid user' ) ;
98+ }
99+ ws . user = user ;
100+ ws . wss = wss ;
101+ onConnection . apply ( ws ) ;
102+ } ) ;
103+ console . log ( 'WebSocketServer was attached.' ) ;
104+ return wss ;
105+ }
106+
107+ var messageIndex = 0 ;
108+
109+ function createMessage ( type , user , data ) {
110+ messageIndex ++ ;
111+ return JSON . stringify ( {
112+ id : messageIndex ,
113+ type : type ,
114+ user : user ,
115+ data : data
116+ } ) ;
117+ }
118+
119+ function onConnect ( ) {
120+ let user = this . user ;
121+ let msg = createMessage ( 'join' , user , `${ user . name } joined.` ) ;
122+ this . wss . broadcast ( msg ) ;
123+ // build user list:
124+ let users = this . wss . clients . forEach ( function ( client ) {
125+ return client . user ;
126+ } ) ;
127+ console . log ( users ) ;
128+ this . send ( createMessage ( 'list' , user , users ) ) ;
129+ }
130+
131+ function onMessage ( message ) {
132+ console . log ( message ) ;
133+ if ( message && message . trim ( ) ) {
134+ let msg = createMessage ( 'chat' , this . user , message . trim ( ) ) ;
135+ this . wss . broadcast ( msg ) ;
136+ }
137+ }
138+
139+ function onClose ( ) {
140+ let user = this . user ;
141+ let msg = createMessage ( 'left' , user , `${ user . name } is left.` ) ;
142+ this . wss . broadcast ( msg ) ;
143+ }
144+
145+ app . wss = createWebSocketServer ( server , onConnect , onMessage , onClose ) ;
146+
147+ console . log ( 'app started at port 3000...' ) ;
148+
149+
150+
151+ /*
152+ 配置nginx反向代理
153+
154+ server {
155+ listen 80;
156+ server_name localhost;
157+
158+ # 处理静态资源文件:
159+ location ^~ /static/ {
160+ root /path/to/ws-with-koa;
161+ }
162+
163+ # 处理WebSocket连接:
164+ location ^~ /ws/ {
165+ proxy_pass http://127.0.0.1:3000;
166+ proxy_http_version 1.1;
167+ proxy_set_header Upgrade $http_upgrade;
168+ proxy_set_header Connection "upgrade";
169+ }
170+
171+ # 其他所有请求:
172+ location / {
173+ proxy_pass http://127.0.0.1:3000;
174+ proxy_set_header X-Real-IP $remote_addr;
175+ proxy_set_header Host $host;
176+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
177+ }
178+ }
179+
180+ */
0 commit comments