testinggospels / camouflage

Camouflage is a backend mocking tool for HTTP, gRPC, Websockets and Thrift protocols, which helps you carry out your front end prototyping, unit testing, functional/performance testing in silos, in absence of one or more Microservices/APIs.
https://testinggospels.github.io/camouflage/
MIT License
277 stars 26 forks source link

`ReferenceError: require is not defined` while loading external middleware #231

Open cat-ninja opened 1 year ago

cat-ninja commented 1 year ago

Describe the bug I'm trying to increase the max request body size by registering this middleware:

(() => {
    this.logger.info("inside middleware");

    const express = require('express');
    this.app.use(express.json({ limit: '10mb' }));
    this.app.use(express.urlencoded({ limit: '10mb', extended: true }));

    this.app.use("/", this.allRoutes);
})();

The server crashes with the next error:

2023-08-07 11:17:57 info: Handlebar helpers registration completed
2023-08-07 11:17:57 warn: Found an external middleware config. Note that if you are using middleware injection, it is required to include this.app.use(prefix, this.allRoutes); in your middleware. prefix can be either root i.e. "/" or any other desired prefix string for your routes.
2023-08-07 11:17:57 info: inside middleware
undefined:6
    const express = require('express');
                    ^

ReferenceError: require is not defined
    at eval (eval at start (/Users/.../.nvm/versions/node/v20.2.0/lib/node_modules/camouflage-server/dist/index.js:175:9), <anonymous>:6:21)
    at Object.eval (eval at start (/Users/.../.nvm/versions/node/v20.2.0/lib/node_modules/camouflage-server/dist/index.js:175:9), <anonymous>:11:3)
    at Object.start (/Users/.../.nvm/versions/node/v20.2.0/lib/node_modules/camouflage-server/dist/index.js:175:40)
    at Object.<anonymous> (/Users/.../.nvm/versions/node/v20.2.0/lib/node_modules/camouflage-server/bin/camouflage.js:252:14)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47
cat-ninja commented 1 year ago

I was able to workaround this by patching this line locally:

new Function(middlewareConfig).call({ require, app, logger: logger_1.default, allRoutes });

and using this.require inside of my custom middleware

shubhendumadhukar commented 1 year ago

I am looking into a more appropriate way to handle this, but would you like to try a dynamic import?

(async () => {
    this.logger.info("inside middleware");

    const express = await import("express");
    this.app.use(express.json({ limit: '10mb' }));
    this.app.use(express.urlencoded({ limit: '10mb', extended: true }));

    this.app.use("/", this.allRoutes);
})();

I don't see any errors, but I haven't validated if the middlewares are actually applied.

cat-ninja commented 1 year ago

@shubhendumadhukar the snippet you provided works okay for me in case of importing express. But if I do

(async () => {
    const multer = await import("multer");
    this.app.use(multer().any());
    this.app.use("/", this.allRoutes);
})();

I get

this.app.use(multer().any());
                 ^
TypeError: multer is not a function
    at eval (eval at start (/Users/fedor/.nvm/versions/node/v20.2.0/lib/node_modules/camouflage-server/dist/index.js:176:9), <anonymous>:5:18)

with this.require it works okay for me

(() => {
    const multer = this.require('multer');
    this.app.use(multer().any());
    this.app.use("/", this.allRoutes);
})();
cat-ninja commented 1 year ago

I figured it works if I do

(async () => {
    const multer = (await import('multer')).default;
    this.app.use(multer().any());
    this.app.use("/", this.allRoutes);
})();