-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix for Next.js POST/PATCH/etc and Server Actions (#122)
As identified in #116 the root cause of the problems with non-get requests in NextJS on Firebase Hosting is that the ExpressJS' readable has been spent on the body-parser middleware. Solution is to create a new Readable from rawBody and pass that to the NextJS request handler. * Proxy express requests through a new IncomingMessage * Drop the LRU cache of next apps, no longer needed --------- Co-authored-by: Leonardo Ortiz <[email protected]> Co-authored-by: Maximilian Fellner <[email protected]>
- Loading branch information
1 parent
68c8e99
commit 0bfcf48
Showing
2 changed files
with
38 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,23 @@ | ||
import { parse } from "url"; | ||
import createNextServer from "next"; | ||
import LRU from "lru-cache"; | ||
|
||
import type { Request } from "firebase-functions/v2/https"; | ||
import type { Response } from "express"; | ||
import type { NextServer } from "next/dist/server/next.js"; | ||
import { incomingMessageFromExpress } from "../utils.js"; | ||
|
||
const nextAppsLRU = new LRU<string, NextServer>({ | ||
// TODO tune this | ||
max: 3, | ||
allowStale: true, | ||
updateAgeOnGet: true, | ||
dispose: (server) => { | ||
server.close(); | ||
}, | ||
// @ts-expect-error - Next.js doesn't export the custom server function with proper types | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const nextApp: NextServer = createNextServer({ | ||
dev: false, | ||
dir: process.cwd(), | ||
hostname: "0.0.0.0", | ||
port: 443, | ||
}); | ||
|
||
export const handle = async (req: Request, res: Response) => { | ||
const { hostname, protocol, url } = req; | ||
const port = protocol === "https" ? 443 : 80; | ||
const key = [hostname, port].join(":"); | ||
// I wish there was a better way to do this, but it seems like this is the | ||
// way to go. Should investigate more if we can get hostname/port to be | ||
// dynamic for middleware. | ||
let nextApp = nextAppsLRU.get(key); | ||
if (!nextApp) { | ||
// @ts-expect-error - Next.js doesn't export the custom server function with proper types | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
nextApp = createNextServer({ | ||
dev: false, | ||
dir: process.cwd(), | ||
hostname: "0.0.0.0", | ||
port, | ||
}); | ||
nextAppsLRU.set(key, nextApp!); | ||
} | ||
await nextApp!.prepare(); | ||
const parsedUrl = parse(url, true); | ||
nextApp!.getRequestHandler()(req, res, parsedUrl); | ||
await nextApp.prepare(); | ||
const parsedUrl = parse(req.url, true); | ||
const incomingMessage = incomingMessageFromExpress(req); | ||
await nextApp.getRequestHandler()(incomingMessage, res, parsedUrl); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters