├── .github ├── ISSUE_TEMPLATE.md └── workflows │ └── ci.yml ├── ky-universal └── browser.js ├── renovate.json ├── docs ├── public │ ├── icon.png │ ├── preview.png │ ├── preview-dark.png │ ├── logo-dark.svg │ └── logo-light.svg ├── .gitignore ├── nuxt.config.ts ├── app.config.ts ├── tokens.config.ts ├── package.json ├── readme.md ├── content │ ├── 2.API │ │ ├── 2.runtime-config.md │ │ ├── 4.hooks.md │ │ ├── 3.helpers.md │ │ └── 1.options.md │ ├── 1.index.md │ ├── 3.migration-guides │ │ └── 1.migration.md │ └── 1.getting-started │ │ ├── 1.setup.md │ │ ├── 2.usage.md │ │ ├── 4.advanced.md │ │ └── 3.http-methods.md └── components │ └── Logo.vue ├── .eslintignore ├── .gitignore ├── types ├── vuex.d.ts └── index.d.ts ├── .eslintrc.js ├── .editorconfig ├── test ├── fixture │ ├── pages │ │ ├── error.vue │ │ ├── asyncData.vue │ │ ├── mounted.vue │ │ ├── index.vue │ │ ├── instance.vue │ │ └── ssr.vue │ ├── store │ │ └── index.js │ ├── api.js │ ├── plugins │ │ ├── instance.js │ │ └── http.js │ └── nuxt.config.js ├── defaults.test.js ├── _utils.js ├── module.test.js └── with-config.test.js ├── jest.config.js ├── netlify.toml ├── lib ├── plugin.server.js ├── module.js └── plugin.js ├── LICENSE ├── package.json ├── README.md └── CHANGELOG.md /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ky-universal/browser.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ky' 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /docs/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt/http/HEAD/docs/public/icon.png -------------------------------------------------------------------------------- /docs/public/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt/http/HEAD/docs/public/preview.png -------------------------------------------------------------------------------- /docs/public/preview-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt/http/HEAD/docs/public/preview-dark.png -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | 7 | # Plugin 8 | lib/plugin.js 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | -------------------------------------------------------------------------------- /types/vuex.d.ts: -------------------------------------------------------------------------------- 1 | import { NuxtHTTPInstance } from '.' 2 | 3 | declare module 'vuex' { 4 | interface Store { 5 | $http: NuxtHTTPInstance, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | extends: [ 8 | '@nuxtjs' 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /docs/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | extends: ['@nuxt-themes/docus'], 3 | 4 | buildModules: ['nuxt-plausible'], 5 | 6 | plausible: { 7 | domain: 'http.nuxtjs.org' 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /docs/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | docus: { 3 | url: 'https://http.nuxtjs.org', 4 | header: { 5 | logo: true 6 | }, 7 | socials: { 8 | twitter: 'nuxt_js', 9 | github: 'nuxt/http' 10 | }, 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /test/fixture/pages/error.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /test/fixture/pages/asyncData.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /test/fixture/store/index.js: -------------------------------------------------------------------------------- 1 | export default { 2 | actions: { 3 | nuxtServerInit ({ commit }, ctx) { 4 | if (!ctx.$http) { 5 | throw new Error('$http is not defined!') 6 | } 7 | 8 | if (!ctx.app.$http) { 9 | throw new Error('$http is not defined!') 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/fixture/api.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | path: '/test_api', 3 | handler (req, res) { 4 | if (req.url === '/error') { 5 | res.statusCode = 418 6 | res.end('Detailed error message') 7 | return 8 | } 9 | 10 | res.end(JSON.stringify({ 11 | url: req.url, 12 | method: req.method 13 | })) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/tokens.config.ts: -------------------------------------------------------------------------------- 1 | import { defineTheme } from 'pinceau' 2 | 3 | export default defineTheme({ 4 | color: { 5 | primary: { 6 | 100: '#E6FAF2', 7 | 200: '#BFF3E0', 8 | 300: '#99EBCD', 9 | 400: '#4DDCA7', 10 | 500: '#00CD81', 11 | 600: '#00B974', 12 | 700: '#007B4D', 13 | 800: '#005C3A', 14 | 900: '#003E27' 15 | } 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | collectCoverage: true, 4 | collectCoverageFrom: [ 5 | 'lib/**/*.js', 6 | '!lib/plugin*' 7 | ], 8 | moduleNameMapper: { 9 | '^~/(.*)$': '/lib/$1', 10 | '^~~$': '', 11 | '^@@$': '', 12 | '^@/(.*)$': '/lib/$1' 13 | }, 14 | transform: { 15 | '^.+\\.js$': 'babel-jest' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "preview": "nuxi preview", 9 | "generate": "nuxi generate" 10 | }, 11 | "dependencies": { 12 | "@nuxt-themes/docus": "^1.1.3", 13 | "nuxt": "^3.0.0" 14 | }, 15 | "devDependencies": { 16 | "nuxt-plausible": "^0.1.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/fixture/pages/mounted.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /test/fixture/plugins/instance.js: -------------------------------------------------------------------------------- 1 | export default function ({ $http, env }, inject) { 2 | // Create a custom HTTP instance 3 | const $api = $http.create({ 4 | // See https://github.com/sindresorhus/ky#options 5 | }) 6 | 7 | // Set baseURL to something different 8 | $api.setBaseURL('https://jsonplaceholder.typicode.com/') 9 | $api.setHeader('testing', 'oui') 10 | 11 | // Inject to context as $github 12 | inject('api', $api) 13 | } 14 | -------------------------------------------------------------------------------- /test/fixture/pages/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 23 | -------------------------------------------------------------------------------- /test/fixture/plugins/http.js: -------------------------------------------------------------------------------- 1 | export default function ({ $http, redirect }) { 2 | $http.setHeader('xsrfHeaderName', 'X-CSRF-TOKEN') 3 | 4 | $http.onRequest((options) => { 5 | // eslint-disable-next-line no-console 6 | console.log('Request:', JSON.stringify(options)) 7 | }) 8 | 9 | $http.onError((err) => { 10 | return { 11 | statusCode: err.statusCode, 12 | message: err.response ? err.response.data : err.message 13 | } 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Global settings applied to the whole site. 2 | # 3 | # “base” is the directory to change to before starting build. If you set base: 4 | # that is where we will look for package.json/.nvmrc/etc, not repo root! 5 | # “command” is your build command. 6 | # “publish” is the directory to publish (relative to the root of your repo). 7 | 8 | [build] 9 | base = "docs" 10 | command = "yarn generate" 11 | publish = "dist" 12 | ignore = "git diff --quiet HEAD^ HEAD . ../package.json" -------------------------------------------------------------------------------- /test/fixture/pages/instance.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # docs 2 | 3 | ## Setup 4 | 5 | Install dependencies: 6 | 7 | ```bash 8 | yarn install 9 | ``` 10 | 11 | ## Development 12 | 13 | ```bash 14 | yarn dev 15 | ``` 16 | 17 | ## Static Generation 18 | 19 | This will create the `dist/` directory for publishing to static hosting: 20 | 21 | ```bash 22 | yarn generate 23 | ``` 24 | 25 | To preview the static generated app, run `yarn start` 26 | 27 | For detailed explanation on how things work, checkout [nuxt/content](https://content.nuxtjs.org) and [@nuxt/content theme docs](https://content.nuxtjs.org/themes-docs). 28 | -------------------------------------------------------------------------------- /test/fixture/nuxt.config.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | 3 | module.exports = { 4 | rootDir: resolve(__dirname, '../..'), 5 | buildDir: resolve(__dirname, '.nuxt'), 6 | srcDir: __dirname, 7 | render: { 8 | resourceHints: false 9 | }, 10 | modules: [ 11 | require('../..') 12 | ], 13 | serverMiddleware: [ 14 | '~/api.js' 15 | ], 16 | http: { 17 | prefix: '/test_api', 18 | serverTimeout: 10000, 19 | clientTimeout: 25000, 20 | proxy: true, 21 | retry: 1 22 | }, 23 | build: { 24 | terser: false 25 | }, 26 | plugins: [ 27 | '~/plugins/instance', 28 | '~/plugins/http' 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/fixture/pages/ssr.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | -------------------------------------------------------------------------------- /lib/plugin.server.js: -------------------------------------------------------------------------------- 1 | import _fetch from 'node-fetch' 2 | import { AbortController as _AbortController } from 'abort-controller' 3 | import { ReadableStream as _ReadableStream } from 'web-streams-polyfill/ponyfill/es2018' 4 | 5 | const TEN_MEGABYTES = 1000 * 1000 * 10 6 | 7 | if (!global.fetch) { 8 | global.fetch = (url, options) => _fetch(url, { highWaterMark: TEN_MEGABYTES, ...options }) 9 | } 10 | 11 | if (!global.Headers) { 12 | global.Headers = _fetch.Headers 13 | } 14 | 15 | if (!global.Request) { 16 | global.Request = _fetch.Request 17 | } 18 | 19 | if (!global.Response) { 20 | global.Response = _fetch.Response 21 | } 22 | 23 | if (!global.AbortController) { 24 | global.AbortController = _AbortController 25 | } 26 | 27 | if (!global.ReadableStream) { 28 | try { 29 | global.ReadableStream = _ReadableStream 30 | } catch (_) { } 31 | } 32 | -------------------------------------------------------------------------------- /docs/content/2.API/2.runtime-config.md: -------------------------------------------------------------------------------- 1 | # Runtime Config 2 | 3 | The use of runtime config is mandatory in case of using environment variables in production. 4 | 5 | --- 6 | 7 | The use of [runtime config](https://nuxtjs.org/guide/runtime-config) is mandatory in case of using environment variables in production. Otherwise, the values will be hard coded during build and won't change until the next build. 8 | 9 | Supported options: 10 | 11 | - `baseURL` 12 | - `browserBaseURL` 13 | 14 | **nuxt.config.js** 15 | 16 | ```js 17 | export default { 18 | modules: [ 19 | '@nuxt/http' 20 | ], 21 | 22 | http: { 23 | baseURL: 'http://localhost:4000', // Used as fallback if no runtime config is provided 24 | }, 25 | 26 | publicRuntimeConfig: { 27 | http: { 28 | browserBaseURL: process.env.BROWSER_BASE_URL 29 | } 30 | }, 31 | 32 | privateRuntimeConfig: { 33 | http: { 34 | baseURL: process.env.BASE_URL 35 | } 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /test/defaults.test.js: -------------------------------------------------------------------------------- 1 | const { setupMockNuxt } = require('./_utils') 2 | 3 | describe('defaults', () => { 4 | test('should render template with defaults', async () => { 5 | const nuxt = await setupMockNuxt({ 6 | http: {} 7 | }) 8 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 9 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 10 | const options = call[0].options 11 | expect(options.baseURL).toBe('http://localhost:3000/') 12 | expect(options.browserBaseURL).toBe('http://localhost:3000/') 13 | expect(options.clientTimeout).toBe(false) 14 | expect(options.serverTimeout).toBe(false) 15 | expect(options.proxyHeaders).toBe(true) 16 | expect(options.proxyHeadersIgnore).toStrictEqual(['accept', 'host', 'cf-ray', 'cf-connecting-ip', 'content-length', 'content-md5', 'content-type']) 17 | expect(options.https).toBe(false) 18 | expect(options.retry).toBe(0) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | ci: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest] 18 | node: [12] 19 | 20 | steps: 21 | - uses: actions/setup-node@v2 22 | with: 23 | node-version: ${{ matrix.node }} 24 | 25 | - name: checkout 26 | uses: actions/checkout@master 27 | 28 | - name: cache node_modules 29 | uses: actions/cache@v2 30 | with: 31 | path: node_modules 32 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 33 | 34 | - name: Install dependencies 35 | if: steps.cache.outputs.cache-hit != 'true' 36 | run: yarn 37 | 38 | - name: Lint 39 | run: yarn lint 40 | 41 | - name: Test 42 | run: yarn jest -i 43 | 44 | - name: Coverage 45 | uses: codecov/codecov-action@v1 46 | -------------------------------------------------------------------------------- /test/_utils.js: -------------------------------------------------------------------------------- 1 | const { Nuxt, Builder } = require('nuxt-edge') 2 | 3 | const defaultConfig = require('./fixture/nuxt.config') 4 | 5 | jest.setTimeout(60000) 6 | 7 | async function setupMockNuxt (config) { 8 | const nuxt = new Nuxt({ 9 | ...defaultConfig, 10 | ...config, 11 | _ready: false 12 | }) 13 | 14 | nuxt.moduleContainer.addTemplate = jest.fn(nuxt.moduleContainer.addTemplate) 15 | nuxt.moduleContainer.requireModule = jest.fn(nuxt.moduleContainer.requireModule) 16 | 17 | await nuxt.ready() 18 | 19 | const builder = new Builder(nuxt) 20 | 21 | await builder.validatePages() 22 | await builder.generateRoutesAndFiles() 23 | nuxt.builder = builder 24 | 25 | return nuxt 26 | } 27 | 28 | async function setupNuxt (config) { 29 | const nuxt = new Nuxt({ 30 | ...defaultConfig, 31 | ...config, 32 | _ready: false 33 | }) 34 | 35 | jest.spyOn(nuxt.moduleContainer, 'addTemplate') 36 | 37 | await nuxt.ready() 38 | 39 | const builder = new Builder(nuxt) 40 | nuxt.builder = builder 41 | 42 | return nuxt 43 | } 44 | 45 | module.exports = { 46 | setupMockNuxt, 47 | setupNuxt 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nuxt Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxt/http", 3 | "version": "0.6.4", 4 | "description": "Universal HTTP Module for Nuxt.js", 5 | "repository": "nuxt/http", 6 | "license": "MIT", 7 | "author": "Pooya Parsa ", 8 | "main": "lib/module.js", 9 | "types": "types/index.d.ts", 10 | "files": [ 11 | "lib", 12 | "types/*.d.ts" 13 | ], 14 | "scripts": { 15 | "dev": "nuxt test/fixture", 16 | "lint": "eslint lib test", 17 | "release": "yarn test && standard-version && git push --follow-tags && npm publish", 18 | "test": "yarn lint && jest -i" 19 | }, 20 | "dependencies": { 21 | "@nuxtjs/proxy": "^2.1.0", 22 | "abort-controller": "^3.0.0", 23 | "consola": "^2.15.0", 24 | "defu": "^3.2.2", 25 | "destr": "^1.0.1", 26 | "ky": "^0.25.1", 27 | "node-fetch": "^2.6.1", 28 | "web-streams-polyfill": "^3.0.1" 29 | }, 30 | "devDependencies": { 31 | "@babel/core": "latest", 32 | "@babel/preset-env": "latest", 33 | "@nuxtjs/eslint-config": "latest", 34 | "babel-eslint": "latest", 35 | "babel-jest": "latest", 36 | "codecov": "latest", 37 | "eslint": "latest", 38 | "eslint-config-standard": "latest", 39 | "eslint-plugin-import": "latest", 40 | "eslint-plugin-jest": "latest", 41 | "eslint-plugin-node": "latest", 42 | "eslint-plugin-promise": "latest", 43 | "eslint-plugin-standard": "latest", 44 | "eslint-plugin-vue": "latest", 45 | "jest": "latest", 46 | "nuxt-edge": "latest", 47 | "puppeteer": "latest", 48 | "standard-version": "latest", 49 | "tib": "latest" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docs/content/1.index.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | HTTP module for Nuxt.js provides a universal way to make HTTP requests to the API backend. 4 | 5 | --- 6 | 7 | ::alert{type="warning"} 8 | HTTP module supports Nuxt 2. Nuxt 3 users can use the new isomorphic [$fetch API](https://nuxt.com/docs/getting-started/data-fetching#isomorphic-fetch-and-fetch) ([migration guide](https://nuxt.com/docs/migration/component-options#isomorphic-fetch)). 9 | :: 10 | 11 | The HTTP module for [Nuxt](https://nuxtjs.org) provides a universal way to make HTTP requests to any API. 12 | 13 | It uses [ky-universal](https://github.com/sindresorhus/ky-universal) and [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to make HTTP requests. Please see the [migration guide](/migration-guides/migration) if you are currently using axios module and wish to migrate. 14 | 15 | Starting from [v2.5.0](https://github.com/nuxt/nuxt.js/releases/tag/v2.5.0), Nuxt.js has built-in support for universal fetch. However, this module provides several advantages. 16 | 17 | > This module is an alternative to the [Axios module](https://axios.nuxtjs.org). 18 | 19 | ## Features 20 | 21 | ::list 22 | 23 | - The fluent ky API has been extended with enhancements and shortcuts 24 | - Highly customizable options support for `BaseURL` 25 | - Automatically proxy cookies and headers when making requests from server side 26 | - Best practices to avoid token sharing when making server side requests 27 | - Easy proxy support to avoid CORS problems and making deployment easier 28 | 29 | :: 30 | 31 | ## Links 32 | 33 | * [ky](https://github.com/sindresorhus/ky) 34 | * [`BaseURL`](/options#baseurl) 35 | -------------------------------------------------------------------------------- /docs/content/2.API/4.hooks.md: -------------------------------------------------------------------------------- 1 | # Hooks 2 | 3 | Hooks with arguments. 4 | 5 | --- 6 | 7 | The `arguments` listed below are those your hook will receive when it's called. 8 | 9 | ## `onRequest` 10 | 11 | - arguments: `(config)` 12 | 13 | **Example:** 14 | 15 | ```ts [plugins/http.js] 16 | export default function ({ $http }) { 17 | $http.onRequest(config => { 18 | console.log('Making request to ' + config.url) 19 | }) 20 | } 21 | ``` 22 | 23 | See [here](/advanced#hooks) for advanced usage. 24 | 25 | ## `onResponse` 26 | 27 | - arguments: `(request, options, response)` 28 | 29 | **Example:** 30 | 31 | ```ts [plugins/http.js] 32 | export default function ({ $http }) { 33 | $http.onResponse((req, options, res) => { 34 | console.log('Making request to ' + req.url) 35 | console.log('Options :', options) 36 | console.log('Response data :', res.body) 37 | }) 38 | } 39 | ``` 40 | 41 | See [here](/advanced#hooks) for advanced usage. 42 | 43 | ## `onError` 44 | 45 | - arguments: `(error)` 46 | 47 | If the error originated from a request. 48 | 49 | **Example:** 50 | 51 | ```ts [plugins/http.js] 52 | export default function ({ $http, redirect }) { 53 | $http.onError((err) => { 54 | // In case of unauthorized, redirect to a specific page 55 | if (err.statusCode === 401) { 56 | redirect('/401') 57 | } 58 | }) 59 | } 60 | ``` 61 | 62 | Available properties: 63 | 64 | - `error.statusCode` (may be undefined) 65 | - `error.response?.data`(may be undefined) 66 | 67 | You can optionally return a value or promise that can resolve for fallback response. If hook returns any value, other hooks **won't** be called. 68 | 69 | See [here](/advanced#hooks) for advanced usage. 70 | -------------------------------------------------------------------------------- /docs/content/2.API/3.helpers.md: -------------------------------------------------------------------------------- 1 | # Helpers 2 | 3 | Helpers available on $http instance. 4 | 5 | --- 6 | 7 | ::alert{type="info"} 8 | Helpers available on `$http` instance. 9 | :: 10 | 11 | ## `setBaseURL` 12 | 13 | - arguments: `(baseURL)` 14 | 15 | Globally set a base URL to all subsequent requests 16 | 17 | ```js 18 | // Set baseURL (both client and server) 19 | this.$http.setBaseURL('http://api.example.com') 20 | 21 | // Change URL only for client 22 | if (process.client) { 23 | this.$http.setBaseURL('http://api.example.com') 24 | } 25 | 26 | // Change URL only for server 27 | if (process.server) { 28 | this.$http.setBaseURL('http://api.example.com') 29 | } 30 | ``` 31 | 32 | ## `getBaseURL` 33 | 34 | Get the value of the base URL 35 | 36 | ```js 37 | // Get baseURL value 38 | this.$http.getBaseURL() 39 | ``` 40 | 41 | ## `setHeader` 42 | 43 | - arguments: `(name, value)` 44 | 45 | Globally set a header to all subsequent requests 46 | 47 | **Example:** 48 | 49 | ```js 50 | // Add header `Content-Type: application/json` 51 | this.$http.setHeader('Content-Type', 'application/json') 52 | ``` 53 | 54 | See [here](/advanced#header-helpers) for usage. 55 | 56 | ## `setToken` 57 | 58 | - arguments: `(token, type)` 59 | 60 | Globally set a `Authorization` header for all subsequent requests. 61 | 62 | ```js 63 | // Adds header: `Authorization: Bearer 123` to all requests 64 | this.$http.setToken('123', 'Bearer') 65 | ``` 66 | 67 | See [here](/advanced#settokentoken-type) for usage. 68 | 69 | ## `create` 70 | 71 | - arguments: `(kyOptions)` 72 | 73 | Create a new KY instance based on defaults, see [create new instance based on defaults](/advanced#create-new-instance-based-on-defaults) for usage. 74 | -------------------------------------------------------------------------------- /docs/content/3.migration-guides/1.migration.md: -------------------------------------------------------------------------------- 1 | # Migration Guides 2 | 3 | How to migrate from Axios module 4 | 5 | --- 6 | 7 | This guide will help you to migrate from [Axios Module](https://github.com/nuxt-community/axios-module). 8 | 9 | ::alert{type="info"} 10 | The nuxt-community axios module is still supported and maintained. The HTTP module uses newer web technologies like fetch which might be beneficial 11 | :: 12 | 13 | ## Differences 14 | 15 | - There is no scope for [`setHeader`](/helpers#setheader), [`setToken`](/helpers#settoken)
16 | _When calling these methods they apply to the global scope and are used for all future requests_ 17 | - The axios hooks `onRequestError` and `onResponseError` are unified
18 | _Use the [`onError`](/hooks#onerror) hook instead_ 19 | - The http module does not have a `debug` option like the axios module
20 | _You can setup a basic logger using the [`onRequest`](/hooks#onrequest) hook_ 21 | - Progress bar integration is not supported (for the moment)
22 | _This option may be added again once [`PR #105 : progress bar`](https://github.com/nuxt/http/pull/105) is merged_ 23 | 24 | ## Response body parsing 25 | 26 | Axios automatically transforms response bodies to JSON, if you wish to keep that behaviour you will 27 | 28 | - either need to switch to using the `$` prefixed methods 29 | 30 | ```diff 31 | -- const resJson = await this.$axios.get('/url') 32 | ++ const resJson = await this.$http.$get('/url') 33 | ``` 34 | 35 | - or explicitly call [`json`](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) on the Response: 36 | 37 | ```diff 38 | -- const resJson = await this.$axios.get('/url') 39 | ++ const resJson = await this.$http.get('/url').json() 40 | ``` 41 | 42 | If you are already using `$` prefixed shortcuts for making requests that return JSON, you can keep using them. 43 | 44 | ```diff 45 | -- const resJson = await this.$axios.$get('/url') 46 | ++ const resJson = await this.$http.$get('/url') 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/1.setup.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | How to setup your module. 4 | 5 | --- 6 | 7 | Checkout the [Nuxt documentation](https://nuxtjs.org/api/configuration-modules#the-modules-property) for more information about installing and using modules. 8 | 9 | ## Install 10 | 11 | Add `@nuxt/http` dependency to your project: 12 | 13 | ::code-group 14 | ```bash [Yarn] 15 | yarn add @nuxt/http 16 | ``` 17 | 18 | ```bash [NPM] 19 | npm install @nuxt/http 20 | ``` 21 | :: 22 | 23 | Then add it to the modules section in your `nuxt.config.js`: 24 | 25 | ```js{}[nuxt.config.js] 26 | export default { 27 | modules: ['@nuxt/http'] 28 | } 29 | ``` 30 | 31 | ::alert{type="success"} 32 | That's it! You can now use [$http](/getting-started/usage) in your Nuxt app ✨ 33 | :: 34 | 35 | ## Configure 36 | 37 | Add a `http` object to your **nuxt.config.js** to configure global options which will be applied to all requests 38 | 39 | ```js{}[nuxt.config.js] 40 | export default { 41 | modules: [ 42 | '@nuxt/http', 43 | ], 44 | 45 | http: { 46 | // proxyHeaders: false 47 | } 48 | } 49 | ``` 50 | 51 | See [http's options](/API/options). 52 | 53 | ::alert{type="warning"} 54 | Note that this module does not currently support IE 11 because of using [ky](https://github.com/sindresorhus/ky) ([open issue](https://github.com/nuxt/http/issues/126)) 55 | :: 56 | 57 | ## TypeScript 58 | 59 | Add the types to your "types" array in `tsconfig.json` after the `@nuxt/types` (Nuxt 2.9.0+) or `@nuxt/vue-app` entry 60 | 61 | ```json{}[tsconfig.json] 62 | { 63 | "compilerOptions": { 64 | "types": [ 65 | "@nuxt/types", 66 | "@nuxt/http" 67 | ] 68 | } 69 | } 70 | ``` 71 | 72 | > **Why?** 73 | > 74 | > Because of the way Nuxt works the `$http` property on the context has to be merged into the Nuxt `Context` interface via [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html). Adding `@nuxt/http` to your types will import the types from the package and make typescript aware of the additions to the `Context` interface. 75 | -------------------------------------------------------------------------------- /test/module.test.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch') 2 | const { createBrowser } = require('tib') 3 | const { setupNuxt } = require('./_utils') 4 | 5 | const url = path => `http://localhost:3000${path}` 6 | 7 | describe('module', () => { 8 | let nuxt, browser 9 | 10 | beforeAll(async () => { 11 | nuxt = await setupNuxt() 12 | await nuxt.builder.build() 13 | await nuxt.listen(3000) 14 | browser = await createBrowser('puppeteer') 15 | }, 60000) 16 | 17 | afterAll(async () => { 18 | await nuxt.close() 19 | await browser.close() 20 | }) 21 | 22 | test('asyncData', async () => { 23 | const html = await fetch(url('/asyncData')).then(r => r.text()) 24 | expect(html).toContain('foo/bar') 25 | }) 26 | 27 | test('mounted', async () => { 28 | const page = await browser.page(url('/mounted')) 29 | const html = await page.getHtml() 30 | expect(html).toContain('foo/bar') 31 | }) 32 | 33 | test('index', async () => { 34 | const page = await browser.page(url('/')) 35 | const html = await page.getHtml() 36 | expect(html).toContain('foo/bar') 37 | }) 38 | 39 | test('defaults', async () => { 40 | const page = await browser.page(url('/mounted')) 41 | const defaults = await page.runScript(() => window.$nuxt.$http._defaults) 42 | expect(defaults.headers.xsrfHeaderName).toBe('X-CSRF-TOKEN') 43 | }) 44 | 45 | test('error', async () => { 46 | const html = await fetch(url('/error')).then(r => r.text()) 47 | expect(html).toMatch('res:{statusCode:418,message:"Detailed error message"}') 48 | }) 49 | 50 | test('ssr', async () => { 51 | const makeReq = login => fetch(url('/ssr' + (login ? '?login' : ''))) 52 | .then(r => r.text()) 53 | .then(h => /session-[0-9]+/.exec(h)) 54 | .then(m => (m && m[0] ? m[0] : null)) 55 | 56 | const a = await makeReq() 57 | const b = await makeReq(true) 58 | const c = await makeReq() 59 | const d = await makeReq(true) 60 | 61 | expect(a).toBeNull() 62 | expect(b).not.toBeNull() 63 | expect(c).toBeNull() // Important! 64 | expect(d).not.toBeNull() 65 | expect(b).not.toBe(d) 66 | }) 67 | 68 | test('ssr no brotli', async () => { 69 | const makeReq = login => fetch(url('/ssr' + (login ? '?login' : ''))) 70 | .then(r => r.text()) 71 | .then(h => /encoding-\$(.*)\$/.exec(h)) 72 | .then(m => (m && m[1] ? m[1] : null)) 73 | 74 | const result = await makeReq() 75 | 76 | expect(result).toBe('gzip, deflate') 77 | }) 78 | 79 | test('instance', async () => { 80 | const html = await fetch(url('/instance')).then(r => r.text()) 81 | 82 | expect(html).toContain('prefixUrl:https://jsonplaceholder.typicode.com/') 83 | expect(html).toContain('baseURL:https://jsonplaceholder.typicode.com/') 84 | expect(html).toContain('testing:oui') 85 | }) 86 | }) 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![@nuxt/http](https://http.nuxtjs.org/preview.png)](https://http.nuxtjs.org) 2 | 3 | # Nuxt HTTP 4 | 5 | [![npm version][npm-version-src]][npm-version-href] 6 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 7 | [![Github Actions CI][github-actions-ci-src]][github-actions-ci-href] 8 | [![Codecov][codecov-src]][codecov-href] 9 | [![License][license-src]][license-href] 10 | [![Standard JS][standard-js-src]][standard-js-href] 11 | 12 | > HTTP module for Nuxt with a universal way to make HTTP requests to the API backend. 13 | 14 | - [✨  Release Notes](https://http.nuxtjs.org/releases) 15 | - [📖  Documentation](https://http.nuxtjs.org) 16 | 17 | ## Nuxt 3 18 | 19 | HTTP module supports Nuxt 2. Nuxt 3 users can use the new isomorphic [$fetch API](https://nuxt.com/docs/getting-started/data-fetching#isomorphic-fetch-and-fetch) ([migration guide](https://nuxt.com/docs/migration/component-options#isomorphic-fetch)). 20 | 21 | ## Features 22 | 23 | - The fluent [ky](https://github.com/sindresorhus/ky) API has been extended with enhancements and shortcuts 24 | - Highly customizable options support for [BaseURL](https://http.nuxtjs.org/options#baseurl) 25 | - Automatically proxy cookies and headers when making requests from server side 26 | - Best practices to avoid token sharing when making server side requests 27 | - Easy proxy support to avoid CORS problems and making deployment easier 28 | 29 | [📖  Read more](https://http.nuxtjs.org) 30 | 31 | ## Development 32 | 33 | 1. Clone this repository 34 | 2. Install dependencies using `yarn install` 35 | 3. Start development server using `yarn dev` 36 | 4. Then go for instance to `http://localhost:3000/mounted` 37 | 38 | ## 📖 Contribute to the documentation 39 | 40 | 1. Go into the docs folder 41 | 2. Install dependencies using `yarn install` 42 | 3. Start development server using `yarn dev` 43 | 44 | ## 📑 License 45 | 46 | [MIT License](./LICENSE) 47 | 48 | Copyright (c) Nuxt.js Team 49 | 50 | 51 | [npm-version-src]: https://flat.badgen.net/npm/v/@nuxt/http 52 | [npm-version-href]: https://npmjs.com/package/@nuxt/http 53 | [npm-downloads-src]: https://flat.badgen.net/npm/dm/@nuxt/http 54 | [npm-downloads-href]: https://npmjs.com/package/@nuxt/http 55 | [github-actions-ci-src]: https://github.com/nuxt/http/workflows/ci/badge.svg 56 | [github-actions-ci-href]: https://github.com/nuxt/http/actions?query=workflow%3Aci 57 | [checks-src]: https://flat.badgen.net/github/checks/nuxt/http/master 58 | [checks-href]: https://github.com/nuxt/http/actions 59 | [codecov-src]: https://flat.badgen.net/codecov/c/github/nuxt/http 60 | [codecov-href]: https://codecov.io/gh/nuxt/http 61 | [standard-js-src]: https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square 62 | [standard-js-href]: https://standardjs.com 63 | [license-src]: https://img.shields.io/npm/l/@nuxt/http.svg 64 | [license-href]: https://npmjs.com/package/@nuxt/http 65 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/2.usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | How to use this module. 4 | 5 | --- 6 | 7 | ## Making Requests 8 | 9 | See the list of [available HTTP methods](/getting-started/http-methods). 10 | 11 | Calling a HTTP methods returns a `Promise` that resolves to a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object or rejects in case of network errors. 12 | 13 | You can use methods to convert response stream into usable data: 14 | 15 | - `json` 16 | - `text` 17 | - `formData` 18 | - `arrayBuffer` 19 | - `blob` 20 | 21 | See [ky](https://github.com/sindresorhus/ky#options) docs for all available options. 22 | 23 | **Example: GET JSON data** 24 | 25 | ```js 26 | const package = await $http.$get('https://unpkg.com/nuxt/package.json') 27 | 28 | console.log(package.name) // log "nuxt" 29 | ``` 30 | 31 | In most of the case, you want to get the JSON response. You can use `$` prefixed shortcut that smartly parses response using [destr](https://github.com/nuxt-contrib/destr). 32 | 33 | Alternatively for other response type, you can use the methods mentioned above: 34 | 35 | **Example: GET data as `text`** 36 | 37 | ```js 38 | const res = await $http.get('https://unpkg.com/nuxt/package.json') 39 | const responseText = await res.text() 40 | ``` 41 | 42 | **Example: GET data as `arrayBuffer`** 43 | 44 | ```js 45 | const response = await this.$http.get('https://nuxtjs.org/logos/nuxt.svg') 46 | const buffer = await response.arrayBuffer() 47 | console.log('buffer.byteLength = ', buffer.byteLength) 48 | ``` 49 | 50 | **Example: GET data as `readable stream`** 51 | 52 | ```js 53 | const response = await this.$http.get('https://example.org') 54 | const reader = response.body.getReader() 55 | 56 | let result = '' 57 | reader.read().then(function process ({ done, value }) { 58 | if (done) { 59 | console.log('Stream complete result =>', result) 60 | return 61 | } 62 | 63 | const decoder = new TextDecoder('utf-8') 64 | result += decoder.decode(value, { stream: true }) 65 | 66 | // Read some more, and call this function again 67 | return reader.read().then(process) 68 | }) 69 | ``` 70 | 71 | **Example: POST with JSON body** 72 | 73 | ```js 74 | const data = await $http.$post('http://api.com', { foo: 'bar' }) 75 | ``` 76 | 77 | ## Using in `asyncData` 78 | 79 | For `asyncData` and `fetch` you can access instance from context: 80 | 81 | ```js 82 | async asyncData({ $http }) { 83 | const res = await $http.get('https://icanhazip.com') 84 | const ip = await res.text() 85 | 86 | return { ip } 87 | } 88 | ``` 89 | 90 | **Example: GET JSON data using $ helper** 91 | 92 | ```js 93 | async asyncData({ $http }) { 94 | const users = await $http.$get('https://reqres.in/api/users') 95 | 96 | return { users } 97 | } 98 | ``` 99 | 100 | ## Using in Component Methods 101 | 102 | When you have access to `this`, you can use `this.$http`: 103 | 104 | ```js 105 | methods: { 106 | async fetchSomething() { 107 | this.ip = await this.$http.$get('https://icanhazip.com') 108 | } 109 | } 110 | ``` 111 | 112 | ::alert{type="info"} 113 | `this` is not available in Nuxt's `asyncData` method, see [using in `asyncData`](#using-in-asyncdata) for how to use this module in `asyncData` 114 | :: 115 | 116 | ## Using in Store 117 | 118 | For store actions you can also use `this.$http`: 119 | 120 | ```js 121 | // In store 122 | { 123 | actions: { 124 | async getIP ({ commit }) { 125 | const ip = await this.$http.$get('https://icanhazip.com') 126 | 127 | commit('SET_IP', ip) 128 | } 129 | } 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/4.advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced 2 | 3 | Advanced concepts. 4 | 5 | --- 6 | 7 | ## Hooks 8 | 9 | Hooks can be used to globally intercept HTTP request and responses. E.g. if you wish to log errors, display a toast on error or need to dynamically modify requests. 10 | 11 | See the [API reference](/hooks) for the list of lifecycle hooks the HTTP module provides 12 | 13 | These functions don't have to return anything by default. 14 | 15 | ### Register Hooks 16 | 17 | For registering hooks, you have to create a nuxt plugin: 18 | 19 | ```js{}[nuxt.config.js] 20 | export default { 21 | plugins: [ 22 | '~/plugins/http' 23 | ] 24 | } 25 | ``` 26 | 27 | ```js{}[plugins/http.js] 28 | import ky from 'ky-universal' 29 | 30 | export default function ({ $http }) { 31 | $http.onRequest(config => { 32 | console.log('Making request to ' + config.url) 33 | }) 34 | 35 | $http.onRetry(async (request, options, errors, retryCount) => { 36 | const token = await ky('https://example.com/refresh-token') 37 | options.header.set('Authorization', `Bearer ${token}`) 38 | }) 39 | 40 | $http.onError(error => { 41 | if (error.statusCode === 500) { 42 | alert('Request Error!') 43 | } 44 | // Tip: error.response will be undefined if the connection dropped to the server 45 | // Tip: You can use error.response.data to get response message 46 | // Tip: You can return an object or Promise as fallback response to avoid rejection 47 | }) 48 | } 49 | ``` 50 | 51 | ## Header Helpers 52 | 53 | ### `setHeader(name, value)` 54 | 55 | Globally set a header to all subsequent requests. 56 | 57 | ::alert{type="warning"} 58 | This method should probably not be called inside hooks as it is global and will apply to all future requests 59 | :: 60 | 61 | ::alert{type="info"} 62 | Please note that HTTP headers are case-insensitive. Therefore all header names will be converted to lower-case to make sure that if you set the same header twice but with different casing the last one set will be used. 63 | 64 | See also [this comment](https://github.com/sindresorhus/ky/issues/105#issuecomment-470169100) in the Ky repository for more information 65 | :: 66 | 67 | Parameters: 68 | 69 | * **name**: Name of the header 70 | * **value**: Value of the header 71 | 72 | ```js 73 | // Add header `Authorization: 123` to all requests 74 | this.$http.setHeader('Authorization', '123') 75 | 76 | // Override `Authorization` header with new value 77 | this.$http.setHeader('Authorization', '456') 78 | 79 | // Add header `Content-Type: application/x-www-form-urlencoded` 80 | this.$http.setHeader('Content-Type', 'application/x-www-form-urlencoded') 81 | 82 | // Remove default Content-Type header 83 | this.$http.setHeader('Content-Type', false) 84 | ``` 85 | 86 | ### `setToken(token, type)` 87 | 88 | Globally set `Authorization` header to all subsequent requests. 89 | 90 | ::alert{type="info"} 91 | This is a global method, you only have to call it once after which all future requests will include the token 92 | :: 93 | 94 | Parameters: 95 | 96 | * **token**: Authorization token 97 | * **type**: Authorization token prefix, usually `Bearer`. Defaults to nothing 98 | 99 | ```js 100 | // Adds header: `Authorization: 123` to all requests 101 | this.$http.setToken('123') 102 | 103 | // Overrides `Authorization` header with new value 104 | this.$http.setToken('456') 105 | 106 | // Adds header: `Authorization: Bearer 123` to all requests 107 | this.$http.setToken('123', 'Bearer') 108 | 109 | // Removes default Authorization header 110 | this.$http.setToken(false) 111 | ``` 112 | 113 | ## Create new instance based on defaults 114 | 115 | If you need to create your own [ky instance](https://github.com/sindresorhus/ky#kycreatedefaultoptions) which based on `$http` defaults, you can use the `create(options)` method. 116 | 117 | ```js{}[plugins/github.js] 118 | export default function ({ $http, env }, inject) { 119 | // Create a custom HTTP instance 120 | const $github = $http.create({ 121 | // See https://github.com/sindresorhus/ky#options 122 | }) 123 | 124 | // Set baseURL to something different 125 | $github.setBaseURL('https://api.github.com') 126 | $github.setToken(env.GITHUB_TOKEN, 'token') 127 | 128 | // Inject to context as $github 129 | inject('github', $github) 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /docs/public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/public/logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/content/2.API/1.options.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | You can pass options using module options or `http` section in `nuxt.config.js`. 4 | 5 | --- 6 | 7 | ```js 8 | { 9 | http: { 10 | // HTTP options here 11 | } 12 | } 13 | ``` 14 | 15 | ## `prefix` 16 | 17 | ## `host` 18 | 19 | ## `port` 20 | 21 | This options are used for default values of `baseURL` and `browserBaseURL`. 22 | 23 | Can be customized with `API_PREFIX`, `API_HOST` (or `HOST`) and `API_PORT` (or `PORT`) environment variables. 24 | 25 | Default value of `prefix` is `/`. 26 | 27 | ## `baseURL` 28 | 29 | * Default: `http://[HOST]:[PORT][PREFIX]` 30 | 31 | Base URL which is used and prepended to make requests in server side. 32 | 33 | Environment variable `API_URL` can be used to **override** `baseURL`. 34 | 35 | ::alert{type="info"} 36 | `baseURL` and `proxy` won't work together, you will need to use [`prefix`](/options#prefix) instead 37 | :: 38 | 39 | ## `browserBaseURL` 40 | 41 | * Default: `baseURL` (or `prefix` when `options.proxy` is enabled) 42 | 43 | Base URL which is used and prepended to make requests in client side. 44 | 45 | Environment variable `API_URL_BROWSER` can be used to **override** `browserBaseURL`. 46 | 47 | ## `https` 48 | 49 | * Default: `false` 50 | 51 | If set to `true`, `http://` in both `baseURL` and `browserBaseURL` will be changed into `https://`. 52 | 53 | ## `debug` 54 | 55 | * Default: `false` 56 | 57 | Adds interceptors that logs http request and responses. 58 | 59 | ## `proxy` 60 | 61 | * Default: `false` 62 | 63 | You can easily integrate HTTP with [Proxy Module](https://github.com/nuxt-community/proxy-module) and is much recommended to prevent CORS and deployment problems. 64 | 65 | **nuxt.config.js** 66 | 67 | ```js 68 | { 69 | modules: [ 70 | '@nuxt/http' 71 | ], 72 | 73 | http: { 74 | proxy: true // Can be also an object with default options 75 | }, 76 | 77 | proxy: { 78 | '/api/': 'http://api.example.com', 79 | '/api2/': 'http://api.another-website.com' 80 | } 81 | } 82 | ``` 83 | 84 | ::alert{type="info"} 85 | It is not required to manually register `@nuxtjs/proxy` module, but it does need to be in your dependencies 86 | :: 87 | 88 | ::alert{type="info"} 89 | `/api/` will be added to all requests to the API end point. If you need to remove it use `pathRewrite`: 90 | 91 | ```js 92 | proxy: { 93 | '/api/': { 94 | target: 'http://api.example.com', 95 | pathRewrite: { '^/api/': '' } 96 | } 97 | } 98 | ``` 99 | :: 100 | 101 | ## `retry` 102 | 103 | * Default: `false` 104 | 105 | Automatically intercept failed requests and retry before failing. 106 | 107 | By default, number of retries will be **2 times**, if `retry` value is set to `true`. You can change it by passing an object like this: 108 | 109 | ```js 110 | http: { 111 | retry: 1 112 | } 113 | ``` 114 | 115 | You can also pass an object to have more control! See [ky docs](https://github.com/sindresorhus/ky#retry). 116 | 117 | ## `serverTimeout` 118 | 119 | * Default: `false` 120 | 121 | Sets the timeout for the server requests in milliseconds. 122 | 123 | ```js 124 | http: { 125 | serverTimeout: 2000 126 | } 127 | ``` 128 | 129 | ## `clientTimeout` 130 | 131 | * Default: `false` 132 | 133 | Sets the timeout for the client requests in milliseconds. 134 | 135 | ```js 136 | http: { 137 | clientTimeout: 5000 138 | } 139 | ``` 140 | 141 | ## `proxyHeaders` 142 | 143 | * Default: `true` 144 | 145 | In SSR context, sets client request header as http default request headers. 146 | This is useful for making requests which need cookie based auth on server side. 147 | Also helps making consistent requests in both SSR and Client Side code. 148 | 149 | ::alert{type="info"} 150 | When directing requests at a url protected by CloudFlare's CDN you should set this to `false` to prevent CloudFlare from mistakenly detecting a reverse proxy loop and returning a 403 error. 151 | :: 152 | 153 | ## `proxyHeadersIgnore` 154 | 155 | * Default `['accept', 'host', 'cf-ray', 'cf-connecting-ip', 'content-length', 'content-md5', 'content-type']` 156 | 157 | Only efficient when `proxyHeaders` is set to true. Removes unwanted request headers to the API backend in SSR. 158 | 159 | ### `headers` 160 | 161 | Headers added to all requests. If provided, will be merged with the defaults. 162 | 163 | * Default: `{}` 164 | 165 | ::alert{type="info"} 166 | Do NOT include any credentials or tokens here. One can easily access them. 167 | :: 168 | 169 | ::alert{type="info"} 170 | This headers are effective to ALL requests. Please take care and consider providing special headers on each call that needs this unless you are pretty sure you always need to add headers. 171 | :: 172 | -------------------------------------------------------------------------------- /docs/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 32 | -------------------------------------------------------------------------------- /lib/module.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const consola = require('consola') 3 | 4 | const logger = consola.withScope('nuxt:http') 5 | 6 | function httpModule (_moduleOptions) { 7 | const { nuxt, addPlugin, requireModule } = this 8 | 9 | // Combine options 10 | const moduleOptions = { ...nuxt.options.http, ..._moduleOptions } 11 | 12 | // Default port 13 | const defaultPort = 14 | process.env.API_PORT || 15 | moduleOptions.port || 16 | process.env.PORT || 17 | process.env.npm_package_config_nuxt_port || 18 | (nuxt.options.server && nuxt.options.server.port) || 19 | 3000 20 | 21 | // Default host 22 | let defaultHost = 23 | process.env.API_HOST || 24 | moduleOptions.host || 25 | process.env.HOST || 26 | process.env.npm_package_config_nuxt_host || 27 | (nuxt.options.server && nuxt.options.server.host) || 28 | 'localhost' 29 | 30 | /* istanbul ignore if */ 31 | if (defaultHost === '0.0.0.0') { 32 | defaultHost = 'localhost' 33 | } 34 | 35 | // Support baseUrl 36 | if (moduleOptions.baseUrl && !moduleOptions.baseURL) { 37 | moduleOptions.baseURL = moduleOptions.baseUrl 38 | 39 | delete moduleOptions.baseUrl 40 | } 41 | 42 | // Default prefix 43 | const prefix = process.env.API_PREFIX || moduleOptions.prefix || '/' 44 | 45 | // HTTPS 46 | const https = Boolean(nuxt.options.server && nuxt.options.server.https) 47 | 48 | // Apply defaults 49 | const options = { 50 | baseURL: undefined, 51 | browserBaseURL: undefined, 52 | debug: false, 53 | proxyHeaders: true, 54 | proxyHeadersIgnore: ['accept', 'host', 'cf-ray', 'cf-connecting-ip', 'content-length', 'content-md5', 'content-type'], 55 | proxy: false, 56 | retry: false, 57 | serverTimeout: false, 58 | clientTimeout: false, 59 | https, 60 | headers: {}, 61 | ...moduleOptions 62 | } 63 | const toHttps = s => options.https ? s.replace('http://', 'https://') : s 64 | 65 | // ENV overrides 66 | /* istanbul ignore if */ 67 | if (process.env.API_URL) { 68 | options.baseURL = process.env.API_URL 69 | } 70 | 71 | /* istanbul ignore if */ 72 | if (process.env.API_URL_BROWSER) { 73 | options.browserBaseURL = process.env.API_URL_BROWSER 74 | } 75 | 76 | // If no baseURL defined, get it from Nuxt server 77 | if (!options.baseURL) { 78 | options.baseURL = `http://${defaultHost}:${defaultPort}${prefix}` 79 | 80 | // Update auto generated baseURL after listen for static target as we use random port 81 | const publicRuntimeConfig = nuxt.options.publicRuntimeConfig = nuxt.options.publicRuntimeConfig || {} 82 | publicRuntimeConfig.http = publicRuntimeConfig.http || {} 83 | 84 | const privateRuntimeConfig = nuxt.options.privateRuntimeConfig = nuxt.options.privateRuntimeConfig || {} 85 | privateRuntimeConfig.http = privateRuntimeConfig.http || {} 86 | 87 | // For static exporting 88 | if (nuxt.options.target === 'static') { 89 | nuxt.hook('listen', (_, { host = 'localhost', port }) => { 90 | publicRuntimeConfig.http.browserBaseURL = toHttps(publicRuntimeConfig.http.browserBaseURL || prefix || '/') 91 | privateRuntimeConfig.http.baseURL = toHttps(privateRuntimeConfig.http.baseURL || `http://${host}:${port}${prefix}`) 92 | }) 93 | } 94 | } 95 | 96 | // Normalize options 97 | if (options.retry === true) { 98 | options.retry = 2 99 | } else if (!options.retry) { 100 | options.retry = 0 101 | } else if (!isNaN(options.retry)) { 102 | options.retry = parseInt(options.retry) 103 | } else if (typeof options.retry === 'object') { 104 | options.retry = JSON.stringify(options.retry) 105 | } 106 | 107 | // Default browserBaseURL 108 | if (typeof options.browserBaseURL === 'undefined') { 109 | options.browserBaseURL = options.proxy ? prefix : options.baseURL 110 | } 111 | 112 | // Remove port 443 when https 113 | if (options.baseURL.includes('https://')) { 114 | options.baseURL = options.baseURL.replace(':443', '') 115 | } 116 | 117 | // Remove port 80 when http 118 | if (/^http:\/\/.*:80(\/|$)/.test(options.baseURL)) { 119 | options.baseURL = options.baseURL.replace(':80', '') 120 | } 121 | 122 | // Convert http:// to https:// if https option is on 123 | options.baseURL = toHttps(options.baseURL) 124 | options.browserBaseURL = toHttps(options.browserBaseURL) 125 | 126 | // Register plugin 127 | addPlugin({ 128 | src: path.resolve(__dirname, 'plugin.js'), 129 | fileName: 'http.js', 130 | options 131 | }) 132 | addPlugin({ 133 | src: path.resolve(__dirname, 'plugin.server.js'), 134 | fileName: 'http.server.js', 135 | options 136 | }) 137 | 138 | // Proxy integration 139 | if (options.proxy) { 140 | requireModule([ 141 | '@nuxtjs/proxy', 142 | typeof options.proxy === 'object' ? options.proxy : {} 143 | ]) 144 | } 145 | 146 | // Transpile ky and ky-universal 147 | nuxt.options.build.transpile = nuxt.options.build.transpile || [] 148 | nuxt.options.build.transpile.push('ky') 149 | 150 | // Set _HTTP_BASE_URL_ for dynamic SSR baseURL 151 | process.env._HTTP_BASE_URL_ = options.baseURL 152 | 153 | logger.debug(`baseURL: ${options.baseURL}`) 154 | logger.debug(`browserBaseURL: ${options.browserBaseURL}`) 155 | } 156 | 157 | module.exports = httpModule 158 | module.exports.meta = require('../package.json') 159 | -------------------------------------------------------------------------------- /test/with-config.test.js: -------------------------------------------------------------------------------- 1 | const { setupMockNuxt } = require('./_utils') 2 | 3 | describe('with-config', () => { 4 | test('should render template with provided config', async () => { 5 | const nuxt = await setupMockNuxt({ 6 | http: { 7 | browserBaseURL: '/test_api', 8 | retry: true, 9 | serverTimeout: 10000, 10 | clientTimeout: 25000 11 | } 12 | }) 13 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 14 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 15 | const options = call[0].options 16 | expect(options.baseURL).toBe('http://localhost:3000/') 17 | expect(options.browserBaseURL).toBe('/test_api') 18 | expect(options.serverTimeout).toBe(10000) 19 | expect(options.clientTimeout).toBe(25000) 20 | }) 21 | 22 | test('should set https to baseURL', async () => { 23 | const nuxt = await setupMockNuxt({ 24 | http: { 25 | https: true 26 | } 27 | }) 28 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 29 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 30 | const options = call[0].options 31 | expect(options.baseURL).toBe('https://localhost:3000/') 32 | expect(options.browserBaseURL).toBe('https://localhost:3000/') 33 | }) 34 | 35 | test('should set retry=2 when retry=true', async () => { 36 | const nuxt = await setupMockNuxt({ 37 | http: { 38 | retry: true 39 | } 40 | }) 41 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 42 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 43 | const options = call[0].options 44 | expect(options.retry).toBe(2) 45 | }) 46 | 47 | test('should set correct number for retry', async () => { 48 | const nuxt = await setupMockNuxt({ 49 | http: { 50 | retry: 5 51 | } 52 | }) 53 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 54 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 55 | const options = call[0].options 56 | expect(options.retry).toBe(5) 57 | }) 58 | 59 | test('should give stringified object for retry', async () => { 60 | const nuxt = await setupMockNuxt({ 61 | http: { 62 | retry: { limit: 2, methods: ['get'] } 63 | } 64 | }) 65 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 66 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 67 | const options = call[0].options 68 | expect(options.retry).toBe(JSON.stringify({ limit: 2, methods: ['get'] })) 69 | }) 70 | 71 | test('should include @nuxtjs/proxy module if proxy: true', async () => { 72 | const nuxt = await setupMockNuxt({ 73 | http: { 74 | proxy: true 75 | } 76 | }) 77 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 78 | expect(nuxt.moduleContainer.requireModule).toBeDefined() 79 | expect(nuxt.moduleContainer.requireModule.mock.calls[0][0]).toStrictEqual(['@nuxtjs/proxy', {}]) 80 | }) 81 | 82 | test('should include @nuxtjs/proxy module and give proxy options', async () => { 83 | const nuxt = await setupMockNuxt({ 84 | http: { 85 | proxy: { 86 | hello: true 87 | } 88 | } 89 | }) 90 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 91 | expect(nuxt.moduleContainer.requireModule).toBeDefined() 92 | expect(nuxt.moduleContainer.requireModule.mock.calls[0][0]).toStrictEqual(['@nuxtjs/proxy', { hello: true }]) 93 | }) 94 | 95 | test('should handle `baseUrl` key', async () => { 96 | const nuxt = await setupMockNuxt({ 97 | http: { 98 | baseUrl: 'http://localhost:5000' 99 | } 100 | }) 101 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 102 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 103 | const options = call[0].options 104 | expect(options.baseURL).toBe('http://localhost:5000') 105 | }) 106 | 107 | test('should remove `:80` port if http', async () => { 108 | const nuxt = await setupMockNuxt({ 109 | http: { 110 | baseUrl: 'http://localhost:80' 111 | } 112 | }) 113 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 114 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 115 | const options = call[0].options 116 | expect(options.baseURL).toBe('http://localhost') 117 | }) 118 | 119 | test('should remove `:443` port if https', async () => { 120 | const nuxt = await setupMockNuxt({ 121 | http: { 122 | baseUrl: 'https://localhost:443' 123 | } 124 | }) 125 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 126 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 127 | const options = call[0].options 128 | expect(options.baseURL).toBe('https://localhost') 129 | }) 130 | 131 | test('should handle static target', async () => { 132 | const nuxt = await setupMockNuxt({ 133 | target: 'static' 134 | }) 135 | expect(nuxt.moduleContainer.addTemplate).toBeDefined() 136 | const call = nuxt.moduleContainer.addTemplate.mock.calls.find(args => args[0].src.includes('plugin.js')) 137 | const options = call[0].options 138 | expect(nuxt.options.privateRuntimeConfig.http).toBeDefined() 139 | expect(nuxt.options.publicRuntimeConfig.http).toBeDefined() 140 | await nuxt.callHook('listen', null, { port: 1234, host: 'hello' }) 141 | expect(nuxt.options.privateRuntimeConfig.http.baseURL).toBe('http://hello:1234/test_api') 142 | expect(nuxt.options.publicRuntimeConfig.http.browserBaseURL).toBe('/test_api') 143 | expect(options.baseURL).toBe('http://localhost:3000/test_api') 144 | expect(options.browserBaseURL).toBe('/test_api') 145 | }) 146 | }) 147 | -------------------------------------------------------------------------------- /lib/plugin.js: -------------------------------------------------------------------------------- 1 | import defu from 'defu' 2 | import destr from 'destr' 3 | import KY from 'ky' 4 | 5 | class HTTP { 6 | constructor(defaults, ky = KY) { 7 | this._defaults = { 8 | hooks: {}, 9 | ...defaults 10 | } 11 | 12 | this._ky = ky 13 | } 14 | 15 | getBaseURL () { 16 | return this._defaults.prefixUrl 17 | } 18 | 19 | setBaseURL (baseURL) { 20 | this._defaults.prefixUrl = baseURL 21 | } 22 | 23 | setHeader(name, value) { 24 | if (!value) { 25 | delete this._defaults.headers[name]; 26 | } else { 27 | this._defaults.headers[name] = value 28 | } 29 | } 30 | 31 | setToken(token, type) { 32 | const value = !token ? null : (type ? type + ' ' : '') + token 33 | this.setHeader('Authorization', value) 34 | } 35 | 36 | _hook(name, fn) { 37 | if (!this._defaults.hooks[name]) { 38 | this._defaults.hooks[name] = [] 39 | } 40 | this._defaults.hooks[name].push(fn) 41 | } 42 | 43 | onRequest(fn) { 44 | this._hook('beforeRequest', fn) 45 | } 46 | 47 | onRetry(fn) { 48 | this._hook('beforeRetry', fn) 49 | } 50 | 51 | onResponse(fn) { 52 | this._hook('afterResponse', fn) 53 | } 54 | 55 | onError(fn) { 56 | this._hook('onError', fn) 57 | } 58 | 59 | create(options) { 60 | const { retry, timeout, prefixUrl, headers } = this._defaults 61 | 62 | return createHttpInstance(defu(options, { retry, timeout, prefixUrl, headers })) 63 | } 64 | } 65 | 66 | for (let method of ['get', 'head', 'delete', 'post', 'put', 'patch']) { 67 | const hasBody = ['post', 'put', 'patch'].includes(method) 68 | 69 | HTTP.prototype[method] = async function (url, arg1, arg2) { 70 | let options 71 | 72 | if (!hasBody) { 73 | options = arg1 74 | } else { 75 | options = arg2 || {} 76 | if (arg1 !== undefined) { 77 | if (arg1.constructor === Object || Array.isArray(arg1)) { 78 | options.json = arg1 79 | } else { 80 | options.body = arg1 81 | } 82 | } 83 | } 84 | 85 | const _options = { ...this._defaults, ...options } 86 | 87 | if (/^https?/.test(url)) { 88 | delete _options.prefixUrl 89 | } else if (_options.prefixUrl && typeof url === 'string' && url.startsWith('/')) { 90 | // Prevents `ky` from throwing "`input` must not begin with a slash when using `prefixUrl`" 91 | url = url.substr(1) 92 | } 93 | 94 | try { 95 | const response = await this._ky[method](url, _options) 96 | return response 97 | } catch (error) { 98 | // Try to fill error with useful data 99 | if (error.response) { 100 | error.statusCode = error.response.status 101 | try { 102 | const text = await error.response.text() 103 | error.response.text = () => Promise.resolve(text) 104 | const json = destr(text) 105 | error.response.json = () => Promise.resolve(json) 106 | error.response.data = json 107 | } catch (_) { } 108 | } 109 | 110 | // Call onError hook 111 | if (_options.hooks.onError) { 112 | for (const fn of _options.hooks.onError) { 113 | const res = fn(error) 114 | if (res !== undefined) { 115 | return res 116 | } 117 | } 118 | } 119 | 120 | // Throw error 121 | throw error 122 | } 123 | } 124 | 125 | HTTP.prototype['$' + method] = function (url, arg1, arg2) { 126 | return this[method](url, arg1, arg2) 127 | .then(response => (response && response.text) ? response.text() : response) 128 | .then(body => destr(body)) 129 | } 130 | } 131 | 132 | const createHttpInstance = options => { 133 | // Create new HTTP instance 134 | const http = new HTTP(options) 135 | 136 | // Setup interceptors 137 | <% if (options.debug) { %>setupDebugInterceptor(http) <% } %> 138 | 139 | return http 140 | } 141 | 142 | <% if (options.debug) { %> 143 | const log = (level, ...messages) => console[level]('[Http]', ...messages) 144 | 145 | const setupDebugInterceptor = http => { 146 | // request 147 | http.onRequest(req => { 148 | log( 149 | 'info', 150 | 'Request:', 151 | '[' + req.method.toUpperCase() + ']', 152 | req.url 153 | ) 154 | 155 | if (process.browser) { 156 | console.log(req) 157 | } else { 158 | console.log(JSON.stringify(req, undefined, 2)) 159 | } 160 | }) 161 | 162 | // response 163 | http.onResponse((req, options, res) => { 164 | log( 165 | 'info', 166 | 'Response:', 167 | '[' + (res.status + ' ' + res.statusText) + ']', 168 | '[' + req.method.toUpperCase() + ']', 169 | res.url, 170 | ) 171 | 172 | if (process.browser) { 173 | console.log(req, options, res) 174 | } else { 175 | console.log(JSON.stringify({ req, options, res }, undefined, 2)) 176 | } 177 | 178 | return res 179 | }) 180 | 181 | // error 182 | http.onError(error => { 183 | log('error', 'Error:', error) 184 | }) 185 | }<% } %> 186 | 187 | export default (ctx, inject) => { 188 | // runtimeConfig 189 | const runtimeConfig = ctx.$config && ctx.$config.http || {} 190 | 191 | // prefixUrl 192 | const prefixUrl = process.browser 193 | ? (runtimeConfig.browserBaseURL || '<%= options.browserBaseURL || '' %>') 194 | : (runtimeConfig.baseURL || process.env._HTTP_BASE_URL_ || '<%= options.baseURL || '' %>') 195 | 196 | const headers = <%= JSON.stringify(options.headers, null, 2) %> 197 | 198 | // Defaults 199 | const defaults = { 200 | retry: <%= options.retry %>, 201 | timeout: process.server ? <%= options.serverTimeout %> : <%= options.clientTimeout %>, 202 | prefixUrl, 203 | headers 204 | } 205 | 206 | <% if (options.proxyHeaders) { %> 207 | // Proxy SSR request headers headers 208 | if (process.server && ctx.req && ctx.req.headers) { 209 | const reqHeaders = { ...ctx.req.headers } 210 | for (let h of <%= serialize(options.proxyHeadersIgnore) %>) { 211 | delete reqHeaders[h] 212 | } 213 | defaults.headers = { ...reqHeaders, ...defaults.headers } 214 | } 215 | <% } %> 216 | 217 | if (process.server) { 218 | // Don't accept brotli encoding because Node can't parse it 219 | defaults.headers['accept-encoding'] = 'gzip, deflate' 220 | } 221 | 222 | const http = createHttpInstance(defaults) 223 | 224 | // Inject http to the context as $http 225 | ctx.$http = http 226 | inject('http', http) 227 | } 228 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ky, { ResponsePromise, Options, BeforeRequestHook, BeforeRetryHook, AfterResponseHook } from 'ky' 3 | import './vuex' 4 | 5 | type Omit = Pick>; 6 | 7 | type RequestBody = string | number | boolean | null | object | BodyInit 8 | 9 | type HTTPError = ky.HTTPError & { 10 | response: HTTPErrorResponse 11 | statusCode?: number 12 | } 13 | 14 | type HTTPErrorResponse = Response & { 15 | text: () => Promise 16 | json: () => Promise 17 | data: any 18 | } 19 | 20 | type OnErrorHook = ( 21 | error: HTTPError 22 | ) => void; 23 | 24 | interface NuxtHTTPInstance { 25 | /** 26 | * Fetches the `url` with the option `{method: 'get'}`. 27 | * 28 | * @param url - `Request` object, `URL` object, or URL string. 29 | * @returns Promise with `Body` method added. 30 | */ 31 | get(url: Request | URL | string, options?: Omit): ResponsePromise; 32 | 33 | /** 34 | * Fetches the `url` with the option `{method: 'post'}`. 35 | * 36 | * @param url - `Request` object, `URL` object, or URL string. 37 | * @returns Promise with `Body` method added. 38 | */ 39 | post(url: Request | URL | string, body?: RequestBody, options?: Options): ResponsePromise; 40 | 41 | /** 42 | * Fetches the `url` with the option `{method: 'put'}`. 43 | * 44 | * @param url - `Request` object, `URL` object, or URL string. 45 | * @returns Promise with `Body` method added. 46 | */ 47 | put(url: Request | URL | string, body?: RequestBody, options?: Options): ResponsePromise; 48 | 49 | /** 50 | * Fetches the `url` with the option `{method: 'patch'}`. 51 | * 52 | * @param url - `Request` object, `URL` object, or URL string. 53 | * @returns Promise with `Body` method added. 54 | */ 55 | patch(url: Request | URL | string, body?: RequestBody, options?: Options): ResponsePromise; 56 | 57 | /** 58 | * Fetches the `url` with the option `{method: 'head'}`. 59 | * 60 | * @param url - `Request` object, `URL` object, or URL string. 61 | * @returns Promise with `Body` method added. 62 | */ 63 | head(url: Request | URL | string, options?: Omit): ResponsePromise; 64 | 65 | /** 66 | * Fetches the `url` with the option `{method: 'delete'}`. 67 | * 68 | * @param url - `Request` object, `URL` object, or URL string. 69 | * @returns Promise with `Body` method added. 70 | */ 71 | delete(url: Request | URL | string, options?: Options): ResponsePromise; 72 | 73 | /** 74 | * Fetches the `url` with the option `{method: 'get'}`. 75 | * 76 | * @param url - `Request` object, `URL` object, or URL string. 77 | * @returns Promise that resolves to JSON parsed value. 78 | */ 79 | $get(url: Request | URL | string, options?: Omit): Promise; 80 | 81 | /** 82 | * Fetches the `url` with the option `{method: 'post'}`. 83 | * 84 | * @param url - `Request` object, `URL` object, or URL string. 85 | * @returns Promise that resolves to JSON parsed value. 86 | */ 87 | $post(url: Request | URL | string, body?: RequestBody, options?: Options): Promise; 88 | 89 | /** 90 | * Fetches the `url` with the option `{method: 'put'}`. 91 | * 92 | * @param url - `Request` object, `URL` object, or URL string. 93 | * @returns Promise that resolves to JSON parsed value. 94 | */ 95 | $put(url: Request | URL | string, body?: RequestBody, options?: Options): Promise; 96 | 97 | /** 98 | * Fetches the `url` with the option `{method: 'patch'}`. 99 | * 100 | * @param url - `Request` object, `URL` object, or URL string. 101 | * @returns Promise that resolves to JSON parsed value. 102 | */ 103 | $patch(url: Request | URL | string, body?: RequestBody, options?: Options): Promise; 104 | 105 | /** 106 | * Fetches the `url` with the option `{method: 'head'}`. 107 | * 108 | * @param url - `Request` object, `URL` object, or URL string. 109 | * @returns Promise that resolves to JSON parsed value. 110 | */ 111 | $head(url: Request | URL | string, options?: Omit): Promise; 112 | 113 | /** 114 | * Fetches the `url` with the option `{method: 'delete'}`. 115 | * 116 | * @param url - `Request` object, `URL` object, or URL string. 117 | * @returns Promise that resolves to JSON parsed value. 118 | */ 119 | $delete(url: Request | URL | string, options?: Options): Promise; 120 | 121 | 122 | /** 123 | * Get the baseURL value. 124 | * @returns string - the base URL value 125 | */ 126 | getBaseURL(): string 127 | 128 | /** 129 | * Set the baseURL for all subsequent requests. 130 | * @param baseURL - the base URL (e.g. `https://myapi.com/`) 131 | */ 132 | setBaseURL(baseURL: string): void 133 | 134 | /** 135 | * Set a header on all subsequent requests. 136 | * @param name - Header name. 137 | * @param value - Header value. 138 | */ 139 | setHeader(name: string, value?: string | false): void 140 | 141 | /** 142 | * Set `Authorization` header on all subsequent requests. 143 | * @param name - Header name. 144 | * @param value - Header value. 145 | */ 146 | setToken(token: string | false, type?: string): void 147 | 148 | 149 | /** 150 | * Set a hook on `beforeRequest` (Before request is sent) 151 | * 152 | * This hook enables you to globally modify the requests right before it is sent. It will make no further changes to the request after this. The hook function receives the normalized options as the first argument. You could, for example, modify `options.headers` here. 153 | */ 154 | onRequest(hook: BeforeRequestHook): void 155 | 156 | /** 157 | * Set a hook on `beforeRetry` (Before request is sent) 158 | * 159 | * This hook enables you to modify the request right before retry. It will make no further changes to the request after this. The hook function receives the normalized input and options, an error instance and the retry count as arguments. You could, for example, modify `options.headers` here. 160 | */ 161 | onRetry(hook: BeforeRetryHook): void 162 | 163 | /** 164 | * Set a hook on `afterResponse` (After the response is received) 165 | * 166 | * This hook enables you to globally read and optionally modify the responses. The return value of the hook function will be used as the response object if it's an instance of [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response). 167 | */ 168 | onResponse(hook: AfterResponseHook): void 169 | 170 | /** 171 | * Set a hook on `onError` (When request failed) 172 | * 173 | * This hook enables you to globally handle request errors. 174 | */ 175 | onError(hook: OnErrorHook): void 176 | 177 | /** 178 | * If you need to create your own ky instance which based on $http defaults, you can use the create(options) method. 179 | */ 180 | create(options: Partial): NuxtHTTPInstance 181 | } 182 | 183 | declare module '@nuxt/vue-app' { 184 | interface Context { 185 | $http: NuxtHTTPInstance 186 | } 187 | } 188 | 189 | // Nuxt 2.9+ 190 | declare module '@nuxt/types' { 191 | interface Context { 192 | $http: NuxtHTTPInstance 193 | } 194 | } 195 | 196 | declare module 'vue/types/vue' { 197 | interface Vue { 198 | $http: NuxtHTTPInstance 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/3.http-methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 'HTTP Methods.' 3 | --- 4 | 5 | # HTTP Methods 6 | 7 | --- 8 | 9 | ::alert{type="info"} 10 | Each http method returns a `Promise` 11 | :: 12 | 13 | ### `$get` 14 | 15 | - arguments: `(url, options?)` 16 | - url: `String` 17 | - options: [options](/options) 18 | - resolves: [JSON](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) if [destr](https://github.com/nuxt-contrib/destr) can convert automatically, otherwise fallback to String 19 | - rejects: `Error` 20 | 21 | **Examples:** 22 | 23 | ```js 24 | const package = await $http.$get('https://unpkg.com/nuxt/package.json') 25 | ``` 26 | 27 | ```js 28 | // With prefixUrl option to call `https://example.com/items` 29 | const items = await $http.$get('items', { prefixUrl: 'https://example.com' }) 30 | ``` 31 | 32 | ### `$post` 33 | 34 | - arguments: `(url, body?, options?)` 35 | - url: `String` 36 | - body: `Object` 37 | - options: [options](/options) 38 | - resolves: [JSON](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) if [destr](https://github.com/nuxt-contrib/destr) can convert automatically, otherwise fallback to String 39 | - rejects: `Error` 40 | 41 | **Examples:** 42 | 43 | ```js 44 | const data = await $http.$post('http://api.com', { foo: 'bar' }) 45 | ``` 46 | 47 | ```js 48 | // With some additional options 49 | const data = await $http.$post('http://api.com', { foo: 'bar' }, { 50 | debug: true, 51 | retry: 2, 52 | serverTimeout: 5000 53 | }) 54 | ``` 55 | 56 | ### `$put` 57 | 58 | - arguments: `(url, body?, options?)` 59 | - url: `String` 60 | - body: `Object` 61 | - options: [options](/options) 62 | - resolves: [JSON](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) if [destr](https://github.com/nuxt-contrib/destr) can convert automatically, otherwise fallback to String 63 | - rejects: `Error` 64 | 65 | **Examples:** 66 | 67 | ```js 68 | const data = await $http.$put('http://api.com/{id}', { foo: 'bar' }) 69 | ``` 70 | 71 | ```js 72 | // With some additional option 73 | const data = await $http.$put('http://api.com/{id}', { foo: 'bar' }, { 74 | clientTimeout: 5000 75 | }) 76 | ``` 77 | 78 | ### `$delete` 79 | 80 | - arguments: `(url, options?)` 81 | - url: `String` 82 | - options: [options](/options) 83 | - resolves: [JSON](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) if [destr](https://github.com/nuxt-contrib/destr) can convert automatically, otherwise fallback to String 84 | - rejects: `Error` 85 | 86 | **Example:** 87 | 88 | ```js 89 | await $http.$delete('https://api.example.com/item/{id}') 90 | ``` 91 | 92 | ```js 93 | // With some options to call `https://example.com/api/item` 94 | const jsonResponse = await $http.$delete('item/{id}', { 95 | baseUrl: 'https://example.com', 96 | prefixUrl: '/api' 97 | }) 98 | ``` 99 | 100 | ### `$patch` 101 | 102 | - arguments: `(url, body?, options?)` 103 | - url: `String` 104 | - body: `Object` 105 | - options: [options](/options) 106 | - resolves: [JSON](https://developer.mozilla.org/en-US/docs/Web/API/Body/json) if [destr](https://github.com/nuxt-contrib/destr) can convert automatically, otherwise fallback to String 107 | - rejects: `Error` 108 | 109 | **Examples:** 110 | 111 | ```js 112 | const data = await $http.$patch('http://api.com/{id}', { foo: 'bar' }) 113 | ``` 114 | 115 | ```js 116 | // With some additional option 117 | const data = await $http.$patch('http://api.com/{id}', { foo: 'bar' }, { 118 | proxyHeaders: true, 119 | proxyHeadersIgnore: ['content-type'] 120 | }) 121 | ``` 122 | 123 | ### `$head` 124 | 125 | - arguments: `(url, options?)` 126 | - url: `String` 127 | - options: [options](/options) 128 | - resolves: - 129 | - rejects: `Error` 130 | 131 | ### `get` 132 | 133 | - arguments: `(url, options?)` 134 | - url: `String` 135 | - options: [options](/options) 136 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 137 | - rejects: `Error` 138 | 139 | **Examples:** 140 | 141 | ```js 142 | const response = await $http.get('https://unpkg.com/nuxt/package.json') 143 | const jsonResponse = await response.json() 144 | ``` 145 | 146 | ```js 147 | // With prefixUrl option to call `https://example.com/items` 148 | const response = await $http.get('items', { prefixUrl: 'https://example.com' }) 149 | const textResponse = await response.text() 150 | ``` 151 | 152 | See [`here`](/usage#making-requests) to convert response stream into usable data. 153 | 154 | These methods corresponds to the similar named HTTP/1.1 methods. 155 | 156 | ### `post` 157 | 158 | - arguments: `(url, body?, options?)` 159 | - url: `String` 160 | - body: `Object` 161 | - options: [options](/options) 162 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 163 | - rejects: `Error` 164 | 165 | **Examples:** 166 | 167 | ```js 168 | const response = await $http.post('http://api.com', { foo: 'bar' }) 169 | const jsonResponse = await response.json() 170 | ``` 171 | 172 | ```js 173 | // With some additional options 174 | const response = await $http.post('http://api.com', { foo: 'bar' }, { 175 | debug: true, 176 | retry: 2, 177 | serverTimeout: 5000 178 | }) 179 | const jsonResponse = await response.json() 180 | ``` 181 | 182 | See [`here`](/usage#making-requests) to convert response stream into usable data. 183 | 184 | These methods corresponds to the similar named HTTP/1.1 methods. 185 | 186 | ### `put` 187 | 188 | - arguments: `(url, body?, options?)` 189 | - url: `String` 190 | - body: `Object` 191 | - options: [options](/options) 192 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 193 | - rejects: `Error` 194 | 195 | **Examples:** 196 | 197 | ```js 198 | const response = await $http.put('http://api.com/{id}', { foo: 'bar' }) 199 | const jsonResponse = await response.json() 200 | ``` 201 | 202 | ```js 203 | // With some additional option 204 | const response = await $http.put('http://api.com/{id}', { foo: 'bar' }, { 205 | clientTimeout: 5000 206 | }) 207 | const jsonResponse = await response.json() 208 | ``` 209 | 210 | See [`here`](/usage#making-requests) to convert response stream into usable data. 211 | 212 | These methods corresponds to the similar named HTTP/1.1 methods. 213 | 214 | ### `delete` 215 | 216 | - arguments: `(url, options?)` 217 | - url: `String` 218 | - options: [options](/options) 219 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 220 | - rejects: `Error` 221 | 222 | **Example:** 223 | 224 | ```js 225 | await $http.delete('https://api.example.com/item/{id}') 226 | ``` 227 | 228 | ```js 229 | // With some options to call `https://example.com/api/item` 230 | const response = await $http.delete('item/{id}', { 231 | baseUrl: 'https://example.com', 232 | prefixUrl: '/api' 233 | }) 234 | ``` 235 | 236 | See [`here`](/usage#making-requests) to convert response stream into usable data. 237 | 238 | These methods corresponds to the similar named HTTP/1.1 methods. 239 | 240 | ### `patch` 241 | 242 | - arguments: `(url, body?, options?)` 243 | - url: `String` 244 | - body: `Object` 245 | - options: [options](/options) 246 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 247 | - rejects: `Error` 248 | 249 | **Examples:** 250 | 251 | ```js 252 | const response = await $http.patch('http://api.com/{id}', { foo: 'bar' }) 253 | const jsonResponse = await response.json() 254 | ``` 255 | 256 | ```js 257 | // With some additional option 258 | const response = await $http.patch('http://api.com/{id}', { foo: 'bar' }, { 259 | proxyHeaders: true, 260 | proxyHeadersIgnore: ['content-type'] 261 | }) 262 | const jsonResponse = await response.json() 263 | ``` 264 | 265 | See [`here`](/usage#making-requests) to convert response stream into usable data. 266 | 267 | These methods corresponds to the similar named HTTP/1.1 methods. 268 | 269 | ### `head` 270 | 271 | - arguments: `(url, options?)` 272 | - url: `String` 273 | - options: [options](/options) 274 | - resolves: [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 275 | - rejects: `Error` 276 | 277 | **Example:** 278 | 279 | ```js 280 | await $http.head('https://unpkg.com/nuxt/package.json') 281 | ``` 282 | 283 | These methods corresponds to the similar named HTTP/1.1 methods. 284 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.6.4](https://github.com/nuxt/http/compare/v0.6.3...v0.6.4) (2021-02-27) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * fix import of AbortController and ReadableStream ([460ac85](https://github.com/nuxt/http/commit/460ac85b777c9b3512060b9597af4b650b0fab1e)) 11 | 12 | ### [0.6.3](https://github.com/nuxt/http/compare/v0.6.2...v0.6.3) (2021-02-27) 13 | 14 | 15 | ### Features 16 | 17 | * `$http.getBaseURL` ([#165](https://github.com/nuxt/http/issues/165)) ([332bf34](https://github.com/nuxt/http/commit/332bf34fd5bb977f9c2f3077effc40b0c3334d62)) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | * use server plugin for polyfill ([74ad5c3](https://github.com/nuxt/http/commit/74ad5c3e0e21934638f055185ddd1772289dcf71)) 23 | 24 | ### [0.6.2](https://github.com/nuxt/http/compare/v0.6.1...v0.6.2) (2020-12-23) 25 | 26 | 27 | ### Bug Fixes 28 | 29 | * **pkg:** add missing defu dependency ([9ee0d00](https://github.com/nuxt/http/commit/9ee0d00153190391ac57abd1343e5cc3a29af9b9)) 30 | 31 | ### [0.6.1](https://github.com/nuxt/http/compare/v0.6.0...v0.6.1) (2020-12-02) 32 | 33 | ## [0.6.0](https://github.com/nuxt/http/compare/v0.5.13...v0.6.0) (2020-10-01) 34 | 35 | 36 | ### ⚠ BREAKING CHANGES 37 | 38 | * **deps:** (ky) remove response property for the first argument passed to `beforeRetry` hook. You can access it on `error.response` instead. 39 | 40 | ### Features 41 | 42 | * **deps:** update dependency ky to ^0.24.0 ([#131](https://github.com/nuxt/http/issues/131)) ([6d16a87](https://github.com/nuxt/http/commit/6d16a87d3c94e190312fc292c074be40a28bd1fe)) 43 | 44 | ### [0.5.13](https://github.com/nuxt/http/compare/v0.5.12...v0.5.13) (2020-09-26) 45 | 46 | 47 | ### Bug Fixes 48 | 49 | * use regex to avoid falsely replacing ports starting with 80 ([#124](https://github.com/nuxt/http/issues/124)) ([e981e62](https://github.com/nuxt/http/commit/e981e622891a347ad0ba651bf7c48db29a989f84)) 50 | 51 | ### [0.5.12](https://github.com/nuxt/http/compare/v0.5.11...v0.5.12) (2020-09-01) 52 | 53 | 54 | ### Bug Fixes 55 | 56 | * **types:** add missing types for `create` and `setBaseURL` ([#122](https://github.com/nuxt/http/issues/122)) ([c002aaa](https://github.com/nuxt/http/commit/c002aaa97c45fa5dfd91325a005fd5cc18a55b57)) 57 | 58 | ### [0.5.11](https://github.com/nuxt/http/compare/v0.5.10...v0.5.11) (2020-08-20) 59 | 60 | 61 | ### Bug Fixes 62 | 63 | * **ky-universal:** server importing es bundle ([#121](https://github.com/nuxt/http/issues/121)) ([029dea6](https://github.com/nuxt/http/commit/029dea6f04f82f8df36459a200751af683788302)) 64 | 65 | ### [0.5.10](https://github.com/nuxt/http/compare/v0.5.9...v0.5.10) (2020-07-16) 66 | 67 | 68 | ### Bug Fixes 69 | 70 | * **plugin:** debug option broken ([#117](https://github.com/nuxt/http/issues/117)) ([6bc1295](https://github.com/nuxt/http/commit/6bc12959a59b855dc9020e56fa0d0acb7f0e54d0)) 71 | 72 | ### [0.5.9](https://github.com/nuxt/http/compare/v0.5.8...v0.5.9) (2020-07-14) 73 | 74 | 75 | ### Bug Fixes 76 | 77 | * set default host ([18e9b11](https://github.com/nuxt/http/commit/18e9b11c395d7ef362ca75dee1ab97c939121864)) 78 | 79 | ### [0.5.8](https://github.com/nuxt/http/compare/v0.5.7...v0.5.8) (2020-07-14) 80 | 81 | 82 | ### Features 83 | 84 | * handle runtimeConfig and static target ([b9f5e05](https://github.com/nuxt/http/commit/b9f5e053d393d6a2f695df04d1d3bbc0ac54123f)) 85 | 86 | 87 | ### Bug Fixes 88 | 89 | * build.transpile should be an array ([823204c](https://github.com/nuxt/http/commit/823204c399149cc149f7a5c31bf93bd6fd729e28)), closes [#115](https://github.com/nuxt/http/issues/115) 90 | 91 | ### [0.5.7](https://github.com/nuxt/http/compare/v0.5.6...v0.5.7) (2020-06-29) 92 | 93 | ### [0.5.6](https://github.com/nuxt/http/compare/v0.5.5...v0.5.6) (2020-06-29) 94 | 95 | 96 | ### Bug Fixes 97 | 98 | * **plugin:** allow reusing error.response.json ([77b084b](https://github.com/nuxt/http/commit/77b084bc01ae9f95a33ad49a84d99c8765c8725a)) 99 | 100 | ### [0.5.5](https://github.com/nuxt/http/compare/v0.5.4...v0.5.5) (2020-06-17) 101 | 102 | ### [0.5.4](https://github.com/nuxt/http/compare/v0.5.3...v0.5.4) (2020-06-17) 103 | 104 | 105 | ### Features 106 | 107 | * improve `$` helpers and error object ([#113](https://github.com/nuxt/http/issues/113)) ([ada7387](https://github.com/nuxt/http/commit/ada73879f7891fbec712e41188bba70ee829adc2)) 108 | 109 | ### [0.5.3](https://github.com/nuxt/http/compare/v0.5.2...v0.5.3) (2020-06-12) 110 | 111 | 112 | ### Features 113 | 114 | * `debug` option ([#109](https://github.com/nuxt/http/issues/109)) ([874b668](https://github.com/nuxt/http/commit/874b668e1e98774e9ad0ef12d402605d00397fb4)) 115 | * https detection ([#106](https://github.com/nuxt/http/issues/106)) ([8ae0cd5](https://github.com/nuxt/http/commit/8ae0cd5655752e15d6d5296ef9fed53a843f0fca)), closes [nuxt-community/axios-module#260](https://github.com/nuxt-community/axios-module/issues/260) 116 | 117 | 118 | ### Bug Fixes 119 | 120 | * ignore proxy headers `content-md4` and `content-type` ([#107](https://github.com/nuxt/http/issues/107)) ([4152f87](https://github.com/nuxt/http/commit/4152f874a168dcdbceadd92b178b6213b535856b)) 121 | * use local version of ky-universal ([#111](https://github.com/nuxt/http/issues/111)) ([e7cb647](https://github.com/nuxt/http/commit/e7cb64704788e38fe0dc685b415b92b90b61df3f)) 122 | 123 | ### [0.5.2](https://github.com/nuxt/http/compare/v0.5.1...v0.5.2) (2020-06-05) 124 | 125 | 126 | ### Features 127 | 128 | * allow adding custom headers with nuxt config ([#101](https://github.com/nuxt/http/issues/101)) ([2839260](https://github.com/nuxt/http/commit/2839260ea97b18f259f79bb3ea0e97b0aa7228c3)) 129 | * support baseUrl and remove port :443 and :80 when http or https ([#103](https://github.com/nuxt/http/issues/103)) ([fc3e78e](https://github.com/nuxt/http/commit/fc3e78e1307455df506dbc8f6ba5269f28f6e364)) 130 | 131 | ### [0.5.1](https://github.com/nuxt/http/compare/v0.5.0...v0.5.1) (2020-04-29) 132 | 133 | 134 | ### Bug Fixes 135 | 136 | * remove leading slash when using prefixUrl ([#96](https://github.com/nuxt/http/issues/96)) ([10fbd67](https://github.com/nuxt/http/commit/10fbd679664c533e8a5fa45afb1f56ac945d8cfa)) 137 | 138 | ## [0.5.0](https://github.com/nuxt/http/compare/v0.4.0...v0.5.0) (2020-04-13) 139 | 140 | 141 | ### New Features 142 | 143 | - Allow creating new instances with `$http.create(kyOptions)` (#3) (#94) ([docs](https://http.nuxtjs.org/guide/advanced.html#create-new-instance-based-on-defaults)) 144 | - ‍Allow changing baseURL on runtime `$http.setBaseURL(baseURL)‍‍` (#82) (#94) 145 | 146 | ### Docs 147 | 148 | #### Restructure sidebar (#94) 149 | 150 | - API > Hooks: https://http.nuxtjs.org/api/#hooks 151 | - API > HTTP methods: https://http.nuxtjs.org/api/#http-methods 152 | 153 | ### Types 154 | 155 | - fix(types): update types for `HTTPError` to `ky.HTTPError` (#91) 156 | 157 | ### Chore 158 | 159 | - Switch to Github Actions ([6205fdaa](https://github.com/nuxt/http/commit/6205fdaa5e1552797fc8f743952cafc44169716f)) 160 | - Use [tib](https://github.com/nuxt/tib) for testing ([5c693a04](https://github.com/nuxt/http/commit/5c693a04b93dc7bb29f6f63c0e38c3db24c8e5a3)) 161 | 162 | ## [0.4.0](https://github.com/nuxt/http/compare/v0.3.9...v0.4.0) (2020-03-27) 163 | 164 | 165 | ### ⚠ BREAKING CHANGES 166 | 167 | * **deps:** Require Node.js 10+ 168 | 169 | ### Bug Fixes 170 | 171 | * **module:** always set protocol to https when `https: true` is set ([50ef8e0](https://github.com/nuxt/http/commit/50ef8e05f7958a5270fdad7dc0f543f5af5bf9fd)) 172 | 173 | 174 | * **deps:** update all non-major dependencies ([#90](https://github.com/nuxt/http/issues/90)) ([2f1411b](https://github.com/nuxt/http/commit/2f1411b64d742fbc8d1372ada5543ebc83629e1a)) 175 | 176 | ### [0.3.9](https://github.com/nuxt/http/compare/v0.3.8...v0.3.9) (2020-01-30) 177 | 178 | 179 | ### Features 180 | 181 | * enable advanced retry options ([#80](https://github.com/nuxt/http/issues/80)) ([bdae0c0](https://github.com/nuxt/http/commit/bdae0c0aab93e1e402747f949045acea31613aab)) 182 | 183 | 184 | ### Bug Fixes 185 | 186 | * use json serialization for plain array ([#87](https://github.com/nuxt/http/issues/87)) ([febf265](https://github.com/nuxt/http/commit/febf2658dc605dfae8762ce0f147cce192c1c0cb)) 187 | * **module:** read port and host from options/cli before fallback ([bc58738](https://github.com/nuxt/http/commit/bc58738c6b1158bd6e6efd45372da9765b8da577)) 188 | 189 | ### [0.3.8](https://github.com/nuxt/http/compare/v0.3.7...v0.3.8) (2019-11-02) 190 | 191 | 192 | ### Features 193 | 194 | * add `onRetry` hook ([#79](https://github.com/nuxt/http/issues/79)) ([3d0aa27](https://github.com/nuxt/http/commit/3d0aa27)) 195 | 196 | ### [0.3.7](https://github.com/nuxt/http/compare/v0.3.6...v0.3.7) (2019-11-01) 197 | 198 | ### [0.3.6](https://github.com/nuxt/http/compare/v0.3.5...v0.3.6) (2019-11-01) 199 | 200 | 201 | ### Features 202 | 203 | * **types:** provide nuxt 2.9 compatible types ([#78](https://github.com/nuxt/http/issues/78)) ([a6bab0f](https://github.com/nuxt/http/commit/a6bab0f)) 204 | 205 | ### [0.3.5](https://github.com/nuxt/http/compare/v0.3.4...v0.3.5) (2019-09-05) 206 | 207 | 208 | ### Bug Fixes 209 | 210 | * **types:** fix argument of onError ([#67](https://github.com/nuxt/http/issues/67)) ([be10314](https://github.com/nuxt/http/commit/be10314)) 211 | 212 | ## [0.3.4](https://github.com/nuxt/http/compare/v0.3.3...v0.3.4) (2019-08-12) 213 | 214 | 215 | ### Bug Fixes 216 | 217 | * **types:** replace `JSONValue import from ky to `unknown` ([#63](https://github.com/nuxt/http/issues/63)) ([aff7a35](https://github.com/nuxt/http/commit/aff7a35)) 218 | 219 | 220 | 221 | ## [0.3.3](https://github.com/nuxt/http/compare/v0.3.2...v0.3.3) (2019-07-24) 222 | 223 | 224 | ### Bug Fixes 225 | 226 | * transpile ky ([#61](https://github.com/nuxt/http/issues/61)) ([2ce08de](https://github.com/nuxt/http/commit/2ce08de)) 227 | 228 | 229 | 230 | ## [0.3.2](https://github.com/nuxt/http/compare/v0.3.1...v0.3.2) (2019-06-05) 231 | 232 | 233 | ### Bug Fixes 234 | 235 | * ignore content-length header ([185dabb](https://github.com/nuxt/http/commit/185dabb)) 236 | 237 | 238 | 239 | ## [0.3.1](https://github.com/nuxt/http/compare/v0.3.0...v0.3.1) (2019-05-30) 240 | 241 | 242 | ### Bug Fixes 243 | 244 | * handle false timeout ([d965efa](https://github.com/nuxt/http/commit/d965efa)) 245 | 246 | 247 | 248 | # [0.3.0](https://github.com/nuxt/http/compare/v0.2.0...v0.3.0) (2019-05-29) 249 | 250 | 251 | ### Features 252 | 253 | * support setting timeout and disable by default ([#51](https://github.com/nuxt/http/issues/51)) ([53287dd](https://github.com/nuxt/http/commit/53287dd)) 254 | 255 | 256 | ### Reverts 257 | 258 | * revert converting header names to lowercase ([2b0f463](https://github.com/nuxt/http/commit/2b0f463)) 259 | 260 | 261 | 262 | # [0.2.0](https://github.com/nuxt/http/compare/v0.1.2...v0.2.0) (2019-05-22) 263 | 264 | 265 | ### Bug Fixes 266 | 267 | * lowercase `accept-encoding` header ([#43](https://github.com/nuxt/http/issues/43)) ([454807c](https://github.com/nuxt/http/commit/454807c)) 268 | 269 | 270 | ### Features 271 | 272 | * convert header names to lowercase ([#45](https://github.com/nuxt/http/issues/45)) ([7ad6645](https://github.com/nuxt/http/commit/7ad6645)) 273 | 274 | 275 | 276 | ## [0.1.2](https://github.com/nuxt/http/compare/v0.1.1...v0.1.2) (2019-04-28) 277 | 278 | 279 | ### Bug Fixes 280 | 281 | * **types:** add missing `JSONValue` import ([#28](https://github.com/nuxt/http/issues/28)) ([60e3370](https://github.com/nuxt/http/commit/60e3370)) 282 | 283 | 284 | 285 | ## [0.1.1](https://github.com/nuxt/http/compare/v0.1.0...v0.1.1) (2019-04-18) 286 | 287 | 288 | ### Bug Fixes 289 | 290 | * correctly handle `proxyHeaders: false` ([#17](https://github.com/nuxt/http/issues/17)) ([15274cb](https://github.com/nuxt/http/commit/15274cb)) 291 | 292 | 293 | 294 | # [0.1.0](https://github.com/nuxt/http/compare/v5.4.1...v0.1.0) (2019-04-09) 295 | 296 | 297 | ### Bug Fixes 298 | 299 | * default retry to 1 ([7bc50f8](https://github.com/nuxt/http/commit/7bc50f8)) 300 | * prefixUrl ([09a5382](https://github.com/nuxt/http/commit/09a5382)) 301 | 302 | 303 | ### Features 304 | 305 | * allow passing body as argument ([57b8a8b](https://github.com/nuxt/http/commit/57b8a8b)) 306 | * http class ([61fb627](https://github.com/nuxt/http/commit/61fb627)) 307 | * migrate to http and ky-universal ([d3e2c08](https://github.com/nuxt/http/commit/d3e2c08)) 308 | --------------------------------------------------------------------------------