UNPKG

6.45 kBJavaScriptView Raw
1import Axios from 'axios'
2import defu from 'defu'
3<% if (options.retry) { %>import axiosRetry from 'axios-retry'<% } %>
4
5// Axios.prototype cannot be modified
6const axiosExtra = {
7 setBaseURL (baseURL) {
8 this.defaults.baseURL = baseURL
9 },
10 setHeader (name, value, scopes = 'common') {
11 for (const scope of Array.isArray(scopes) ? scopes : [ scopes ]) {
12 if (!value) {
13 delete this.defaults.headers[scope][name];
14 return
15 }
16 this.defaults.headers[scope][name] = value
17 }
18 },
19 setToken (token, type, scopes = 'common') {
20 const value = !token ? null : (type ? type + ' ' : '') + token
21 this.setHeader('Authorization', value, scopes)
22 },
23 onRequest(fn) {
24 this.interceptors.request.use(config => fn(config) || config)
25 },
26 onResponse(fn) {
27 this.interceptors.response.use(response => fn(response) || response)
28 },
29 onRequestError(fn) {
30 this.interceptors.request.use(undefined, error => fn(error) || Promise.reject(error))
31 },
32 onResponseError(fn) {
33 this.interceptors.response.use(undefined, error => fn(error) || Promise.reject(error))
34 },
35 onError(fn) {
36 this.onRequestError(fn)
37 this.onResponseError(fn)
38 },
39 create(options) {
40 return createAxiosInstance(defu(options, this.defaults))
41 }
42}
43
44// Request helpers ($get, $post, ...)
45for (const method of ['request', 'delete', 'get', 'head', 'options', 'post', 'put', 'patch']) {
46 axiosExtra['$' + method] = function () { return this[method].apply(this, arguments).then(res => res && res.data) }
47}
48
49const extendAxiosInstance = axios => {
50 for (const key in axiosExtra) {
51 axios[key] = axiosExtra[key].bind(axios)
52 }
53}
54
55const createAxiosInstance = axiosOptions => {
56 // Create new axios instance
57 const axios = Axios.create(axiosOptions)
58 axios.CancelToken = Axios.CancelToken
59 axios.isCancel = Axios.isCancel
60
61 // Extend axios proto
62 extendAxiosInstance(axios)
63
64 // Intercept to apply default headers
65 axios.onRequest((config) => {
66 config.headers = { ...axios.defaults.headers.common, ...config.headers }
67 })
68
69 // Setup interceptors
70 <% if (options.debug) { %>setupDebugInterceptor(axios) <% } %>
71 <% if (options.credentials) { %>setupCredentialsInterceptor(axios) <% } %>
72 <% if (options.progress) { %>setupProgress(axios) <% } %>
73 <% if (options.retry) { %>axiosRetry(axios, <%= serialize(options.retry) %>) <% } %>
74
75 return axios
76}
77
78<% if (options.debug) { %>
79const log = (level, ...messages) => console[level]('[Axios]', ...messages)
80
81const setupDebugInterceptor = axios => {
82 // request
83 axios.onRequestError(error => {
84 log('error', 'Request error:', error)
85 })
86
87 // response
88 axios.onResponseError(error => {
89 log('error', 'Response error:', error)
90 })
91 axios.onResponse(res => {
92 log(
93 'info',
94 '[' + (res.status + ' ' + res.statusText) + ']',
95 '[' + res.config.method.toUpperCase() + ']',
96 res.config.url)
97
98 if (process.browser) {
99 console.log(res)
100 } else {
101 console.log(JSON.stringify(res.data, undefined, 2))
102 }
103
104 return res
105 })
106}<% } %>
107
108<% if (options.credentials) { %>
109const setupCredentialsInterceptor = axios => {
110 // Send credentials only to relative and API Backend requests
111 axios.onRequest(config => {
112 if (config.withCredentials === undefined) {
113 if (!/^https?:\/\//i.test(config.url) || config.url.indexOf(config.baseURL) === 0) {
114 config.withCredentials = true
115 }
116 }
117 })
118}<% } %>
119
120<% if (options.progress) { %>
121const setupProgress = (axios) => {
122 if (process.server) {
123 return
124 }
125
126 // A noop loading inteterface for when $nuxt is not yet ready
127 const noopLoading = {
128 finish: () => { },
129 start: () => { },
130 fail: () => { },
131 set: () => { }
132 }
133
134 const $loading = () => {
135 const $nuxt = typeof window !== 'undefined' && window['$<%= options.globalName %>']
136 return ($nuxt && $nuxt.$loading && $nuxt.$loading.set) ? $nuxt.$loading : noopLoading
137 }
138
139 let currentRequests = 0
140
141 axios.onRequest(config => {
142 if (config && config.progress === false) {
143 return
144 }
145
146 currentRequests++
147 })
148
149 axios.onResponse(response => {
150 if (response && response.config && response.config.progress === false) {
151 return
152 }
153
154 currentRequests--
155 if (currentRequests <= 0) {
156 currentRequests = 0
157 $loading().finish()
158 }
159 })
160
161 axios.onError(error => {
162 if (error && error.config && error.config.progress === false) {
163 return
164 }
165
166 currentRequests--
167
168 if (Axios.isCancel(error)) {
169 if (currentRequests <= 0) {
170 currentRequests = 0
171 $loading().finish()
172 }
173 return
174 }
175
176 $loading().fail()
177 $loading().finish()
178 })
179
180 const onProgress = e => {
181 if (!currentRequests || !e.total) {
182 return
183 }
184 const progress = ((e.loaded * 100) / (e.total * currentRequests))
185 $loading().set(Math.min(100, progress))
186 }
187
188 axios.defaults.onUploadProgress = onProgress
189 axios.defaults.onDownloadProgress = onProgress
190}<% } %>
191
192export default (ctx, inject) => {
193 // runtimeConfig
194 const runtimeConfig = ctx.$config && ctx.$config.axios || {}
195 // baseURL
196 const baseURL = process.browser
197 ? (runtimeConfig.browserBaseURL || runtimeConfig.browserBaseUrl || runtimeConfig.baseURL || runtimeConfig.baseUrl || '<%= options.browserBaseURL || '' %>')
198 : (runtimeConfig.baseURL || runtimeConfig.baseUrl || process.env._AXIOS_BASE_URL_ || '<%= options.baseURL || '' %>')
199
200 // Create fresh objects for all default header scopes
201 // Axios creates only one which is shared across SSR requests!
202 // https://github.com/mzabriskie/axios/blob/master/lib/defaults.js
203 const headers = <%= JSON.stringify(options.headers, null, 4) %>
204
205 const axiosOptions = {
206 baseURL,
207 headers
208 }
209
210 <% if (options.proxyHeaders) { %>
211 // Proxy SSR request headers headers
212 if (process.server && ctx.req && ctx.req.headers) {
213 const reqHeaders = { ...ctx.req.headers }
214 for (const h of <%= serialize(options.proxyHeadersIgnore) %>) {
215 delete reqHeaders[h]
216 }
217 axiosOptions.headers.common = { ...reqHeaders, ...axiosOptions.headers.common }
218 }
219 <% } %>
220
221 if (process.server) {
222 // Don't accept brotli encoding because Node can't parse it
223 axiosOptions.headers.common['accept-encoding'] = 'gzip, deflate'
224 }
225
226 const axios = createAxiosInstance(axiosOptions)
227
228 // Inject axios to the context as $axios
229 ctx.$axios = axios
230 inject('axios', axios)
231}
232
\No newline at end of file