Skip to content

Commit d6ae7cf

Browse files
authored
fix: compatability check header shown if client is using cached responses (@fehmer) (monkeytypegame#6602)
If frontend and backend are deployed with a new COMPATABILITY_CHECK header frontend might show the backend version is lower because of the http header of a cached response. Adding the COMPATABILITY_CHECK version as part of the etag fixes this.
1 parent 093a17b commit d6ae7cf

File tree

4 files changed

+34
-0
lines changed

4 files changed

+34
-0
lines changed

backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"cron": "2.3.0",
3939
"date-fns": "3.6.0",
4040
"dotenv": "16.4.5",
41+
"etag": "1.8.1",
4142
"express": "4.21.1",
4243
"express-rate-limit": "7.4.0",
4344
"firebase-admin": "12.0.0",

backend/src/app.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import {
1010
} from "./middlewares/rate-limit";
1111
import { compatibilityCheckMiddleware } from "./middlewares/compatibilityCheck";
1212
import { COMPATIBILITY_CHECK_HEADER } from "@monkeytype/contracts";
13+
import { createETagGenerator } from "./utils/etag";
14+
15+
const etagFn = createETagGenerator({ weak: true });
1316

1417
function buildApp(): express.Application {
1518
const app = express();
@@ -27,6 +30,8 @@ function buildApp(): express.Application {
2730
app.use(badAuthRateLimiterHandler);
2831
app.use(rootRateLimiter);
2932

33+
app.set("etag", etagFn);
34+
3035
addApiRoutes(app);
3136

3237
app.use(errorHandlingMiddleware);

backend/src/utils/etag.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { COMPATIBILITY_CHECK } from "@monkeytype/contracts";
2+
import { default as etag } from "etag";
3+
4+
/**
5+
* create etag generator, based on the express implementation https://github.com/expressjs/express/blob/9f4dbe3a1332cd883069ba9b73a9eed99234cfc7/lib/utils.js#L247
6+
* Adds the api COMPATIBILITY_CHECK version in front of the etag.
7+
* @param options
8+
* @returns
9+
*/
10+
export function createETagGenerator(options: {
11+
weak: boolean;
12+
}): (body: Buffer | string, encoding: BufferEncoding | undefined) => string {
13+
return function generateETag(body, encoding) {
14+
const buf = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body;
15+
16+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
17+
const generatedTag: string = etag(buf, options);
18+
19+
//custom code to add the version number
20+
if (generatedTag.startsWith("W/")) {
21+
return `W/"V${COMPATIBILITY_CHECK}-${generatedTag.slice(3)}`;
22+
}
23+
return `"V${COMPATIBILITY_CHECK}-${generatedTag.slice(1)}`;
24+
};
25+
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)