From 61fb62747731d0969f9305a5ca4b823bba171ca5 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Tue, 19 Mar 2019 00:08:46 +0330 Subject: [PATCH] feat: http class --- lib/module.js | 14 ++--- lib/plugin.js | 118 ++++++++++++++++++++--------------- test/fixture/plugins/http.js | 4 +- 3 files changed, 78 insertions(+), 58 deletions(-) diff --git a/lib/module.js b/lib/module.js index d46449a..11df75a 100755 --- a/lib/module.js +++ b/lib/module.js @@ -1,11 +1,11 @@ const path = require('path') const consola = require('consola') -const logger = consola.withScope('nuxt:axios') +const logger = consola.withScope('nuxt:http') -function axiosModule(_moduleOptions) { +function httpModule(_moduleOptions) { // Combine options - const moduleOptions = { ...this.options.axios, ..._moduleOptions } + const moduleOptions = { ...this.options.http, ..._moduleOptions } // Default port const defaultPort = @@ -78,7 +78,7 @@ function axiosModule(_moduleOptions) { // Register plugin this.addPlugin({ src: path.resolve(__dirname, 'plugin.js'), - fileName: 'axios.js', + fileName: 'http.js', options }) @@ -90,12 +90,12 @@ function axiosModule(_moduleOptions) { ]) } - // Set _AXIOS_BASE_URL_ for dynamic SSR baseURL - process.env._AXIOS_BASE_URL_ = options.baseURL + // Set _HTTP_BASE_URL_ for dynamic SSR baseURL + process.env._HTTP_BASE_URL_ = options.baseURL logger.debug(`baseURL: ${options.baseURL}`) logger.debug(`browserBaseURL: ${options.browserBaseURL}`) } -module.exports = axiosModule +module.exports = httpModule module.exports.meta = require('../package.json') diff --git a/lib/plugin.js b/lib/plugin.js index 6abd31d..7590bc3 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -1,79 +1,99 @@ import KY from 'ky-universal' -// KY.prototype cannot be modified -const KYExtra = { - setHeader(name, value, scopes = 'common') { - // for (let scope of Array.isArray(scopes) ? scopes : [scopes]) { - // if (!value) { - // delete this.defaults.headers[scope][name]; - // return - // } - // this.defaults.headers[scope][name] = value - // } - }, - setToken(token, type, scopes = 'common') { - // const value = !token ? null : (type ? type + ' ' : '') + token - // this.setHeader('Authorization', value, scopes) - }, +class HTTP { + constructor(defaults, ky = KY) { + this._defaults = { + hooks: {}, + headers: {}, + retry: 0, + ...defaults + } + this._ky = ky + } + + setHeader(name, value) { + if (!value) { + delete this._defaults.headers[name]; + } else { + this._defaults.headers[name] = value + } + } + + setToken(token, type) { + const value = !token ? null : (type ? type + ' ' : '') + token + this.setHeader('Authorization', value) + } + + _hook(name, fn) { + if (!this._defaults.hooks[name]) { + this._defaults.hooks[name] = [] + } + this._defaults.hooks[name].push(fn) + } + onRequest(fn) { - // this.interceptors.request.use(config => fn(config) || config) - }, + this._hook('beforeRequest', fn) + } + onResponse(fn) { - // this.interceptors.response.use(response => fn(response) || response) - }, - onRequestError(fn) { - // this.interceptors.request.use(undefined, error => fn(error) || Promise.reject(error)) - }, - onResponseError(fn) { - // this.interceptors.response.use(undefined, error => fn(error) || Promise.reject(error)) - }, + this._hook('afterResponse', fn) + } + onError(fn) { - // this.onRequestError(fn) - // this.onResponseError(fn) + this._hook('onError', fn) } } -// Request helpers ($get, $post, ...) for (let method of ['get', 'post', 'put', 'patch', 'head', 'delete']) { - KYExtra['$' + method] = function () { return this[method].apply(this, arguments).then(res => res.json()) } -} + HTTP.prototype[method] = async function (input, options) { + const _options = { ...this._defaults, ...options } -const extendKYInstance = instance => { - for (let key in KYExtra) { - instance[key] = KYExtra[key].bind(instance) + if (/^https?/.test(input)) { + delete _options.prefixUrl + } + + try { + const response = await this._ky[method](input, _options) + return response + } catch (error) { + // Call onError hook + if (_options.hooks.onError) { + _options.hooks.onError.forEach(fn => fn(error)) + } + // Throw error + throw error + } + } + + HTTP.prototype['$' + method] = function (input, options) { + return this[method](input, options).then(res => res.json()) } } export default (ctx, inject) => { - // Set prefixUrl + // prefixUrl const prefixUrl = process.browser ? '<%= options.browserBaseURL %>' : (process.env._HTTP_BASE_URL_ || '<%= options.baseURL %>') - const kyDefaults = { - prefixUrl, - headers: {}, - retry: 0, - } + // Defaults + const defaults = { prefixUrl } <% if (options.proxyHeaders) { %> // Proxy SSR request headers headers - kyDefaults.headers = (ctx.req && ctx.req.headers) ? { ...ctx.req.headers } : {} - <% for (let h of options.proxyHeadersIgnore) { %> delete kyDefaults.headers['<%= h %>'] + defaults.headers = (ctx.req && ctx.req.headers) ? { ...ctx.req.headers } : {} + <% for (let h of options.proxyHeadersIgnore) { %> delete defaults.headers['<%= h %>'] <% } %><% } %> if (process.server) { // Don't accept brotli encoding because Node can't parse it - kyDefaults.headers['Accept-Encoding'] = 'gzip, deflate' + defaults.headers['Accept-Encoding'] = 'gzip, deflate' } - // Extend ky with defaults - const ky = KY.extend(kyDefaults) - - // Extend instance proto - extendKYInstance(ky) + // Create new HTTP instance + const http = new HTTP(defaults) // Inject http to the context as $http - ctx.$http = ky - inject('http', ky) + ctx.$http = http + inject('http', http) } diff --git a/test/fixture/plugins/http.js b/test/fixture/plugins/http.js index 4d82857..82a922a 100644 --- a/test/fixture/plugins/http.js +++ b/test/fixture/plugins/http.js @@ -1,8 +1,8 @@ export default function ({ $http, redirect }) { $http.setHeader('xsrfHeaderName', 'X-CSRF-TOKEN') - $http.onRequest((config) => { + $http.onRequest((options) => { // eslint-disable-next-line no-console - console.log('SPY: ' + config.url) + console.log('Request:', JSON.stringify(options)) }) }