diff --git a/health-services/project-factory/src/server/app.ts b/health-services/project-factory/src/server/app.ts index f662b76d104..c1ca2179a3b 100644 --- a/health-services/project-factory/src/server/app.ts +++ b/health-services/project-factory/src/server/app.ts @@ -11,6 +11,7 @@ import { tracingMiddleware } from "./tracing"; import { createProxyMiddleware } from "http-proxy-middleware"; import * as v8 from "v8"; import { logger } from "./utils/logger"; +import { handleGzipRequest } from "./utils/gzipHandler"; const printMemoryInMB = (memoryInBytes: number) => { const memoryInMB = memoryInBytes / (1024 * 1024); // Convert bytes to MB @@ -41,16 +42,24 @@ class App { } private initializeMiddlewares() { - this.app.use( - bodyParser.json({ limit: config.app.incomingRequestPayloadLimit }) - ); + this.app.use((req, res, next) => { + const contentType = req.headers["content-type"]; + + if (contentType === "application/gzip") { + return handleGzipRequest(req, res, next); + } + + return bodyParser.json({ limit: config.app.incomingRequestPayloadLimit })(req, res, next); + }); + + this.app.use( bodyParser.urlencoded({ limit: config.app.incomingRequestPayloadLimit, extended: true, }) ); - this.app.use(bodyParser.json()); + // this.app.use(bodyParser.json()); this.app.use(tracingMiddleware); this.app.use(requestMiddleware); this.app.use(errorLogger); diff --git a/health-services/project-factory/src/server/utils/gzipHandler.ts b/health-services/project-factory/src/server/utils/gzipHandler.ts new file mode 100644 index 00000000000..73b608aa24a --- /dev/null +++ b/health-services/project-factory/src/server/utils/gzipHandler.ts @@ -0,0 +1,41 @@ +import zlib from "zlib"; +import { Request, Response, NextFunction } from "express"; +import { logger } from "./logger"; + +export const handleGzipRequest = ( + req: Request, + res: Response, + next: NextFunction +) => { + const buffers: Buffer[] = []; + + req.on("data", (chunk) => buffers.push(chunk)); + req.on("end", () => { + try { + const gzipBuffer = Buffer.concat(buffers); + + // Decompress the Gzip data + zlib.gunzip(gzipBuffer, (err, decompressedBuffer) => { + if (err) { + logger.error("Error decompressing Gzip file:", err); + res.status(500).send("Invalid Gzip file"); + return; + } + + try { + // Convert the decompressed buffer to string and parse as JSON + const jsonData = decompressedBuffer.toString(); + const parsedData = JSON.parse(jsonData); + req.body = parsedData; // Attach parsed data to the request body + next(); // Proceed to next middleware + } catch (parseError) { + logger.error("Error parsing JSON data:", parseError); + res.status(500).send("Invalid JSON in Gzip content"); + } + }); + } catch (err) { + logger.error("Error processing Gzip content:", err); + res.status(500).send("Invalid Gzip content"); + } + }); +}; diff --git a/health-services/project-factory/src/server/utils/middlewares/requestMiddleware.ts b/health-services/project-factory/src/server/utils/middlewares/requestMiddleware.ts index a8bfd34a330..ce8b70d8196 100644 --- a/health-services/project-factory/src/server/utils/middlewares/requestMiddleware.ts +++ b/health-services/project-factory/src/server/utils/middlewares/requestMiddleware.ts @@ -1,46 +1,46 @@ -import { NextFunction, Request, Response } from "express"; // Importing necessary modules from Express -const { object, string } = require("yup"); // Importing object and string from yup for schema validation -import { errorResponder } from "../genericUtils"; // Importing errorResponder function from genericUtils -import { logger } from "../logger"; + import { NextFunction, Request, Response } from "express"; // Importing necessary modules from Express + const { object, string } = require("yup"); // Importing object and string from yup for schema validation + import { errorResponder } from "../genericUtils"; // Importing errorResponder function from genericUtils + import { logger } from "../logger"; -// Defining the request schema using yup -const requestSchema = object({ - apiId: string().nullable(), // Nullable string field for API ID - action: string().nullable(), // Nullable string field for action - msgId: string().required(), // Required string field for message ID - authToken: string().nullable(), // Nullable string field for authentication token - userInfo: object().nonNullable() // Non-nullable object field for user information -}); + // Defining the request schema using yup + const requestSchema = object({ + apiId: string().nullable(), // Nullable string field for API ID + action: string().nullable(), // Nullable string field for action + msgId: string().required(), // Required string field for message ID + authToken: string().nullable(), // Nullable string field for authentication token + userInfo: object().nonNullable() // Non-nullable object field for user information + }); -// Middleware function to validate request payload -const requestMiddleware = (req: Request, res: Response, next: NextFunction) => { - try { - logger.info(`RECEIVED A HTTP REQUEST :: URI :: ${req.url}`); - // Check if the content type is 'application/json' - const contentType = req.headers['content-type']; - if (!contentType || !contentType.split(';').map(part => part.trim()).includes('application/json')) { - // If content type is not 'application/json', throw Unsupported Media Type error - let e: any = new Error("Unsupported Media Type: Content-Type should be 'application/json'"); - e = Object.assign(e, { status: 415, code: "UNSUPPORTED_MEDIA_TYPE" }); - errorResponder(e, req, res, 415) - return; + // Middleware function to validate request payload + const requestMiddleware = (req: Request, res: Response, next: NextFunction) => { + try { + logger.info(`RECEIVED A HTTP REQUEST :: URI :: ${req.url}`); + // Check if the content type is 'application/json' + const contentType = req.headers['content-type']; + if (!contentType || !contentType.split(';').map(part => part.trim()).includes('application/json') && !contentType.split(';').map(part => part.trim()).includes('application/gzip')) { + // If content type is not 'application/json' or 'application/gzip', throw Unsupported Media Type error + let e: any = new Error("Unsupported Media Type: Content-Type should be 'application/json' or 'application/gzip'"); + e = Object.assign(e, { status: 415, code: "UNSUPPORTED_MEDIA_TYPE" }); + errorResponder(e, req, res, 415) + return; + } + // Check if tenantId is missing in RequestInfo.userInfo + if (!req?.body?.RequestInfo?.userInfo?.tenantId) { + // If tenantId is missing, throw Validation Error + let e: any = new Error("RequestInfo.userInfo.tenantId is missing"); + e = Object.assign(e, { status: 400, code: "VALIDATION_ERROR" }); + errorResponder(e, req, res, 400) + return; + } + // Validate request payload against the defined schema + requestSchema.validateSync(req.body.RequestInfo); + // If validation succeeds, proceed to the next middleware + next(); + } catch (error) { + // If an error occurs during validation process, handle the error using errorResponder function + errorResponder(error, req, res); } - // Check if tenantId is missing in RequestInfo.userInfo - if (!req?.body?.RequestInfo?.userInfo?.tenantId) { - // If tenantId is missing, throw Validation Error - let e: any = new Error("RequestInfo.userInfo.tenantId is missing"); - e = Object.assign(e, { status: 400, code: "VALIDATION_ERROR" }); - errorResponder(e, req, res, 400) - return; - } - // Validate request payload against the defined schema - requestSchema.validateSync(req.body.RequestInfo); - // If validation succeeds, proceed to the next middleware - next(); - } catch (error) { - // If an error occurs during validation process, handle the error using errorResponder function - errorResponder(error, req, res); - } -}; + }; -export default requestMiddleware; // Exporting the requestMiddleware function for use in Express middleware chain + export default requestMiddleware; // Exporting the requestMiddleware function for use in Express middleware chain