From b7194103e39267bf59dcd6ba00f522e424219d16 Mon Sep 17 00:00:00 2001 From: Eric R Glass Date: Fri, 24 Mar 2023 11:30:47 -0400 Subject: [PATCH] Fix for Node SSR with Express JSON middleware fails on POST (#6192) * Fix for Node SSR with Express JSON middleware fails on POST * Removed the unwanted setting of the req property * Removed the unwanted setting of the req property * Removed the unwanted setting of the req property * Fixed the if statement to not break the existing logic and unit test * Cleaned up the if statement * Changed to better solution from Geoffrey-Pliez * Added class NodeIncomingMessage with body defined as any --------- Co-authored-by: Matthew Phillips --- .changeset/afraid-vans-wonder.md | 5 +++++ packages/astro/src/core/app/node.ts | 29 +++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .changeset/afraid-vans-wonder.md diff --git a/.changeset/afraid-vans-wonder.md b/.changeset/afraid-vans-wonder.md new file mode 100644 index 0000000000..1d54cb4611 --- /dev/null +++ b/.changeset/afraid-vans-wonder.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Updated to fix the Node SSR fails on POST with Express JSON middleware diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts index 882cd3132a..8561c459c3 100644 --- a/packages/astro/src/core/app/node.ts +++ b/packages/astro/src/core/app/node.ts @@ -9,7 +9,7 @@ import { App, type MatchOptions } from './index.js'; const clientAddressSymbol = Symbol.for('astro.clientAddress'); -function createRequestFromNodeRequest(req: IncomingMessage, body?: Uint8Array): Request { +function createRequestFromNodeRequest(req: NodeIncomingMessage, body?: Uint8Array): Request { const protocol = req.socket instanceof TLSSocket || req.headers['x-forwarded-proto'] === 'https' ? 'https' @@ -29,11 +29,32 @@ function createRequestFromNodeRequest(req: IncomingMessage, body?: Uint8Array): return request; } +class NodeIncomingMessage extends IncomingMessage { + /** + * The read-only body property of the Request interface contains a ReadableStream with the body contents that have been added to the request. + */ + body?: any | undefined; +} + export class NodeApp extends App { - match(req: IncomingMessage | Request, opts: MatchOptions = {}) { + match(req: NodeIncomingMessage | Request, opts: MatchOptions = {}) { return super.match(req instanceof Request ? req : createRequestFromNodeRequest(req), opts); } - render(req: IncomingMessage | Request, routeData?: RouteData) { + render(req: NodeIncomingMessage | Request, routeData?: RouteData) { + if (typeof (req.body) === 'string' && req.body.length > 0) { + return super.render( + req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(req.body)), + routeData + ); + } + + if ((typeof (req.body) === 'object') && (Object.keys(req.body).length > 0)) { + return super.render( + req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(JSON.stringify(req.body))), + routeData + ); + } + if ('on' in req) { let body = Buffer.from([]); let reqBodyComplete = new Promise((resolve, reject) => { @@ -72,4 +93,4 @@ export async function loadManifest(rootFolder: URL): Promise { export async function loadApp(rootFolder: URL): Promise { const manifest = await loadManifest(rootFolder); return new NodeApp(manifest); -} +} \ No newline at end of file