Skip to content

Commit 23b6380

Browse files
chatroom
1 parent 78aea39 commit 23b6380

File tree

12 files changed

+2643
-1
lines changed

12 files changed

+2643
-1
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ Desktop.ini
5353
*.msp
5454

5555
# Windows shortcuts
56-
*.lnk
56+
*.lnk
57+
58+
node_modules/

11-nodejs/koa2/8-chatroom/app.js

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
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+
*/
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
const fs = require('fs');
3+
4+
// add url-route in /controllers:
5+
6+
function addMapping(router, mapping) {
7+
for (var url in mapping) {
8+
var path = '';
9+
if (url.startsWith('GET ')) {
10+
path = url.substring(4);
11+
router.get(path, mapping[url]);
12+
console.log(`register URL mapping: GET ${path}`);
13+
} else if (url.startsWith('POST ')) {
14+
path = url.substring(5);
15+
router.post(path, mapping[url]);
16+
console.log(`register URL mapping: POST ${path}`);
17+
} else if (url.startsWith('PUT ')) {
18+
path = url.substring(4);
19+
router.put(path, mapping[url]);
20+
console.log(`register URL mapping: PUT ${path}`);
21+
} else if (url.startsWith('DELETE ')) {
22+
path = url.substring(7);
23+
router.del(path, mapping[url]);
24+
console.log(`register URL mapping: DELETE ${path}`);
25+
} else {
26+
console.log(`invalid URL: ${url}`);
27+
}
28+
}
29+
}
30+
31+
function addControllers(router, dir) {
32+
fs.readdirSync(__dirname + '/' + dir).filter((f) => {
33+
return f.endsWith('.js');
34+
}).forEach((f) => {
35+
console.log(`process controller: ${f}...`);
36+
let mapping = require(__dirname + '/' + dir + '/' + f);
37+
addMapping(router, mapping);
38+
});
39+
}
40+
41+
module.exports = function (dir) {
42+
let
43+
controllers_dir = dir || 'controllers',
44+
router = require('koa-router')();
45+
addControllers(router, controllers_dir);
46+
return router.routes();
47+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
module.exports = {
3+
'GET /': async (ctx, next) => {
4+
let user = ctx.state.user;
5+
if (user) {
6+
console.log("response GET / : " + user);
7+
} else {
8+
ctx.response.redirect('/signin');
9+
}
10+
}
11+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// sign in:
2+
3+
module.exports = {
4+
'GET /signin': async (ctx, next) => {
5+
console.log('GET /signin');
6+
},
7+
8+
'POST /signin': async (ctx, next) => {
9+
console.log('POST /signin');
10+
let name = ctx.request.body.name || 'csxiaoyao';
11+
let user = {
12+
name: name
13+
};
14+
let value = Buffer.from(JSON.stringify(user)).toString('base64');
15+
console.log(`Set cookie value: ${value}`);
16+
ctx.cookies.set('name', value);
17+
ctx.response.redirect('/');
18+
},
19+
20+
'GET /signout': async (ctx, next) => {
21+
ctx.cookies.set('name', '');
22+
ctx.response.redirect('/signin');
23+
}
24+
};

0 commit comments

Comments
 (0)