mudb
Version:
Real-time database for multiplayer games
166 lines • 6.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const parse_body_1 = require("../../util/parse-body");
function opt(key, options, defaultValue) {
if (options && (key in options)) {
return options[key];
}
return defaultValue;
}
class MuRPCHttpConnection {
constructor(request, response, useCookie, cookie, auth) {
this.request = request;
this.response = response;
this.useCookie = useCookie;
this.cookie = cookie;
this.auth = auth;
}
setAuth(auth, options) {
if (this.useCookie) {
const tokens = [`${this.cookie}=${encodeURIComponent(auth)}`];
if (auth === '') {
tokens.push('Expires=Thu, 01 Jan 1970 00:00:00 GMT');
}
else {
const maxAge = opt('maxAge', options, 0);
if (maxAge) {
tokens.push(`Max-Age=${Math.ceil(maxAge)}`);
}
const httpOnly = opt('httpOnly', options, false);
if (httpOnly) {
tokens.push('HttpOnly');
}
const secure = opt('secure', options, false);
if (secure) {
tokens.push('Secure');
}
const sameSite = opt('sameSite', options, '');
if (sameSite) {
tokens.push(`SameSite=${sameSite}`);
}
}
const domain = opt('domain', options, '');
if (domain) {
tokens.push(`Domain=${domain}`);
}
const path = opt('path', options, '');
if (path) {
tokens.push(`Path=${path}`);
}
this.response.setHeader('Set-Cookie', tokens.join('; '));
}
this.auth = auth;
}
}
exports.MuRPCHttpConnection = MuRPCHttpConnection;
class MuRPCHttpServerTransport {
constructor(spec) {
this._handlers = {};
this.handler = async (request, response) => {
const method = request.method;
if (method !== 'post' && method !== 'POST') {
return false;
}
const url = request.url;
if (!url || !url.startsWith(this._route)) {
return false;
}
const suffix = url.substr(this._route.length);
const handler = this._handlers[suffix];
if (!handler) {
return false;
}
const ret = handler.schemas.responseSchema.alloc();
const length = parseInt(request.headers['content-length'] || '', 10) || 0;
if (this._byteLimit < length) {
ret.type = 'error';
ret.data = 'size limit exceeded';
}
else {
try {
let auth = '';
if (this._useCookie) {
const cookies = request.headers.cookie;
if (cookies) {
if (Array.isArray(cookies)) {
for (let i = 0; i < cookies.length; ++i) {
const match = cookies[i].match(this._matchCookie);
if (match && match[1]) {
auth = decodeURIComponent(match[1]);
break;
}
}
}
else {
const match = cookies.match(this._matchCookie);
if (match && match[1]) {
auth = decodeURIComponent(match[1]);
}
}
}
}
const connection = new MuRPCHttpConnection(request, response, this._useCookie, this._cookie, auth);
if (!(await handler.auth(connection))) {
ret.type = 'error';
ret.data = 'unauthorized';
}
else {
const body = await parse_body_1.getRawBody(request, length);
const bodyStr = body.toString('utf8');
let bodyJSON = void 0;
if (bodyStr.length > 0) {
bodyJSON = JSON.parse(bodyStr);
}
const arg = handler.schemas.argSchema.fromJSON(bodyJSON);
await handler.recv(connection, arg, ret);
}
}
catch (e) {
ret.type = 'error';
if (e instanceof Error && typeof e.stack !== 'undefined') {
ret.data = e.stack;
}
else {
ret.data = '' + e;
}
}
}
response.statusCode = ret.type === 'success' ? 200 : 400;
response.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
response.setHeader('Expires', '0');
response.setHeader('Pragma', 'no-cache');
response.setHeader('Surrogate-Control', 'no-store');
response.setHeader('Content-Type', 'application/json; charset=utf-8');
response.end(JSON.stringify(handler.schemas.responseSchema.toJSON(ret)));
handler.schemas.responseSchema.free(ret);
return true;
};
this._route = spec.route;
this._byteLimit = spec.byteLimit;
if (this._route.charAt(0) !== '/') {
this._route = '/' + this._route;
}
if (this._route.charAt(this._route.length - 1) !== '/') {
this._route += '/';
}
if ('cookie' in spec) {
this._useCookie = true;
const cookie = this._cookie = spec.cookie || '';
this._matchCookie = new RegExp(`(?:^|;) *${cookie}=([^;]*)`);
}
else {
this._useCookie = false;
this._cookie = '';
this._matchCookie = new RegExp('');
}
}
listen(schemas, auth, recv) {
this._handlers[schemas.protocol.name] = {
schemas,
auth,
recv: recv,
};
}
}
exports.MuRPCHttpServerTransport = MuRPCHttpServerTransport;
//# sourceMappingURL=server.js.map