Skip to content

Commit 73fff04

Browse files
committed
Unify API calls by http(s) and ws(s)
PR-URL: #105
1 parent a32c427 commit 73fff04

File tree

1 file changed

+34
-58
lines changed

1 file changed

+34
-58
lines changed

lib/server.js

Lines changed: 34 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const TRANSPORT = { http, https, ws: http, wss: https };
99

1010
const MIME_TYPES = {
1111
html: 'text/html; charset=UTF-8',
12+
json: 'application/json; charset=UTF-8',
1213
js: 'application/javascript; charset=UTF-8',
1314
css: 'text/css',
1415
png: 'image/png',
@@ -64,82 +65,58 @@ class Client {
6465
else this.error(404);
6566
}
6667

67-
error(status) {
68-
if (this.res.finished) return;
69-
this.res.writeHead(status, { 'Content-Type': 'text/plain' });
70-
this.res.end(`HTTP ${status}: ${http.STATUS_CODES[status]}`);
71-
}
72-
73-
async apihttp(method, args) {
74-
const { res, application } = this;
75-
const { semaphore } = application.server;
76-
try {
77-
await semaphore.enter();
78-
} catch {
79-
this.error(504);
68+
error(status, err) {
69+
const { application, req, res, connection } = this;
70+
const reason = http.STATUS_CODES[status];
71+
const message = err ? err.stack : reason;
72+
application.logger.error(`${req.url} - ${message} - ${status}`);
73+
const result = JSON.stringify({ result: 'error', reason });
74+
if (connection) {
75+
connection.send(result);
8076
return;
8177
}
82-
const session = await this.application.auth.restore(this);
83-
const sandbox = session ? session.sandbox : undefined;
84-
const context = session ? session.context : {};
85-
try {
86-
const exp = this.application.runScript(method, sandbox);
87-
const proc = exp(context);
88-
if (!session && proc.access !== 'public') {
89-
this.application.logger.error(`Forbidden ${method}`);
90-
this.error(403);
91-
semaphore.leave();
92-
return;
93-
}
94-
const result = await proc.method(args);
95-
if (res.finished) {
96-
semaphore.leave();
97-
return;
98-
}
99-
if (!session && proc.access === 'public') {
100-
this.application.auth.start(this, result.userId);
101-
}
102-
res.end(JSON.stringify(result));
103-
} catch (err) {
104-
this.application.logger.error(err.stack);
105-
this.error(err.message === 'Not found' ? 404 : 500);
106-
}
107-
semaphore.leave();
78+
if (res.finished) return;
79+
res.writeHead(status, { 'Content-Type': MIME_TYPES.json });
80+
res.end(result);
10881
}
10982

110-
async apiws(method, args) {
111-
const { connection, application } = this;
83+
async execute(method, args) {
84+
const { application } = this;
11285
const { semaphore } = application.server;
113-
const send = obj => connection.send(JSON.stringify(obj));
114-
try {
115-
await semaphore.enter();
116-
} catch {
117-
send({ result: 'error', reason: 'timeout' });
118-
return;
119-
}
86+
await semaphore.enter();
12087
try {
12188
const session = await application.auth.restore(this);
12289
const sandbox = session ? session.sandbox : undefined;
12390
const context = session ? session.context : {};
12491
const exp = application.runScript(method, sandbox);
12592
const proc = exp(context);
12693
if (!session && proc.access !== 'public') {
127-
application.logger.error(`Forbidden: ${method}`);
128-
send({ result: 'error', reason: 'forbidden' });
12994
semaphore.leave();
130-
return;
95+
throw new Error(`Forbidden: ${method}`);
13196
}
13297
const result = await proc.method(args);
13398
if (!session && proc.access === 'public') {
13499
const session = application.auth.start(this, result.userId);
135100
result.token = session.token;
136101
}
137-
send(result);
102+
return JSON.stringify(result);
103+
} finally {
104+
semaphore.leave();
105+
}
106+
}
107+
108+
async rpc(method, args) {
109+
const { res, connection } = this;
110+
try {
111+
const result = await this.execute(method, args);
112+
if (connection) connection.send(result);
113+
else res.end(result);
138114
} catch (err) {
139-
application.logger.error(err.stack);
140-
send({ result: 'error' });
115+
if (err.message === 'Not found') this.error(404);
116+
else if (err.message === 'Semaphore timeout') this.error(504);
117+
else if (err.message.startsWith('Forbidden:')) this.error(403);
118+
else this.error(500, err);
141119
}
142-
semaphore.leave();
143120
}
144121
}
145122

@@ -171,14 +148,13 @@ const listener = application => (req, res) => {
171148
}
172149
receiveArgs(req).then(args => {
173150
const method = url.substring(METHOD_OFFSET);
174-
client.apihttp(method, args);
151+
client.rpc(method, args);
175152
});
176153
} else {
177154
client.static();
178155
}
179156
};
180157

181-
182158
class Server {
183159
constructor(config, application) {
184160
this.config = config;
@@ -196,7 +172,7 @@ class Server {
196172
const client = new Client(req, null, application, connection);
197173
connection.on('message', message => {
198174
const { method, args } = JSON.parse(message);
199-
client.apiws(method, args);
175+
client.rpc(method, args);
200176
});
201177
});
202178
}

0 commit comments

Comments
 (0)