6989a98d75
- Arkitektur: docs/auth/passwordless-architecture.md - Backend: iom/quixzoom-auth-service/ (FastAPI + Redis) - Webb: quixzoom-market-pages/se/login/ (QR-kod + polling) - App: iom/quixzoom-app/src/features/auth/ (push + deep links) Flöde: QR-kod → app-godkännande → webb-inloggad
79 lines
2.8 KiB
JavaScript
79 lines
2.8 KiB
JavaScript
import * as querystring from 'node:querystring';
|
|
import * as zlib from 'node:zlib';
|
|
import { stringifyFormData } from './fix-request-body-utils/stringify-form-data.js';
|
|
/**
|
|
* Fix proxied body if bodyParser is involved.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* createProxyMiddleware({
|
|
* target: 'http://example.com',
|
|
* on: {
|
|
* proxyReq: fixRequestBody,
|
|
* }
|
|
* });
|
|
* ```
|
|
*
|
|
* Alternative solution without using `fixRequestBody()`: put `http-proxy-middleware` before `bodyParser` in the middleware stack.
|
|
*
|
|
* @see {@link https://github.com/chimurai/http-proxy-middleware/issues/40 Github issue #40 - POST request body is not proxied}
|
|
*/
|
|
export function fixRequestBody(proxyReq, req) {
|
|
// skip fixRequestBody() when req.readableLength not 0 (bodyParser failure)
|
|
if (req.readableLength !== 0) {
|
|
return;
|
|
}
|
|
const requestBody = req.body;
|
|
if (!requestBody) {
|
|
return;
|
|
}
|
|
const contentType = proxyReq.getHeader('Content-Type');
|
|
if (!contentType) {
|
|
return;
|
|
}
|
|
const writeBody = (bodyData) => {
|
|
let proxyData = bodyData;
|
|
const contentEncoding = String(proxyReq.getHeader('Content-Encoding')).toLowerCase();
|
|
switch (contentEncoding) {
|
|
case 'br':
|
|
proxyData = zlib.brotliCompressSync(proxyData);
|
|
break;
|
|
case 'deflate':
|
|
proxyData = zlib.deflateSync(proxyData);
|
|
break;
|
|
case 'gzip':
|
|
proxyData = zlib.gzipSync(proxyData);
|
|
break;
|
|
case 'zstd':
|
|
proxyData = zlib.zstdCompressSync(proxyData);
|
|
break;
|
|
}
|
|
proxyReq.setHeader('Content-Length', Buffer.byteLength(proxyData));
|
|
proxyReq.write(proxyData);
|
|
};
|
|
try {
|
|
// Use if-elseif to prevent multiple writeBody/setHeader calls:
|
|
// Error: "Cannot set headers after they are sent to the client"
|
|
if (contentType.includes('application/json') || contentType.includes('+json')) {
|
|
writeBody(JSON.stringify(requestBody));
|
|
}
|
|
else if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
writeBody(querystring.stringify(requestBody));
|
|
}
|
|
else if (contentType.includes('multipart/form-data')) {
|
|
writeBody(stringifyFormData(contentType, requestBody));
|
|
}
|
|
else if (contentType.includes('text/plain')) {
|
|
writeBody(requestBody);
|
|
}
|
|
}
|
|
catch (error) {
|
|
// proxyReq listeners run outside the middleware try/catch path; re-throwing here can bubble as
|
|
// an unhandled exception in consumers, so destroy() is used to fail closed through proxy error handling.
|
|
proxyReq.destroy(toError(error));
|
|
}
|
|
}
|
|
function toError(error) {
|
|
return error instanceof Error ? error : new Error(String(error));
|
|
}
|