Skip to content

Commit 31f89a8

Browse files
authored
Merge pull request #681 from namecheap/fix/fix_fastify_callback
fix: fix fastify hook callback handling to prevent request hanging
2 parents 00a2198 + 60039b1 commit 31f89a8

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

ilc/server/app.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,25 @@ module.exports = (registryService, pluginManager, context) => {
3131

3232
app.addHook('onRequest', (req, reply, done) => {
3333
context.run({ request: req, requestId: reportingPluginManager.getRequestId() ?? request.id }, async () => {
34+
let doneWithContext;
35+
3436
try {
3537
const asyncResource = new AsyncResource('fastify-request-context');
3638
req[asyncResourceSymbol] = asyncResource;
37-
const doneWithContext = () => asyncResource.runInAsyncScope(done, req.raw);
39+
doneWithContext = () => asyncResource.runInAsyncScope(done, req.raw);
3840

3941
const { url, method } = req.raw;
4042
accessLogger.logRequest();
4143

4244
if (!['GET', 'OPTIONS', 'HEAD'].includes(method)) {
4345
logger.warn(`Request method ${method} is not allowed for url ${url}`);
4446
reply.code(405).send({ message: 'Method Not Allowed' });
45-
return;
47+
return doneWithContext();
4648
}
4749

4850
if (isDataUri(url)) {
4951
reply.code(400).send({ message: 'Bad Request: Data URIs are not valid HTTP paths' });
50-
return;
52+
return doneWithContext();
5153
}
5254

5355
req.raw.ilcState = {};
@@ -67,9 +69,15 @@ module.exports = (registryService, pluginManager, context) => {
6769

6870
await i18nOnRequest(req, reply);
6971

70-
doneWithContext();
72+
return doneWithContext();
7173
} catch (error) {
7274
errorHandler.handleError(error, req, reply);
75+
76+
if (typeof doneWithContext === 'function') {
77+
doneWithContext();
78+
} else {
79+
done();
80+
}
7381
}
7482
});
7583
});

ilc/server/app.spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,25 @@ describe('App', () => {
9393
chai.expect(responseCombined2.body.message).to.include('Data URIs');
9494
});
9595

96+
it('should block data URI in onRequest hook before wildcardRequestHandler (prevents FragmentError)', async () => {
97+
// Production NewRelic alert scenario: data URI reached wildcardRequestHandler -> special:404 -> FragmentError
98+
// This test verifies the fix: data URI blocked in onRequest with 400, never reaches wildcardRequestHandler
99+
const productionDataUri =
100+
'/data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJiIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTQ0IiBoZWlnaHQ9IjY1NSI';
101+
102+
const response = await server.get(productionDataUri).expect(400);
103+
104+
// Verify: Blocked with 400 (not 404 which would indicate wildcardRequestHandler was reached)
105+
chai.expect(response.status).to.equal(400);
106+
chai.expect(response.body.message).to.include('Bad Request');
107+
chai.expect(response.body.message).to.include('Data URIs');
108+
109+
// Key assertion: Status is 400, not 404
110+
// If this were 404, it would mean wildcardRequestHandler processed it as special:404
111+
// which would trigger Tailor fragment fetching -> FragmentError in NewRelic
112+
chai.expect(response.status).to.not.equal(404);
113+
});
114+
96115
it('should parse "invalid" urls', async () => {
97116
await server.get('///').expect(200);
98117
});

0 commit comments

Comments
 (0)