Server: Added way to batch requests (currently disabled)

pull/5092/head
Laurent Cozic 2021-06-17 16:55:45 +01:00
parent e8532441bc
commit c682c8879c
2 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,92 @@
import { bodyFields } from '../../utils/requestUtils';
import { SubPath } from '../../utils/routeUtils';
import Router from '../../utils/Router';
import { HttpMethod, RouteType } from '../../utils/types';
import { AppContext } from '../../utils/types';
import routeHandler from '../../middleware/routeHandler';
import config from '../../config';
import { ErrorBadRequest } from '../../utils/errors';
const router = new Router(RouteType.Api);
const maxSubRequests = 50;
interface SubRequest {
method: HttpMethod;
url: string;
headers: Record<string, string>;
body: any;
}
type SubRequests = Record<string, SubRequest>;
interface SubRequestResponse {
status: number;
body: any;
header: Record<string, any>;
}
type BatchResponse = Record<string, SubRequestResponse>;
function createSubRequestContext(ctx: AppContext, subRequest: SubRequest): AppContext {
const fullUrl = `${config().apiBaseUrl}/${subRequest.url.trim()}`;
const newContext: AppContext = {
...ctx,
URL: new URL(fullUrl),
request: {
...ctx.request,
method: subRequest.method,
},
method: subRequest.method,
headers: {
...ctx.headers,
...subRequest.headers,
},
body: subRequest.body,
appLogger: ctx.appLogger,
path: `/${subRequest.url}`,
url: fullUrl,
services: ctx.services,
db: ctx.db,
models: ctx.models,
routes: ctx.routes,
};
return newContext;
}
function validateRequest(request: SubRequest): SubRequest {
const output = { ...request };
if (!output.method) output.method = HttpMethod.GET;
if (!output.url) throw new Error('"url" is required');
return output;
}
router.post('api/batch', async (_path: SubPath, ctx: AppContext) => {
throw new Error('Not enabled');
// eslint-disable-next-line no-unreachable
const subRequests = await bodyFields<SubRequests>(ctx.req);
if (Object.keys(subRequests).length > maxSubRequests) throw new ErrorBadRequest(`Can only process up to ${maxSubRequests} requests`);
const response: BatchResponse = {};
for (const subRequestId of Object.keys(subRequests)) {
const subRequest = validateRequest(subRequests[subRequestId]);
const subRequestContext = createSubRequestContext(ctx, subRequest);
await routeHandler(subRequestContext);
const r = subRequestContext.response;
response[subRequestId] = {
status: r.status,
body: typeof r.body === 'object' ? { ...r.body } : r.body,
header: r.header ? { ...r.header } : {},
};
}
return response;
});
export default router;

View File

@ -1,5 +1,6 @@
import { Routers } from '../utils/routeUtils';
import apiBatch from './api/batch';
import apiDebug from './api/debug';
import apiEvents from './api/events';
import apiItems from './api/items';
@ -25,6 +26,7 @@ import indexPrivacy from './index/privacy';
import defaultRoute from './default';
const routes: Routers = {
'api/batch': apiBatch,
'api/debug': apiDebug,
'api/events': apiEvents,
'api/items': apiItems,