Fix middleware build result. Return middleware next when invalid result. (#6963)

* Fix middleware build result. Return middleware next when invalid result.

* Add a unit test that would have failed before previous commit.

* Copy next.js behavior.

* Add a test for invalid responses from middleware.

Co-authored-by: Leo Lamprecht <leo@vercel.com>
This commit is contained in:
Gary Borton
2021-11-09 11:06:16 -08:00
committed by GitHub
parent ed1dacd276
commit c277c649c6
6 changed files with 77 additions and 16 deletions

View File

@@ -1358,13 +1358,20 @@ export default class DevServer {
this.cwd, this.cwd,
this.output this.output
); );
for (let plugin of devMiddlewarePlugins) { try {
const result = await plugin.plugin.runDevMiddleware(req, res, this.cwd); for (let plugin of devMiddlewarePlugins) {
if (result.finished) { const result = await plugin.plugin.runDevMiddleware(req, res, this.cwd);
return result; if (result.finished) {
return result;
}
} }
return { finished: false };
} catch (e) {
return {
finished: true,
error: e,
};
} }
return { finished: false };
}; };
/** /**

View File

@@ -0,0 +1,3 @@
export default function () {
return 'freecandy';
}

View File

@@ -374,4 +374,15 @@ describe('DevServer', () => {
); );
}) })
); );
it(
'should render an error page when the middleware returns not a Response',
testFixture('edge-middleware-invalid-response', async server => {
const response = await fetch(`${server.address}/index.html`);
const body = await response.text();
expect(body).toStrictEqual(
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED\n'
);
})
);
}); });

View File

@@ -3,13 +3,16 @@ _ENTRIES = typeof _ENTRIES === 'undefined' ? {} : _ENTRIES;
_ENTRIES['middleware_pages/_middleware'] = { _ENTRIES['middleware_pages/_middleware'] = {
default: async function (ev) { default: async function (ev) {
const result = await middleware.default(ev.request, ev); const result = await middleware.default(ev.request, ev);
if (result instanceof Response) { return {
return { promise: Promise.resolve(),
promise: Promise.resolve(), waitUntil: Promise.resolve(),
waitUntil: Promise.resolve(), response:
response: result, result ||
}; new Response(null, {
} headers: {
return result; 'x-middleware-next': 1,
},
}),
};
}, },
}; };

View File

@@ -1,8 +1,19 @@
import { join } from 'path'; import { join } from 'path';
import { promises as fsp } from 'fs'; import { promises as fsp } from 'fs';
import { build } from '../src'; import { build } from '../src';
import { Response } from 'node-fetch';
describe('build()', () => { describe('build()', () => {
beforeEach(() => {
//@ts-ignore
global.Response = Response;
});
afterEach(() => {
//@ts-ignore
delete global.Response;
//@ts-ignore
delete global._ENTRIES;
});
it('should build simple middleware', async () => { it('should build simple middleware', async () => {
const fixture = join(__dirname, 'fixtures/simple'); const fixture = join(__dirname, 'fixtures/simple');
await build({ await build({
@@ -17,8 +28,30 @@ describe('build()', () => {
); );
expect(middlewareManifest).toMatchSnapshot(); expect(middlewareManifest).toMatchSnapshot();
const outputFile = join(fixture, '.output/server/pages/_middleware.js');
expect(await fsp.stat(outputFile)).toBeTruthy();
require(outputFile);
//@ts-ignore
const middleware = global._ENTRIES['middleware_pages/_middleware'].default;
expect(typeof middleware).toStrictEqual('function');
const handledResponse = await middleware({
request: {
url: 'http://google.com',
},
});
const unhandledResponse = await middleware({
request: {
url: 'literallyanythingelse',
},
});
expect(String(handledResponse.response.body)).toEqual('Hi from the edge!');
expect( expect(
await fsp.stat(join(fixture, '.output/server/pages/_middleware.js')) (handledResponse.response as Response).headers.get('x-middleware-next')
).toBeTruthy(); ).toEqual(null);
expect(unhandledResponse.response.body).toEqual(null);
expect(
(unhandledResponse.response as Response).headers.get('x-middleware-next')
).toEqual('1');
}); });
}); });

View File

@@ -1 +1,5 @@
export default () => new Response('Hi from the edge!'); export default req => {
if (req.url === 'http://google.com') {
return new Response('Hi from the edge!');
}
};