UNPKG

3.34 kBJavaScriptView Raw
1import toPlainObject from 'lodash/toPlainObject';
2import hash from 'hash-obj';
3// import sizeof from 'object-sizeof';
4import * as Cookies from 'es-cookie';
5import QuickLRU from 'quick-lru';
6
7const getCacheKey = config => {
8 let headers = config.headers;
9
10 if (config.headers.common) {
11 headers = Object.assign(
12 {},
13 config.headers.common,
14 config.headers[config.method]
15 );
16 }
17
18 const hashObj = {
19 method: config.method,
20 url: config.url.replace(config.baseURL, ''),
21 headers,
22 params: config.params,
23 data: config.data,
24 };
25
26 return hash(toPlainObject(hashObj));
27};
28
29// TODO: check time and maxAge of stored value and destroy if necessary
30// eslint-disable-next-line
31const cacheGet = (cache, key, maxAge) => cache.get(key);
32
33// TODO: set time and maxAge on stored value
34// eslint-disable-next-line
35const cacheSet = (cache, key, value, maxAge) => cache.set(key, value);
36
37export default ({ $axios, env, store, req, res, query }) => {
38 env = Object.assign(
39 {
40 CACHE_ENABLED: true,
41 CACHE_MAX_AGE: 30 * 60 * 1000, // 30 mins
42 // CACHE_MAX_SIZE: 128 * 1000 * 1000, // 128mb
43 // TODO: reimplement max size based on memory
44 CACHE_MAX_SIZE: 1000,
45 },
46 env
47 );
48
49 let cache;
50
51 if (env.CACHE_ENABLED) {
52 cache = new QuickLRU({
53 maxSize: env.CACHE_MAX_SIZE,
54 });
55 }
56
57 $axios.onRequest(
58 config => {
59 let cookies = {};
60 if (req && req.headers.cookie) {
61 cookies = Cookies.parse(req.headers.cookie);
62 }
63
64 if (res && query.apiToken) {
65 res.setHeader(
66 'Set-Cookie',
67 Cookies.encode('apiToken', query.apiToken, { maxAge: 3600 })
68 );
69 }
70
71 config.headers.common['x-api-token'] =
72 query.apiToken || cookies.apiToken || env.API_TOKEN;
73
74 const role = store.state.role || env.ROLE;
75
76 if (env.CACHE_ENABLED && role === 'guest') {
77 const key = getCacheKey(config);
78
79 if (cache.has(key)) {
80 const data = cacheGet(cache, key);
81
82 config.data = data;
83
84 // Set the request adapter to send the cached response
85 // and prevent the request from actually running
86 config.adapter = () =>
87 Promise.resolve({
88 data,
89 status: config.status,
90 statusText: config.statusText,
91 headers: config.headers,
92 config,
93 request: config,
94 });
95 }
96 }
97
98 return config;
99 },
100 error => {
101 // eslint-disable-next-line
102 console.error(error);
103 return Promise.reject(error);
104 }
105 );
106
107 $axios.onResponse(
108 response => {
109 if (response.headers['x-role']) {
110 store.commit('ROLE', response.headers['x-role']);
111 }
112
113 const role = store.state.role || env.ROLE;
114
115 if (env.CACHE_ENABLED && role === 'guest') {
116 let maxAge = env.CACHE_MAX_AGE;
117
118 try {
119 maxAge = JSON.parse(response.config.params.__cache);
120 } catch (error) {
121 //
122 }
123
124 if (maxAge !== false) {
125 const key = getCacheKey(response.config);
126 cacheSet(cache, key, response.data, maxAge);
127 }
128 }
129
130 return response;
131 },
132 error => {
133 // eslint-disable-next-line
134 console.error(error);
135 return Promise.reject(error);
136 }
137 );
138};