134 lines
4.0 KiB
JavaScript
134 lines
4.0 KiB
JavaScript
// === Handler ===
|
|
export const postHandler = async (req, res) => {
|
|
try {
|
|
const modified = processPostRequest(req.body?.response);
|
|
return res.status(200).json(modified);
|
|
} catch (err) {
|
|
return handleError(err, res);
|
|
}
|
|
};
|
|
|
|
// === Core Processing ===
|
|
function processPostRequest(response) {
|
|
if (!response || typeof response !== 'object') {
|
|
throw new InvalidJsonContentTypeError('Missing or invalid response body', 400);
|
|
}
|
|
|
|
const modified = postRequestHandlerWrapper(response);
|
|
return modified;
|
|
}
|
|
|
|
// === Unified Error Handler ===
|
|
function handleError(err, res) {
|
|
const isJsonTypeError = err instanceof InvalidJsonContentTypeError ||
|
|
err?.message?.includes('Body content-type is not valid JSON');
|
|
|
|
const status = isJsonTypeError ? err.statusCode || 415 : 500;
|
|
|
|
return res.status(status).json({
|
|
error: err.name || 'InternalServerError',
|
|
message: err.message || 'Unexpected error occurred',
|
|
...(err.details && { details: err.details }),
|
|
});
|
|
}
|
|
let currentResponse = null;
|
|
let postContext = null;
|
|
|
|
function createPostContext() {
|
|
return {
|
|
addedHeaders: {},
|
|
removedHeaders: [],
|
|
modifiedBody: null,
|
|
modifiedStatus: null,
|
|
};
|
|
}
|
|
|
|
export function postRequestHandlerWrapper(response) {
|
|
postContext = createPostContext();
|
|
currentResponse = response;
|
|
postRequestHandler();
|
|
const ctx = postContext;
|
|
postContext = null;
|
|
currentResponse = null;
|
|
return ctx;
|
|
}
|
|
|
|
export function postRequestHandler() {
|
|
setHeader('x-post-transform', 'applied');
|
|
removeHeader('x-unwanted-header');
|
|
|
|
const body = getJsonBody();
|
|
if (body) {
|
|
body.modifiedAt = new Date().toISOString();
|
|
body.transformed = "transformed***********";
|
|
setJsonBody(body);
|
|
}
|
|
|
|
setStatus(202);
|
|
}
|
|
export function setHeader(key, value) {
|
|
if (!currentResponse?.headers) currentResponse.headers = {};
|
|
currentResponse.headers[key.toLowerCase()] = value;
|
|
postContext?.addedHeaders && (postContext.addedHeaders[key.toLowerCase()] = value);
|
|
}
|
|
|
|
export function removeHeader(key) {
|
|
if (currentResponse?.headers?.[key.toLowerCase()] !== undefined) {
|
|
delete currentResponse.headers[key.toLowerCase()];
|
|
postContext?.removedHeaders?.push(key.toLowerCase());
|
|
}
|
|
}
|
|
|
|
export function getHeader(key) {
|
|
if (!currentResponse?.headers) return null;
|
|
return currentResponse.headers[key.toLowerCase()] || null;
|
|
}
|
|
|
|
export function getJsonBody() {
|
|
if (!currentResponse?.body) return null;
|
|
|
|
const contentType = currentResponse.contentType || currentResponse.headers?.['content-type'] || '';
|
|
|
|
if (!contentType.includes('application/json')) {
|
|
throw new InvalidJsonContentTypeError();
|
|
}
|
|
|
|
try {
|
|
return typeof currentResponse.body === 'string'
|
|
? JSON.parse(currentResponse.body)
|
|
: currentResponse.body;
|
|
} catch (err) {
|
|
throw new InvalidJsonContentTypeError('Failed to parse JSON body', 415, { originalError: err });
|
|
}
|
|
}
|
|
|
|
export function setJsonBody(json) {
|
|
const contentType = currentResponse.contentType || currentResponse.headers?.['content-type'] || '';
|
|
|
|
if (!contentType.includes('application/json')) {
|
|
throw new InvalidJsonContentTypeError();
|
|
}
|
|
|
|
try {
|
|
currentResponse.body = JSON.stringify(json);
|
|
postContext && (postContext.modifiedBody = json);
|
|
} catch (err) {
|
|
throw new InvalidJsonContentTypeError('Failed to stringify JSON body', 415, { originalError: err });
|
|
}
|
|
}
|
|
|
|
export function setStatus(statusCode) {
|
|
if (typeof statusCode === 'number') {
|
|
currentResponse.status = statusCode;
|
|
postContext && (postContext.modifiedStatus = statusCode);
|
|
}
|
|
}
|
|
export class InvalidJsonContentTypeError extends Error {
|
|
constructor(message = 'Body content-type is not valid JSON', statusCode = 415, details = {}) {
|
|
super(message);
|
|
this.name = 'InvalidJsonContentTypeError';
|
|
this.statusCode = statusCode;
|
|
this.details = details;
|
|
}
|
|
}
|