mudb
Version:
Real-time database for multiplayer games
96 lines (91 loc) • 3.52 kB
text/typescript
import { MuRPCClientTransport, MuRPCProtocol, MuRPCSchemas } from '../protocol';
import * as http from 'http';
export class MuRPCHttpClientTransport implements MuRPCClientTransport<any> {
private _url:string;
private _cookies:{
[cookie:string]:string;
} = {};
private _headers;
constructor (spec:{
url:string;
timeout:number;
headers?:object;
}) {
this._url = spec.url;
this._headers = spec.headers || {};
}
public send<Protocol extends MuRPCProtocol<any>> (
schemas:MuRPCSchemas<Protocol>,
arg:MuRPCSchemas<Protocol>['argSchema']['identity'],
) {
const argBuffer = Buffer.from(JSON.stringify(schemas.argSchema.toJSON(arg)), 'utf8');
return new Promise<MuRPCSchemas<Protocol>['responseSchema']['identity']>((resolve, reject) => {
let completed = false;
const chunks:string[] = [];
function done (error:any, payload?:string) {
if (completed) {
return;
}
completed = true;
chunks.length = 0;
if (error) {
return reject(error);
} else if (!payload) {
return reject('unspecified error');
}
try {
let json:any = void 0;
if (payload.length > 0) {
json = JSON.parse(payload);
}
return resolve(schemas.responseSchema.fromJSON(json));
} catch (e) {
return reject(e);
}
}
const url = new URL(this._url + '/' + schemas.protocol.name);
const req = http.request({
hostname: url.hostname,
port: url.port,
path: url.pathname,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': argBuffer.length,
'Cookie': Object.keys(this._cookies).map((cookie) => `${cookie}=${encodeURIComponent(this._cookies[cookie])}`).join('; '),
...this._headers,
},
}, (res) => {
const cookie = res.headers['set-cookie'];
if (cookie) {
for (let i = 0; i < cookie.length; ++i) {
const parts = cookie[i].split('; ');
if (parts.length < 1) {
continue;
}
const tokens = parts[0].split('=');
this._cookies[tokens[0]] = decodeURIComponent(tokens[1]);
}
}
res.setEncoding('utf8');
res.on('data', (chunk) => {
if (completed) {
return;
} else if (typeof chunk === 'string') {
chunks.push(chunk);
} else {
chunks.push(chunk.toString('utf8'));
}
});
res.on('end', () => {
if (completed) {
return;
}
done(void 0, chunks.join(''));
});
});
req.on('error', (err) => done(err));
req.end(argBuffer);
});
}
}