Rename createRouteId to getRouteId and update related references; improve raw body capture stream handling

This commit is contained in:
Debadutta Panda 2025-02-08 10:59:37 +05:30
parent 90328ef75e
commit 7321cd20db

View File

@ -78,7 +78,7 @@ module.exports = function(RED) {
return getRootApp(app.parent)
}
function createRouteId(req) {
function getRouteId(req) {
var method = req.method.toLowerCase(), url = req.url;
return `${method}:${url}`;
}
@ -94,49 +94,63 @@ module.exports = function(RED) {
rootApp.set('httpInNodes', httpInNodes);
// This middleware must always be at the root to handle the raw request body correctly
/**
* This middleware must always be at the root to handle the raw request body correctly
* @param {import('express').Request} req
* @param {import('express').Response} _res
* @param {import('express').NextFunction} next
* @returns
*/
function setupRawBodyCapture(req, _res, next) {
var httpInNodeId = createRouteId(req)
var httpInNodeId = getRouteId(req)
// Check if settings for this ID exist
if (httpInNodes.has(httpInNodeId)) {
// Get the httpInNode by routeId
var httpInNode = httpInNodes.get(httpInNodeId);
// If raw body inclusion is disabled, skip the processing
if (!httpInNode.includeRawBody) {
return next();
}
// Create a PassThrough stream to capture the request body
var passThrough = new PassThrough();
var cloneStream = new PassThrough();
// Function to handle 'data' event
function onData(chunk) {
passThrough.write(chunk);
// Continue pushing chunks into clone stream if it is writable.
if (!cloneStream.writable) {
cloneStream.write(chunk);
}
}
// Function to handle 'end' or 'error' events
function onEnd(err) {
if (err) {
passThrough.destroy(err);
// If clone stream is already destroyed don't call destory function again
if (!cloneStream.destroyed) {
cloneStream.destroy(err);
}
} else {
passThrough.end();
cloneStream.end();
}
}
// Attach event listeners to the request stream
req.on('data', onData);
req.once('end', onEnd);
req.once('error', onEnd);
req.on('data', onData)
.once('end', onEnd)
.once('error', onEnd)
// Remove listeners once the request is closed
.once('close', () => {
req.removeListener('data', onData);
})
// Remove listeners once the request is closed
req.once('close', function () {
req.removeListener('data', onData);
});
// Attach the passThrough stream to the request
// Attach the clone stream to the request
Object.defineProperty(req, "_nodeRedReqStream", {
value: passThrough
value: cloneStream
});
// Proceed to the next middleware if no settings found
return next();
}
// Proceed to the next middleware if no settings found
@ -351,7 +365,7 @@ module.exports = function(RED) {
}
// unique id for httpInNode based on method name and url path
var httpInNodeId = createRouteId({url: this.url, method: this.method})
var httpInNodeId = getRouteId({url: this.url, method: this.method})
// get httpInNode from RED.httpNode
var httpInNodes = rootApp.get('httpInNodes')