Skip to content

Commit e62ce79

Browse files
authored
feat: add Warning http response deprecation notices (#2253)
* feat: add `Warning` http response deprecation notices for deprecated endpoints * ci: lint fix
1 parent d707c58 commit e62ce79

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/api/deprecation-plugin.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fp from 'fastify-plugin';
2+
import { FastifyPluginAsync } from 'fastify';
3+
4+
declare module 'fastify' {
5+
interface FastifySchema {
6+
deprecatedMessage?: string;
7+
}
8+
}
9+
10+
const pluginCb: FastifyPluginAsync<{ defaultDeprecatedMessage: string }> = async (
11+
fastify,
12+
options
13+
) => {
14+
fastify.addHook('onSend', async (request, reply) => {
15+
if (request.routeOptions.schema?.deprecated) {
16+
const warningMessage =
17+
request.routeOptions.schema.deprecatedMessage ??
18+
options.defaultDeprecatedMessage ??
19+
'Endpoint is deprecated';
20+
const warning = `299 - "Deprecated: ${warningMessage}"`;
21+
if (!reply.getHeader('Warning')) {
22+
void reply.header('Warning', warning);
23+
}
24+
}
25+
});
26+
await Promise.resolve();
27+
};
28+
29+
/**
30+
* Fastify plugin that adds deprecation warnings to HTTP responses.
31+
*
32+
* If a route's schema has `deprecated: true`, a `Warning` header will be added to the response.
33+
* - If the schema includes a `deprecatedMessage`, it will be used in the warning.
34+
* - If not, the plugin uses the `defaultDeprecatedMessage` provided in the plugin options.
35+
* - If neither is available, a generic warning message `299 - "Deprecated"` is used.
36+
*/
37+
const DeprecationPlugin = fp(pluginCb);
38+
39+
export default DeprecationPlugin;

src/api/init.ts

+6
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import FastifyMetrics from 'fastify-metrics';
5757
import FastifyCors from '@fastify/cors';
5858
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
5959
import * as promClient from 'prom-client';
60+
import DeprecationPlugin from './deprecation-plugin';
6061

6162
export interface ApiServer {
6263
fastifyApp: FastifyInstance;
@@ -271,6 +272,11 @@ export async function startApiServer(opts: {
271272
// Setup direct proxy to core-node RPC endpoints (/v2)
272273
await fastify.register(CoreNodeRpcProxyRouter, { prefix: '/v2' });
273274

275+
// Middleware to annotate http responses with deprecation warnings
276+
await fastify.register(DeprecationPlugin, {
277+
defaultDeprecatedMessage: 'See https://docs.hiro.so/stacks/api for more information',
278+
});
279+
274280
// Wait for all routes and middleware to be ready before starting the server
275281
await fastify.ready();
276282

tests/api/address.test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,9 @@ describe('address tests', () => {
15471547
);
15481548
expect(fetchAddrBalance1.status).toBe(200);
15491549
expect(fetchAddrBalance1.type).toBe('application/json');
1550+
expect(fetchAddrBalance1.headers['warning']).toBe(
1551+
'299 - "Deprecated: See https://docs.hiro.so/stacks/api for more information"'
1552+
);
15501553
const expectedResp1 = {
15511554
stx: {
15521555
balance: '88679',

0 commit comments

Comments
 (0)