0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-10 23:01:26 -05:00

Fixes Node adapter receiving a request body (#4023)

* Fixes Node adapter receiving a request body

* Updated lockfile
This commit is contained in:
Matthew Phillips 2022-07-22 15:22:31 -04:00 committed by GitHub
parent 9970dde630
commit 3b104fb8a5
6 changed files with 134 additions and 14 deletions

View file

@ -24,13 +24,15 @@
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"dev": "astro-scripts dev \"src/**/*.ts\""
"dev": "astro-scripts dev \"src/**/*.ts\"",
"test": "mocha --exit --timeout 20000 test/"
},
"dependencies": {
"@astrojs/webapi": "^0.12.0"
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*"
"astro-scripts": "workspace:*",
"node-mocks-http": "^1.11.0"
}
}

View file

@ -12,21 +12,28 @@ export function createExports(manifest: SSRManifest) {
const app = new NodeApp(manifest);
return {
async handler(req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) {
const route = app.match(req);
try {
const route = app.match(req);
if (route) {
try {
const response = await app.render(req);
await writeWebResponse(res, response);
} catch (err: unknown) {
if (next) {
next(err);
} else {
throw err;
if (route) {
try {
const response = await app.render(req);
await writeWebResponse(res, response);
} catch (err: unknown) {
if (next) {
next(err);
} else {
throw err;
}
}
} else if (next) {
return next();
}
} catch(err: unknown) {
if(!res.headersSent) {
res.writeHead(500, `Server error`);
res.end();
}
} else if (next) {
return next();
}
},
};

View file

@ -0,0 +1,37 @@
import nodejs from '../dist/index.js';
import { loadFixture, createRequestAndResponse, toPromise } from './test-utils.js';
import { expect } from 'chai';
describe('API routes', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/api-route/',
experimental: {
ssr: true,
},
adapter: nodejs(),
});
await fixture.build();
});
it('Can get the request body', async () => {
const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');
let { req, res, done } = createRequestAndResponse({
method: 'POST',
url: '/recipes'
});
handler(req, res);
req.send(JSON.stringify({ id: 2 }));
let [ buffer ] = await done;
let json = JSON.parse(buffer.toString('utf-8'));
expect(json.length).to.equal(1);
expect(json[0].name).to.equal('Broccoli Soup');
});
});

View file

@ -0,0 +1,9 @@
{
"name": "@test/nodejs-api-route",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*",
"@astrojs/node": "workspace:*"
}
}

View file

@ -0,0 +1,24 @@
export async function post({ request }) {
let body = await request.json();
const recipes = [
{
id: 1,
name: 'Potato Soup'
},
{
id: 2,
name: 'Broccoli Soup'
}
];
let out = recipes.filter(r => {
return r.id === body.id;
});
return new Response(JSON.stringify(out), {
headers: {
'Content-Type': 'application/json'
}
});
}

View file

@ -0,0 +1,41 @@
import { loadFixture as baseLoadFixture } from '../../../astro/test/test-utils.js';
import httpMocks from 'node-mocks-http';
import { EventEmitter } from 'events';
/**
* @typedef {import('../../../astro/test/test-utils').Fixture} Fixture
*/
export function loadFixture(inlineConfig) {
if (!inlineConfig || !inlineConfig.root)
throw new Error("Must provide { root: './fixtures/...' }");
// resolve the relative root (i.e. "./fixtures/tailwindcss") to a full filepath
// without this, the main `loadFixture` helper will resolve relative to `packages/astro/test`
return baseLoadFixture({
...inlineConfig,
root: new URL(inlineConfig.root, import.meta.url).toString(),
});
}
export function createRequestAndResponse(reqOptions) {
let req = httpMocks.createRequest(reqOptions);
let res = httpMocks.createResponse({
eventEmitter: EventEmitter,
req
});
let done = toPromise(res);
return { req, res, done };
}
export function toPromise(res) {
return new Promise(resolve => {
res.on('end', () => {
let chunks = res._getChunks();
resolve(chunks);
});
});
}