@chubbyts/chubbyts-http-uwebsockets-bridge
Version:
A uwebsockets req/res http bridge.
63 lines (62 loc) • 2.54 kB
JavaScript
import { PassThrough } from 'stream';
const getUri = (req, uriOptions) => {
const query = req.getQuery();
const pathAndQuery = req.getUrl() + (query ? `?${query}` : '');
if (uriOptions === 'forwarded') {
const headers = Object.fromEntries(['x-forwarded-proto', 'x-forwarded-host', 'x-forwarded-port'].map((name) => [name, req.getHeader(name)]));
const missingHeaders = Object.keys(headers).filter((name) => !headers[name]);
if (missingHeaders.length) {
throw new Error(`Missing "${missingHeaders.join('", "')}" header(s).`);
}
const { 'x-forwarded-proto': schema, 'x-forwarded-host': host, 'x-forwarded-port': port } = headers;
return `${schema}://${host}:${port}${pathAndQuery}`;
}
const hostHeader = req.getHeader('host');
const schema = uriOptions.schema ?? 'http';
const host = uriOptions.host ?? (hostHeader || 'localhost');
return `${schema}://${host}${pathAndQuery}`;
};
const normalizeHeader = (header) => {
return header
.split(',')
.map((headerPart) => headerPart.trim())
.filter((headerPart) => headerPart);
};
const getBody = (res) => {
const stream = new PassThrough();
res.onData((chunk, isLast) => {
stream.write(Buffer.from(chunk));
if (isLast) {
stream.end();
}
});
return stream;
};
export const createUwebsocketsToServerRequestFactory = (uriFactory, serverRequestFactory, streamFromResourceFactory, uriOptions = {}) => {
return (req, res) => {
const headers = {};
req.forEach((name, value) => {
const normalizedHeaders = normalizeHeader(value);
if (normalizedHeaders.length) {
// eslint-disable-next-line functional/immutable-data
headers[name] = normalizedHeaders;
}
});
return {
...serverRequestFactory(req.getMethod().toUpperCase(), uriFactory(getUri(req, uriOptions))),
protocolVersion: '1.1',
body: streamFromResourceFactory(getBody(res)),
headers,
};
};
};
export const createResponseToUwebsocketsEmitter = () => {
return (response, res) => {
res.writeStatus(`${response.status} ${response.reasonPhrase}`);
Object.entries(response.headers).forEach(([name, value]) => {
res.writeHeader(name, value.join(', '));
});
response.body.on('data', (data) => res.write(data));
response.body.on('end', () => res.end());
};
};