bunrest icon indicating copy to clipboard operation
bunrest copied to clipboard

Handlers Failing to Chain

Open lewisjr opened this issue 8 months ago • 0 comments

Update 2 | Notes for Global Use

Global use seems to be failing for handlers that have a middleware with the following type: (req: BunRequest, res: BunResponse, next?: (err?: Error) => {}, err?: Error) => void | Promise<any> . Once I removed the err?: Error from my cors handler it was registering globally. I could then proceed to use it as follows:

app.use(cors());

Update 1 | Fix for Chaining

Got a solution for the chaining:

bunrest/src/server.ts

private openServer(...args): Server {
   // other code
  
   // middlewares hander
   if (that.middlewares.length !== 0) {
      const plainMid = that.middlewares.filter(mid => req.path.startsWith(mid.path) || mid.path === '*');

      // rest of code
   }
}

Slightly altering the plainMid variable makes all the difference. Now middlewares in route handlers chain such as:

app.get("/path", middleware1, middleware2, async (req, res) => {
   // code
});

Original Issue

So I was having issues with the Express cors package and began creating one that is fully compatible and typed with bunrest (ideally for release as a package down the road). That being said, my middlewares are not chaining. I have a custom auth middleware to handle API keys and what not which is crucial, however, my cors is only being hit when there's a preflight (I have to specifically add it to router.options). Here is what I have:

auth.ts
authRouter.post(
	"/logout",
	cors({
		allowedHeaders: ["X-API-KEY", "X-AUTH-TOKEN"],
		methods: ["GET", "POST", "PATCH"],
		origins: ["https://www.test.dev"],
	}),
	authMiddleware,
	async (req, res) => {
		try {
			await doSomething();

			res.status(200).json({ success: true });
		} catch (ex) {
			res.status(500).json({ success: false });
		}
	}
);

cors.ts

NOTE: this is a stripped down version

export default function cors(options?: CorsOptions) {

	const _isOrigin = (header: string): boolean => {
		if (Array.isArray(origins)) return origins.includes(header);
		else return true;
	};

	const middelware: Handler = (req, res, next?, err?) => {
				console.log("hit");

				// @ts-ignore
				const host = req.headers["host"];
				const isvalidOriginNoPreflight = _isOrigin(host);

				if (!isvalidOriginNoPreflight) {
					res.status(400).send("");
				}

				// @ts-ignore
				next();
		}
	};

	return middelware;
}

authMiddleware.ts
export const authMiddleware: Handler = (req, res, next?, err?) => {
	const isValid = validateStuff();

	if (!isValid) {
			res.status(401).json({
				message: "Access Denied",
			});
		} else {

			// @ts-ignore
			next();
		}
	} else {
		res.status(400).json({ message: "Invalid credentials provided." });
	}
};

I am sending my request from Postman localhost, so when I only include the cors middleware it rejects my request due to the host not being part of the origins. Equally, when I only include the authMiddleware it does what it should. However, when I chain them, only the last middleware works. So if it goes cors, then authMiddleware; only the auth middleware will run and vice versa.

Additionally, the global app.use(req, res, next?, err?) => {...} does not hit the cors (express or my custom one) middleware if I put it in there.

Other Relevant Info: Bun version: v1.0.7 bunrest version: v1.3.6 platform: ubuntu 20.04 (docker image) node installed: yes node version: v18.18.2

lewisjr avatar Oct 23 '23 02:10 lewisjr