55*/
66'use strict' ;
77
8+ const url = require ( 'url' ) ;
9+ const ws = require ( 'ws' ) ;
10+ const Cookies = require ( 'cookies' ) ;
811const Koa = require ( 'koa' ) ;
9-
1012const bodyParser = require ( 'koa-bodyparser' ) ;
11-
1213const controller = require ( './controller' ) ;
13-
1414const templating = require ( './templating' ) ;
15+ const WebSocketServer = ws . Server ;
1516
1617// 创建一个Koa对象表示web app本身:
1718const app = new Koa ( ) ;
@@ -53,49 +54,45 @@ const isProduction = process.env.NODE_ENV === 'production';
5354// console.log('created: ' + JSON.stringify(dog));
5455// })();
5556
56- const WebSocket = require ( 'ws' ) ;
57- const WebSocketServer = WebSocket . Server ;
58- const wss = new WebSocketServer ( {
59- port : 3000
60- } ) ;
61-
62- wss . on ( 'connection' , function ( ws ) {
63- console . log ( `[SERVER] connection()` ) ;
64- ws . on ( 'message' , function ( message ) {
65- console . log ( `[SERVER] Receieved: ${ message } ` ) ;
66- setTimeout ( ( ) => {
67- ws . send ( `What's your name?` , ( err ) => {
68- if ( err ) {
69- console . log ( `[SERVER] error: ${ err } ` ) ;
70- }
71- } ) ;
72- } , 1000 ) ;
73- } ) ;
74- } ) ;
75-
76- console . log ( 'ws server started at port 3000...' ) ;
57+ // const wss = new WebSocketServer({
58+ // port: 3000
59+ // });
60+ //
61+ // wss.on('connection', function (ws) {
62+ // console.log(`[SERVER] connection()`);
63+ // ws.on('message', function (message) {
64+ // console.log(`[SERVER] Receieved: ${message}`);
65+ // setTimeout(() => {
66+ // ws.send(`What's your name?`, (err) => {
67+ // if (err) {
68+ // console.log(`[SERVER] error: ${err}`);
69+ // }
70+ // });
71+ // }, 1000);
72+ // });
73+ // });
7774
7875// client test:
79- let count = 0 ;
80- let ws = new WebSocket ( 'ws://localhost:3000/ws/chat' ) ;
81-
82- ws . on ( 'open' , function ( ) {
83- console . log ( `[CLIENT] open()` ) ;
84- ws . send ( 'Hello!' ) ;
85- } ) ;
86-
87- ws . on ( 'message' , function ( message ) {
88- console . log ( `[CLIENT] Received: ${ message } ` ) ;
89- count ++ ;
90- if ( count > 3 ) {
91- ws . send ( 'Goodbye!' ) ;
92- ws . close ( ) ;
93- } else {
94- setTimeout ( ( ) => {
95- ws . send ( `Hello, I'm Mr No.${ count } !` ) ;
96- } , 1000 ) ;
97- }
98- } ) ;
76+ // let count = 0;
77+ // let ws = new WebSocket('ws://localhost:3000/ws/chat');
78+ //
79+ // ws.on('open', function () {
80+ // console.log(`[CLIENT] open()`);
81+ // ws.send('Hello!');
82+ // });
83+ //
84+ // ws.on('message', function (message) {
85+ // console.log(`[CLIENT] Received: ${message}`);
86+ // count++;
87+ // if (count > 3) {
88+ // ws.send('Goodbye!');
89+ // ws.close();
90+ // } else {
91+ // setTimeout(() => {
92+ // ws.send(`Hello, I'm Mr No.${count}!`);
93+ // }, 1000);
94+ // }
95+ // });
9996
10097// log request URL
10198app . use ( async ( ctx , next ) => {
@@ -108,12 +105,18 @@ app.use(async (ctx, next) => {
108105 ctx . response . set ( 'X-Response-Time' , `${ execTime } ms` ) ;
109106} ) ;
110107
108+ // parse user from cookie:
111109app . use ( async ( ctx , next ) => {
112- var name = ctx . request . query . name || 'world' ;
113- ctx . response . type = 'text/html' ;
114- ctx . response . body = `<h1>Hello, ${ name } !</h1>` ;
110+ ctx . state . user = parseUser ( ctx . cookies . get ( 'name' || '' ) ) ;
111+ await next ( ) ;
115112} ) ;
116113
114+ // app.use(async (ctx, next) => {
115+ // var name = ctx.request.query.name || 'world';
116+ // ctx.response.type = 'text/html';
117+ // ctx.response.body = `<h1>Hello, ${name}!</h1>`;
118+ // });
119+
117120// static file support:
118121if ( ! isProduction ) {
119122 let staticFiles = require ( './static-files' ) ;
@@ -124,12 +127,130 @@ if (!isProduction) {
124127app . use ( bodyParser ( ) ) ;
125128
126129// add nunjucks as view:
127- // app.use(templating('views', {
128- // noCache: !isProduction,
129- // watch: !isProduction
130- // }));
130+ app . use ( templating ( 'views' , {
131+ noCache : ! isProduction ,
132+ watch : ! isProduction
133+ } ) ) ;
131134
132135// add controller:
133- // app.use(controller());
136+ app . use ( controller ( ) ) ;
137+
138+ let server = app . listen ( 3000 ) ;
139+
140+ function parseUser ( obj ) {
141+ if ( ! obj ) {
142+ return false ;
143+ }
144+
145+ console . log ( 'try parse: ' + obj ) ;
146+ let s = '' ;
147+ if ( typeof obj === 'string' ) {
148+ s = obj ;
149+ } else if ( obj . headers ) {
150+ let cookies = new Cookies ( obj , null ) ;
151+ s = cookies . get ( 'name' ) ;
152+ }
153+ if ( s ) {
154+ try {
155+ let user = JSON . parse ( Buffer . from ( s , 'base64' ) . toString ( ) ) ;
156+ console . log ( `User: ${ user . name } , ID: ${ user . id } ` ) ;
157+ return user ;
158+ } catch ( e ) {
159+ // ignore
160+ console . log ( e ) ;
161+ }
162+ }
163+ }
164+
165+ function createWebSocketServer ( server , onConnection , onMessage , onClose , onError ) {
166+ let wss = new WebSocketServer ( {
167+ server : server
168+ } ) ;
169+
170+ wss . broadcast = function broadcast ( data ) {
171+ wss . clients . forEach ( function each ( client ) {
172+ client . send ( data ) ;
173+ } ) ;
174+ } ;
175+ onConnection = onConnection || function ( ) {
176+ console . log ( '[WebSocket] connected.' ) ;
177+ } ;
178+ onMessage = onMessage || function ( msg ) {
179+ console . log ( '[WebSocket] message received: ' + msg ) ;
180+ } ;
181+ onClose = onClose || function ( code , message ) {
182+ console . log ( `[WebSocket] closed: ${ code } - ${ message } ` ) ;
183+ } ;
184+ onError = onError || function ( err ) {
185+ console . log ( '[WebSocket] error: ' + err ) ;
186+ } ;
187+ wss . on ( 'connection' , function ( ws ) {
188+ let location = url . parse ( ws . upgradeReq . url , true ) ;
189+ console . log ( '[WebSocketServer] connection: ' + location . href ) ;
190+
191+ ws . on ( 'message' , onMessage ) ;
192+ ws . on ( 'close' , onClose ) ;
193+ ws . on ( 'error' , onError ) ;
194+
195+ if ( location . pathname !== '/ws/chat' ) {
196+ // close ws:
197+ ws . close ( 4000 , 'Invalid URL' ) ;
198+ }
199+ // check user:
200+ let user = parseUser ( ws . upgradeReq ) ;
201+ if ( ! user ) {
202+ ws . close ( 4001 , 'Invalid user' ) ;
203+ }
204+ ws . user = user ;
205+ ws . wss = wss ;
206+ onConnection . apply ( ws ) ;
207+ } ) ;
208+
209+ console . log ( 'WebSocketServer was attached.' ) ;
210+ return wss ;
211+ }
212+
213+ let messageIndex = 0 ;
214+
215+ function createMessage ( type , user , data ) {
216+ messageIndex ++ ;
217+ return JSON . stringify ( {
218+ id : messageIndex ,
219+ type : type ,
220+ user : user ,
221+ data : data
222+ } ) ;
223+ }
224+
225+ function onConnect ( ) {
226+ let user = this . user ;
227+ let msg = createMessage ( 'join' , user , `${ user . name } joined.` ) ;
228+
229+ this . wss . broadcast ( msg ) ;
230+ // build user list:
231+ let users = this . wss . clients . map ( function ( client ) {
232+ return client . user ;
233+ } ) ;
234+ this . send ( createMessage ( 'list' , user , users ) ) ;
235+ }
236+
237+ function onMessage ( ) {
238+ console . log ( message ) ;
239+
240+ if ( message && message . trim ( ) ) {
241+ let msg = createMessage ( 'chat' , this . user , message . trim ( ) ) ;
242+ this . wss . broadcast ( msg ) ;
243+ }
244+ }
245+
246+ function onClose ( ) {
247+ let user = this . user ;
248+ let msg = createMessage ( 'left' , user , `${ user . name } is left.` ) ;
249+ this . wss . broadcast ( msg ) ;
250+ }
251+
252+ // module.exports = app;
253+
254+ app . wss = createWebSocketServer ( server , onConnect , onMessage , onClose ) ;
134255
135- module . exports = app ;
256+ console . log ( 'app started at port 3000...' ) ;
0 commit comments