-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin.ts
77 lines (69 loc) · 2.13 KB
/
plugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import {
FastifyInstance,
FastifyPluginAsync,
FastifyPluginOptions,
FastifyReply,
FastifyRequest,
RequestPayload
} from 'fastify'
import fp from 'fastify-plugin'
import _ from 'lodash'
export interface CacheService {
get(key: string): Promise<any | null>
set(key: string, value: any, options: { ttl: number }): Promise<void>
}
const isCacheableRequest = (request: FastifyRequest) => {
if (
request.method !== 'GET' ||
request.headers['cache-control'] === 'no-cache' ||
request.headers['x-cache-bypass'] === 'true' ||
_.isNil(_.get(request.routeOptions.config, 'cache'))
) {
return false
}
return true
}
const isCacheableResponse = (reply: FastifyReply, payload: RequestPayload) => {
if (
reply.statusCode !== 200 ||
reply.getHeader('x-cache') === 'hit' ||
reply.request.method !== 'GET' ||
_.isNil(_.get(reply.request.routeOptions.config, 'cache')) ||
_.isEmpty(payload)
) {
return false
}
return true
}
const cacheOnRequestHook = (service: CacheService) => async (request: FastifyRequest, reply: FastifyReply) => {
if (!isCacheableRequest(request)) {
return
}
const cacheKey = request.url
const cacheData = await service.get(cacheKey)
if (_.isNil(cacheData)) {
reply.header('x-cache', 'miss')
return
}
reply.header('x-cache', 'hit').status(200).send(cacheData)
}
const cacheOnSendHook =
(service: CacheService) => async (request: FastifyRequest, reply: FastifyReply, payload: RequestPayload) => {
if (!isCacheableResponse(reply, payload)) {
return payload
}
const cacheKey = request.url
const ttl = _.get(reply.request.routeOptions.config, 'cache.ttl', 600) // defaulting to 10mins
await service.set(cacheKey, payload, { ttl })
return payload
}
const plugin = (service: CacheService) => async (server: FastifyInstance, options: FastifyPluginOptions) => {
server.addHook('onRequest', cacheOnRequestHook(service))
server.addHook('onSend', cacheOnSendHook(service))
}
const cachePlugin = (service: CacheService): FastifyPluginAsync =>
fp(plugin(service), {
name: 'fastify-cache',
fastify: '5.x'
})
export default cachePlugin