mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 12:57:46 +00:00
[dev] log middleware errors in vc dev (#8267)
Middleware server setup wasn't logging errors the same way that dev server setup was. This meant that middleware instantiation errors (like invalid config) would cause requests to 500, but no errors to be logged to the console. This PR updates the invalid config error, makes sure errors in this area are logged out, and adds a test for this behavior. **It may be appropriate to fail the deploy (and crash `vc dev`) in this case instead, though. What do others think?** --- During `vc dev` with middleware that has an invalid `config.matcher` value... Before: You see a 500 response in the browser and no output in the terminal. After: You see a 500 response in the browser and this output in the terminal: ``` Error! Middleware's `config.matcher` values must start with "/". Received: not-a-valid-matcher ``` --- Related Issue: https://github.com/vercel/edge-functions/issues/220
This commit is contained in:
@@ -1556,6 +1556,8 @@ export default class DevServer {
|
|||||||
(err as any).link = 'https://vercel.link/command-not-found';
|
(err as any).link = 'https://vercel.link/command-not-found';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.output.prettyError(err);
|
||||||
|
|
||||||
await this.sendError(
|
await this.sendError(
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export const config = {
|
||||||
|
matcher: 'not-a-valid-matcher',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function middleware(request, _event) {
|
||||||
|
return new Response(null);
|
||||||
|
}
|
||||||
@@ -227,7 +227,7 @@ test('[vercel dev] should handle syntax errors thrown in edge functions', async
|
|||||||
expect(await res.text()).toMatch(
|
expect(await res.text()).toMatch(
|
||||||
/<strong>500<\/strong>: INTERNAL_SERVER_ERROR/g
|
/<strong>500<\/strong>: INTERNAL_SERVER_ERROR/g
|
||||||
);
|
);
|
||||||
expect(stderr).toMatch(/Failed to instantiate edge runtime./g);
|
expect(stderr).toMatch(/Failed to compile user code for edge runtime./g);
|
||||||
expect(stderr).toMatch(/Unexpected end of file/g);
|
expect(stderr).toMatch(/Unexpected end of file/g);
|
||||||
expect(stderr).toMatch(
|
expect(stderr).toMatch(
|
||||||
/Failed to complete request to \/api\/edge-error-syntax: Error: socket hang up/g
|
/Failed to complete request to \/api\/edge-error-syntax: Error: socket hang up/g
|
||||||
@@ -307,6 +307,35 @@ test('[vercel dev] should handle missing handler errors thrown in edge functions
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('[vercel dev] should handle invalid middleware config', async () => {
|
||||||
|
const dir = fixture('middleware-matchers-invalid');
|
||||||
|
const { dev, port, readyResolver } = await testFixture(dir);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await readyResolver;
|
||||||
|
|
||||||
|
let res = await fetch(`http://localhost:${port}/api/whatever`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Accept:
|
||||||
|
'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
validateResponseHeaders(res);
|
||||||
|
|
||||||
|
const { stderr } = await dev.kill('SIGTERM');
|
||||||
|
|
||||||
|
expect(await res.text()).toMatch(
|
||||||
|
/<strong>500<\/strong>: INTERNAL_SERVER_ERROR/g
|
||||||
|
);
|
||||||
|
expect(stderr).toMatch(
|
||||||
|
/Middleware's `config.matcher` .+ Received: not-a-valid-matcher/g
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await dev.kill('SIGTERM');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('[vercel dev] should support request body', async () => {
|
test('[vercel dev] should support request body', async () => {
|
||||||
const dir = fixture('node-request-body');
|
const dir = fixture('node-request-body');
|
||||||
const { dev, port, readyResolver } = await testFixture(dir);
|
const { dev, port, readyResolver } = await testFixture(dir);
|
||||||
|
|||||||
@@ -348,7 +348,10 @@ function testFixtureStdio(
|
|||||||
: []),
|
: []),
|
||||||
'deploy',
|
'deploy',
|
||||||
...(process.env.VERCEL_CLI_VERSION
|
...(process.env.VERCEL_CLI_VERSION
|
||||||
? ['--build-env', `VERCEL_CLI_VERSION=${process.env.VERCEL_CLI_VERSION}`]
|
? [
|
||||||
|
'--build-env',
|
||||||
|
`VERCEL_CLI_VERSION=${process.env.VERCEL_CLI_VERSION}`,
|
||||||
|
]
|
||||||
: []),
|
: []),
|
||||||
'--public',
|
'--public',
|
||||||
'--debug',
|
'--debug',
|
||||||
@@ -430,7 +433,7 @@ function testFixtureStdio(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stderr.includes('Command failed') || stderr.includes('Error!')) {
|
if (stderr.includes('Command failed')) {
|
||||||
dev.kill('SIGTERM');
|
dev.kill('SIGTERM');
|
||||||
throw new Error(`Failed for "${directory}" with stderr "${stderr}".`);
|
throw new Error(`Failed for "${directory}" with stderr "${stderr}".`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ async function compileUserCode(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// We can't easily show a meaningful stack trace from ncc -> edge-runtime.
|
// We can't easily show a meaningful stack trace from ncc -> edge-runtime.
|
||||||
// So, stick with just the message for now.
|
// So, stick with just the message for now.
|
||||||
console.error(`Failed to instantiate edge runtime.`);
|
console.error(`Failed to compile user code for edge runtime.`);
|
||||||
logError(error);
|
logError(error);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ export function getRegExpFromMatchers(matcherOrMatchers: unknown): string {
|
|||||||
function getRegExpFromMatcher(matcher: unknown): string {
|
function getRegExpFromMatcher(matcher: unknown): string {
|
||||||
if (typeof matcher !== 'string') {
|
if (typeof matcher !== 'string') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'`matcher` must be a path matcher or an array of path matchers'
|
"Middleware's `config.matcher` must be a path matcher (string) or an array of path matchers (string[])"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matcher.startsWith('/')) {
|
if (!matcher.startsWith('/')) {
|
||||||
throw new Error('`matcher`: path matcher must start with /');
|
throw new Error(
|
||||||
|
`Middleware's \`config.matcher\` values must start with "/". Received: ${matcher}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const re = pathToRegexp(matcher);
|
const re = pathToRegexp(matcher);
|
||||||
|
|||||||
Reference in New Issue
Block a user