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