Skip to content

Commit

Permalink
chore: don't alter mithril error responses
Browse files Browse the repository at this point in the history
  • Loading branch information
slowbackspace committed May 27, 2024
1 parent 357a058 commit 10787b2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 45 deletions.
5 changes: 1 addition & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ const start = (options = {}): FastifyInstance => {
});

// proxies
if (config.mithril.enabled) {
console.log(`Mithril proxy enabled. Aggregator: ${config.mithril.aggregator}.`);
registerMithrilProxy(app);
}
registerMithrilProxy(app);

// addresses
registerRoute(app, import('./routes/addresses/address/extended.js'));
Expand Down
36 changes: 21 additions & 15 deletions src/proxies/mithril.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import fastifyHttpProxy from '@fastify/http-proxy';
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
import { getConfig } from '../config.js';
import { handle404, handle500 } from '../utils/error-handler.js';
import { handle500 } from '../utils/error-handler.js';
import { convertStreamToString } from '@blockfrost/blockfrost-utils/lib/fastify.js';
import { matchUrlToEndpoint } from '../utils/string-utils.js';
import { appendLocationToSnapshot } from '../utils/mithril.js';

export const registerMithrilProxy = (app: FastifyInstance) => {
const config = getConfig();

if (!config.mithril.enabled) {
return;
}

console.log(`Mithril proxy enabled. Aggregator: ${config.mithril.aggregator}.`);

const snapshotCDN = config.mithril.snapshotCDN;

app.register(fastifyHttpProxy, {
Expand Down Expand Up @@ -43,23 +50,22 @@ export const registerMithrilProxy = (app: FastifyInstance) => {
const isErrorResponse = reply.statusCode >= 400;

if (isErrorResponse) {
// When replying with a body of a different length it is necessary to remove the content-length header.
reply.removeHeader('content-length');

// error response returned from the proxy can originate from:
// 1) Mithril Aggregator, 2) varnish, 3) nginx, 4) whatever
// Mithril Aggregator returns only error status codes without body
if (reply.statusCode === 404) {
return handle404(reply as FastifyReply);
} else if (reply.statusCode === 412) {
return reply.code(412).send({
error: 'Api Version mismatch',
message:
'Api Version mismatch. Please check https://docs.blockfrost.io/#section/Mithril',
status_code: 412,
});
// 1) Mithril Aggregator or 2) some middleware in between (nginx/varnish/etc)
// Mithril Aggregator returns 404, 412 error status codes without body
// 500 comes with label and message props
const isMithrilError = reply.hasHeader('mithril-api-version');

if (isMithrilError) {
// Set custom header for errors that originate from Mithril
reply.header('X-Mithril-Error', '1');
return reply.send(response);
} else {
// Unexpected error
const errorBody = await convertStreamToString(response);
// When replying with a body of a different length it is necessary to remove the content-length header.

reply.removeHeader('content-length');

return handle500(reply as FastifyReply, errorBody, request as FastifyRequest);
}
Expand Down
36 changes: 10 additions & 26 deletions test/unit/tests/proxies/mithril.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,59 +348,43 @@ describe('mithril proxy text', () => {
test('error handling - mithril aggregator error (404) should be forwarded', async () => {
const app = buildFastify();

nock(mithrilAggregatorURL).get('/').reply(404);
nock(mithrilAggregatorURL).get('/').reply(404, undefined, { 'mithril-api-version': '0.1.21' });

const response = await app.inject({
method: 'GET',
url: '/mithril/',
});

expect(response.statusCode).toBe(404);
expect(response.body).toBe(
JSON.stringify({
error: 'Not Found',
message: 'The requested component has not been found.',
status_code: 404,
}),
);
expect(response.body).toBe('');
});

test('error handling - mithril aggregator error (412) should be forwarded', async () => {
const app = buildFastify();

nock(mithrilAggregatorURL).get('/').reply(412);
nock(mithrilAggregatorURL).get('/').reply(412, undefined, { 'mithril-api-version': '0.1.21' });

const response = await app.inject({
method: 'GET',
url: '/mithril/',
});

expect(response.statusCode).toBe(412);
expect(response.body).toBe(
JSON.stringify({
error: 'Api Version mismatch',
message: 'Api Version mismatch. Please check https://docs.blockfrost.io/#section/Mithril',
status_code: 412,
}),
);
expect(response.body).toBe('');
});
test('error handling - unknown mithril aggregator error (400) returns as 500', async () => {
test('error handling - unknown mithril aggregator error (400) forwarded', async () => {
const app = buildFastify();

nock(mithrilAggregatorURL).get('/').reply(400, 'unexpected body');
nock(mithrilAggregatorURL)
.get('/')
.reply(400, 'unexpected body', { 'mithril-api-version': '0.1.21' });

const response = await app.inject({
method: 'GET',
url: '/mithril/',
});

expect(response.statusCode).toBe(500);
expect(response.body).toBe(
JSON.stringify({
error: 'Internal Server Error',
message: 'An unexpected response was received from the backend.',
status_code: 500,
}),
);
expect(response.statusCode).toBe(400);
expect(response.body).toBe('unexpected body');
});
});

0 comments on commit 10787b2

Please sign in to comment.