├── .eslintrc.cjs ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── BUG_REPORT.yml │ ├── DOCUMENTATION.yml │ ├── FEATURE_REQUEST.yml │ ├── SUPPORT_QUESTION.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── depsreview.yaml │ ├── notify.yml │ ├── npm-tag.yml │ ├── pr.yml │ ├── publish.yml │ ├── sponsors.yml │ └── stale.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── COLLABORATOR_GUIDE.md ├── CONTRIBUTING.md ├── ECOSYSTEM.md ├── LICENSE ├── MIGRATION_GUIDE.md ├── README.md ├── SECURITY.md ├── bin ├── GithubAPI.js ├── RepoBot.js ├── actions │ └── notify_published.js ├── api.js ├── check-build-version.js ├── contributors.js ├── githubAxios.js ├── helpers │ ├── colorize.js │ └── parser.js ├── injectContributorsList.js ├── pr.js ├── repo.js ├── resolveNPMTag.js ├── sponsors.js └── ssl_hotfix.js ├── bower.json ├── dist ├── axios.js ├── axios.js.map ├── axios.min.js ├── axios.min.js.map ├── browser │ ├── axios.cjs │ └── axios.cjs.map ├── esm │ ├── axios.js │ ├── axios.js.map │ ├── axios.min.js │ └── axios.min.js.map └── node │ ├── axios.cjs │ └── axios.cjs.map ├── examples ├── README.md ├── all │ └── index.html ├── amd │ └── index.html ├── get │ ├── index.html │ └── server.js ├── post │ ├── index.html │ └── server.js ├── postMultipartFormData │ ├── index.html │ └── server.js ├── server.js ├── transform-response │ └── index.html └── upload │ ├── index.html │ └── server.js ├── gulpfile.js ├── index.d.cts ├── index.d.ts ├── index.js ├── karma.conf.cjs ├── lib ├── adapters │ ├── README.md │ ├── adapters.js │ ├── fetch.js │ ├── http.js │ └── xhr.js ├── axios.js ├── cancel │ ├── CancelToken.js │ ├── CanceledError.js │ └── isCancel.js ├── core │ ├── Axios.js │ ├── AxiosError.js │ ├── AxiosHeaders.js │ ├── InterceptorManager.js │ ├── README.md │ ├── buildFullPath.js │ ├── dispatchRequest.js │ ├── mergeConfig.js │ ├── settle.js │ └── transformData.js ├── defaults │ ├── index.js │ └── transitional.js ├── env │ ├── README.md │ ├── classes │ │ └── FormData.js │ └── data.js ├── helpers │ ├── AxiosTransformStream.js │ ├── AxiosURLSearchParams.js │ ├── HttpStatusCode.js │ ├── README.md │ ├── ZlibHeaderTransformStream.js │ ├── bind.js │ ├── buildURL.js │ ├── callbackify.js │ ├── combineURLs.js │ ├── composeSignals.js │ ├── cookies.js │ ├── deprecatedMethod.js │ ├── formDataToJSON.js │ ├── formDataToStream.js │ ├── fromDataURI.js │ ├── isAbsoluteURL.js │ ├── isAxiosError.js │ ├── isURLSameOrigin.js │ ├── null.js │ ├── parseHeaders.js │ ├── parseProtocol.js │ ├── progressEventReducer.js │ ├── readBlob.js │ ├── resolveConfig.js │ ├── speedometer.js │ ├── spread.js │ ├── throttle.js │ ├── toFormData.js │ ├── toURLEncodedForm.js │ ├── trackStream.js │ └── validator.js ├── platform │ ├── browser │ │ ├── classes │ │ │ ├── Blob.js │ │ │ ├── FormData.js │ │ │ └── URLSearchParams.js │ │ └── index.js │ ├── common │ │ └── utils.js │ ├── index.js │ └── node │ │ ├── classes │ │ ├── FormData.js │ │ └── URLSearchParams.js │ │ └── index.js └── utils.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── sandbox ├── client.html ├── client.js └── server.js ├── templates ├── contributors.hbs ├── pr.hbs ├── pr_published.hbs └── prs.hbs ├── test ├── helpers │ └── server.js ├── manual │ ├── basic.html │ ├── cors.html │ ├── fixture.json │ ├── progress.html │ └── promise.js ├── module │ ├── cjs │ │ ├── index.js │ │ └── package.json │ ├── esm │ │ ├── index.js │ │ └── package.json │ ├── test.js │ ├── ts-require-default │ │ ├── index.js │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ ├── ts-require │ │ ├── index.js │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ ├── ts │ │ ├── index.js │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ └── typings │ │ ├── cjs │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ │ └── esm │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json ├── specs │ ├── __helpers.js │ ├── adapter.spec.js │ ├── api.spec.js │ ├── basicAuth.spec.js │ ├── cancel.spec.js │ ├── cancel │ │ ├── CancelToken.spec.js │ │ ├── CanceledError.spec.js │ │ └── isCancel.spec.js │ ├── core │ │ ├── AxiosError.spec.js │ │ ├── buildFullPath.spec.js │ │ ├── enhanceError.spec.js │ │ ├── mergeConfig.spec.js │ │ ├── settle.spec.js │ │ └── transformData.spec.js │ ├── defaults.spec.js │ ├── formdata.spec.js │ ├── headers.spec.js │ ├── helpers │ │ ├── bind.spec.js │ │ ├── buildURL.spec.js │ │ ├── combineURLs.spec.js │ │ ├── cookies.spec.js │ │ ├── formDataToJSON.spec.js │ │ ├── isAbsoluteURL.spec.js │ │ ├── isAxiosError.spec.js │ │ ├── isURLSameOrigin.spec.js │ │ ├── parseHeaders.spec.js │ │ ├── spread.spec.js │ │ ├── toFormData.spec.js │ │ └── validator.spec.js │ ├── instance.spec.js │ ├── interceptors.spec.js │ ├── options.spec.js │ ├── progress.spec.js │ ├── promise.spec.js │ ├── requests.spec.js │ ├── transform.spec.js │ ├── utils │ │ ├── endsWith.js │ │ ├── extend.spec.js │ │ ├── forEach.spec.js │ │ ├── isX.spec.js │ │ ├── kindOf.js │ │ ├── kindOfTest.js │ │ ├── merge.spec.js │ │ ├── toArray.js │ │ ├── toFlatObject.js │ │ └── trim.spec.js │ └── xsrf.spec.js └── unit │ ├── adapters │ ├── adapters.js │ ├── axios.png │ ├── cert.pem │ ├── fetch.js │ ├── http.js │ └── key.pem │ ├── core │ ├── Axios.js │ └── AxiosHeaders.js │ ├── defaults │ └── transformReponse.js │ ├── helpers │ ├── composeSignals.js │ ├── fromDataURI.js │ └── parseProtocol.js │ ├── platform │ └── index.js │ ├── regression │ ├── SNYK-JS-AXIOS-1038255.js │ ├── SNYK-JS-AXIOS-7361793.js │ └── bugs.js │ └── utils │ └── utils.js ├── tsconfig.json ├── tslint.json └── webpack.config.js /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es2018": true, 5 | "node": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "ecmaVersion": 2018, 10 | "sourceType": "module" 11 | }, 12 | "rules": { 13 | "no-cond-assign": 0 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: axios 2 | github: axios 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | #### Summary 18 | 19 | Describe your issue here, including as much detail as necessary. 20 | 21 | If you're reporting a bug, include the relevant code and stack traces to debug it (removing any private information). 22 | 23 | If you're requesting a feature, include some context and examples of code using it. 24 | 25 | #### Environment 26 | - **Axios Version [e.g. 1.7.0]** 27 | - **Target platform [e.g Node / Browser / React Native version where Axios is running]** 28 | - **Adapter [e.g. FETCH / XHR / HTTP]** 29 | - Additional Library/Framework Versions [e.g. React 16.7] 30 | - OS: [e.g. iOS 12.1.0, OSX 10.13.4] 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/DOCUMENTATION.yml: -------------------------------------------------------------------------------- 1 | name: '📝 Documentation' 2 | description: Report an error or area that needs clarification. 3 | labels: ['documentation'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: 'If you found an area that needs clarification, feel free to open a PR or list the section/content that could be improved below' 8 | - type: markdown 9 | attributes: 10 | value: '⚠️👆 Feel free to these instructions before submitting the issue 👆⚠️' 11 | - type: textarea 12 | id: content 13 | attributes: 14 | label: 'Section/Content To Improve' 15 | description: Quote or link to section 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: solution 20 | attributes: 21 | label: 'Suggested Improvement' 22 | description: Identify what is confusing or incorrect and what could make it better 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: files 27 | attributes: 28 | label: 'Relevant File(s)' 29 | placeholder: e.g. README.md 30 | render: bash 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml: -------------------------------------------------------------------------------- 1 | name: '✨ Feature Request' 2 | description: Suggest an idea or feature. 3 | labels: ['feature'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: 'Please read and follow the instructions before submitting an issue:' 8 | - type: markdown 9 | attributes: 10 | value: | 11 | - Read all our documentation, especially the [README](https://github.com/axios/axios/blob/master/README.md). It may contain information that helps you solve your issue. 12 | - Ensure your issue isn't already [reported](https://github.com/axios/axios/issues?utf8=%E2%9C%93&q=is%3Aissue). 13 | - If you aren't sure that the issue is caused by Axios or you just need help, please use [Stack Overflow](https://stackoverflow.com/questions/tagged/axios) or [our chat](https://gitter.im/mzabriskie/axios). 14 | - type: markdown 15 | attributes: 16 | value: '⚠️👆 Feel free to these instructions before submitting the issue 👆⚠️' 17 | - type: textarea 18 | id: description 19 | attributes: 20 | label: 'Is your feature request related to a problem? Please describe.' 21 | description: A clear and concise description of what the problem is. 22 | placeholder: I'm always frustrated when [...] 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: solution 27 | attributes: 28 | label: Describe the solution you'd like 29 | description: A clear and concise description of what you want to happen. 30 | validations: 31 | required: false 32 | - type: textarea 33 | id: alternative 34 | attributes: 35 | label: Describe alternatives you've considered 36 | description: A clear and concise description of any alternative solutions or features you've considered. 37 | validations: 38 | required: false 39 | - type: textarea 40 | id: additional-context 41 | attributes: 42 | label: 'Additional context/Screenshots' 43 | description: Add any other context or screenshots about the feature request here. 44 | render: bash 45 | validations: 46 | required: false 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.yml: -------------------------------------------------------------------------------- 1 | name: '🤔 Support or Usage Question' 2 | description: Get help using Axios. 3 | labels: ['question'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: 'Please read and follow the instructions before submitting an issue:' 8 | - type: markdown 9 | attributes: 10 | value: | 11 | - Read all our documentation, especially the [README](https://github.com/axios/axios/blob/master/README.md). It may contain information that helps you solve your issue. 12 | - Ensure your issue isn't already [reported](https://github.com/axios/axios/issues?utf8=%E2%9C%93&q=is%3Aissue). 13 | - If you aren't sure that the issue is caused by Axios or you just need help, please use [Stack Overflow](https://stackoverflow.com/questions/tagged/axios) or [our chat](https://gitter.im/mzabriskie/axios). 14 | - If you're reporting a bug, ensure it isn't already fixed in the latest Axios version. 15 | - type: markdown 16 | attributes: 17 | value: '⚠️👆 Feel free to delete these instructions before submitting the issue 👆⚠️' 18 | - type: textarea 19 | id: description 20 | attributes: 21 | label: 'Describe the issue' 22 | description: A clear and concise description of what the issue is. 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: example 27 | attributes: 28 | label: 'Example Code' 29 | description: Code snippet to illustrate your question 30 | render: js 31 | validations: 32 | required: false 33 | - type: textarea 34 | id: expected 35 | attributes: 36 | label: 'Expected behavior' 37 | description: A clear and concise description of what you expected to happen. 38 | validations: 39 | required: false 40 | - type: markdown 41 | attributes: 42 | value: Environment 43 | - type: input 44 | id: axios-version 45 | attributes: 46 | label: 'Axios Version' 47 | placeholder: 'e.g. 0.18.0' 48 | - type: input 49 | id: adapter-version 50 | attributes: 51 | label: 'Adapter Version' 52 | placeholder: 'e.g. XHR/HTTP' 53 | - type: input 54 | id: browser 55 | attributes: 56 | label: 'Browser' 57 | placeholder: 'e.g. Chrome, Safari' 58 | - type: input 59 | id: browser-version 60 | attributes: 61 | label: 'Browser Version' 62 | placeholder: 'e.g. 42' 63 | - type: input 64 | id: node-version 65 | attributes: 66 | label: 'Node.js Version' 67 | description: 'node --version' 68 | placeholder: 'e.g. 13.0.1' 69 | - type: input 70 | id: os 71 | attributes: 72 | label: 'OS' 73 | placeholder: 'e.g. iOS 16.0.2, OSX 12.6.0' 74 | - type: textarea 75 | id: other-version 76 | attributes: 77 | label: 'Additional Library Versions' 78 | placeholder: | 79 | e.g. 80 | React 16.7, 81 | React Native 0.58.0 82 | render: bash 83 | validations: 84 | required: false 85 | - type: textarea 86 | id: additional-context 87 | attributes: 88 | label: 'Additional context/Screenshots' 89 | description: Add any other context about the problem here. If applicable, add screenshots to help explain. 90 | render: bash 91 | validations: 92 | required: false 93 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### Instructions 4 | 5 | Please read and follow the instructions before creating and submitting a pull request: 6 | 7 | - Create an issue explaining the feature. It could save you some effort in case we don't consider it should be included in axios. 8 | - If you're fixing a bug, try to commit the failing test/s and the code fixing it in different commits. 9 | - Ensure you're following our [contributing guide](https://github.com/axios/axios/blob/master/CONTRIBUTING.md). 10 | 11 | **⚠️👆 Delete the instructions before submitting the pull request 👆⚠️** 12 | 13 | Describe your pull request here. 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | groups: 6 | github-actions: 7 | patterns: 8 | - "*" # Group all Actions updates into a single larger pull request 9 | schedule: 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: 'CI' 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | - '*/*' 8 | - '**' 9 | - '!sponsors' 10 | pull_request: 11 | branches: 12 | - '*' 13 | - '*/*' 14 | - '**' 15 | - '!sponsors' 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-latest 23 | 24 | strategy: 25 | matrix: 26 | node-version: [12.x, 14.x, 16.x, 18.x, 20.x, 22.x] 27 | fail-fast: false 28 | 29 | steps: 30 | - uses: actions/checkout@v4 31 | with: 32 | persist-credentials: true 33 | - name: Get changed files 34 | id: changed-files 35 | uses: tj-actions/changed-files@v46 36 | - name: List all changed files 37 | run: | 38 | for file in ${{ steps.changed-files.outputs.all_changed_files }}; do 39 | echo "$file was changed" 40 | done 41 | - name: Check changes 42 | id: changed-ignored 43 | uses: tj-actions/changed-files@v46 44 | with: 45 | files: | 46 | **.md 47 | sandbox/** 48 | examples/** 49 | .github/** 50 | templates/** 51 | bin/** 52 | - name: Setup node 53 | uses: actions/setup-node@v4 54 | with: 55 | node-version: ${{ matrix.node-version }} 56 | cache: npm 57 | if: steps.changed-ignored.outputs.only_modified == 'false' 58 | - run: npm ci 59 | if: steps.changed-ignored.outputs.only_modified == 'false' 60 | - run: npm test 61 | if: steps.changed-ignored.outputs.only_modified == 'false' 62 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: 'CodeQL' 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | - '*/*' 8 | - '**' 9 | - '!sponsors' 10 | pull_request: 11 | branches: 12 | - '*' 13 | - '*/*' 14 | - '**' 15 | - '!sponsors' 16 | schedule: 17 | - cron: '21 23 * * 5' 18 | 19 | jobs: 20 | analyze: 21 | name: Analyze 22 | runs-on: ubuntu-latest 23 | permissions: 24 | actions: read 25 | contents: read 26 | security-events: write 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | 33 | steps: 34 | - name: Checkout repository 35 | uses: actions/checkout@v4 36 | with: 37 | persist-credentials: false 38 | 39 | # Initializes the CodeQL tools for scanning. 40 | - name: Initialize CodeQL 41 | uses: github/codeql-action/init@v3 42 | with: 43 | languages: ${{ matrix.language }} 44 | queries: security-extended,security-and-quality 45 | 46 | - name: Perform CodeQL Analysis 47 | uses: github/codeql-action/analyze@v3 48 | -------------------------------------------------------------------------------- /.github/workflows/depsreview.yaml: -------------------------------------------------------------------------------- 1 | name: 'Dependency Review' 2 | on: [pull_request] 3 | 4 | permissions: 5 | contents: read 6 | 7 | jobs: 8 | dependency-review: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: 'Checkout Repository' 12 | uses: actions/checkout@v4 13 | with: 14 | persist-credentials: false 15 | - name: 'Dependency Review' 16 | uses: actions/dependency-review-action@v4 17 | -------------------------------------------------------------------------------- /.github/workflows/notify.yml: -------------------------------------------------------------------------------- 1 | name: notify 2 | 3 | on: 4 | #workflow_run: 5 | # workflows: ["publish"] 6 | # types: 7 | # - completed 8 | #repository_dispatch: 9 | # types: [ notify ] 10 | #release: 11 | # types: [published] 12 | # branches: 13 | # - main 14 | # - 'v**' 15 | #push: 16 | # tags: 17 | # - 'v[0-9]+.[0-9]+.[0-9]+' 18 | # branches: 19 | # - main 20 | # - 'v**' 21 | 22 | workflow_dispatch: 23 | inputs: 24 | tag: 25 | required: false 26 | jobs: 27 | notify: 28 | runs-on: ubuntu-latest 29 | #if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 30 | steps: 31 | #- name: Dump GitHub context 32 | # env: 33 | # GITHUB_CONTEXT: ${{ toJson(github) }} 34 | # run: echo "$GITHUB_CONTEXT" 35 | - uses: actions/checkout@v4 36 | with: 37 | fetch-depth: 0 38 | - name: git config 39 | run: | 40 | git config user.name "${GITHUB_ACTOR}" 41 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 42 | - name: Setup node 43 | uses: actions/setup-node@v4 44 | with: 45 | node-version: 18 46 | cache: npm 47 | - run: npm ci 48 | - name: Notify published PRs 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | run: node ./bin/actions/notify_published.js --tag ${{ github.event.inputs.tag || github.event.release.tag_name }} 52 | -------------------------------------------------------------------------------- /.github/workflows/npm-tag.yml: -------------------------------------------------------------------------------- 1 | name: NPM Tag 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | version: 6 | required: true 7 | tag: 8 | required: true 9 | default: "latest" 10 | jobs: 11 | publish: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | id-token: write 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: git config 19 | run: | 20 | git config user.name "${GITHUB_ACTOR}" 21 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version: 18 25 | registry-url: https://registry.npmjs.org/ 26 | ############# TAG RELEASE ############## 27 | - name: Tag release 28 | run: npm dist-tag add axios@${{ github.event.inputs.version }} ${{ github.event.inputs.tag }} 29 | env: 30 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 31 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: Release PR 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | type: 6 | type: choice 7 | description: Choose release type 8 | options: 9 | - auto 10 | - patch 11 | - minor 12 | - major 13 | default: auto 14 | beta: 15 | type: boolean 16 | description: Prerelease 17 | default: false 18 | jobs: 19 | releaseIt: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: git config 26 | run: | 27 | git config user.name "${GITHUB_ACTOR}" 28 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 29 | - name: Setup node 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: 16 33 | cache: npm 34 | - run: npm ci 35 | - name: Prepare release 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | TYPE_ARG: ${{ fromJSON('{"auto":"", "patch":"patch", "minor":"minor", "major":"major"}')[github.event.inputs.type] }} 39 | BETA_ARG: ${{ github.event.inputs.beta == 'true' && '--preRelease=beta' || '' }} 40 | run: npm run release -- $TYPE_ARG --ci --verbose --no-git.push --no-git.commit --no-git.tag --no-github $BETA_ARG $DRY_ARG 41 | - name: Show git status 42 | if: failure() 43 | run: git status && git diff 44 | - name: Add contributors list to CHANGELOG.md 45 | run: npm run release:changelog:fix 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | - name: get-npm-version 49 | id: package-version 50 | uses: martinbeentjes/npm-get-version-action@main 51 | - name: Extract release notes 52 | id: extract-release-notes 53 | uses: ffurrer2/extract-release-notes@v2 54 | - name: Generate PR body 55 | id: body 56 | uses: mathiasvr/command-output@v1 57 | with: 58 | run: node ./bin/pr.js 59 | - name: Create pull request 60 | uses: peter-evans/create-pull-request@v7 61 | id: cpr 62 | with: 63 | branch: release 64 | delete-branch: true 65 | commit-message: 'chore(release): v${{ steps.package-version.outputs.current-version}}' 66 | title: '[Release] v${{ steps.package-version.outputs.current-version}}' 67 | body: | 68 | ${{ steps.body.outputs.stdout }} 69 | ## Release notes: 70 | ${{ steps.extract-release-notes.outputs.release_notes }} 71 | labels: | 72 | release 73 | automated pr 74 | signoff: false 75 | #team-reviewers: | 76 | # owners 77 | # maintainers 78 | #assignees: jasonsaayman 79 | #reviewers: jasonsaayman 80 | draft: false 81 | - name: Show PR link 82 | if: ${{ steps.cpr.outputs.pull-request-url }} 83 | run: | 84 | echo "Axios Release v${{ steps.package-version.outputs.current-version}}' pull request - ${{ steps.cpr.outputs.pull-request-url }}" 85 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | pull_request: 4 | types: 5 | - closed 6 | branches: 7 | - main 8 | - 'v**' 9 | workflow_dispatch: 10 | jobs: 11 | publish: 12 | if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && github.event.pull_request.head.label == 'axios:release') 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | id-token: write 17 | steps: 18 | - name: "Release PR info" 19 | if: github.event_name != 'workflow_dispatch' 20 | run: echo "PR ${{ github.event.number }}" 21 | - uses: actions/checkout@v4 22 | - name: git config 23 | run: | 24 | git config user.name "${GITHUB_ACTOR}" 25 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 26 | - uses: actions/setup-node@v4 27 | with: 28 | node-version: 18 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - name: get-npm-version 32 | id: package-version 33 | uses: martinbeentjes/npm-get-version-action@main 34 | - name: Extract release notes 35 | id: extract-release-notes 36 | uses: ffurrer2/extract-release-notes@v2 37 | - name: Check versions 38 | run: node ./bin/check-build-version.js 39 | ############# TAG RELEASE ############## 40 | - name: "Push tag v${{ steps.package-version.outputs.current-version }}" 41 | uses: rickstaa/action-create-tag@v1 42 | id: tag_version 43 | with: 44 | tag: "v${{ steps.package-version.outputs.current-version }}" 45 | ############# RESOLVE NPM TAG ############## 46 | - name: NPM TAG 47 | id: 'npm_tag' 48 | run: node ./bin/resolveNPMTag.js 49 | ############# GITHUB RELEASE ############## 50 | - name: "Create a GitHub release v${{ steps.package-version.outputs.current-version }}" 51 | uses: ncipollo/release-action@v1 52 | with: 53 | tag: "v${{ steps.package-version.outputs.current-version }}" 54 | name: "Release v${{ steps.package-version.outputs.current-version }}" 55 | body: | 56 | ## Release notes: 57 | ${{ steps.extract-release-notes.outputs.release_notes }} 58 | ############# NPM RELEASE ############## 59 | - name: Publish the release to NPM 60 | run: npm publish --provenance --access public --tag ${{ steps.npm_tag.outputs.tag || 'latest' }} 61 | env: 62 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 63 | notify: 64 | needs: [publish] 65 | runs-on: ubuntu-latest 66 | steps: 67 | - uses: actions/checkout@v4 68 | with: 69 | fetch-depth: 0 70 | - name: git config 71 | run: | 72 | git config user.name "${GITHUB_ACTOR}" 73 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 74 | - name: Setup node 75 | uses: actions/setup-node@v4 76 | with: 77 | node-version: 18 78 | cache: npm 79 | - run: npm ci 80 | ############# Add release comments and tags to published PRs ############## 81 | - name: Notify published PRs 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | run: node ./bin/actions/notify_published.js --tag ${{ github.event.inputs.tag || github.event.release.tag_name }} 85 | -------------------------------------------------------------------------------- /.github/workflows/sponsors.yml: -------------------------------------------------------------------------------- 1 | name: Update Readme sponsor list 2 | on: 3 | workflow_dispatch: 4 | repository_dispatch: 5 | types: 6 | - webhook 7 | schedule: 8 | # Run at 0000 daily 9 | - cron: '0 1 * * *' 10 | jobs: 11 | sponsors: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - name: git config 18 | run: | 19 | git config user.name "${GITHUB_ACTOR}" 20 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 21 | - name: Setup node 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: 16 25 | cache: npm 26 | - run: npm ci 27 | - name: Check sponsors updates 28 | id: sponsors 29 | run: node ./bin/sponsors.js 30 | - name: Notify status 31 | if: ${{ steps.sponsors.outputs.changed == 'true'}} 32 | run: | 33 | echo "Sponsor block has changed. Creating PR with updates..." 34 | - name: Read sponsors.md file content 35 | if: ${{ steps.sponsors.outputs.changed == 'true'}} 36 | id: read_file 37 | run: | 38 | echo 'CONTENT<> $GITHUB_ENV 39 | cat ./temp/sponsors.md >> $GITHUB_ENV 40 | echo 'EOF' >> $GITHUB_ENV 41 | shell: bash 42 | - name: Echo 43 | run: | 44 | echo "$CONTENT" 45 | - name: Create pull request 46 | if: ${{ steps.sponsors.outputs.changed == 'true'}} 47 | uses: peter-evans/create-pull-request@v7 48 | id: cpr 49 | with: 50 | branch: sponsors 51 | delete-branch: true 52 | commit-message: 'chore(sponsor): update sponsor block' 53 | title: '[Chore] Update sponsor block' 54 | body: | 55 | **New sponsor block update:** 56 | ${{ env.CONTENT }} 57 | labels: | 58 | readme 59 | automated pr 60 | automerge 61 | signoff: false 62 | #team-reviewers: | 63 | # owners 64 | # maintainers 65 | #assignees: jasonsaayman 66 | #reviewers: jasonsaayman 67 | draft: false 68 | - name: Show PR link 69 | if: ${{ steps.sponsors.outputs.changed == 'true'}} 70 | run: | 71 | echo "Sponsor block has changed. Creating PR..." 72 | echo "Axios Release v${{ steps.package-version.outputs.current-version}}' pull request - ${{ steps.cpr.outputs.pull-request-url }}" 73 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Close Stale' 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 1' 6 | 7 | jobs: 8 | stale: 9 | permissions: 10 | issues: write # for actions/stale to close stale issues 11 | pull-requests: write # for actions/stale to close stale PRs 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Close Stale Issues 15 | uses: actions/stale@v9 16 | with: 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | stale-issue-message: | 19 | Hello! :wave: 20 | 21 | This issue is being automatically marked as stale because it has not been updated in a while. Please confirm that the issue is still present and reproducible. If no updates or new comments are received the issue will be closed in a few days. 22 | 23 | Thanks. 24 | stale-pr-message: | 25 | Hello! :wave: 26 | 27 | This pull request is being automatically marked as stale because it has not been updated in a while. Please confirm that the issue is still present and reproducible. If no updates or new comments are received the pull request will be closed in a few days. 28 | 29 | Thanks. 30 | stale-issue-label: 'status:stale' 31 | stale-pr-label: 'status:stale' 32 | only-labels: 'status:more info needed' 33 | days-before-stale: 30 34 | days-before-close: 14 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .tscache 4 | .DS_Store 5 | node_modules/ 6 | coverage/ 7 | temp/ 8 | test/typescript/axios.js* 9 | sauce_connect.log 10 | test/module/**/package-lock.json 11 | backup/ 12 | /.husky/ 13 | .npmrc 14 | .env 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | **/* 2 | !/dist/** 3 | !/lib/** 4 | !index.js 5 | !index.d.ts 6 | !index.d.cts 7 | !CHANGELOG.md 8 | !LICENSE 9 | !MIGRATION_GUIDE.md 10 | !README.md 11 | -------------------------------------------------------------------------------- /COLLABORATOR_GUIDE.md: -------------------------------------------------------------------------------- 1 | # Collaborator Guide 2 | 3 | As a collaborator, you will be involved with axios with some administrative responsibilities. This guide will help you understand your role and the responsibilities that come with being a collaborator. 4 | 5 | 1. __Adhere to and help enforce the Code of Conduct.__ It is expected that you have read the [code of conduct](https://github.com/axios/axios/blob/master/CODE_OF_CONDUCT.md) and that you agree to live by it. This community should be friendly and welcoming. 6 | 7 | 1. __Triage issues.__ As a collaborator, you may help sort through the issues that are reported. Issues vary from bugs, regressions, feature requests, questions, etc. Apply the appropriate label(s) and respond as needed. If it is a legitimate request, please address it, otherwise feel free to close the issue and include a comment with a suggestion on where to find support. If an issue has been inactive for more than a week (i.e., the owner of the issue hasn’t responded to you), close the issue with a note indicating stale issues are closed; it can always be reopened if needed. In the case of issues that require a code change, encourage the owner to submit a PR. For less complex code changes, add a very simple and detailed checklist, apply the “first-timers-only” label, and encourage a newcomer to open source to get involved. 8 | 9 | 1. __Answer questions.__ It is not expected that you provide answers to questions that aren’t relevant, nor do you need to mentor people on how to use JavaScript, etc. If the question is not directly about the module, please close the issue. If the question stems from poor documentation, please update the docs and consider adding a code example. In any event try to be helpful and remember that there’s no such thing as a stupid question. 10 | 11 | 1. __Assist with PRs.__ By encouraging contributors to supply a PR for their own issue this is ideally where most of your attention will be focused. Keep a few things in mind as you review PRs. 12 | 13 | - When fixing a bug: does the PR adequately solve the problem without introducing any regressions? 14 | - When implementing a feature: does the feature fit within the scope of axios? 15 | - When removing functionality: is it properly deprecated with a warning? 16 | - When introducing functionality: is the API predictable? 17 | - Does the new code work for all supported platforms/browsers? 18 | - Do the tests and linting pass CI? 19 | - Are there tests to validate the changes that have been made? 20 | 21 | 1. __Fix bugs and implement features.__ When things need to be fixed or implemented, and a PR can’t wait, you may do things yourself. You should still submit a PR yourself and get it checked off by at least one other contributor. Keep the points from number 4 in consideration as you push your code. 22 | 23 | Thank you again for your help as a collaborator and in making axios community great! If you have any questions or need any assistance, please feel free to contact another collaborator or the owner. 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We are open to, and grateful for, any contributions made by the community. By contributing to axios, you agree to abide by the [code of conduct](https://github.com/axios/axios/blob/master/CODE_OF_CONDUCT.md). 4 | 5 | ## Code Style 6 | 7 | Please follow the [node style guide](https://github.com/felixge/node-style-guide). 8 | 9 | ## Commit Messages 10 | 11 | Please follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) 12 | 13 | ## Testing 14 | 15 | Please update the tests to reflect your code changes. Pull requests will not be accepted if they are failing on GitHub actions. 16 | 17 | ## Documentation 18 | 19 | Please update the [docs](README.md) accordingly so that there are no discrepancies between the API and the documentation. 20 | 21 | ## Developing 22 | 23 | - `npm run test` run the jasmine and mocha tests 24 | - `npm run build` run rollup and bundle the source 25 | - `npm run version` prepare the code for release 26 | 27 | Please don't include changes to `dist/` in your pull request. This should only be updated when releasing a new version. 28 | 29 | ## Running Examples 30 | 31 | Examples are included in part to allow manual testing. 32 | 33 | Running example 34 | 35 | ```bash 36 | > npm run examples 37 | # Open 127.0.0.1:3000 38 | ``` 39 | 40 | Running sandbox in browser 41 | 42 | ```bash 43 | > npm start 44 | # Open 127.0.0.1:3000 45 | ``` 46 | 47 | Running sandbox in terminal 48 | 49 | ```bash 50 | > npm start 51 | > node ./sandbox/client 52 | ``` 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014-present Matt Zabriskie & Collaborators 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /MIGRATION_GUIDE.md: -------------------------------------------------------------------------------- 1 | # Migration Guide 2 | 3 | ## 0.x.x -> 1.1.0 4 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | The following versions will receive security updates promptly based on the maintainers' discretion. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 0.x.x | :white_check_mark: | 10 | | 1.x.x | :white_check_mark: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | To report a vulnerability, please use the GitHub discolsure in the security tab to alert us to a security issue. 15 | -------------------------------------------------------------------------------- /bin/actions/notify_published.js: -------------------------------------------------------------------------------- 1 | import minimist from "minimist"; 2 | import RepoBot from '../RepoBot.js'; 3 | import fs from 'fs/promises'; 4 | 5 | const argv = minimist(process.argv.slice(2)); 6 | console.log(argv); 7 | 8 | let {tag} = argv; 9 | 10 | (async() => { 11 | if (!tag || tag === true) { 12 | const {version} = JSON.parse((await fs.readFile('./package.json')).toString()); 13 | 14 | tag = 'v' + version; 15 | } else if (typeof tag !== 'string') { 16 | 17 | throw new Error('tag must be a string'); 18 | } 19 | 20 | const bot = new RepoBot(); 21 | 22 | try { 23 | await bot.notifyPublishedPRs(tag); 24 | } catch (err) { 25 | console.warn('Error:', err.message); 26 | } 27 | })(); 28 | 29 | -------------------------------------------------------------------------------- /bin/api.js: -------------------------------------------------------------------------------- 1 | import GithubAPI from "./GithubAPI.js"; 2 | 3 | export default new GithubAPI('axios', 'axios'); 4 | -------------------------------------------------------------------------------- /bin/check-build-version.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import assert from 'assert'; 3 | import axios from '../index.js'; 4 | import axiosBuild from '../dist/node/axios.cjs'; 5 | 6 | const {version} = JSON.parse(fs.readFileSync('./package.json')); 7 | 8 | console.log('Checking versions...\n----------------------------') 9 | 10 | console.log(`Package version: v${version}`); 11 | console.log(`Axios version: v${axios.VERSION}`); 12 | console.log(`Axios build version: v${axiosBuild.VERSION}`); 13 | console.log(`----------------------------`); 14 | 15 | assert.strictEqual( 16 | version, 17 | axios.VERSION, 18 | `Version mismatch between package and Axios ${version} != ${axios.VERSION}` 19 | ); 20 | 21 | assert.strictEqual( 22 | version, 23 | axiosBuild.VERSION, 24 | `Version mismatch between package and build ${version} != ${axiosBuild.VERSION}` 25 | ); 26 | 27 | console.log('✔️ PASSED\n'); 28 | 29 | 30 | -------------------------------------------------------------------------------- /bin/githubAxios.js: -------------------------------------------------------------------------------- 1 | import axios from '../index.js'; 2 | import {colorize} from "./helpers/colorize.js"; 3 | 4 | const {GITHUB_TOKEN} = process.env; 5 | 6 | GITHUB_TOKEN ? console.log(`[GITHUB_TOKEN OK]`) : console.warn(`[GITHUB_TOKEN is not defined]`); 7 | 8 | const defaultTransform = axios.defaults.transformRequest; 9 | 10 | export default axios.create({ 11 | transformRequest: [defaultTransform[0], function (data) { 12 | console.log(colorize()`[${this.method.toUpperCase()}] Request [${new URL(axios.getUri(this)).pathname}]`); 13 | return data; 14 | }], 15 | baseURL: 'https://api.github.com/', 16 | headers: { 17 | Authorization: GITHUB_TOKEN ? `token ${GITHUB_TOKEN}` : null 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /bin/helpers/colorize.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | export const colorize = (...colors)=> { 4 | if(!colors.length) { 5 | colors = ['green', 'cyan', 'magenta', 'blue', 'yellow', 'red']; 6 | } 7 | 8 | const colorsCount = colors.length; 9 | 10 | return (strings, ...values) => { 11 | const {length} = values; 12 | return strings.map((str, i) => i < length ? str + chalk[colors[i%colorsCount]].bold(values[i]) : str).join(''); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bin/helpers/parser.js: -------------------------------------------------------------------------------- 1 | export const matchAll = (text, regexp, cb) => { 2 | let match; 3 | while((match = regexp.exec(text))) { 4 | cb(match); 5 | } 6 | } 7 | 8 | export const parseSection = (body, name, cb) => { 9 | matchAll(body, new RegExp(`^(#+)\\s+${name}?(.*?)^\\1\\s+\\w+`, 'gims'), cb); 10 | } 11 | 12 | export const parseVersion = (rawVersion) => /^v?(\d+).(\d+).(\d+)/.exec(rawVersion); 13 | -------------------------------------------------------------------------------- /bin/injectContributorsList.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs/promises'; 2 | import path from 'path'; 3 | import {renderContributorsList, getTagRef, renderPRsList} from './contributors.js'; 4 | import asyncReplace from 'string-replace-async'; 5 | import {fileURLToPath} from "url"; 6 | import {colorize} from "./helpers/colorize.js"; 7 | 8 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 9 | 10 | const CONTRIBUTORS_TEMPLATE = path.resolve(__dirname, '../templates/contributors.hbs'); 11 | const PRS_TEMPLATE = path.resolve(__dirname, '../templates/prs.hbs'); 12 | 13 | const injectSection = async (name, contributorsRE, injector, infile = '../CHANGELOG.md') => { 14 | console.log(colorize()`Checking ${name} sections in ${infile}`); 15 | 16 | infile = path.resolve(__dirname, infile); 17 | 18 | const content = String(await fs.readFile(infile)); 19 | const headerRE = /^#+\s+\[([-_\d.\w]+)].+?$/mig; 20 | 21 | let tag; 22 | let index = 0; 23 | let isFirstTag = true; 24 | 25 | const newContent = await asyncReplace(content, headerRE, async (match, nextTag, offset) => { 26 | const releaseContent = content.slice(index, offset); 27 | 28 | const hasSection = contributorsRE.test(releaseContent); 29 | 30 | const currentTag = tag; 31 | 32 | tag = nextTag; 33 | index = offset + match.length; 34 | 35 | if(currentTag) { 36 | if (hasSection) { 37 | console.log(colorize()`[${currentTag}]: ✓ OK`); 38 | } else { 39 | const target = isFirstTag && (!await getTagRef(currentTag)) ? '' : currentTag; 40 | 41 | console.log(colorize()`[${currentTag}]: ❌ MISSED` + (!target ? ' (UNRELEASED)' : '')); 42 | 43 | isFirstTag = false; 44 | 45 | console.log(`Generating section...`); 46 | 47 | const section = await injector(target); 48 | 49 | if (!section) { 50 | return match; 51 | } 52 | 53 | console.log(colorize()`\nRENDERED SECTION [${name}] for [${currentTag}]:`); 54 | console.log('-------------BEGIN--------------\n'); 55 | console.log(section); 56 | console.log('--------------END---------------\n'); 57 | 58 | return section + '\n' + match; 59 | } 60 | } 61 | 62 | return match; 63 | }); 64 | 65 | await fs.writeFile(infile, newContent); 66 | } 67 | 68 | await injectSection( 69 | 'PRs', 70 | /^\s*### PRs/mi, 71 | (tag) => tag ? '' : renderPRsList(tag, PRS_TEMPLATE, {awesome_threshold: 5, comments_threshold: 7}), 72 | ); 73 | 74 | await injectSection( 75 | 'contributors', 76 | /^\s*### Contributors/mi, 77 | (tag) => renderContributorsList(tag, CONTRIBUTORS_TEMPLATE) 78 | ); 79 | -------------------------------------------------------------------------------- /bin/pr.js: -------------------------------------------------------------------------------- 1 | import Handlebars from "handlebars"; 2 | import fs from "fs/promises"; 3 | import prettyBytes from 'pretty-bytes'; 4 | import {gzipSize} from 'gzip-size'; 5 | import {getBlobHistory} from './repo.js'; 6 | 7 | const generateFileReport = async (files) => { 8 | const stat = {}; 9 | 10 | for(const [name, file] of Object.entries(files)) { 11 | const commits = await getBlobHistory(file); 12 | 13 | stat[file] = { 14 | name, 15 | size: (await fs.stat(file)).size, 16 | path: file, 17 | gzip: await gzipSize(String(await fs.readFile(file))), 18 | commits, 19 | history: commits.map(({tag, size}) => `${prettyBytes(size)} (${tag})`).join(' ← ') 20 | } 21 | } 22 | 23 | return stat; 24 | } 25 | 26 | const generateBody = async ({files, template = './templates/pr.hbs'} = {}) => { 27 | const data = { 28 | files: await generateFileReport(files) 29 | }; 30 | 31 | Handlebars.registerHelper('filesize', (bytes)=> prettyBytes(bytes)); 32 | 33 | return Handlebars.compile(String(await fs.readFile(template)))(data); 34 | } 35 | 36 | console.log(await generateBody({ 37 | files: { 38 | 'Browser build (UMD)' : './dist/axios.min.js', 39 | 'Browser build (ESM)' : './dist/esm/axios.min.js', 40 | } 41 | })); 42 | 43 | -------------------------------------------------------------------------------- /bin/repo.js: -------------------------------------------------------------------------------- 1 | import util from "util"; 2 | import cp from "child_process"; 3 | 4 | export const exec = util.promisify(cp.exec); 5 | 6 | export const getBlobSize = async (filepath, sha ='HEAD') => { 7 | const size = (await exec( 8 | `git cat-file -s ${sha}:${filepath}` 9 | )).stdout; 10 | 11 | return size ? +size : 0; 12 | } 13 | 14 | export const getBlobHistory = async (filepath, maxCount= 5) => { 15 | const log = (await exec( 16 | `git log --max-count=${maxCount} --no-walk --tags=v* --oneline --format=%H%d -- ${filepath}` 17 | )).stdout; 18 | 19 | const commits = []; 20 | 21 | let match; 22 | 23 | const regexp = /^(\w+) \(tag: (v?[.\d]+)\)$/gm; 24 | 25 | while((match = regexp.exec(log))) { 26 | commits.push({ 27 | sha: match[1], 28 | tag: match[2], 29 | size: await getBlobSize(filepath, match[1]) 30 | }) 31 | } 32 | 33 | return commits; 34 | } 35 | 36 | export const getTags = async (pattern = 'v*', sort = '-v:refname') => { 37 | const log = (await exec( 38 | `git tag -l ${pattern} --sort=${sort}` 39 | )).stdout; 40 | 41 | return log.split(/\r?\n/); 42 | } 43 | -------------------------------------------------------------------------------- /bin/resolveNPMTag.js: -------------------------------------------------------------------------------- 1 | import {exec, getTags} from "./repo.js"; 2 | import fs from "fs"; 3 | import {colorize} from "./helpers/colorize.js"; 4 | 5 | const {version} = JSON.parse(fs.readFileSync('./package.json')); 6 | 7 | const [major] = version.split('.'); 8 | const tags = await getTags(); 9 | const latestTag = (tags[0] || '').replace(/^v/, ''); 10 | 11 | const isBeta = !/^v?(\d+).(\d)+.(\d)+$/.test(version); 12 | const isLatest = latestTag === version; 13 | 14 | let tag = isBeta ? 'next' : isLatest ? 'latest' : `v${major}`; 15 | 16 | console.log(colorize()`Version [${version}] [${isBeta ? 'prerelease' : 'release'}] latest [${latestTag}]=> NPM Tag [${tag}]`); 17 | 18 | await exec(`echo "tag=${tag}" >> $GITHUB_OUTPUT`); 19 | -------------------------------------------------------------------------------- /bin/sponsors.js: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises"; 2 | import _axios from '../index.js'; 3 | import {exec} from "./repo.js"; 4 | import {colorize} from "./helpers/colorize.js"; 5 | 6 | const axios = _axios.create({ 7 | headers: { 8 | "User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' 9 | } 10 | }); 11 | 12 | const getWithRetry = (url, retries = 3) => { 13 | let counter = 0; 14 | const doRequest = async () => { 15 | try { 16 | return await axios.get(url) 17 | } catch (err) { 18 | if (counter++ >= retries) { 19 | throw err; 20 | } 21 | await new Promise(resolve => setTimeout(resolve, counter ** counter * 1000)); 22 | return doRequest(); 23 | } 24 | } 25 | 26 | return doRequest(); 27 | }; 28 | 29 | const updateReadmeSponsors = async (url, path, marker = '') => { 30 | let fileContent = (await fs.readFile(path)).toString(); 31 | 32 | const index = fileContent.indexOf(marker); 33 | 34 | if(index >= 0) { 35 | const readmeContent = fileContent.slice(index); 36 | 37 | let {data: sponsorContent} = await getWithRetry(url); 38 | sponsorContent += '\n'; 39 | 40 | const currentSponsorContent = fileContent.slice(0, index); 41 | 42 | if (currentSponsorContent !== sponsorContent) { 43 | console.log(colorize()`Sponsor block in [${path}] is outdated`); 44 | await fs.writeFile(path, sponsorContent + readmeContent); 45 | return sponsorContent; 46 | } else { 47 | console.log(colorize()`Sponsor block in [${path}] is up to date`); 48 | } 49 | } else { 50 | console.warn(colorize()`Can not find marker (${marker}) in ${path} to inject sponsor block`); 51 | } 52 | 53 | return false; 54 | }; 55 | 56 | (async(url) => { 57 | const newContent = await updateReadmeSponsors(url, './README.md'); 58 | 59 | await exec(`echo "changed=${newContent ? 'true' : 'false'}" >> $GITHUB_OUTPUT`); 60 | if (newContent !== false) { 61 | await fs.mkdir('./temp').catch(() => {}); 62 | await fs.writeFile('./temp/sponsors.md', newContent); 63 | } 64 | })('https://axios-http.com/data/sponsors.md'); 65 | -------------------------------------------------------------------------------- /bin/ssl_hotfix.js: -------------------------------------------------------------------------------- 1 | import {spawn} from 'child_process'; 2 | 3 | const args = process.argv.slice(2); 4 | 5 | console.log(`Running ${args.join(' ')} on ${process.version}\n`); 6 | 7 | const match = /v(\d+)/.exec(process.version); 8 | 9 | const isHotfixNeeded = match && match[1] > 16; 10 | 11 | isHotfixNeeded && console.warn('Setting --openssl-legacy-provider as ssl hotfix'); 12 | 13 | const test = spawn('cross-env', 14 | isHotfixNeeded ? ['NODE_OPTIONS=--openssl-legacy-provider', ...args] : args, { 15 | shell: true, 16 | stdio: 'inherit' 17 | } 18 | ); 19 | 20 | test.on('exit', function (code) { 21 | process.exit(code) 22 | }) 23 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axios", 3 | "main": "./dist/axios.js", 4 | "version": "1.8.4", 5 | "homepage": "https://axios-http.com", 6 | "authors": [ 7 | "Matt Zabriskie" 8 | ], 9 | "description": "Promise based HTTP client for the browser and node.js", 10 | "moduleType": [ 11 | "amd", 12 | "globals" 13 | ], 14 | "keywords": [ 15 | "xhr", 16 | "http", 17 | "ajax", 18 | "promise", 19 | "node" 20 | ], 21 | "license": "MIT", 22 | "ignore": [ 23 | "**/.*", 24 | "*.iml", 25 | "examples", 26 | "lib", 27 | "node_modules", 28 | "sandbox", 29 | "test", 30 | "CONTRIBUTING.md", 31 | "COOKBOOK.md", 32 | "Gruntfile.js", 33 | "index.js", 34 | "karma.conf.js", 35 | "package.json", 36 | "webpack.*.js" 37 | ] 38 | } -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # axios examples 2 | 3 | To run the examples: 4 | 5 | 1. `git clone https://github.com/axios/axios.git` 6 | 2. `cd axios` 7 | 3. `npm install` 8 | 4. `npm run build` 9 | 5. `npm run examples` 10 | 6. [http://localhost:3000](http://localhost:3000) -------------------------------------------------------------------------------- /examples/all/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios - all example 5 | 6 | 7 | 8 |

axios.all

9 | 10 |
11 |

User

12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 |

Orgs

20 | 21 |
22 | 23 | 24 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/amd/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AMD 5 | 6 | 7 | 8 |

AMD

9 | 10 |
11 |

User

12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 | 21 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/get/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios - get example 5 | 6 | 7 | 8 |

axios.get

9 | 10 | 11 | 12 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/get/server.js: -------------------------------------------------------------------------------- 1 | const people = [ 2 | { 3 | "name": "Matt Zabriskie", 4 | "github": "mzabriskie", 5 | "twitter": "mzabriskie", 6 | "avatar": "199035" 7 | }, 8 | { 9 | "name": "Ryan Florence", 10 | "github": "rpflorence", 11 | "twitter": "ryanflorence", 12 | "avatar": "100200" 13 | }, 14 | { 15 | "name": "Kent C. Dodds", 16 | "github": "kentcdodds", 17 | "twitter": "kentcdodds", 18 | "avatar": "1500684" 19 | }, 20 | { 21 | "name": "Chris Esplin", 22 | "github": "deltaepsilon", 23 | "twitter": "chrisesplin", 24 | "avatar": "878947" 25 | } 26 | ]; 27 | 28 | export default function (req, res) { 29 | res.writeHead(200, { 30 | 'Content-Type': 'text/json' 31 | }); 32 | res.write(JSON.stringify(people)); 33 | res.end(); 34 | }; 35 | -------------------------------------------------------------------------------- /examples/post/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios - post example 5 | 6 | 7 | 8 |

axios.post

9 | 10 |
11 |
12 | 13 | 14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/post/server.js: -------------------------------------------------------------------------------- 1 | export default function (req, res) { 2 | let data = ''; 3 | 4 | req.on('data', function (chunk) { 5 | data += chunk; 6 | }); 7 | 8 | req.on('end', function () { 9 | console.log('POST data received'); 10 | res.writeHead(200, { 11 | 'Content-Type': 'text/json' 12 | }); 13 | res.write(JSON.stringify(data)); 14 | res.end(); 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /examples/postMultipartFormData/server.js: -------------------------------------------------------------------------------- 1 | export default function (req, res) { 2 | 3 | req.on('data', function (chunk) { 4 | }); 5 | 6 | req.on('end', function () { 7 | console.log('POST received'); 8 | res.writeHead(200, { 9 | 'Content-Type': 'text/json' 10 | }); 11 | res.end(); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /examples/transform-response/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios - transform response example 5 | 6 | 7 | 8 |

transformResponse

9 | 10 |
11 | 12 |
13 |
14 | Created:
15 | Updated: 16 |
17 |
18 | 19 | 20 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/upload/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios - file upload example 5 | 6 | 7 | 8 |

file upload

9 | 10 |
11 |
12 | 13 | 14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples/upload/server.js: -------------------------------------------------------------------------------- 1 | export default function (req, res) { 2 | let data = ''; 3 | 4 | req.on('data', function (chunk) { 5 | data += chunk; 6 | }); 7 | 8 | req.on('end', function () { 9 | console.log('File uploaded'); 10 | res.writeHead(200); 11 | res.end(); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import fs from 'fs-extra'; 3 | import axios from './bin/githubAxios.js'; 4 | import minimist from 'minimist' 5 | 6 | const argv = minimist(process.argv.slice(2)); 7 | 8 | gulp.task('default', async function(){ 9 | console.log('hello!'); 10 | }); 11 | 12 | const clear = gulp.task('clear', async function() { 13 | await fs.emptyDir('./dist/') 14 | }); 15 | 16 | const bower = gulp.task('bower', async function () { 17 | const npm = JSON.parse(await fs.readFile('package.json')); 18 | const bower = JSON.parse(await fs.readFile('bower.json')); 19 | 20 | const fields = [ 21 | 'name', 22 | 'description', 23 | 'version', 24 | 'homepage', 25 | 'license', 26 | 'keywords' 27 | ]; 28 | 29 | for (let i = 0, l = fields.length; i < l; i++) { 30 | const field = fields[i]; 31 | bower[field] = npm[field]; 32 | } 33 | 34 | await fs.writeFile('bower.json', JSON.stringify(bower, null, 2)); 35 | }); 36 | 37 | async function getContributors(user, repo, maxCount = 1) { 38 | const contributors = (await axios.get( 39 | `https://api.github.com/repos/${encodeURIComponent(user)}/${encodeURIComponent(repo)}/contributors`, 40 | { params: { per_page: maxCount } } 41 | )).data; 42 | 43 | return Promise.all(contributors.map(async (contributor)=> { 44 | return {...contributor, ...(await axios.get( 45 | `https://api.github.com/users/${encodeURIComponent(contributor.login)}` 46 | )).data}; 47 | })) 48 | } 49 | 50 | const packageJSON = gulp.task('package', async function () { 51 | const CONTRIBUTION_THRESHOLD = 3; 52 | 53 | const npm = JSON.parse(await fs.readFile('package.json')); 54 | 55 | try { 56 | const contributors = await getContributors('axios', 'axios', 15); 57 | 58 | npm.contributors = contributors 59 | .filter( 60 | ({type, contributions}) => type.toLowerCase() === 'user' && contributions >= CONTRIBUTION_THRESHOLD 61 | ) 62 | .map(({login, name, url}) => `${name || login} (https://github.com/${login})`); 63 | 64 | await fs.writeFile('package.json', JSON.stringify(npm, null, 2)); 65 | } catch (err) { 66 | if (axios.isAxiosError(err) && err.response && err.response.status === 403) { 67 | throw Error(`GitHub API Error: ${err.response.data && err.response.data.message}`); 68 | } 69 | throw err; 70 | } 71 | }); 72 | 73 | const env = gulp.task('env', async function () { 74 | var npm = JSON.parse(await fs.readFile('package.json')); 75 | 76 | const envFilePath = './lib/env/data.js'; 77 | 78 | await fs.writeFile(envFilePath, Object.entries({ 79 | VERSION: (argv.bump || npm.version).replace(/^v/, '') 80 | }).map(([key, value]) => { 81 | return `export const ${key} = ${JSON.stringify(value)};` 82 | }).join('\n')); 83 | }); 84 | 85 | const version = gulp.series('bower', 'env', 'package'); 86 | 87 | export { 88 | bower, 89 | env, 90 | clear, 91 | version, 92 | packageJSON 93 | } 94 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import axios from './lib/axios.js'; 2 | 3 | // This module is intended to unwrap Axios default export as named. 4 | // Keep top-level export same with static properties 5 | // so that it can keep same with es module or cjs 6 | const { 7 | Axios, 8 | AxiosError, 9 | CanceledError, 10 | isCancel, 11 | CancelToken, 12 | VERSION, 13 | all, 14 | Cancel, 15 | isAxiosError, 16 | spread, 17 | toFormData, 18 | AxiosHeaders, 19 | HttpStatusCode, 20 | formToJSON, 21 | getAdapter, 22 | mergeConfig 23 | } = axios; 24 | 25 | export { 26 | axios as default, 27 | Axios, 28 | AxiosError, 29 | CanceledError, 30 | isCancel, 31 | CancelToken, 32 | VERSION, 33 | all, 34 | Cancel, 35 | isAxiosError, 36 | spread, 37 | toFormData, 38 | AxiosHeaders, 39 | HttpStatusCode, 40 | formToJSON, 41 | getAdapter, 42 | mergeConfig 43 | } 44 | -------------------------------------------------------------------------------- /lib/adapters/README.md: -------------------------------------------------------------------------------- 1 | # axios // adapters 2 | 3 | The modules under `adapters/` are modules that handle dispatching a request and settling a returned `Promise` once a response is received. 4 | 5 | ## Example 6 | 7 | ```js 8 | var settle = require('./../core/settle'); 9 | 10 | module.exports = function myAdapter(config) { 11 | // At this point: 12 | // - config has been merged with defaults 13 | // - request transformers have already run 14 | // - request interceptors have already run 15 | 16 | // Make the request using config provided 17 | // Upon response settle the Promise 18 | 19 | return new Promise(function(resolve, reject) { 20 | 21 | var response = { 22 | data: responseData, 23 | status: request.status, 24 | statusText: request.statusText, 25 | headers: responseHeaders, 26 | config: config, 27 | request: request 28 | }; 29 | 30 | settle(resolve, reject, response); 31 | 32 | // From here: 33 | // - response transformers will run 34 | // - response interceptors will run 35 | }); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /lib/adapters/adapters.js: -------------------------------------------------------------------------------- 1 | import utils from '../utils.js'; 2 | import httpAdapter from './http.js'; 3 | import xhrAdapter from './xhr.js'; 4 | import fetchAdapter from './fetch.js'; 5 | import AxiosError from "../core/AxiosError.js"; 6 | 7 | const knownAdapters = { 8 | http: httpAdapter, 9 | xhr: xhrAdapter, 10 | fetch: fetchAdapter 11 | } 12 | 13 | utils.forEach(knownAdapters, (fn, value) => { 14 | if (fn) { 15 | try { 16 | Object.defineProperty(fn, 'name', {value}); 17 | } catch (e) { 18 | // eslint-disable-next-line no-empty 19 | } 20 | Object.defineProperty(fn, 'adapterName', {value}); 21 | } 22 | }); 23 | 24 | const renderReason = (reason) => `- ${reason}`; 25 | 26 | const isResolvedHandle = (adapter) => utils.isFunction(adapter) || adapter === null || adapter === false; 27 | 28 | export default { 29 | getAdapter: (adapters) => { 30 | adapters = utils.isArray(adapters) ? adapters : [adapters]; 31 | 32 | const {length} = adapters; 33 | let nameOrAdapter; 34 | let adapter; 35 | 36 | const rejectedReasons = {}; 37 | 38 | for (let i = 0; i < length; i++) { 39 | nameOrAdapter = adapters[i]; 40 | let id; 41 | 42 | adapter = nameOrAdapter; 43 | 44 | if (!isResolvedHandle(nameOrAdapter)) { 45 | adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; 46 | 47 | if (adapter === undefined) { 48 | throw new AxiosError(`Unknown adapter '${id}'`); 49 | } 50 | } 51 | 52 | if (adapter) { 53 | break; 54 | } 55 | 56 | rejectedReasons[id || '#' + i] = adapter; 57 | } 58 | 59 | if (!adapter) { 60 | 61 | const reasons = Object.entries(rejectedReasons) 62 | .map(([id, state]) => `adapter ${id} ` + 63 | (state === false ? 'is not supported by the environment' : 'is not available in the build') 64 | ); 65 | 66 | let s = length ? 67 | (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) : 68 | 'as no adapter specified'; 69 | 70 | throw new AxiosError( 71 | `There is no suitable adapter to dispatch the request ` + s, 72 | 'ERR_NOT_SUPPORT' 73 | ); 74 | } 75 | 76 | return adapter; 77 | }, 78 | adapters: knownAdapters 79 | } 80 | -------------------------------------------------------------------------------- /lib/axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from './utils.js'; 4 | import bind from './helpers/bind.js'; 5 | import Axios from './core/Axios.js'; 6 | import mergeConfig from './core/mergeConfig.js'; 7 | import defaults from './defaults/index.js'; 8 | import formDataToJSON from './helpers/formDataToJSON.js'; 9 | import CanceledError from './cancel/CanceledError.js'; 10 | import CancelToken from './cancel/CancelToken.js'; 11 | import isCancel from './cancel/isCancel.js'; 12 | import {VERSION} from './env/data.js'; 13 | import toFormData from './helpers/toFormData.js'; 14 | import AxiosError from './core/AxiosError.js'; 15 | import spread from './helpers/spread.js'; 16 | import isAxiosError from './helpers/isAxiosError.js'; 17 | import AxiosHeaders from "./core/AxiosHeaders.js"; 18 | import adapters from './adapters/adapters.js'; 19 | import HttpStatusCode from './helpers/HttpStatusCode.js'; 20 | 21 | /** 22 | * Create an instance of Axios 23 | * 24 | * @param {Object} defaultConfig The default config for the instance 25 | * 26 | * @returns {Axios} A new instance of Axios 27 | */ 28 | function createInstance(defaultConfig) { 29 | const context = new Axios(defaultConfig); 30 | const instance = bind(Axios.prototype.request, context); 31 | 32 | // Copy axios.prototype to instance 33 | utils.extend(instance, Axios.prototype, context, {allOwnKeys: true}); 34 | 35 | // Copy context to instance 36 | utils.extend(instance, context, null, {allOwnKeys: true}); 37 | 38 | // Factory for creating new instances 39 | instance.create = function create(instanceConfig) { 40 | return createInstance(mergeConfig(defaultConfig, instanceConfig)); 41 | }; 42 | 43 | return instance; 44 | } 45 | 46 | // Create the default instance to be exported 47 | const axios = createInstance(defaults); 48 | 49 | // Expose Axios class to allow class inheritance 50 | axios.Axios = Axios; 51 | 52 | // Expose Cancel & CancelToken 53 | axios.CanceledError = CanceledError; 54 | axios.CancelToken = CancelToken; 55 | axios.isCancel = isCancel; 56 | axios.VERSION = VERSION; 57 | axios.toFormData = toFormData; 58 | 59 | // Expose AxiosError class 60 | axios.AxiosError = AxiosError; 61 | 62 | // alias for CanceledError for backward compatibility 63 | axios.Cancel = axios.CanceledError; 64 | 65 | // Expose all/spread 66 | axios.all = function all(promises) { 67 | return Promise.all(promises); 68 | }; 69 | 70 | axios.spread = spread; 71 | 72 | // Expose isAxiosError 73 | axios.isAxiosError = isAxiosError; 74 | 75 | // Expose mergeConfig 76 | axios.mergeConfig = mergeConfig; 77 | 78 | axios.AxiosHeaders = AxiosHeaders; 79 | 80 | axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing); 81 | 82 | axios.getAdapter = adapters.getAdapter; 83 | 84 | axios.HttpStatusCode = HttpStatusCode; 85 | 86 | axios.default = axios; 87 | 88 | // this module should only have a default export 89 | export default axios 90 | -------------------------------------------------------------------------------- /lib/cancel/CanceledError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AxiosError from '../core/AxiosError.js'; 4 | import utils from '../utils.js'; 5 | 6 | /** 7 | * A `CanceledError` is an object that is thrown when an operation is canceled. 8 | * 9 | * @param {string=} message The message. 10 | * @param {Object=} config The config. 11 | * @param {Object=} request The request. 12 | * 13 | * @returns {CanceledError} The created error. 14 | */ 15 | function CanceledError(message, config, request) { 16 | // eslint-disable-next-line no-eq-null,eqeqeq 17 | AxiosError.call(this, message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request); 18 | this.name = 'CanceledError'; 19 | } 20 | 21 | utils.inherits(CanceledError, AxiosError, { 22 | __CANCEL__: true 23 | }); 24 | 25 | export default CanceledError; 26 | -------------------------------------------------------------------------------- /lib/cancel/isCancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function isCancel(value) { 4 | return !!(value && value.__CANCEL__); 5 | } 6 | -------------------------------------------------------------------------------- /lib/core/AxiosError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from '../utils.js'; 4 | 5 | /** 6 | * Create an Error with the specified message, config, error code, request and response. 7 | * 8 | * @param {string} message The error message. 9 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 10 | * @param {Object} [config] The config. 11 | * @param {Object} [request] The request. 12 | * @param {Object} [response] The response. 13 | * 14 | * @returns {Error} The created error. 15 | */ 16 | function AxiosError(message, code, config, request, response) { 17 | Error.call(this); 18 | 19 | if (Error.captureStackTrace) { 20 | Error.captureStackTrace(this, this.constructor); 21 | } else { 22 | this.stack = (new Error()).stack; 23 | } 24 | 25 | this.message = message; 26 | this.name = 'AxiosError'; 27 | code && (this.code = code); 28 | config && (this.config = config); 29 | request && (this.request = request); 30 | if (response) { 31 | this.response = response; 32 | this.status = response.status ? response.status : null; 33 | } 34 | } 35 | 36 | utils.inherits(AxiosError, Error, { 37 | toJSON: function toJSON() { 38 | return { 39 | // Standard 40 | message: this.message, 41 | name: this.name, 42 | // Microsoft 43 | description: this.description, 44 | number: this.number, 45 | // Mozilla 46 | fileName: this.fileName, 47 | lineNumber: this.lineNumber, 48 | columnNumber: this.columnNumber, 49 | stack: this.stack, 50 | // Axios 51 | config: utils.toJSONObject(this.config), 52 | code: this.code, 53 | status: this.status 54 | }; 55 | } 56 | }); 57 | 58 | const prototype = AxiosError.prototype; 59 | const descriptors = {}; 60 | 61 | [ 62 | 'ERR_BAD_OPTION_VALUE', 63 | 'ERR_BAD_OPTION', 64 | 'ECONNABORTED', 65 | 'ETIMEDOUT', 66 | 'ERR_NETWORK', 67 | 'ERR_FR_TOO_MANY_REDIRECTS', 68 | 'ERR_DEPRECATED', 69 | 'ERR_BAD_RESPONSE', 70 | 'ERR_BAD_REQUEST', 71 | 'ERR_CANCELED', 72 | 'ERR_NOT_SUPPORT', 73 | 'ERR_INVALID_URL' 74 | // eslint-disable-next-line func-names 75 | ].forEach(code => { 76 | descriptors[code] = {value: code}; 77 | }); 78 | 79 | Object.defineProperties(AxiosError, descriptors); 80 | Object.defineProperty(prototype, 'isAxiosError', {value: true}); 81 | 82 | // eslint-disable-next-line func-names 83 | AxiosError.from = (error, code, config, request, response, customProps) => { 84 | const axiosError = Object.create(prototype); 85 | 86 | utils.toFlatObject(error, axiosError, function filter(obj) { 87 | return obj !== Error.prototype; 88 | }, prop => { 89 | return prop !== 'isAxiosError'; 90 | }); 91 | 92 | AxiosError.call(axiosError, error.message, code, config, request, response); 93 | 94 | axiosError.cause = error; 95 | 96 | axiosError.name = error.name; 97 | 98 | customProps && Object.assign(axiosError, customProps); 99 | 100 | return axiosError; 101 | }; 102 | 103 | export default AxiosError; 104 | -------------------------------------------------------------------------------- /lib/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from './../utils.js'; 4 | 5 | class InterceptorManager { 6 | constructor() { 7 | this.handlers = []; 8 | } 9 | 10 | /** 11 | * Add a new interceptor to the stack 12 | * 13 | * @param {Function} fulfilled The function to handle `then` for a `Promise` 14 | * @param {Function} rejected The function to handle `reject` for a `Promise` 15 | * 16 | * @return {Number} An ID used to remove interceptor later 17 | */ 18 | use(fulfilled, rejected, options) { 19 | this.handlers.push({ 20 | fulfilled, 21 | rejected, 22 | synchronous: options ? options.synchronous : false, 23 | runWhen: options ? options.runWhen : null 24 | }); 25 | return this.handlers.length - 1; 26 | } 27 | 28 | /** 29 | * Remove an interceptor from the stack 30 | * 31 | * @param {Number} id The ID that was returned by `use` 32 | * 33 | * @returns {Boolean} `true` if the interceptor was removed, `false` otherwise 34 | */ 35 | eject(id) { 36 | if (this.handlers[id]) { 37 | this.handlers[id] = null; 38 | } 39 | } 40 | 41 | /** 42 | * Clear all interceptors from the stack 43 | * 44 | * @returns {void} 45 | */ 46 | clear() { 47 | if (this.handlers) { 48 | this.handlers = []; 49 | } 50 | } 51 | 52 | /** 53 | * Iterate over all the registered interceptors 54 | * 55 | * This method is particularly useful for skipping over any 56 | * interceptors that may have become `null` calling `eject`. 57 | * 58 | * @param {Function} fn The function to call for each interceptor 59 | * 60 | * @returns {void} 61 | */ 62 | forEach(fn) { 63 | utils.forEach(this.handlers, function forEachHandler(h) { 64 | if (h !== null) { 65 | fn(h); 66 | } 67 | }); 68 | } 69 | } 70 | 71 | export default InterceptorManager; 72 | -------------------------------------------------------------------------------- /lib/core/README.md: -------------------------------------------------------------------------------- 1 | # axios // core 2 | 3 | The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are: 4 | 5 | - Dispatching requests 6 | - Requests sent via `adapters/` (see lib/adapters/README.md) 7 | - Managing interceptors 8 | - Handling config 9 | -------------------------------------------------------------------------------- /lib/core/buildFullPath.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import isAbsoluteURL from '../helpers/isAbsoluteURL.js'; 4 | import combineURLs from '../helpers/combineURLs.js'; 5 | 6 | /** 7 | * Creates a new URL by combining the baseURL with the requestedURL, 8 | * only when the requestedURL is not already an absolute URL. 9 | * If the requestURL is absolute, this function returns the requestedURL untouched. 10 | * 11 | * @param {string} baseURL The base URL 12 | * @param {string} requestedURL Absolute or relative URL to combine 13 | * 14 | * @returns {string} The combined full path 15 | */ 16 | export default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { 17 | let isRelativeUrl = !isAbsoluteURL(requestedURL); 18 | if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) { 19 | return combineURLs(baseURL, requestedURL); 20 | } 21 | return requestedURL; 22 | } 23 | -------------------------------------------------------------------------------- /lib/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import transformData from './transformData.js'; 4 | import isCancel from '../cancel/isCancel.js'; 5 | import defaults from '../defaults/index.js'; 6 | import CanceledError from '../cancel/CanceledError.js'; 7 | import AxiosHeaders from '../core/AxiosHeaders.js'; 8 | import adapters from "../adapters/adapters.js"; 9 | 10 | /** 11 | * Throws a `CanceledError` if cancellation has been requested. 12 | * 13 | * @param {Object} config The config that is to be used for the request 14 | * 15 | * @returns {void} 16 | */ 17 | function throwIfCancellationRequested(config) { 18 | if (config.cancelToken) { 19 | config.cancelToken.throwIfRequested(); 20 | } 21 | 22 | if (config.signal && config.signal.aborted) { 23 | throw new CanceledError(null, config); 24 | } 25 | } 26 | 27 | /** 28 | * Dispatch a request to the server using the configured adapter. 29 | * 30 | * @param {object} config The config that is to be used for the request 31 | * 32 | * @returns {Promise} The Promise to be fulfilled 33 | */ 34 | export default function dispatchRequest(config) { 35 | throwIfCancellationRequested(config); 36 | 37 | config.headers = AxiosHeaders.from(config.headers); 38 | 39 | // Transform request data 40 | config.data = transformData.call( 41 | config, 42 | config.transformRequest 43 | ); 44 | 45 | if (['post', 'put', 'patch'].indexOf(config.method) !== -1) { 46 | config.headers.setContentType('application/x-www-form-urlencoded', false); 47 | } 48 | 49 | const adapter = adapters.getAdapter(config.adapter || defaults.adapter); 50 | 51 | return adapter(config).then(function onAdapterResolution(response) { 52 | throwIfCancellationRequested(config); 53 | 54 | // Transform response data 55 | response.data = transformData.call( 56 | config, 57 | config.transformResponse, 58 | response 59 | ); 60 | 61 | response.headers = AxiosHeaders.from(response.headers); 62 | 63 | return response; 64 | }, function onAdapterRejection(reason) { 65 | if (!isCancel(reason)) { 66 | throwIfCancellationRequested(config); 67 | 68 | // Transform response data 69 | if (reason && reason.response) { 70 | reason.response.data = transformData.call( 71 | config, 72 | config.transformResponse, 73 | reason.response 74 | ); 75 | reason.response.headers = AxiosHeaders.from(reason.response.headers); 76 | } 77 | } 78 | 79 | return Promise.reject(reason); 80 | }); 81 | } 82 | -------------------------------------------------------------------------------- /lib/core/settle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AxiosError from './AxiosError.js'; 4 | 5 | /** 6 | * Resolve or reject a Promise based on response status. 7 | * 8 | * @param {Function} resolve A function that resolves the promise. 9 | * @param {Function} reject A function that rejects the promise. 10 | * @param {object} response The response. 11 | * 12 | * @returns {object} The response. 13 | */ 14 | export default function settle(resolve, reject, response) { 15 | const validateStatus = response.config.validateStatus; 16 | if (!response.status || !validateStatus || validateStatus(response.status)) { 17 | resolve(response); 18 | } else { 19 | reject(new AxiosError( 20 | 'Request failed with status code ' + response.status, 21 | [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], 22 | response.config, 23 | response.request, 24 | response 25 | )); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/core/transformData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from './../utils.js'; 4 | import defaults from '../defaults/index.js'; 5 | import AxiosHeaders from '../core/AxiosHeaders.js'; 6 | 7 | /** 8 | * Transform the data for a request or a response 9 | * 10 | * @param {Array|Function} fns A single function or Array of functions 11 | * @param {?Object} response The response object 12 | * 13 | * @returns {*} The resulting transformed data 14 | */ 15 | export default function transformData(fns, response) { 16 | const config = this || defaults; 17 | const context = response || config; 18 | const headers = AxiosHeaders.from(context.headers); 19 | let data = context.data; 20 | 21 | utils.forEach(fns, function transform(fn) { 22 | data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); 23 | }); 24 | 25 | headers.normalize(); 26 | 27 | return data; 28 | } 29 | -------------------------------------------------------------------------------- /lib/defaults/transitional.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default { 4 | silentJSONParsing: true, 5 | forcedJSONParsing: true, 6 | clarifyTimeoutError: false 7 | }; 8 | -------------------------------------------------------------------------------- /lib/env/README.md: -------------------------------------------------------------------------------- 1 | # axios // env 2 | 3 | The `data.js` file is updated automatically when the package version is upgrading. Please do not edit it manually. 4 | -------------------------------------------------------------------------------- /lib/env/classes/FormData.js: -------------------------------------------------------------------------------- 1 | import _FormData from 'form-data'; 2 | export default typeof FormData !== 'undefined' ? FormData : _FormData; 3 | -------------------------------------------------------------------------------- /lib/env/data.js: -------------------------------------------------------------------------------- 1 | export const VERSION = "1.8.4"; -------------------------------------------------------------------------------- /lib/helpers/AxiosURLSearchParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import toFormData from './toFormData.js'; 4 | 5 | /** 6 | * It encodes a string by replacing all characters that are not in the unreserved set with 7 | * their percent-encoded equivalents 8 | * 9 | * @param {string} str - The string to encode. 10 | * 11 | * @returns {string} The encoded string. 12 | */ 13 | function encode(str) { 14 | const charMap = { 15 | '!': '%21', 16 | "'": '%27', 17 | '(': '%28', 18 | ')': '%29', 19 | '~': '%7E', 20 | '%20': '+', 21 | '%00': '\x00' 22 | }; 23 | return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { 24 | return charMap[match]; 25 | }); 26 | } 27 | 28 | /** 29 | * It takes a params object and converts it to a FormData object 30 | * 31 | * @param {Object} params - The parameters to be converted to a FormData object. 32 | * @param {Object} options - The options object passed to the Axios constructor. 33 | * 34 | * @returns {void} 35 | */ 36 | function AxiosURLSearchParams(params, options) { 37 | this._pairs = []; 38 | 39 | params && toFormData(params, this, options); 40 | } 41 | 42 | const prototype = AxiosURLSearchParams.prototype; 43 | 44 | prototype.append = function append(name, value) { 45 | this._pairs.push([name, value]); 46 | }; 47 | 48 | prototype.toString = function toString(encoder) { 49 | const _encode = encoder ? function(value) { 50 | return encoder.call(this, value, encode); 51 | } : encode; 52 | 53 | return this._pairs.map(function each(pair) { 54 | return _encode(pair[0]) + '=' + _encode(pair[1]); 55 | }, '').join('&'); 56 | }; 57 | 58 | export default AxiosURLSearchParams; 59 | -------------------------------------------------------------------------------- /lib/helpers/HttpStatusCode.js: -------------------------------------------------------------------------------- 1 | const HttpStatusCode = { 2 | Continue: 100, 3 | SwitchingProtocols: 101, 4 | Processing: 102, 5 | EarlyHints: 103, 6 | Ok: 200, 7 | Created: 201, 8 | Accepted: 202, 9 | NonAuthoritativeInformation: 203, 10 | NoContent: 204, 11 | ResetContent: 205, 12 | PartialContent: 206, 13 | MultiStatus: 207, 14 | AlreadyReported: 208, 15 | ImUsed: 226, 16 | MultipleChoices: 300, 17 | MovedPermanently: 301, 18 | Found: 302, 19 | SeeOther: 303, 20 | NotModified: 304, 21 | UseProxy: 305, 22 | Unused: 306, 23 | TemporaryRedirect: 307, 24 | PermanentRedirect: 308, 25 | BadRequest: 400, 26 | Unauthorized: 401, 27 | PaymentRequired: 402, 28 | Forbidden: 403, 29 | NotFound: 404, 30 | MethodNotAllowed: 405, 31 | NotAcceptable: 406, 32 | ProxyAuthenticationRequired: 407, 33 | RequestTimeout: 408, 34 | Conflict: 409, 35 | Gone: 410, 36 | LengthRequired: 411, 37 | PreconditionFailed: 412, 38 | PayloadTooLarge: 413, 39 | UriTooLong: 414, 40 | UnsupportedMediaType: 415, 41 | RangeNotSatisfiable: 416, 42 | ExpectationFailed: 417, 43 | ImATeapot: 418, 44 | MisdirectedRequest: 421, 45 | UnprocessableEntity: 422, 46 | Locked: 423, 47 | FailedDependency: 424, 48 | TooEarly: 425, 49 | UpgradeRequired: 426, 50 | PreconditionRequired: 428, 51 | TooManyRequests: 429, 52 | RequestHeaderFieldsTooLarge: 431, 53 | UnavailableForLegalReasons: 451, 54 | InternalServerError: 500, 55 | NotImplemented: 501, 56 | BadGateway: 502, 57 | ServiceUnavailable: 503, 58 | GatewayTimeout: 504, 59 | HttpVersionNotSupported: 505, 60 | VariantAlsoNegotiates: 506, 61 | InsufficientStorage: 507, 62 | LoopDetected: 508, 63 | NotExtended: 510, 64 | NetworkAuthenticationRequired: 511, 65 | }; 66 | 67 | Object.entries(HttpStatusCode).forEach(([key, value]) => { 68 | HttpStatusCode[value] = key; 69 | }); 70 | 71 | export default HttpStatusCode; 72 | -------------------------------------------------------------------------------- /lib/helpers/README.md: -------------------------------------------------------------------------------- 1 | # axios // helpers 2 | 3 | The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like: 4 | 5 | - Browser polyfills 6 | - Managing cookies 7 | - Parsing HTTP headers 8 | -------------------------------------------------------------------------------- /lib/helpers/ZlibHeaderTransformStream.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import stream from "stream"; 4 | 5 | class ZlibHeaderTransformStream extends stream.Transform { 6 | __transform(chunk, encoding, callback) { 7 | this.push(chunk); 8 | callback(); 9 | } 10 | 11 | _transform(chunk, encoding, callback) { 12 | if (chunk.length !== 0) { 13 | this._transform = this.__transform; 14 | 15 | // Add Default Compression headers if no zlib headers are present 16 | if (chunk[0] !== 120) { // Hex: 78 17 | const header = Buffer.alloc(2); 18 | header[0] = 120; // Hex: 78 19 | header[1] = 156; // Hex: 9C 20 | this.push(header, encoding); 21 | } 22 | } 23 | 24 | this.__transform(chunk, encoding, callback); 25 | } 26 | } 27 | 28 | export default ZlibHeaderTransformStream; 29 | -------------------------------------------------------------------------------- /lib/helpers/bind.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function bind(fn, thisArg) { 4 | return function wrap() { 5 | return fn.apply(thisArg, arguments); 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /lib/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from '../utils.js'; 4 | import AxiosURLSearchParams from '../helpers/AxiosURLSearchParams.js'; 5 | 6 | /** 7 | * It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their 8 | * URI encoded counterparts 9 | * 10 | * @param {string} val The value to be encoded. 11 | * 12 | * @returns {string} The encoded value. 13 | */ 14 | function encode(val) { 15 | return encodeURIComponent(val). 16 | replace(/%3A/gi, ':'). 17 | replace(/%24/g, '$'). 18 | replace(/%2C/gi, ','). 19 | replace(/%20/g, '+'). 20 | replace(/%5B/gi, '['). 21 | replace(/%5D/gi, ']'); 22 | } 23 | 24 | /** 25 | * Build a URL by appending params to the end 26 | * 27 | * @param {string} url The base of the url (e.g., http://www.google.com) 28 | * @param {object} [params] The params to be appended 29 | * @param {?(object|Function)} options 30 | * 31 | * @returns {string} The formatted url 32 | */ 33 | export default function buildURL(url, params, options) { 34 | /*eslint no-param-reassign:0*/ 35 | if (!params) { 36 | return url; 37 | } 38 | 39 | const _encode = options && options.encode || encode; 40 | 41 | if (utils.isFunction(options)) { 42 | options = { 43 | serialize: options 44 | }; 45 | } 46 | 47 | const serializeFn = options && options.serialize; 48 | 49 | let serializedParams; 50 | 51 | if (serializeFn) { 52 | serializedParams = serializeFn(params, options); 53 | } else { 54 | serializedParams = utils.isURLSearchParams(params) ? 55 | params.toString() : 56 | new AxiosURLSearchParams(params, options).toString(_encode); 57 | } 58 | 59 | if (serializedParams) { 60 | const hashmarkIndex = url.indexOf("#"); 61 | 62 | if (hashmarkIndex !== -1) { 63 | url = url.slice(0, hashmarkIndex); 64 | } 65 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; 66 | } 67 | 68 | return url; 69 | } 70 | -------------------------------------------------------------------------------- /lib/helpers/callbackify.js: -------------------------------------------------------------------------------- 1 | import utils from "../utils.js"; 2 | 3 | const callbackify = (fn, reducer) => { 4 | return utils.isAsyncFn(fn) ? function (...args) { 5 | const cb = args.pop(); 6 | fn.apply(this, args).then((value) => { 7 | try { 8 | reducer ? cb(null, ...reducer(value)) : cb(null, value); 9 | } catch (err) { 10 | cb(err); 11 | } 12 | }, cb); 13 | } : fn; 14 | } 15 | 16 | export default callbackify; 17 | -------------------------------------------------------------------------------- /lib/helpers/combineURLs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Creates a new URL by combining the specified URLs 5 | * 6 | * @param {string} baseURL The base URL 7 | * @param {string} relativeURL The relative URL 8 | * 9 | * @returns {string} The combined URL 10 | */ 11 | export default function combineURLs(baseURL, relativeURL) { 12 | return relativeURL 13 | ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') 14 | : baseURL; 15 | } 16 | -------------------------------------------------------------------------------- /lib/helpers/composeSignals.js: -------------------------------------------------------------------------------- 1 | import CanceledError from "../cancel/CanceledError.js"; 2 | import AxiosError from "../core/AxiosError.js"; 3 | import utils from '../utils.js'; 4 | 5 | const composeSignals = (signals, timeout) => { 6 | const {length} = (signals = signals ? signals.filter(Boolean) : []); 7 | 8 | if (timeout || length) { 9 | let controller = new AbortController(); 10 | 11 | let aborted; 12 | 13 | const onabort = function (reason) { 14 | if (!aborted) { 15 | aborted = true; 16 | unsubscribe(); 17 | const err = reason instanceof Error ? reason : this.reason; 18 | controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err)); 19 | } 20 | } 21 | 22 | let timer = timeout && setTimeout(() => { 23 | timer = null; 24 | onabort(new AxiosError(`timeout ${timeout} of ms exceeded`, AxiosError.ETIMEDOUT)) 25 | }, timeout) 26 | 27 | const unsubscribe = () => { 28 | if (signals) { 29 | timer && clearTimeout(timer); 30 | timer = null; 31 | signals.forEach(signal => { 32 | signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort); 33 | }); 34 | signals = null; 35 | } 36 | } 37 | 38 | signals.forEach((signal) => signal.addEventListener('abort', onabort)); 39 | 40 | const {signal} = controller; 41 | 42 | signal.unsubscribe = () => utils.asap(unsubscribe); 43 | 44 | return signal; 45 | } 46 | } 47 | 48 | export default composeSignals; 49 | -------------------------------------------------------------------------------- /lib/helpers/cookies.js: -------------------------------------------------------------------------------- 1 | import utils from './../utils.js'; 2 | import platform from '../platform/index.js'; 3 | 4 | export default platform.hasStandardBrowserEnv ? 5 | 6 | // Standard browser envs support document.cookie 7 | { 8 | write(name, value, expires, path, domain, secure) { 9 | const cookie = [name + '=' + encodeURIComponent(value)]; 10 | 11 | utils.isNumber(expires) && cookie.push('expires=' + new Date(expires).toGMTString()); 12 | 13 | utils.isString(path) && cookie.push('path=' + path); 14 | 15 | utils.isString(domain) && cookie.push('domain=' + domain); 16 | 17 | secure === true && cookie.push('secure'); 18 | 19 | document.cookie = cookie.join('; '); 20 | }, 21 | 22 | read(name) { 23 | const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); 24 | return (match ? decodeURIComponent(match[3]) : null); 25 | }, 26 | 27 | remove(name) { 28 | this.write(name, '', Date.now() - 86400000); 29 | } 30 | } 31 | 32 | : 33 | 34 | // Non-standard browser env (web workers, react-native) lack needed support. 35 | { 36 | write() {}, 37 | read() { 38 | return null; 39 | }, 40 | remove() {} 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /lib/helpers/deprecatedMethod.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*eslint no-console:0*/ 4 | 5 | /** 6 | * Supply a warning to the developer that a method they are using 7 | * has been deprecated. 8 | * 9 | * @param {string} method The name of the deprecated method 10 | * @param {string} [instead] The alternate method to use if applicable 11 | * @param {string} [docs] The documentation URL to get further details 12 | * 13 | * @returns {void} 14 | */ 15 | export default function deprecatedMethod(method, instead, docs) { 16 | try { 17 | console.warn( 18 | 'DEPRECATED method `' + method + '`.' + 19 | (instead ? ' Use `' + instead + '` instead.' : '') + 20 | ' This method will be removed in a future release.'); 21 | 22 | if (docs) { 23 | console.warn('For more information about usage see ' + docs); 24 | } 25 | } catch (e) { /* Ignore */ } 26 | } 27 | -------------------------------------------------------------------------------- /lib/helpers/formDataToJSON.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from '../utils.js'; 4 | 5 | /** 6 | * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z'] 7 | * 8 | * @param {string} name - The name of the property to get. 9 | * 10 | * @returns An array of strings. 11 | */ 12 | function parsePropPath(name) { 13 | // foo[x][y][z] 14 | // foo.x.y.z 15 | // foo-x-y-z 16 | // foo x y z 17 | return utils.matchAll(/\w+|\[(\w*)]/g, name).map(match => { 18 | return match[0] === '[]' ? '' : match[1] || match[0]; 19 | }); 20 | } 21 | 22 | /** 23 | * Convert an array to an object. 24 | * 25 | * @param {Array} arr - The array to convert to an object. 26 | * 27 | * @returns An object with the same keys and values as the array. 28 | */ 29 | function arrayToObject(arr) { 30 | const obj = {}; 31 | const keys = Object.keys(arr); 32 | let i; 33 | const len = keys.length; 34 | let key; 35 | for (i = 0; i < len; i++) { 36 | key = keys[i]; 37 | obj[key] = arr[key]; 38 | } 39 | return obj; 40 | } 41 | 42 | /** 43 | * It takes a FormData object and returns a JavaScript object 44 | * 45 | * @param {string} formData The FormData object to convert to JSON. 46 | * 47 | * @returns {Object | null} The converted object. 48 | */ 49 | function formDataToJSON(formData) { 50 | function buildPath(path, value, target, index) { 51 | let name = path[index++]; 52 | 53 | if (name === '__proto__') return true; 54 | 55 | const isNumericKey = Number.isFinite(+name); 56 | const isLast = index >= path.length; 57 | name = !name && utils.isArray(target) ? target.length : name; 58 | 59 | if (isLast) { 60 | if (utils.hasOwnProp(target, name)) { 61 | target[name] = [target[name], value]; 62 | } else { 63 | target[name] = value; 64 | } 65 | 66 | return !isNumericKey; 67 | } 68 | 69 | if (!target[name] || !utils.isObject(target[name])) { 70 | target[name] = []; 71 | } 72 | 73 | const result = buildPath(path, value, target[name], index); 74 | 75 | if (result && utils.isArray(target[name])) { 76 | target[name] = arrayToObject(target[name]); 77 | } 78 | 79 | return !isNumericKey; 80 | } 81 | 82 | if (utils.isFormData(formData) && utils.isFunction(formData.entries)) { 83 | const obj = {}; 84 | 85 | utils.forEachEntry(formData, (name, value) => { 86 | buildPath(parsePropPath(name), value, obj, 0); 87 | }); 88 | 89 | return obj; 90 | } 91 | 92 | return null; 93 | } 94 | 95 | export default formDataToJSON; 96 | -------------------------------------------------------------------------------- /lib/helpers/fromDataURI.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AxiosError from '../core/AxiosError.js'; 4 | import parseProtocol from './parseProtocol.js'; 5 | import platform from '../platform/index.js'; 6 | 7 | const DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/; 8 | 9 | /** 10 | * Parse data uri to a Buffer or Blob 11 | * 12 | * @param {String} uri 13 | * @param {?Boolean} asBlob 14 | * @param {?Object} options 15 | * @param {?Function} options.Blob 16 | * 17 | * @returns {Buffer|Blob} 18 | */ 19 | export default function fromDataURI(uri, asBlob, options) { 20 | const _Blob = options && options.Blob || platform.classes.Blob; 21 | const protocol = parseProtocol(uri); 22 | 23 | if (asBlob === undefined && _Blob) { 24 | asBlob = true; 25 | } 26 | 27 | if (protocol === 'data') { 28 | uri = protocol.length ? uri.slice(protocol.length + 1) : uri; 29 | 30 | const match = DATA_URL_PATTERN.exec(uri); 31 | 32 | if (!match) { 33 | throw new AxiosError('Invalid URL', AxiosError.ERR_INVALID_URL); 34 | } 35 | 36 | const mime = match[1]; 37 | const isBase64 = match[2]; 38 | const body = match[3]; 39 | const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8'); 40 | 41 | if (asBlob) { 42 | if (!_Blob) { 43 | throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT); 44 | } 45 | 46 | return new _Blob([buffer], {type: mime}); 47 | } 48 | 49 | return buffer; 50 | } 51 | 52 | throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT); 53 | } 54 | -------------------------------------------------------------------------------- /lib/helpers/isAbsoluteURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Determines whether the specified URL is absolute 5 | * 6 | * @param {string} url The URL to test 7 | * 8 | * @returns {boolean} True if the specified URL is absolute, otherwise false 9 | */ 10 | export default function isAbsoluteURL(url) { 11 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 12 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 13 | // by any combination of letters, digits, plus, period, or hyphen. 14 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); 15 | } 16 | -------------------------------------------------------------------------------- /lib/helpers/isAxiosError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from './../utils.js'; 4 | 5 | /** 6 | * Determines whether the payload is an error thrown by Axios 7 | * 8 | * @param {*} payload The value to test 9 | * 10 | * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false 11 | */ 12 | export default function isAxiosError(payload) { 13 | return utils.isObject(payload) && (payload.isAxiosError === true); 14 | } 15 | -------------------------------------------------------------------------------- /lib/helpers/isURLSameOrigin.js: -------------------------------------------------------------------------------- 1 | import platform from '../platform/index.js'; 2 | 3 | export default platform.hasStandardBrowserEnv ? ((origin, isMSIE) => (url) => { 4 | url = new URL(url, platform.origin); 5 | 6 | return ( 7 | origin.protocol === url.protocol && 8 | origin.host === url.host && 9 | (isMSIE || origin.port === url.port) 10 | ); 11 | })( 12 | new URL(platform.origin), 13 | platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent) 14 | ) : () => true; 15 | -------------------------------------------------------------------------------- /lib/helpers/null.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line strict 2 | export default null; 3 | -------------------------------------------------------------------------------- /lib/helpers/parseHeaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from './../utils.js'; 4 | 5 | // RawAxiosHeaders whose duplicates are ignored by node 6 | // c.f. https://nodejs.org/api/http.html#http_message_headers 7 | const ignoreDuplicateOf = utils.toObjectSet([ 8 | 'age', 'authorization', 'content-length', 'content-type', 'etag', 9 | 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 10 | 'last-modified', 'location', 'max-forwards', 'proxy-authorization', 11 | 'referer', 'retry-after', 'user-agent' 12 | ]); 13 | 14 | /** 15 | * Parse headers into an object 16 | * 17 | * ``` 18 | * Date: Wed, 27 Aug 2014 08:58:49 GMT 19 | * Content-Type: application/json 20 | * Connection: keep-alive 21 | * Transfer-Encoding: chunked 22 | * ``` 23 | * 24 | * @param {String} rawHeaders Headers needing to be parsed 25 | * 26 | * @returns {Object} Headers parsed into an object 27 | */ 28 | export default rawHeaders => { 29 | const parsed = {}; 30 | let key; 31 | let val; 32 | let i; 33 | 34 | rawHeaders && rawHeaders.split('\n').forEach(function parser(line) { 35 | i = line.indexOf(':'); 36 | key = line.substring(0, i).trim().toLowerCase(); 37 | val = line.substring(i + 1).trim(); 38 | 39 | if (!key || (parsed[key] && ignoreDuplicateOf[key])) { 40 | return; 41 | } 42 | 43 | if (key === 'set-cookie') { 44 | if (parsed[key]) { 45 | parsed[key].push(val); 46 | } else { 47 | parsed[key] = [val]; 48 | } 49 | } else { 50 | parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; 51 | } 52 | }); 53 | 54 | return parsed; 55 | }; 56 | -------------------------------------------------------------------------------- /lib/helpers/parseProtocol.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function parseProtocol(url) { 4 | const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); 5 | return match && match[1] || ''; 6 | } 7 | -------------------------------------------------------------------------------- /lib/helpers/progressEventReducer.js: -------------------------------------------------------------------------------- 1 | import speedometer from "./speedometer.js"; 2 | import throttle from "./throttle.js"; 3 | import utils from "../utils.js"; 4 | 5 | export const progressEventReducer = (listener, isDownloadStream, freq = 3) => { 6 | let bytesNotified = 0; 7 | const _speedometer = speedometer(50, 250); 8 | 9 | return throttle(e => { 10 | const loaded = e.loaded; 11 | const total = e.lengthComputable ? e.total : undefined; 12 | const progressBytes = loaded - bytesNotified; 13 | const rate = _speedometer(progressBytes); 14 | const inRange = loaded <= total; 15 | 16 | bytesNotified = loaded; 17 | 18 | const data = { 19 | loaded, 20 | total, 21 | progress: total ? (loaded / total) : undefined, 22 | bytes: progressBytes, 23 | rate: rate ? rate : undefined, 24 | estimated: rate && total && inRange ? (total - loaded) / rate : undefined, 25 | event: e, 26 | lengthComputable: total != null, 27 | [isDownloadStream ? 'download' : 'upload']: true 28 | }; 29 | 30 | listener(data); 31 | }, freq); 32 | } 33 | 34 | export const progressEventDecorator = (total, throttled) => { 35 | const lengthComputable = total != null; 36 | 37 | return [(loaded) => throttled[0]({ 38 | lengthComputable, 39 | total, 40 | loaded 41 | }), throttled[1]]; 42 | } 43 | 44 | export const asyncDecorator = (fn) => (...args) => utils.asap(() => fn(...args)); 45 | -------------------------------------------------------------------------------- /lib/helpers/readBlob.js: -------------------------------------------------------------------------------- 1 | const {asyncIterator} = Symbol; 2 | 3 | const readBlob = async function* (blob) { 4 | if (blob.stream) { 5 | yield* blob.stream() 6 | } else if (blob.arrayBuffer) { 7 | yield await blob.arrayBuffer() 8 | } else if (blob[asyncIterator]) { 9 | yield* blob[asyncIterator](); 10 | } else { 11 | yield blob; 12 | } 13 | } 14 | 15 | export default readBlob; 16 | -------------------------------------------------------------------------------- /lib/helpers/resolveConfig.js: -------------------------------------------------------------------------------- 1 | import platform from "../platform/index.js"; 2 | import utils from "../utils.js"; 3 | import isURLSameOrigin from "./isURLSameOrigin.js"; 4 | import cookies from "./cookies.js"; 5 | import buildFullPath from "../core/buildFullPath.js"; 6 | import mergeConfig from "../core/mergeConfig.js"; 7 | import AxiosHeaders from "../core/AxiosHeaders.js"; 8 | import buildURL from "./buildURL.js"; 9 | 10 | export default (config) => { 11 | const newConfig = mergeConfig({}, config); 12 | 13 | let {data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth} = newConfig; 14 | 15 | newConfig.headers = headers = AxiosHeaders.from(headers); 16 | 17 | newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), config.params, config.paramsSerializer); 18 | 19 | // HTTP basic authentication 20 | if (auth) { 21 | headers.set('Authorization', 'Basic ' + 22 | btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')) 23 | ); 24 | } 25 | 26 | let contentType; 27 | 28 | if (utils.isFormData(data)) { 29 | if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { 30 | headers.setContentType(undefined); // Let the browser set it 31 | } else if ((contentType = headers.getContentType()) !== false) { 32 | // fix semicolon duplication issue for ReactNative FormData implementation 33 | const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : []; 34 | headers.setContentType([type || 'multipart/form-data', ...tokens].join('; ')); 35 | } 36 | } 37 | 38 | // Add xsrf header 39 | // This is only done if running in a standard browser environment. 40 | // Specifically not if we're in a web worker, or react-native. 41 | 42 | if (platform.hasStandardBrowserEnv) { 43 | withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); 44 | 45 | if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) { 46 | // Add xsrf header 47 | const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); 48 | 49 | if (xsrfValue) { 50 | headers.set(xsrfHeaderName, xsrfValue); 51 | } 52 | } 53 | } 54 | 55 | return newConfig; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /lib/helpers/speedometer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Calculate data maxRate 5 | * @param {Number} [samplesCount= 10] 6 | * @param {Number} [min= 1000] 7 | * @returns {Function} 8 | */ 9 | function speedometer(samplesCount, min) { 10 | samplesCount = samplesCount || 10; 11 | const bytes = new Array(samplesCount); 12 | const timestamps = new Array(samplesCount); 13 | let head = 0; 14 | let tail = 0; 15 | let firstSampleTS; 16 | 17 | min = min !== undefined ? min : 1000; 18 | 19 | return function push(chunkLength) { 20 | const now = Date.now(); 21 | 22 | const startedAt = timestamps[tail]; 23 | 24 | if (!firstSampleTS) { 25 | firstSampleTS = now; 26 | } 27 | 28 | bytes[head] = chunkLength; 29 | timestamps[head] = now; 30 | 31 | let i = tail; 32 | let bytesCount = 0; 33 | 34 | while (i !== head) { 35 | bytesCount += bytes[i++]; 36 | i = i % samplesCount; 37 | } 38 | 39 | head = (head + 1) % samplesCount; 40 | 41 | if (head === tail) { 42 | tail = (tail + 1) % samplesCount; 43 | } 44 | 45 | if (now - firstSampleTS < min) { 46 | return; 47 | } 48 | 49 | const passed = startedAt && now - startedAt; 50 | 51 | return passed ? Math.round(bytesCount * 1000 / passed) : undefined; 52 | }; 53 | } 54 | 55 | export default speedometer; 56 | -------------------------------------------------------------------------------- /lib/helpers/spread.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Syntactic sugar for invoking a function and expanding an array for arguments. 5 | * 6 | * Common use case would be to use `Function.prototype.apply`. 7 | * 8 | * ```js 9 | * function f(x, y, z) {} 10 | * var args = [1, 2, 3]; 11 | * f.apply(null, args); 12 | * ``` 13 | * 14 | * With `spread` this example can be re-written. 15 | * 16 | * ```js 17 | * spread(function(x, y, z) {})([1, 2, 3]); 18 | * ``` 19 | * 20 | * @param {Function} callback 21 | * 22 | * @returns {Function} 23 | */ 24 | export default function spread(callback) { 25 | return function wrap(arr) { 26 | return callback.apply(null, arr); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /lib/helpers/throttle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Throttle decorator 3 | * @param {Function} fn 4 | * @param {Number} freq 5 | * @return {Function} 6 | */ 7 | function throttle(fn, freq) { 8 | let timestamp = 0; 9 | let threshold = 1000 / freq; 10 | let lastArgs; 11 | let timer; 12 | 13 | const invoke = (args, now = Date.now()) => { 14 | timestamp = now; 15 | lastArgs = null; 16 | if (timer) { 17 | clearTimeout(timer); 18 | timer = null; 19 | } 20 | fn.apply(null, args); 21 | } 22 | 23 | const throttled = (...args) => { 24 | const now = Date.now(); 25 | const passed = now - timestamp; 26 | if ( passed >= threshold) { 27 | invoke(args, now); 28 | } else { 29 | lastArgs = args; 30 | if (!timer) { 31 | timer = setTimeout(() => { 32 | timer = null; 33 | invoke(lastArgs) 34 | }, threshold - passed); 35 | } 36 | } 37 | } 38 | 39 | const flush = () => lastArgs && invoke(lastArgs); 40 | 41 | return [throttled, flush]; 42 | } 43 | 44 | export default throttle; 45 | -------------------------------------------------------------------------------- /lib/helpers/toURLEncodedForm.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import utils from '../utils.js'; 4 | import toFormData from './toFormData.js'; 5 | import platform from '../platform/index.js'; 6 | 7 | export default function toURLEncodedForm(data, options) { 8 | return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({ 9 | visitor: function(value, key, path, helpers) { 10 | if (platform.isNode && utils.isBuffer(value)) { 11 | this.append(key, value.toString('base64')); 12 | return false; 13 | } 14 | 15 | return helpers.defaultVisitor.apply(this, arguments); 16 | } 17 | }, options)); 18 | } 19 | -------------------------------------------------------------------------------- /lib/helpers/trackStream.js: -------------------------------------------------------------------------------- 1 | 2 | export const streamChunk = function* (chunk, chunkSize) { 3 | let len = chunk.byteLength; 4 | 5 | if (!chunkSize || len < chunkSize) { 6 | yield chunk; 7 | return; 8 | } 9 | 10 | let pos = 0; 11 | let end; 12 | 13 | while (pos < len) { 14 | end = pos + chunkSize; 15 | yield chunk.slice(pos, end); 16 | pos = end; 17 | } 18 | } 19 | 20 | export const readBytes = async function* (iterable, chunkSize) { 21 | for await (const chunk of readStream(iterable)) { 22 | yield* streamChunk(chunk, chunkSize); 23 | } 24 | } 25 | 26 | const readStream = async function* (stream) { 27 | if (stream[Symbol.asyncIterator]) { 28 | yield* stream; 29 | return; 30 | } 31 | 32 | const reader = stream.getReader(); 33 | try { 34 | for (;;) { 35 | const {done, value} = await reader.read(); 36 | if (done) { 37 | break; 38 | } 39 | yield value; 40 | } 41 | } finally { 42 | await reader.cancel(); 43 | } 44 | } 45 | 46 | export const trackStream = (stream, chunkSize, onProgress, onFinish) => { 47 | const iterator = readBytes(stream, chunkSize); 48 | 49 | let bytes = 0; 50 | let done; 51 | let _onFinish = (e) => { 52 | if (!done) { 53 | done = true; 54 | onFinish && onFinish(e); 55 | } 56 | } 57 | 58 | return new ReadableStream({ 59 | async pull(controller) { 60 | try { 61 | const {done, value} = await iterator.next(); 62 | 63 | if (done) { 64 | _onFinish(); 65 | controller.close(); 66 | return; 67 | } 68 | 69 | let len = value.byteLength; 70 | if (onProgress) { 71 | let loadedBytes = bytes += len; 72 | onProgress(loadedBytes); 73 | } 74 | controller.enqueue(new Uint8Array(value)); 75 | } catch (err) { 76 | _onFinish(err); 77 | throw err; 78 | } 79 | }, 80 | cancel(reason) { 81 | _onFinish(reason); 82 | return iterator.return(); 83 | } 84 | }, { 85 | highWaterMark: 2 86 | }) 87 | } 88 | -------------------------------------------------------------------------------- /lib/helpers/validator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {VERSION} from '../env/data.js'; 4 | import AxiosError from '../core/AxiosError.js'; 5 | 6 | const validators = {}; 7 | 8 | // eslint-disable-next-line func-names 9 | ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => { 10 | validators[type] = function validator(thing) { 11 | return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; 12 | }; 13 | }); 14 | 15 | const deprecatedWarnings = {}; 16 | 17 | /** 18 | * Transitional option validator 19 | * 20 | * @param {function|boolean?} validator - set to false if the transitional option has been removed 21 | * @param {string?} version - deprecated version / removed since version 22 | * @param {string?} message - some message with additional info 23 | * 24 | * @returns {function} 25 | */ 26 | validators.transitional = function transitional(validator, version, message) { 27 | function formatMessage(opt, desc) { 28 | return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : ''); 29 | } 30 | 31 | // eslint-disable-next-line func-names 32 | return (value, opt, opts) => { 33 | if (validator === false) { 34 | throw new AxiosError( 35 | formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), 36 | AxiosError.ERR_DEPRECATED 37 | ); 38 | } 39 | 40 | if (version && !deprecatedWarnings[opt]) { 41 | deprecatedWarnings[opt] = true; 42 | // eslint-disable-next-line no-console 43 | console.warn( 44 | formatMessage( 45 | opt, 46 | ' has been deprecated since v' + version + ' and will be removed in the near future' 47 | ) 48 | ); 49 | } 50 | 51 | return validator ? validator(value, opt, opts) : true; 52 | }; 53 | }; 54 | 55 | validators.spelling = function spelling(correctSpelling) { 56 | return (value, opt) => { 57 | // eslint-disable-next-line no-console 58 | console.warn(`${opt} is likely a misspelling of ${correctSpelling}`); 59 | return true; 60 | } 61 | }; 62 | 63 | /** 64 | * Assert object's properties type 65 | * 66 | * @param {object} options 67 | * @param {object} schema 68 | * @param {boolean?} allowUnknown 69 | * 70 | * @returns {object} 71 | */ 72 | 73 | function assertOptions(options, schema, allowUnknown) { 74 | if (typeof options !== 'object') { 75 | throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE); 76 | } 77 | const keys = Object.keys(options); 78 | let i = keys.length; 79 | while (i-- > 0) { 80 | const opt = keys[i]; 81 | const validator = schema[opt]; 82 | if (validator) { 83 | const value = options[opt]; 84 | const result = value === undefined || validator(value, opt, options); 85 | if (result !== true) { 86 | throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE); 87 | } 88 | continue; 89 | } 90 | if (allowUnknown !== true) { 91 | throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION); 92 | } 93 | } 94 | } 95 | 96 | export default { 97 | assertOptions, 98 | validators 99 | }; 100 | -------------------------------------------------------------------------------- /lib/platform/browser/classes/Blob.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | export default typeof Blob !== 'undefined' ? Blob : null 4 | -------------------------------------------------------------------------------- /lib/platform/browser/classes/FormData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default typeof FormData !== 'undefined' ? FormData : null; 4 | -------------------------------------------------------------------------------- /lib/platform/browser/classes/URLSearchParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AxiosURLSearchParams from '../../../helpers/AxiosURLSearchParams.js'; 4 | export default typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams; 5 | -------------------------------------------------------------------------------- /lib/platform/browser/index.js: -------------------------------------------------------------------------------- 1 | import URLSearchParams from './classes/URLSearchParams.js' 2 | import FormData from './classes/FormData.js' 3 | import Blob from './classes/Blob.js' 4 | 5 | export default { 6 | isBrowser: true, 7 | classes: { 8 | URLSearchParams, 9 | FormData, 10 | Blob 11 | }, 12 | protocols: ['http', 'https', 'file', 'blob', 'url', 'data'] 13 | }; 14 | -------------------------------------------------------------------------------- /lib/platform/common/utils.js: -------------------------------------------------------------------------------- 1 | const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; 2 | 3 | const _navigator = typeof navigator === 'object' && navigator || undefined; 4 | 5 | /** 6 | * Determine if we're running in a standard browser environment 7 | * 8 | * This allows axios to run in a web worker, and react-native. 9 | * Both environments support XMLHttpRequest, but not fully standard globals. 10 | * 11 | * web workers: 12 | * typeof window -> undefined 13 | * typeof document -> undefined 14 | * 15 | * react-native: 16 | * navigator.product -> 'ReactNative' 17 | * nativescript 18 | * navigator.product -> 'NativeScript' or 'NS' 19 | * 20 | * @returns {boolean} 21 | */ 22 | const hasStandardBrowserEnv = hasBrowserEnv && 23 | (!_navigator || ['ReactNative', 'NativeScript', 'NS'].indexOf(_navigator.product) < 0); 24 | 25 | /** 26 | * Determine if we're running in a standard browser webWorker environment 27 | * 28 | * Although the `isStandardBrowserEnv` method indicates that 29 | * `allows axios to run in a web worker`, the WebWorker will still be 30 | * filtered out due to its judgment standard 31 | * `typeof window !== 'undefined' && typeof document !== 'undefined'`. 32 | * This leads to a problem when axios post `FormData` in webWorker 33 | */ 34 | const hasStandardBrowserWebWorkerEnv = (() => { 35 | return ( 36 | typeof WorkerGlobalScope !== 'undefined' && 37 | // eslint-disable-next-line no-undef 38 | self instanceof WorkerGlobalScope && 39 | typeof self.importScripts === 'function' 40 | ); 41 | })(); 42 | 43 | const origin = hasBrowserEnv && window.location.href || 'http://localhost'; 44 | 45 | export { 46 | hasBrowserEnv, 47 | hasStandardBrowserWebWorkerEnv, 48 | hasStandardBrowserEnv, 49 | _navigator as navigator, 50 | origin 51 | } 52 | -------------------------------------------------------------------------------- /lib/platform/index.js: -------------------------------------------------------------------------------- 1 | import platform from './node/index.js'; 2 | import * as utils from './common/utils.js'; 3 | 4 | export default { 5 | ...utils, 6 | ...platform 7 | } 8 | -------------------------------------------------------------------------------- /lib/platform/node/classes/FormData.js: -------------------------------------------------------------------------------- 1 | import FormData from 'form-data'; 2 | 3 | export default FormData; 4 | -------------------------------------------------------------------------------- /lib/platform/node/classes/URLSearchParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import url from 'url'; 4 | export default url.URLSearchParams; 5 | -------------------------------------------------------------------------------- /lib/platform/node/index.js: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto'; 2 | import URLSearchParams from './classes/URLSearchParams.js' 3 | import FormData from './classes/FormData.js' 4 | 5 | const ALPHA = 'abcdefghijklmnopqrstuvwxyz' 6 | 7 | const DIGIT = '0123456789'; 8 | 9 | const ALPHABET = { 10 | DIGIT, 11 | ALPHA, 12 | ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT 13 | } 14 | 15 | const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => { 16 | let str = ''; 17 | const {length} = alphabet; 18 | const randomValues = new Uint32Array(size); 19 | crypto.randomFillSync(randomValues); 20 | for (let i = 0; i < size; i++) { 21 | str += alphabet[randomValues[i] % length]; 22 | } 23 | 24 | return str; 25 | } 26 | 27 | 28 | export default { 29 | isNode: true, 30 | classes: { 31 | URLSearchParams, 32 | FormData, 33 | Blob: typeof Blob !== 'undefined' && Blob || null 34 | }, 35 | ALPHABET, 36 | generateString, 37 | protocols: [ 'http', 'https', 'file', 'data' ] 38 | }; 39 | -------------------------------------------------------------------------------- /sandbox/client.js: -------------------------------------------------------------------------------- 1 | import axios from '../index.js'; 2 | 3 | const URL = 'http://127.0.0.1:3000/api'; 4 | const BODY = { 5 | foo: 'bar', 6 | baz: 1234 7 | }; 8 | 9 | function handleSuccess(data) { console.log(data); } 10 | function handleFailure(data) { console.log('error', data); } 11 | 12 | // GET 13 | axios.get(URL, { params: BODY }) 14 | .then(handleSuccess) 15 | .catch(handleFailure); 16 | 17 | // POST 18 | axios.post(URL, BODY) 19 | .then(handleSuccess) 20 | .catch(handleFailure); 21 | -------------------------------------------------------------------------------- /sandbox/server.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import url from 'url'; 3 | import path from 'path'; 4 | import http from 'http'; 5 | let server; 6 | 7 | function pipeFileToResponse(res, file, type) { 8 | if (type) { 9 | res.writeHead(200, { 10 | 'Content-Type': type 11 | }); 12 | } 13 | 14 | fs.createReadStream(path.join(path.resolve() ,'sandbox', file)).pipe(res); 15 | } 16 | 17 | server = http.createServer(function (req, res) { 18 | req.setEncoding('utf8'); 19 | 20 | const parsed = url.parse(req.url, true); 21 | let pathname = parsed.pathname; 22 | 23 | console.log('[' + new Date() + ']', req.method, pathname); 24 | 25 | if (pathname === '/') { 26 | pathname = '/index.html'; 27 | } 28 | 29 | if (pathname === '/index.html') { 30 | pipeFileToResponse(res, './client.html', 'text/html'); 31 | } else if (pathname === '/axios.js') { 32 | pipeFileToResponse(res, '../dist/axios.js', 'text/javascript'); 33 | } else if (pathname === '/axios.js.map') { 34 | pipeFileToResponse(res, '../dist/axios.js.map', 'text/javascript'); 35 | } else if (pathname === '/api') { 36 | let status; 37 | let result; 38 | let data = ''; 39 | 40 | req.on('data', function (chunk) { 41 | data += chunk; 42 | }); 43 | 44 | req.on('end', function () { 45 | try { 46 | status = 200; 47 | result = { 48 | url: req.url, 49 | data: data ? JSON.parse(data) : undefined, 50 | method: req.method, 51 | headers: req.headers 52 | }; 53 | } catch (e) { 54 | console.error('Error:', e.message); 55 | status = 400; 56 | result = { 57 | error: e.message 58 | }; 59 | } 60 | 61 | res.writeHead(status, { 62 | 'Content-Type': 'application/json' 63 | }); 64 | res.end(JSON.stringify(result)); 65 | }); 66 | } else { 67 | res.writeHead(404); 68 | res.end('

404 Not Found

'); 69 | } 70 | }); 71 | 72 | const PORT = 3000; 73 | 74 | server.listen(PORT, console.log(`Listening on localhost:${PORT}...`)); 75 | server.on('error', (error) => { 76 | if (error.code === 'EADDRINUSE') { 77 | console.log(`Address localhost:${PORT} in use please retry when the port is available!`); 78 | server.close(); 79 | } 80 | }); 81 | -------------------------------------------------------------------------------- /templates/contributors.hbs: -------------------------------------------------------------------------------- 1 | {{#if authors}} 2 | ### Contributors to this release 3 | 4 | {{#each authors}} 5 | {{#unless isBot}} 6 | {{#if login}} 7 | - {{#if avatar_url}}avatar{{/if}} [{{displayName}}]({{html_url}} "+{{insertions}}/-{{deletions}} ({{#each prs}}#{{this}} {{/each}})") 8 | {{else}} 9 | - {{displayName}} 10 | {{/if}} 11 | {{/unless}} 12 | {{/each}} 13 | {{/if}} 14 | -------------------------------------------------------------------------------- /templates/pr.hbs: -------------------------------------------------------------------------------- 1 | {{#if files}} 2 | ### Build info 3 | 4 | {{#each files}} 5 | - {{ name}} ({{ path }}) {{ filesize size }} (**{{ filesize gzip }}** gzipped) 6 | {{#each commits}} 7 | - {{ tag }} - {{filesize size}} 8 | {{/each}} 9 | {{/each}} 10 | {{/if}} 11 | -------------------------------------------------------------------------------- /templates/pr_published.hbs: -------------------------------------------------------------------------------- 1 | Hi, @{{ author.login }}! This PR has been published in [{{ release.tag }}]({{ release.url }}) release. Thank you for your contribution ❤️! 2 | -------------------------------------------------------------------------------- /templates/prs.hbs: -------------------------------------------------------------------------------- 1 | {{#if prs}} 2 | ### PRs 3 | {{#each prs}} 4 | - {{title}} ( [#{{number}}]({{pull_request.url}}) ){{#if isHot}} 🔥{{/if}}{{#if isHot}} 🚀{{/if}} 5 | {{#if messages}} 6 | {{#each messages}} 7 | ``` 8 | {{this}} 9 | ``` 10 | {{/each}} 11 | {{/if}} 12 | {{/each}} 13 | {{/if}} 14 | -------------------------------------------------------------------------------- /test/manual/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | An alert should be shown with the {"name":"axios"} 9 | 10 | 11 | 12 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/manual/cors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | An alert should be shown with {"status":"ok"} 9 | 10 | 11 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/manual/fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axios" 3 | } -------------------------------------------------------------------------------- /test/manual/progress.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | See your console 8 | 9 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/module/cjs/index.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const assert = require('assert'); 3 | 4 | const {CanceledError, AxiosError, AxiosHeaders} = axios; 5 | 6 | assert.strictEqual(typeof axios, 'function'); 7 | assert.strictEqual(typeof CanceledError, 'function'); 8 | assert.strictEqual(typeof AxiosError, 'function'); 9 | assert.strictEqual(typeof AxiosHeaders, 'function'); 10 | 11 | console.log('CommonJS importing test passed'); 12 | -------------------------------------------------------------------------------- /test/module/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cjs-entrypoint-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm i --no-save --no-package-lock && node index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "axios": "file:../../.." 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/module/esm/index.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import axios, {CanceledError, AxiosError, AxiosHeaders} from 'axios'; 3 | import settle from 'axios/unsafe/core/settle.js'; 4 | 5 | assert.strictEqual(typeof axios, 'function'); 6 | assert.strictEqual(typeof CanceledError, 'function'); 7 | assert.strictEqual(typeof AxiosError, 'function'); 8 | assert.strictEqual(typeof AxiosHeaders, 'function'); 9 | 10 | assert.strictEqual(axios.CanceledError, CanceledError); 11 | assert.strictEqual(axios.AxiosError, AxiosError); 12 | assert.strictEqual(axios.AxiosHeaders, AxiosHeaders); 13 | 14 | assert.strictEqual(typeof settle, 'function'); 15 | 16 | console.log('ESM importing test passed'); 17 | -------------------------------------------------------------------------------- /test/module/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-entrypoint-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "npm i --no-save --no-package-lock && node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "axios": "file:../../.." 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/module/ts-require-default/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const assert = require('assert'); 3 | const axios = require('axios').default; 4 | const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData } = axios; 5 | assert.strictEqual(typeof axios, 'function'); 6 | assert.strictEqual(typeof CanceledError, 'function'); 7 | assert.strictEqual(typeof AxiosError, 'function'); 8 | assert.strictEqual(typeof AxiosHeaders, 'function'); 9 | assert.strictEqual(typeof formToJSON, 'function'); 10 | assert.strictEqual(typeof spread, 'function'); 11 | assert.strictEqual(typeof isAxiosError, 'function'); 12 | assert.strictEqual(typeof isCancel, 'function'); 13 | assert.strictEqual(typeof all, 'function'); 14 | assert.strictEqual(typeof toFormData, 'function'); 15 | assert.strictEqual(typeof axios.CanceledError, 'function'); 16 | assert.strictEqual(typeof axios.AxiosError, 'function'); 17 | assert.strictEqual(typeof axios.AxiosHeaders, 'function'); 18 | assert.strictEqual(typeof axios.formToJSON, 'function'); 19 | assert.strictEqual(typeof axios.spread, 'function'); 20 | assert.strictEqual(typeof axios.isAxiosError, 'function'); 21 | assert.strictEqual(typeof axios.isCancel, 'function'); 22 | assert.strictEqual(typeof axios.all, 'function'); 23 | assert.strictEqual(typeof axios.toFormData, 'function'); 24 | -------------------------------------------------------------------------------- /test/module/ts-require-default/index.ts: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const axios = require('axios').default; 3 | const {CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData} = axios; 4 | 5 | assert.strictEqual(typeof axios, 'function'); 6 | 7 | assert.strictEqual(typeof CanceledError, 'function'); 8 | assert.strictEqual(typeof AxiosError, 'function'); 9 | assert.strictEqual(typeof AxiosHeaders, 'function'); 10 | assert.strictEqual(typeof formToJSON, 'function'); 11 | assert.strictEqual(typeof spread, 'function'); 12 | assert.strictEqual(typeof isAxiosError, 'function'); 13 | assert.strictEqual(typeof isCancel, 'function'); 14 | assert.strictEqual(typeof all, 'function'); 15 | assert.strictEqual(typeof toFormData, 'function'); 16 | 17 | assert.strictEqual(typeof axios.CanceledError, 'function'); 18 | assert.strictEqual(typeof axios.AxiosError, 'function'); 19 | assert.strictEqual(typeof axios.AxiosHeaders, 'function'); 20 | assert.strictEqual(typeof axios.formToJSON, 'function'); 21 | assert.strictEqual(typeof axios.spread, 'function'); 22 | assert.strictEqual(typeof axios.isAxiosError, 'function'); 23 | assert.strictEqual(typeof axios.isCancel, 'function'); 24 | assert.strictEqual(typeof axios.all, 'function'); 25 | assert.strictEqual(typeof axios.toFormData, 'function'); 26 | -------------------------------------------------------------------------------- /test/module/ts-require-default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-entrypoint-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm i --no-save --no-package-lock && npm run build && node index.js", 8 | "build": "tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@types/node": "^18.11.3", 15 | "axios": "file:../../.." 16 | }, 17 | "devDependencies": { 18 | "typescript": "^4.8.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/module/ts-require/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const assert = require('assert'); 3 | const axios = require('axios'); 4 | const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData } = axios; 5 | assert.strictEqual(typeof axios, 'function'); 6 | assert.strictEqual(typeof CanceledError, 'function'); 7 | assert.strictEqual(typeof AxiosError, 'function'); 8 | assert.strictEqual(typeof AxiosHeaders, 'function'); 9 | assert.strictEqual(typeof formToJSON, 'function'); 10 | assert.strictEqual(typeof spread, 'function'); 11 | assert.strictEqual(typeof isAxiosError, 'function'); 12 | assert.strictEqual(typeof isCancel, 'function'); 13 | assert.strictEqual(typeof all, 'function'); 14 | assert.strictEqual(typeof toFormData, 'function'); 15 | assert.strictEqual(typeof axios.CanceledError, 'function'); 16 | assert.strictEqual(typeof axios.AxiosError, 'function'); 17 | assert.strictEqual(typeof axios.AxiosHeaders, 'function'); 18 | assert.strictEqual(typeof axios.formToJSON, 'function'); 19 | assert.strictEqual(typeof axios.spread, 'function'); 20 | assert.strictEqual(typeof axios.isAxiosError, 'function'); 21 | assert.strictEqual(typeof axios.isCancel, 'function'); 22 | assert.strictEqual(typeof axios.all, 'function'); 23 | assert.strictEqual(typeof axios.toFormData, 'function'); 24 | -------------------------------------------------------------------------------- /test/module/ts-require/index.ts: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const axios = require('axios'); 3 | const {CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData} = axios; 4 | 5 | assert.strictEqual(typeof axios, 'function'); 6 | 7 | assert.strictEqual(typeof CanceledError, 'function'); 8 | assert.strictEqual(typeof AxiosError, 'function'); 9 | assert.strictEqual(typeof AxiosHeaders, 'function'); 10 | assert.strictEqual(typeof formToJSON, 'function'); 11 | assert.strictEqual(typeof spread, 'function'); 12 | assert.strictEqual(typeof isAxiosError, 'function'); 13 | assert.strictEqual(typeof isCancel, 'function'); 14 | assert.strictEqual(typeof all, 'function'); 15 | assert.strictEqual(typeof toFormData, 'function'); 16 | 17 | assert.strictEqual(typeof axios.CanceledError, 'function'); 18 | assert.strictEqual(typeof axios.AxiosError, 'function'); 19 | assert.strictEqual(typeof axios.AxiosHeaders, 'function'); 20 | assert.strictEqual(typeof axios.formToJSON, 'function'); 21 | assert.strictEqual(typeof axios.spread, 'function'); 22 | assert.strictEqual(typeof axios.isAxiosError, 'function'); 23 | assert.strictEqual(typeof axios.isCancel, 'function'); 24 | assert.strictEqual(typeof axios.all, 'function'); 25 | assert.strictEqual(typeof axios.toFormData, 'function'); 26 | -------------------------------------------------------------------------------- /test/module/ts-require/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-entrypoint-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm i --no-save --no-package-lock && npm run build && node index.js", 8 | "build": "tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@types/node": "^18.11.3", 15 | "axios": "file:../../.." 16 | }, 17 | "devDependencies": { 18 | "typescript": "^4.8.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/module/ts/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | const assert_1 = __importDefault(require("assert")); 30 | const axios_1 = __importStar(require("axios")); 31 | assert_1.default.strictEqual(typeof axios_1.default, 'function'); 32 | assert_1.default.strictEqual(typeof axios_1.CanceledError, 'function'); 33 | assert_1.default.strictEqual(typeof axios_1.AxiosError, 'function'); 34 | assert_1.default.strictEqual(typeof axios_1.AxiosHeaders, 'function'); 35 | assert_1.default.strictEqual(typeof axios_1.formToJSON, 'function'); 36 | assert_1.default.strictEqual(typeof axios_1.spread, 'function'); 37 | assert_1.default.strictEqual(typeof axios_1.isAxiosError, 'function'); 38 | assert_1.default.strictEqual(typeof axios_1.isCancel, 'function'); 39 | assert_1.default.strictEqual(typeof axios_1.all, 'function'); 40 | assert_1.default.strictEqual(typeof axios_1.toFormData, 'function'); 41 | assert_1.default.strictEqual(typeof axios_1.default.CanceledError, 'function'); 42 | assert_1.default.strictEqual(typeof axios_1.default.AxiosError, 'function'); 43 | assert_1.default.strictEqual(typeof axios_1.default.AxiosHeaders, 'function'); 44 | assert_1.default.strictEqual(typeof axios_1.default.formToJSON, 'function'); 45 | assert_1.default.strictEqual(typeof axios_1.default.spread, 'function'); 46 | assert_1.default.strictEqual(typeof axios_1.default.isAxiosError, 'function'); 47 | assert_1.default.strictEqual(typeof axios_1.default.isCancel, 'function'); 48 | assert_1.default.strictEqual(typeof axios_1.default.all, 'function'); 49 | assert_1.default.strictEqual(typeof axios_1.default.toFormData, 'function'); 50 | -------------------------------------------------------------------------------- /test/module/ts/index.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import axios, {CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData} from 'axios'; 3 | 4 | assert.strictEqual(typeof axios, 'function'); 5 | 6 | assert.strictEqual(typeof CanceledError, 'function'); 7 | assert.strictEqual(typeof AxiosError, 'function'); 8 | assert.strictEqual(typeof AxiosHeaders, 'function'); 9 | assert.strictEqual(typeof formToJSON, 'function'); 10 | assert.strictEqual(typeof spread, 'function'); 11 | assert.strictEqual(typeof isAxiosError, 'function'); 12 | assert.strictEqual(typeof isCancel, 'function'); 13 | assert.strictEqual(typeof all, 'function'); 14 | assert.strictEqual(typeof toFormData, 'function'); 15 | 16 | assert.strictEqual(typeof axios.CanceledError, 'function'); 17 | assert.strictEqual(typeof axios.AxiosError, 'function'); 18 | assert.strictEqual(typeof axios.AxiosHeaders, 'function'); 19 | assert.strictEqual(typeof axios.formToJSON, 'function'); 20 | assert.strictEqual(typeof axios.spread, 'function'); 21 | assert.strictEqual(typeof axios.isAxiosError, 'function'); 22 | assert.strictEqual(typeof axios.isCancel, 'function'); 23 | assert.strictEqual(typeof axios.all, 'function'); 24 | assert.strictEqual(typeof axios.toFormData, 'function'); 25 | -------------------------------------------------------------------------------- /test/module/ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-entrypoint-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm i --no-save --no-package-lock && npm run build && node index.js", 8 | "build": "tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@types/node": "^18.11.3", 15 | "axios": "file:../../.." 16 | }, 17 | "devDependencies": { 18 | "typescript": "^4.8.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/module/typings/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commonjs-typings-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm i --no-save --no-package-lock && tsc -v && npm run test:types", 8 | "test:types": "tsc --noEmit" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@types/node": "^18.11.3", 15 | "axios": "file:../../../.." 16 | }, 17 | "devDependencies": { 18 | "typescript": "^4.9.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/module/typings/cjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "module": "node16" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/module/typings/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-typings-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test:types": "tsc --noEmit", 9 | "test": "npm i --no-save --no-package-lock && tsc -v && npm run test:types" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "MIT", 14 | "dependencies": { 15 | "@types/node": "^18.11.3", 16 | "axios": "file:../../../.." 17 | }, 18 | "devDependencies": { 19 | "typescript": "^4.9.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/module/typings/esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "module": "node16" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/specs/__helpers.js: -------------------------------------------------------------------------------- 1 | import _axios from '../../index.js'; 2 | 3 | window.axios = _axios; 4 | 5 | // Jasmine config 6 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; 7 | jasmine.getEnv().defaultTimeoutInterval = 60000; 8 | 9 | // Get Ajax request using an increasing timeout to retry 10 | window.getAjaxRequest = (function () { 11 | let attempts = 0; 12 | const MAX_ATTEMPTS = 5; 13 | const ATTEMPT_DELAY_FACTOR = 5; 14 | 15 | function getAjaxRequest() { 16 | return new Promise(function (resolve, reject) { 17 | attempts = 0; 18 | attemptGettingAjaxRequest(resolve, reject); 19 | }); 20 | } 21 | 22 | function attemptGettingAjaxRequest(resolve, reject) { 23 | const delay = attempts * attempts * ATTEMPT_DELAY_FACTOR; 24 | 25 | if (attempts++ > MAX_ATTEMPTS) { 26 | reject(new Error('No request was found')); 27 | return; 28 | } 29 | 30 | setTimeout(function () { 31 | const request = jasmine.Ajax.requests.mostRecent(); 32 | if (request) { 33 | resolve(request); 34 | } else { 35 | attemptGettingAjaxRequest(resolve, reject); 36 | } 37 | }, delay); 38 | } 39 | 40 | return getAjaxRequest; 41 | })(); 42 | -------------------------------------------------------------------------------- /test/specs/adapter.spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('adapter', function () { 3 | beforeEach(function () { 4 | jasmine.Ajax.install(); 5 | }); 6 | 7 | afterEach(function () { 8 | jasmine.Ajax.uninstall(); 9 | }); 10 | 11 | it('should support custom adapter', function (done) { 12 | axios('/foo', { 13 | adapter: function barAdapter(config) { 14 | return new Promise(function dispatchXhrRequest(resolve) { 15 | const request = new XMLHttpRequest(); 16 | request.open('GET', '/bar'); 17 | 18 | request.onreadystatechange = function () { 19 | resolve({ 20 | config: config, 21 | request: request 22 | }); 23 | }; 24 | 25 | request.send(null); 26 | }); 27 | } 28 | }).catch(done); 29 | 30 | getAjaxRequest().then(function(request) { 31 | expect(request.url).toBe('/bar'); 32 | done(); 33 | }); 34 | }); 35 | 36 | it('should execute adapter code synchronously', function (done) { 37 | let asyncFlag = false; 38 | axios('/foo', { 39 | adapter: function barAdapter(config) { 40 | return new Promise(function dispatchXhrRequest(resolve) { 41 | const request = new XMLHttpRequest(); 42 | request.open('GET', '/bar'); 43 | 44 | request.onreadystatechange = function () { 45 | resolve({ 46 | config: config, 47 | request: request 48 | }); 49 | }; 50 | 51 | expect(asyncFlag).toBe(false); 52 | request.send(null); 53 | }); 54 | } 55 | }).catch(done); 56 | 57 | asyncFlag = true; 58 | 59 | getAjaxRequest().then(function() { 60 | done(); 61 | }); 62 | }); 63 | 64 | it('should execute adapter code asynchronously when interceptor is present', function (done) { 65 | let asyncFlag = false; 66 | 67 | axios.interceptors.request.use(function (config) { 68 | config.headers.async = 'async it!'; 69 | return config; 70 | }); 71 | 72 | axios('/foo', { 73 | adapter: function barAdapter(config) { 74 | return new Promise(function dispatchXhrRequest(resolve) { 75 | const request = new XMLHttpRequest(); 76 | request.open('GET', '/bar'); 77 | 78 | request.onreadystatechange = function () { 79 | resolve({ 80 | config: config, 81 | request: request 82 | }); 83 | }; 84 | 85 | expect(asyncFlag).toBe(true); 86 | request.send(null); 87 | }); 88 | } 89 | }).catch(done); 90 | 91 | asyncFlag = true; 92 | 93 | getAjaxRequest().then(function() { 94 | done(); 95 | }); 96 | }); 97 | }); 98 | -------------------------------------------------------------------------------- /test/specs/api.spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('static api', function () { 3 | it('should have request method helpers', function () { 4 | expect(typeof axios.request).toEqual('function'); 5 | expect(typeof axios.get).toEqual('function'); 6 | expect(typeof axios.head).toEqual('function'); 7 | expect(typeof axios.options).toEqual('function'); 8 | expect(typeof axios.delete).toEqual('function'); 9 | expect(typeof axios.post).toEqual('function'); 10 | expect(typeof axios.put).toEqual('function'); 11 | expect(typeof axios.patch).toEqual('function'); 12 | }); 13 | 14 | it('should have promise method helpers', function () { 15 | const promise = axios('/test'); 16 | 17 | expect(typeof promise.then).toEqual('function'); 18 | expect(typeof promise.catch).toEqual('function'); 19 | }); 20 | 21 | it('should have defaults', function () { 22 | expect(typeof axios.defaults).toEqual('object'); 23 | expect(typeof axios.defaults.headers).toEqual('object'); 24 | }); 25 | 26 | it('should have interceptors', function () { 27 | expect(typeof axios.interceptors.request).toEqual('object'); 28 | expect(typeof axios.interceptors.response).toEqual('object'); 29 | }); 30 | 31 | it('should have all/spread helpers', function () { 32 | expect(typeof axios.all).toEqual('function'); 33 | expect(typeof axios.spread).toEqual('function'); 34 | }); 35 | 36 | it('should have factory method', function () { 37 | expect(typeof axios.create).toEqual('function'); 38 | }); 39 | 40 | it('should have CanceledError, CancelToken, and isCancel properties', function () { 41 | expect(typeof axios.Cancel).toEqual('function'); 42 | expect(typeof axios.CancelToken).toEqual('function'); 43 | expect(typeof axios.isCancel).toEqual('function'); 44 | }); 45 | 46 | it('should have getUri method', function() { 47 | expect(typeof axios.getUri).toEqual('function'); 48 | }); 49 | 50 | it('should have isAxiosError properties', function () { 51 | expect(typeof axios.isAxiosError).toEqual('function'); 52 | }); 53 | 54 | it('should have mergeConfig properties', function () { 55 | expect(typeof axios.mergeConfig).toEqual('function'); 56 | }); 57 | 58 | it('should have getAdapter properties', function () { 59 | expect(typeof axios.getAdapter).toEqual('function'); 60 | }); 61 | }); 62 | 63 | describe('instance api', function () { 64 | const instance = axios.create(); 65 | 66 | it('should have request methods', function () { 67 | expect(typeof instance.request).toEqual('function'); 68 | expect(typeof instance.get).toEqual('function'); 69 | expect(typeof instance.options).toEqual('function'); 70 | expect(typeof instance.head).toEqual('function'); 71 | expect(typeof instance.delete).toEqual('function'); 72 | expect(typeof instance.post).toEqual('function'); 73 | expect(typeof instance.put).toEqual('function'); 74 | expect(typeof instance.patch).toEqual('function'); 75 | }); 76 | 77 | it('should have interceptors', function () { 78 | expect(typeof instance.interceptors.request).toEqual('object'); 79 | expect(typeof instance.interceptors.response).toEqual('object'); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /test/specs/basicAuth.spec.js: -------------------------------------------------------------------------------- 1 | import axios from "../../index"; 2 | 3 | function validateInvalidCharacterError(error) { 4 | expect(/character/i.test(error.message)).toEqual(true); 5 | }; 6 | 7 | describe('basicAuth', function () { 8 | // Validate an invalid character error 9 | beforeEach(function () { 10 | jasmine.Ajax.install(); 11 | }); 12 | 13 | afterEach(function () { 14 | jasmine.Ajax.uninstall(); 15 | }); 16 | 17 | it('should accept HTTP Basic auth with username/password', function (done) { 18 | axios('/foo', { 19 | auth: { 20 | username: 'Aladdin', 21 | password: 'open sesame' 22 | } 23 | }); 24 | 25 | setTimeout(function () { 26 | const request = jasmine.Ajax.requests.mostRecent(); 27 | 28 | expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='); 29 | done(); 30 | }, 100); 31 | }); 32 | 33 | it('should accept HTTP Basic auth credentials without the password parameter', function (done) { 34 | axios('/foo', { 35 | auth: { 36 | username: 'Aladdin' 37 | } 38 | }); 39 | 40 | setTimeout(function () { 41 | const request = jasmine.Ajax.requests.mostRecent(); 42 | 43 | expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjo='); 44 | done(); 45 | }, 100); 46 | }); 47 | 48 | it('should accept HTTP Basic auth credentials with non-Latin1 characters in password', function (done) { 49 | axios('/foo', { 50 | auth: { 51 | username: 'Aladdin', 52 | password: 'open ßç£☃sesame' 53 | } 54 | }); 55 | 56 | setTimeout(function () { 57 | const request = jasmine.Ajax.requests.mostRecent(); 58 | 59 | expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjpvcGVuIMOfw6fCo+KYg3Nlc2FtZQ=='); 60 | done(); 61 | }, 100); 62 | }); 63 | 64 | it('should fail to encode HTTP Basic auth credentials with non-Latin1 characters in username', function (done) { 65 | axios('/foo', { 66 | auth: { 67 | username: 'Aladßç£☃din', 68 | password: 'open sesame' 69 | } 70 | }).then(function (response) { 71 | done(new Error('Should not succeed to make a HTTP Basic auth request with non-latin1 chars in credentials.')); 72 | }).catch(function (error) { 73 | validateInvalidCharacterError(error); 74 | done(); 75 | }); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/specs/cancel/CancelToken.spec.js: -------------------------------------------------------------------------------- 1 | import CancelToken from '../../../lib/cancel/CancelToken'; 2 | import CanceledError from '../../../lib/cancel/CanceledError'; 3 | 4 | describe('CancelToken', function() { 5 | describe('constructor', function() { 6 | it('throws when executor is not specified', function() { 7 | expect(function() { 8 | new CancelToken(); 9 | }).toThrowError(TypeError, 'executor must be a function.'); 10 | }); 11 | 12 | it('throws when executor is not a function', function() { 13 | expect(function() { 14 | new CancelToken(123); 15 | }).toThrowError(TypeError, 'executor must be a function.'); 16 | }); 17 | }); 18 | 19 | describe('reason', function() { 20 | it('returns a CanceledError if cancellation has been requested', function() { 21 | let cancel; 22 | const token = new CancelToken(function(c) { 23 | cancel = c; 24 | }); 25 | cancel('Operation has been canceled.'); 26 | expect(token.reason).toEqual(jasmine.any(CanceledError)); 27 | expect(token.reason.message).toBe('Operation has been canceled.'); 28 | }); 29 | 30 | it('returns undefined if cancellation has not been requested', function() { 31 | const token = new CancelToken(function() {}); 32 | expect(token.reason).toBeUndefined(); 33 | }); 34 | }); 35 | 36 | describe('promise', function() { 37 | it('returns a Promise that resolves when cancellation is requested', function(done) { 38 | let cancel; 39 | const token = new CancelToken(function(c) { 40 | cancel = c; 41 | }); 42 | token.promise.then(function onFulfilled(value) { 43 | expect(value).toEqual(jasmine.any(CanceledError)); 44 | expect(value.message).toBe('Operation has been canceled.'); 45 | done(); 46 | }); 47 | cancel('Operation has been canceled.'); 48 | }); 49 | }); 50 | 51 | describe('throwIfRequested', function() { 52 | it('throws if cancellation has been requested', function() { 53 | // Note: we cannot use expect.toThrowError here as CanceledError does not inherit from Error 54 | let cancel; 55 | const token = new CancelToken(function(c) { 56 | cancel = c; 57 | }); 58 | cancel('Operation has been canceled.'); 59 | try { 60 | token.throwIfRequested(); 61 | fail('Expected throwIfRequested to throw.'); 62 | } catch (thrown) { 63 | if (!(thrown instanceof CanceledError)) { 64 | fail('Expected throwIfRequested to throw a CanceledError, but it threw ' + thrown + '.'); 65 | } 66 | expect(thrown.message).toBe('Operation has been canceled.'); 67 | } 68 | }); 69 | 70 | it('does not throw if cancellation has not been requested', function() { 71 | const token = new CancelToken(function() {}); 72 | token.throwIfRequested(); 73 | }); 74 | }); 75 | 76 | describe('source', function() { 77 | it('returns an object containing token and cancel function', function() { 78 | const source = CancelToken.source(); 79 | expect(source.token).toEqual(jasmine.any(CancelToken)); 80 | expect(source.cancel).toEqual(jasmine.any(Function)); 81 | expect(source.token.reason).toBeUndefined(); 82 | source.cancel('Operation has been canceled.'); 83 | expect(source.token.reason).toEqual(jasmine.any(CanceledError)); 84 | expect(source.token.reason.message).toBe('Operation has been canceled.'); 85 | }); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /test/specs/cancel/CanceledError.spec.js: -------------------------------------------------------------------------------- 1 | import CanceledError from '../../../lib/cancel/CanceledError'; 2 | 3 | describe('Cancel', function() { 4 | describe('toString', function() { 5 | it('returns correct result when message is not specified', function() { 6 | const cancel = new CanceledError(); 7 | expect(cancel.toString()).toBe('CanceledError: canceled'); 8 | }); 9 | 10 | it('returns correct result when message is specified', function() { 11 | const cancel = new CanceledError('Operation has been canceled.'); 12 | expect(cancel.toString()).toBe('CanceledError: Operation has been canceled.'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/specs/cancel/isCancel.spec.js: -------------------------------------------------------------------------------- 1 | import isCancel from '../../../lib/cancel/isCancel'; 2 | import CanceledError from '../../../lib/cancel/CanceledError'; 3 | 4 | describe('isCancel', function() { 5 | it('returns true if value is a CanceledError', function() { 6 | expect(isCancel(new CanceledError())).toBe(true); 7 | }); 8 | 9 | it('returns false if value is not a CanceledError', function() { 10 | expect(isCancel({ foo: 'bar' })).toBe(false); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/core/AxiosError.spec.js: -------------------------------------------------------------------------------- 1 | import AxiosError from '../../../lib/core/AxiosError'; 2 | 3 | describe('core::AxiosError', function() { 4 | it('should create an Error with message, config, code, request, response, stack and isAxiosError', function() { 5 | const request = { path: '/foo' }; 6 | const response = { status: 200, data: { foo: 'bar' } }; 7 | const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); 8 | expect(error instanceof Error).toBe(true); 9 | expect(error.message).toBe('Boom!'); 10 | expect(error.config).toEqual({ foo: 'bar' }); 11 | expect(error.code).toBe('ESOMETHING'); 12 | expect(error.request).toBe(request); 13 | expect(error.response).toBe(response); 14 | expect(error.isAxiosError).toBe(true); 15 | expect(error.stack).toBeDefined(); 16 | }); 17 | it('should create an Error that can be serialized to JSON', function() { 18 | // Attempting to serialize request and response results in 19 | // TypeError: Converting circular structure to JSON 20 | const request = { path: '/foo' }; 21 | const response = { status: 200, data: { foo: 'bar' } }; 22 | const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); 23 | const json = error.toJSON(); 24 | expect(json.message).toBe('Boom!'); 25 | expect(json.config).toEqual({ foo: 'bar' }); 26 | expect(json.code).toBe('ESOMETHING'); 27 | expect(json.status).toBe(200); 28 | expect(json.request).toBe(undefined); 29 | expect(json.response).toBe(undefined); 30 | }); 31 | 32 | describe('core::createError.from', function() { 33 | it('should add config, config, request and response to error', function() { 34 | const error = new Error('Boom!'); 35 | const request = { path: '/foo' }; 36 | const response = { status: 200, data: { foo: 'bar' } }; 37 | 38 | const axiosError = AxiosError.from(error, 'ESOMETHING', { foo: 'bar' }, request, response); 39 | expect(axiosError.config).toEqual({ foo: 'bar' }); 40 | expect(axiosError.code).toBe('ESOMETHING'); 41 | expect(axiosError.request).toBe(request); 42 | expect(axiosError.response).toBe(response); 43 | expect(axiosError.isAxiosError).toBe(true); 44 | }); 45 | 46 | it('should return error', function() { 47 | const error = new Error('Boom!'); 48 | expect(AxiosError.from(error, 'ESOMETHING', { foo: 'bar' }) instanceof AxiosError).toBeTruthy(); 49 | }); 50 | }); 51 | 52 | it('should have status property when response was passed to the constructor', () => { 53 | const err = new AxiosError('test', 'foo', {}, {}, {status: 400}); 54 | expect(err.status).toBe(400); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /test/specs/core/buildFullPath.spec.js: -------------------------------------------------------------------------------- 1 | import buildFullPath from '../../../lib/core/buildFullPath'; 2 | 3 | describe('helpers::buildFullPath', function () { 4 | it('should combine URLs when the requestedURL is relative', function () { 5 | expect(buildFullPath('https://api.github.com', '/users')).toBe('https://api.github.com/users'); 6 | }); 7 | 8 | it('should not combine the URLs when the requestedURL is absolute', function () { 9 | expect(buildFullPath('https://api.github.com', 'https://api.example.com/users')).toBe('https://api.example.com/users'); 10 | }); 11 | 12 | it('should combine the URLs when the requestedURL is absolute and allowAbsoluteUrls is false', function () { 13 | expect(buildFullPath('https://api.github.com', 'https://api.example.com/users', false)).toBe('https://api.github.com/https://api.example.com/users'); 14 | }); 15 | 16 | it('should not combine the URLs when the requestedURL is absolute, allowAbsoluteUrls is false, and the baseURL is not configured', function () { 17 | expect(buildFullPath(undefined, 'https://api.example.com/users', false)).toBe('https://api.example.com/users'); 18 | }); 19 | 20 | it('should not combine URLs when the baseURL is not configured', function () { 21 | expect(buildFullPath(undefined, '/users')).toBe('/users'); 22 | }); 23 | 24 | it('should combine URLs when the baseURL and requestedURL are relative', function () { 25 | expect(buildFullPath('/api', '/users')).toBe('/api/users'); 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/specs/core/enhanceError.spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KOSASIH/axios/e61a8934d8f94dd429a2f309b48c67307c700df0/test/specs/core/enhanceError.spec.js -------------------------------------------------------------------------------- /test/specs/core/settle.spec.js: -------------------------------------------------------------------------------- 1 | import settle from '../../../lib/core/settle'; 2 | 3 | describe('core::settle', function() { 4 | let resolve; 5 | let reject; 6 | 7 | beforeEach(function() { 8 | resolve = jasmine.createSpy('resolve'); 9 | reject = jasmine.createSpy('reject'); 10 | }); 11 | 12 | it('should resolve promise if status is not set', function() { 13 | const response = { 14 | config: { 15 | validateStatus: function() { 16 | return true; 17 | } 18 | } 19 | }; 20 | settle(resolve, reject, response); 21 | expect(resolve).toHaveBeenCalledWith(response); 22 | expect(reject).not.toHaveBeenCalled(); 23 | }); 24 | 25 | it('should resolve promise if validateStatus is not set', function() { 26 | const response = { 27 | status: 500, 28 | config: { 29 | } 30 | }; 31 | settle(resolve, reject, response); 32 | expect(resolve).toHaveBeenCalledWith(response); 33 | expect(reject).not.toHaveBeenCalled(); 34 | }); 35 | 36 | it('should resolve promise if validateStatus returns true', function() { 37 | const response = { 38 | status: 500, 39 | config: { 40 | validateStatus: function() { 41 | return true; 42 | } 43 | } 44 | }; 45 | settle(resolve, reject, response); 46 | expect(resolve).toHaveBeenCalledWith(response); 47 | expect(reject).not.toHaveBeenCalled(); 48 | }); 49 | 50 | it('should reject promise if validateStatus returns false', function() { 51 | const req = { 52 | path: '/foo' 53 | }; 54 | const response = { 55 | status: 500, 56 | config: { 57 | validateStatus: function() { 58 | return false; 59 | } 60 | }, 61 | request: req 62 | }; 63 | settle(resolve, reject, response); 64 | expect(resolve).not.toHaveBeenCalled(); 65 | expect(reject).toHaveBeenCalled(); 66 | const reason = reject.calls.first().args[0]; 67 | expect(reason instanceof Error).toBe(true); 68 | expect(reason.message).toBe('Request failed with status code 500'); 69 | expect(reason.config).toBe(response.config); 70 | expect(reason.request).toBe(req); 71 | expect(reason.response).toBe(response); 72 | }); 73 | 74 | it('should pass status to validateStatus', function() { 75 | const validateStatus = jasmine.createSpy('validateStatus'); 76 | const response = { 77 | status: 500, 78 | config: { 79 | validateStatus: validateStatus 80 | } 81 | }; 82 | settle(resolve, reject, response); 83 | expect(validateStatus).toHaveBeenCalledWith(500); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /test/specs/core/transformData.spec.js: -------------------------------------------------------------------------------- 1 | import transformData from '../../../lib/core/transformData'; 2 | 3 | describe('core::transformData', function () { 4 | it('should support a single transformer', function () { 5 | let data; 6 | 7 | data = transformData.call({ 8 | 9 | }, function (data) { 10 | data = 'foo'; 11 | return data; 12 | }) 13 | 14 | expect(data).toEqual('foo'); 15 | }); 16 | 17 | it('should support an array of transformers', function () { 18 | let data = ''; 19 | data = transformData.call({data}, [function (data) { 20 | data += 'f'; 21 | return data; 22 | }, function (data) { 23 | data += 'o'; 24 | return data; 25 | }, function (data) { 26 | data += 'o'; 27 | return data; 28 | }]); 29 | 30 | expect(data).toEqual('foo'); 31 | }); 32 | 33 | it('should support reference headers in transformData', function () { 34 | const headers = { 35 | 'content-type': 'foo/bar', 36 | }; 37 | let data = ''; 38 | data = transformData.call({data, headers}, [function (data, headers) { 39 | data += headers['content-type']; 40 | return data; 41 | }]); 42 | 43 | expect(data).toEqual('foo/bar'); 44 | }); 45 | 46 | it('should support reference status code in transformData', function () { 47 | let data = ''; 48 | data = transformData.call({}, [function (data, headers, status) { 49 | data += status; 50 | return data; 51 | }], {data, status: 200}); 52 | 53 | expect(data).toEqual('200'); 54 | }); 55 | }); 56 | 57 | -------------------------------------------------------------------------------- /test/specs/formdata.spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('FormData', function() { 3 | it('should allow FormData posting', function () { 4 | return axios.postForm('http://httpbin.org/post', { 5 | a: 'foo', 6 | b: 'bar' 7 | }).then(({data}) => { 8 | expect(data.form).toEqual({ 9 | a: 'foo', 10 | b: 'bar' 11 | }); 12 | }); 13 | }); 14 | }) 15 | -------------------------------------------------------------------------------- /test/specs/helpers/bind.spec.js: -------------------------------------------------------------------------------- 1 | import bind from '../../../lib/helpers/bind'; 2 | 3 | describe('bind', function () { 4 | it('should bind an object to a function', function () { 5 | const o = { val: 123 }; 6 | const f = bind(function (num) { 7 | return this.val * num; 8 | }, o); 9 | 10 | expect(f(2)).toEqual(246); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/helpers/buildURL.spec.js: -------------------------------------------------------------------------------- 1 | import buildURL from '../../../lib/helpers/buildURL'; 2 | 3 | describe('helpers::buildURL', function () { 4 | it('should support null params', function () { 5 | expect(buildURL('/foo')).toEqual('/foo'); 6 | }); 7 | 8 | it('should support params', function () { 9 | expect(buildURL('/foo', { 10 | foo: 'bar', 11 | isUndefined: undefined, 12 | isNull: null 13 | })).toEqual('/foo?foo=bar'); 14 | }); 15 | 16 | it('should support sending raw params to custom serializer func', function () { 17 | const serializer = sinon.stub(); 18 | const params = { foo: "bar" }; 19 | serializer.returns("foo=bar"); 20 | expect( 21 | buildURL( 22 | "/foo", 23 | { 24 | foo: "bar", 25 | }, 26 | { 27 | serialize: serializer, 28 | } 29 | ) 30 | ).toEqual("/foo?foo=bar"); 31 | expect(serializer.calledOnce).toBe(true); 32 | expect(serializer.calledWith(params)).toBe(true); 33 | }); 34 | 35 | it('should support object params', function () { 36 | expect(buildURL('/foo', { 37 | foo: { 38 | bar: 'baz' 39 | } 40 | })).toEqual('/foo?foo[bar]=baz'); 41 | }); 42 | 43 | it('should support date params', function () { 44 | const date = new Date(); 45 | 46 | expect(buildURL('/foo', { 47 | date: date 48 | })).toEqual('/foo?date=' + date.toISOString()); 49 | }); 50 | 51 | it('should support array params', function () { 52 | expect(buildURL('/foo', { 53 | foo: ['bar', 'baz', null, undefined] 54 | })).toEqual('/foo?foo[]=bar&foo[]=baz'); 55 | }); 56 | 57 | it('should support special char params', function () { 58 | expect(buildURL('/foo', { 59 | foo: ':$, ' 60 | })).toEqual('/foo?foo=:$,+'); 61 | }); 62 | 63 | it('should support existing params', function () { 64 | expect(buildURL('/foo?foo=bar', { 65 | bar: 'baz' 66 | })).toEqual('/foo?foo=bar&bar=baz'); 67 | }); 68 | 69 | it('should support "length" parameter', function () { 70 | expect(buildURL('/foo', { 71 | query: 'bar', 72 | start: 0, 73 | length: 5 74 | })).toEqual('/foo?query=bar&start=0&length=5'); 75 | }); 76 | 77 | it('should correct discard url hash mark', function () { 78 | expect(buildURL('/foo?foo=bar#hash', { 79 | query: 'baz' 80 | })).toEqual('/foo?foo=bar&query=baz'); 81 | }); 82 | 83 | it('should support URLSearchParams', function () { 84 | expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz'); 85 | }); 86 | 87 | it('should support custom serialize function', function () { 88 | const params = { 89 | x: 1 90 | } 91 | 92 | const options = { 93 | serialize: (thisParams, thisOptions) => { 94 | expect(thisParams).toEqual(params); 95 | expect(thisOptions).toEqual(options); 96 | return "rendered" 97 | } 98 | }; 99 | 100 | expect(buildURL('/foo', params, options)).toEqual('/foo?rendered'); 101 | 102 | const customSerializer = (thisParams) => { 103 | expect(thisParams).toEqual(params); 104 | return "rendered" 105 | }; 106 | 107 | expect(buildURL('/foo', params, customSerializer)).toEqual('/foo?rendered'); 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /test/specs/helpers/combineURLs.spec.js: -------------------------------------------------------------------------------- 1 | import combineURLs from '../../../lib/helpers/combineURLs'; 2 | 3 | describe('helpers::combineURLs', function () { 4 | it('should combine URLs', function () { 5 | expect(combineURLs('https://api.github.com', '/users')).toBe('https://api.github.com/users'); 6 | }); 7 | 8 | it('should remove duplicate slashes', function () { 9 | expect(combineURLs('https://api.github.com/', '/users')).toBe('https://api.github.com/users'); 10 | }); 11 | 12 | it('should insert missing slash', function () { 13 | expect(combineURLs('https://api.github.com', 'users')).toBe('https://api.github.com/users'); 14 | }); 15 | 16 | it('should not insert slash when relative url missing/empty', function () { 17 | expect(combineURLs('https://api.github.com/users', '')).toBe('https://api.github.com/users'); 18 | }); 19 | 20 | it('should allow a single slash for relative url', function () { 21 | expect(combineURLs('https://api.github.com/users', '/')).toBe('https://api.github.com/users/'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/specs/helpers/cookies.spec.js: -------------------------------------------------------------------------------- 1 | import cookies from '../../../lib/helpers/cookies'; 2 | 3 | describe('helpers::cookies', function () { 4 | afterEach(function () { 5 | // Remove all the cookies 6 | const expires = Date.now() - (60 * 60 * 24 * 7); 7 | document.cookie.split(';').map(function (cookie) { 8 | return cookie.split('=')[0]; 9 | }).forEach(function (name) { 10 | document.cookie = name + '=; expires=' + new Date(expires).toGMTString(); 11 | }); 12 | }); 13 | 14 | it('should write cookies', function () { 15 | cookies.write('foo', 'baz'); 16 | expect(document.cookie).toEqual('foo=baz'); 17 | }); 18 | 19 | it('should read cookies', function () { 20 | cookies.write('foo', 'abc'); 21 | cookies.write('bar', 'def'); 22 | expect(cookies.read('foo')).toEqual('abc'); 23 | expect(cookies.read('bar')).toEqual('def'); 24 | }); 25 | 26 | it('should remove cookies', function () { 27 | cookies.write('foo', 'bar'); 28 | cookies.remove('foo'); 29 | expect(cookies.read('foo')).toEqual(null); 30 | }); 31 | 32 | it('should uri encode values', function () { 33 | cookies.write('foo', 'bar baz%'); 34 | expect(document.cookie).toEqual('foo=bar%20baz%25'); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/specs/helpers/formDataToJSON.spec.js: -------------------------------------------------------------------------------- 1 | import formDataToJSON from '../../../lib/helpers/formDataToJSON'; 2 | 3 | describe('formDataToJSON', function () { 4 | it('should convert a FormData Object to JSON Object', function () { 5 | const formData = new FormData(); 6 | 7 | formData.append('foo[bar][baz]', '123'); 8 | 9 | expect(formDataToJSON(formData)).toEqual({ 10 | foo: { 11 | bar: { 12 | baz: '123' 13 | } 14 | } 15 | }); 16 | }); 17 | 18 | it('should convert repeatable values as an array', function () { 19 | const formData = new FormData(); 20 | 21 | formData.append('foo', '1'); 22 | formData.append('foo', '2'); 23 | 24 | expect(formDataToJSON(formData)).toEqual({ 25 | foo: ['1', '2'] 26 | }); 27 | }); 28 | 29 | it('should convert props with empty brackets to arrays', function () { 30 | const formData = new FormData(); 31 | 32 | formData.append('foo[]', '1'); 33 | formData.append('foo[]', '2'); 34 | 35 | expect(formDataToJSON(formData)).toEqual({ 36 | foo: ['1', '2'] 37 | }); 38 | }); 39 | 40 | it('should supported indexed arrays', function () { 41 | const formData = new FormData(); 42 | 43 | formData.append('foo[0]', '1'); 44 | formData.append('foo[1]', '2'); 45 | 46 | expect(formDataToJSON(formData)).toEqual({ 47 | foo: ['1', '2'] 48 | }); 49 | }); 50 | 51 | it('should resist prototype pollution CVE', () => { 52 | const formData = new FormData(); 53 | 54 | formData.append('foo[0]', '1'); 55 | formData.append('foo[1]', '2'); 56 | formData.append('__proto__.x', 'hack'); 57 | formData.append('constructor.prototype.y', 'value'); 58 | 59 | expect(formDataToJSON(formData)).toEqual({ 60 | foo: ['1', '2'], 61 | constructor: { 62 | prototype: { 63 | y: 'value' 64 | } 65 | } 66 | }); 67 | 68 | expect({}.x).toEqual(undefined); 69 | expect({}.y).toEqual(undefined); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /test/specs/helpers/isAbsoluteURL.spec.js: -------------------------------------------------------------------------------- 1 | import isAbsoluteURL from '../../../lib/helpers/isAbsoluteURL'; 2 | 3 | describe('helpers::isAbsoluteURL', function () { 4 | it('should return true if URL begins with valid scheme name', function () { 5 | expect(isAbsoluteURL('https://api.github.com/users')).toBe(true); 6 | expect(isAbsoluteURL('custom-scheme-v1.0://example.com/')).toBe(true); 7 | expect(isAbsoluteURL('HTTP://example.com/')).toBe(true); 8 | }); 9 | 10 | it('should return false if URL begins with invalid scheme name', function () { 11 | expect(isAbsoluteURL('123://example.com/')).toBe(false); 12 | expect(isAbsoluteURL('!valid://example.com/')).toBe(false); 13 | }); 14 | 15 | it('should return true if URL is protocol-relative', function () { 16 | expect(isAbsoluteURL('//example.com/')).toBe(true); 17 | }); 18 | 19 | it('should return false if URL is relative', function () { 20 | expect(isAbsoluteURL('/foo')).toBe(false); 21 | expect(isAbsoluteURL('foo')).toBe(false); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/specs/helpers/isAxiosError.spec.js: -------------------------------------------------------------------------------- 1 | import AxiosError from '../../../lib/core/AxiosError'; 2 | import isAxiosError from '../../../lib/helpers/isAxiosError'; 3 | 4 | describe('helpers::isAxiosError', function() { 5 | it('should return true if the error is created by core::createError', function() { 6 | expect(isAxiosError(new AxiosError('Boom!', null, { foo: 'bar' }))) 7 | .toBe(true); 8 | }); 9 | 10 | it('should return true if the error is enhanced by core::enhanceError', function() { 11 | expect(isAxiosError(AxiosError.from(new Error('Boom!'), null, { foo: 'bar' }))) 12 | .toBe(true); 13 | }); 14 | 15 | it('should return false if the error is a normal Error instance', function() { 16 | expect(isAxiosError(new Error('Boom!'))) 17 | .toBe(false); 18 | }); 19 | 20 | it('should return false if the error is null', function () { 21 | expect(isAxiosError(null)) 22 | .toBe(false); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/specs/helpers/isURLSameOrigin.spec.js: -------------------------------------------------------------------------------- 1 | import isURLSameOrigin from '../../../lib/helpers/isURLSameOrigin'; 2 | 3 | describe('helpers::isURLSameOrigin', function () { 4 | it('should detect same origin', function () { 5 | expect(isURLSameOrigin(window.location.href)).toEqual(true); 6 | }); 7 | 8 | it('should detect different origin', function () { 9 | expect(isURLSameOrigin('https://github.com/axios/axios')).toEqual(false); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/specs/helpers/parseHeaders.spec.js: -------------------------------------------------------------------------------- 1 | import parseHeaders from '../../../lib/helpers/parseHeaders'; 2 | 3 | describe('helpers::parseHeaders', function () { 4 | it('should parse headers', function () { 5 | const date = new Date(); 6 | const parsed = parseHeaders( 7 | 'Date: ' + date.toISOString() + '\n' + 8 | 'Content-Type: application/json\n' + 9 | 'Connection: keep-alive\n' + 10 | 'Transfer-Encoding: chunked' 11 | ); 12 | 13 | expect(parsed['date']).toEqual(date.toISOString()); 14 | expect(parsed['content-type']).toEqual('application/json'); 15 | expect(parsed['connection']).toEqual('keep-alive'); 16 | expect(parsed['transfer-encoding']).toEqual('chunked'); 17 | }); 18 | 19 | it('should use array for set-cookie', function() { 20 | const parsedZero = parseHeaders(''); 21 | const parsedSingle = parseHeaders( 22 | 'Set-Cookie: key=val;' 23 | ); 24 | const parsedMulti = parseHeaders( 25 | 'Set-Cookie: key=val;\n' + 26 | 'Set-Cookie: key2=val2;\n' 27 | ); 28 | 29 | expect(parsedZero['set-cookie']).toBeUndefined(); 30 | expect(parsedSingle['set-cookie']).toEqual(['key=val;']); 31 | expect(parsedMulti['set-cookie']).toEqual(['key=val;', 'key2=val2;']); 32 | }); 33 | 34 | it('should handle duplicates', function() { 35 | const parsed = parseHeaders( 36 | 'Age: age-a\n' + // age is in ignore duplicates blocklist 37 | 'Age: age-b\n' + 38 | 'Foo: foo-a\n' + 39 | 'Foo: foo-b\n' 40 | ); 41 | 42 | expect(parsed['age']).toEqual('age-a'); 43 | expect(parsed['foo']).toEqual('foo-a, foo-b'); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/specs/helpers/spread.spec.js: -------------------------------------------------------------------------------- 1 | import spread from '../../../lib/helpers/spread'; 2 | 3 | describe('helpers::spread', function () { 4 | it('should spread array to arguments', function () { 5 | let value = 0; 6 | spread(function (a, b) { 7 | value = a * b; 8 | })([5, 10]); 9 | 10 | expect(value).toEqual(50); 11 | }); 12 | 13 | it('should return callback result', function () { 14 | const value = spread(function (a, b) { 15 | return a * b; 16 | })([5, 10]); 17 | 18 | expect(value).toEqual(50); 19 | }); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /test/specs/helpers/validator.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import validator from '../../../lib/helpers/validator'; 4 | 5 | describe('validator::assertOptions', function() { 6 | it('should throw only if unknown an option was passed', function() { 7 | expect(function() { 8 | validator.assertOptions({ 9 | x: true 10 | }, { 11 | y: validator.validators.boolean 12 | }); 13 | }).toThrow(new Error('Unknown option x')); 14 | 15 | expect(function() { 16 | validator.assertOptions({ 17 | x: true 18 | }, { 19 | x: validator.validators.boolean, 20 | y: validator.validators.boolean 21 | }); 22 | }).not.toThrow(new Error('Unknown option x')); 23 | }); 24 | 25 | it('should throw TypeError only if option type doesn\'t match', function() { 26 | expect(function() { 27 | validator.assertOptions({ 28 | x: 123 29 | }, { 30 | x: validator.validators.boolean 31 | }); 32 | }).toThrow(new TypeError('option x must be a boolean')); 33 | 34 | expect(function() { 35 | validator.assertOptions({ 36 | x: true 37 | }, { 38 | x: validator.validators.boolean, 39 | y: validator.validators.boolean 40 | }); 41 | }).not.toThrow(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/specs/promise.spec.js: -------------------------------------------------------------------------------- 1 | describe('promise', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | }); 9 | 10 | it('should provide succinct object to then', function (done) { 11 | let response; 12 | 13 | axios('/foo').then(function (r) { 14 | response = r; 15 | }); 16 | 17 | getAjaxRequest().then(function (request) { 18 | request.respondWith({ 19 | status: 200, 20 | responseText: '{"hello":"world"}' 21 | }); 22 | 23 | setTimeout(function () { 24 | expect(typeof response).toEqual('object'); 25 | expect(response.data.hello).toEqual('world'); 26 | expect(response.status).toEqual(200); 27 | expect(response.headers['content-type']).toEqual('application/json'); 28 | expect(response.config.url).toEqual('/foo'); 29 | done(); 30 | }, 100); 31 | }); 32 | }); 33 | 34 | it('should support all', function (done) { 35 | let fulfilled = false; 36 | 37 | axios.all([true, 123]).then(function () { 38 | fulfilled = true; 39 | }); 40 | 41 | setTimeout(function () { 42 | expect(fulfilled).toEqual(true); 43 | done(); 44 | }, 100); 45 | }); 46 | 47 | it('should support spread', function (done) { 48 | let sum = 0; 49 | let fulfilled = false; 50 | let result; 51 | 52 | axios 53 | .all([123, 456]) 54 | .then(axios.spread(function (a, b) { 55 | sum = a + b; 56 | fulfilled = true; 57 | return 'hello world'; 58 | })) 59 | .then(function (res) { 60 | result = res; 61 | }).catch(done); 62 | 63 | setTimeout(function () { 64 | expect(fulfilled).toEqual(true); 65 | expect(sum).toEqual(123 + 456); 66 | expect(result).toEqual('hello world'); 67 | done(); 68 | }, 100); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /test/specs/utils/endsWith.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {kindOf} = utils; 4 | 5 | describe('utils::kindOf', function () { 6 | it('should return object tag', function () { 7 | expect(kindOf({})).toEqual('object'); 8 | // cached result 9 | expect(kindOf({})).toEqual('object'); 10 | expect(kindOf([])).toEqual('array'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/utils/extend.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {extend} = utils; 4 | 5 | describe('utils::extend', function () { 6 | it('should be mutable', function () { 7 | const a = {}; 8 | const b = {foo: 123}; 9 | 10 | extend(a, b); 11 | 12 | expect(a.foo).toEqual(b.foo); 13 | }); 14 | 15 | it('should extend properties', function () { 16 | let a = {foo: 123, bar: 456}; 17 | const b = {bar: 789}; 18 | 19 | a = extend(a, b); 20 | 21 | expect(a.foo).toEqual(123); 22 | expect(a.bar).toEqual(789); 23 | }); 24 | 25 | it('should bind to thisArg', function () { 26 | const a = {}; 27 | const b = {getFoo: function getFoo() { return this.foo; }}; 28 | const thisArg = { foo: 'barbaz' }; 29 | 30 | extend(a, b, thisArg); 31 | 32 | expect(typeof a.getFoo).toEqual('function'); 33 | expect(a.getFoo()).toEqual(thisArg.foo); 34 | }); 35 | }); 36 | 37 | -------------------------------------------------------------------------------- /test/specs/utils/forEach.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {forEach} = utils; 4 | 5 | describe('utils::forEach', function () { 6 | it('should loop over an array', function () { 7 | let sum = 0; 8 | 9 | forEach([1, 2, 3, 4, 5], function (val) { 10 | sum += val; 11 | }); 12 | 13 | expect(sum).toEqual(15); 14 | }); 15 | 16 | it('should loop over object keys', function () { 17 | let keys = ''; 18 | let vals = 0; 19 | const obj = { 20 | b: 1, 21 | a: 2, 22 | r: 3 23 | }; 24 | 25 | forEach(obj, function (v, k) { 26 | keys += k; 27 | vals += v; 28 | }); 29 | 30 | expect(keys).toEqual('bar'); 31 | expect(vals).toEqual(6); 32 | }); 33 | 34 | it('should handle undefined gracefully', function () { 35 | let count = 0; 36 | 37 | forEach(undefined, function () { 38 | count++; 39 | }); 40 | 41 | expect(count).toEqual(0); 42 | }); 43 | 44 | it('should make an array out of non-array argument', function () { 45 | let count = 0; 46 | 47 | forEach(function () {}, function () { 48 | count++; 49 | }); 50 | 51 | expect(count).toEqual(1); 52 | }); 53 | 54 | it('should handle non object prototype gracefully', function () { 55 | let count = 0; 56 | const data = Object.create(null); 57 | data.foo = 'bar' 58 | 59 | forEach(data, function () { 60 | count++; 61 | }); 62 | 63 | expect(count).toEqual(1); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/specs/utils/isX.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | describe('utils::isX', function () { 4 | it('should validate Array', function () { 5 | expect(utils.isArray([])).toEqual(true); 6 | expect(utils.isArray({length: 5})).toEqual(false); 7 | }); 8 | 9 | it('should validate ArrayBuffer', function () { 10 | expect(utils.isArrayBuffer(new ArrayBuffer(2))).toEqual(true); 11 | expect(utils.isArrayBuffer({})).toEqual(false); 12 | }); 13 | 14 | it('should validate ArrayBufferView', function () { 15 | expect(utils.isArrayBufferView(new DataView(new ArrayBuffer(2)))).toEqual(true); 16 | }); 17 | 18 | it('should validate FormData', function () { 19 | expect(utils.isFormData(new FormData())).toEqual(true); 20 | }); 21 | 22 | it('should validate Blob', function () { 23 | expect(utils.isBlob(new Blob())).toEqual(true); 24 | }); 25 | 26 | it('should validate String', function () { 27 | expect(utils.isString('')).toEqual(true); 28 | expect(utils.isString({toString: function () { return ''; }})).toEqual(false); 29 | }); 30 | 31 | it('should validate Number', function () { 32 | expect(utils.isNumber(123)).toEqual(true); 33 | expect(utils.isNumber('123')).toEqual(false); 34 | }); 35 | 36 | it('should validate Undefined', function () { 37 | expect(utils.isUndefined()).toEqual(true); 38 | expect(utils.isUndefined(null)).toEqual(false); 39 | }); 40 | 41 | it('should validate Object', function () { 42 | expect(utils.isObject({})).toEqual(true); 43 | expect(utils.isObject([])).toEqual(true); 44 | expect(utils.isObject(null)).toEqual(false); 45 | }); 46 | 47 | it('should validate plain Object', function () { 48 | expect(utils.isPlainObject({})).toEqual(true); 49 | expect(utils.isPlainObject([])).toEqual(false); 50 | expect(utils.isPlainObject(null)).toEqual(false); 51 | expect(utils.isPlainObject(Object.create({}))).toEqual(false); 52 | }); 53 | 54 | it('should validate Date', function () { 55 | expect(utils.isDate(new Date())).toEqual(true); 56 | expect(utils.isDate(Date.now())).toEqual(false); 57 | }); 58 | 59 | it('should validate Function', function () { 60 | expect(utils.isFunction(function () {})).toEqual(true); 61 | expect(utils.isFunction('function')).toEqual(false); 62 | }); 63 | 64 | it('should validate URLSearchParams', function () { 65 | expect(utils.isURLSearchParams(new URLSearchParams())).toEqual(true); 66 | expect(utils.isURLSearchParams('foo=1&bar=2')).toEqual(false); 67 | }); 68 | 69 | it('should validate TypedArray instance', function () { 70 | expect(utils.isTypedArray(new Uint8Array([1, 2, 3]))).toEqual(true); 71 | expect(utils.isTypedArray([1, 2, 3])).toEqual(false); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/specs/utils/kindOf.js: -------------------------------------------------------------------------------- 1 | import {kindOfTest} from '../../../lib/utils'; 2 | 3 | describe('utils::endsWith', function () { 4 | it('should return true if the string ends with passed substring', function () { 5 | const test = kindOfTest('number'); 6 | 7 | expect(test(123)).toEqual(true); 8 | expect(test('123')).toEqual(false); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/specs/utils/kindOfTest.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {kindOf} = utils; 4 | 5 | describe('utils::kindOf', function () { 6 | it('should return object tag', function () { 7 | expect(kindOf({})).toEqual('object'); 8 | // cached result 9 | expect(kindOf({})).toEqual('object'); 10 | expect(kindOf([])).toEqual('array'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/utils/merge.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {merge} = utils; 4 | 5 | describe('utils::merge', function () { 6 | it('should be immutable', function () { 7 | const a = {}; 8 | const b = {foo: 123}; 9 | const c = {bar: 456}; 10 | 11 | merge(a, b, c); 12 | 13 | expect(typeof a.foo).toEqual('undefined'); 14 | expect(typeof a.bar).toEqual('undefined'); 15 | expect(typeof b.bar).toEqual('undefined'); 16 | expect(typeof c.foo).toEqual('undefined'); 17 | }); 18 | 19 | it('should merge properties', function () { 20 | const a = {foo: 123}; 21 | const b = {bar: 456}; 22 | const c = {foo: 789}; 23 | const d = merge(a, b, c); 24 | 25 | expect(d.foo).toEqual(789); 26 | expect(d.bar).toEqual(456); 27 | }); 28 | 29 | it('should merge recursively', function () { 30 | const a = {foo: {bar: 123}}; 31 | const b = {foo: {baz: 456}, bar: {qux: 789}}; 32 | 33 | expect(merge(a, b)).toEqual({ 34 | foo: { 35 | bar: 123, 36 | baz: 456 37 | }, 38 | bar: { 39 | qux: 789 40 | } 41 | }); 42 | }); 43 | 44 | it('should remove all references from nested objects', function () { 45 | const a = {foo: {bar: 123}}; 46 | const b = {}; 47 | const d = merge(a, b); 48 | 49 | expect(d).toEqual({ 50 | foo: { 51 | bar: 123 52 | } 53 | }); 54 | 55 | expect(d.foo).not.toBe(a.foo); 56 | }); 57 | 58 | it('handles null and undefined arguments', function () { 59 | expect(merge(undefined, undefined)).toEqual({}); 60 | expect(merge(undefined, {foo: 123})).toEqual({foo: 123}); 61 | expect(merge({foo: 123}, undefined)).toEqual({foo: 123}); 62 | 63 | expect(merge(null, null)).toEqual({}); 64 | expect(merge(null, {foo: 123})).toEqual({foo: 123}); 65 | expect(merge({foo: 123}, null)).toEqual({foo: 123}); 66 | }); 67 | 68 | it('should replace properties with null', function () { 69 | expect(merge({}, {a: null})).toEqual({a: null}); 70 | expect(merge({a: null}, {})).toEqual({a: null}); 71 | }); 72 | 73 | it('should replace properties with arrays', function () { 74 | expect(merge({}, {a: [1, 2, 3]})).toEqual({a: [1, 2, 3]}); 75 | expect(merge({a: 2}, {a: [1, 2, 3]})).toEqual({a: [1, 2, 3]}); 76 | expect(merge({a: {b: 2}}, {a: [1, 2, 3]})).toEqual({a: [1, 2, 3]}); 77 | }); 78 | 79 | it('should replace properties with cloned arrays', function () { 80 | const a = [1, 2, 3]; 81 | const d = merge({}, {a: a}); 82 | 83 | expect(d).toEqual({a: [1, 2, 3]}); 84 | expect(d.a).not.toBe(a); 85 | }); 86 | 87 | it('should support caseless option', ()=> { 88 | const a = {x: 1}; 89 | const b = {X: 2}; 90 | const merged = merge.call({caseless: true}, a, b); 91 | 92 | expect(merged).toEqual({ 93 | x: 2 94 | }); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /test/specs/utils/toArray.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {toArray} = utils; 4 | 5 | describe('utils::kindOf', function () { 6 | it('should return object tag', function () { 7 | expect(toArray()).toEqual(null); 8 | expect(toArray([])).toEqual([]); 9 | expect(toArray([1])).toEqual([1]); 10 | expect(toArray([1, 2, 3])).toEqual([1, 2, 3]); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/utils/toFlatObject.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | const {toFlatObject} = utils; 4 | 5 | describe('utils::toFlatObject', function () { 6 | it('should resolve object proto chain to a flat object representation', function () { 7 | const a = {x: 1}; 8 | const b = Object.create(a, {y: {value: 2}}); 9 | const c = Object.create(b, {z: {value: 3}}); 10 | expect(toFlatObject(c)).toEqual({x: 1, y: 2, z: 3}); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/utils/trim.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../../../lib/utils'; 2 | 3 | describe('utils::trim', function () { 4 | it('should trim spaces', function () { 5 | expect(utils.trim(' foo ')).toEqual('foo'); 6 | }); 7 | 8 | it('should trim tabs', function () { 9 | expect(utils.trim('\tfoo\t')).toEqual('foo'); 10 | }); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /test/unit/adapters/adapters.js: -------------------------------------------------------------------------------- 1 | import adapters from '../../../lib/adapters/adapters.js'; 2 | import assert from 'assert'; 3 | 4 | 5 | describe('adapters', function () { 6 | const store = {...adapters.adapters}; 7 | 8 | beforeEach(() => { 9 | Object.keys(adapters.adapters).forEach((name) => { 10 | delete adapters.adapters[name]; 11 | }); 12 | 13 | Object.assign(adapters.adapters, store); 14 | }); 15 | 16 | it('should support loading by fn handle', function () { 17 | const adapter = () => {}; 18 | assert.strictEqual(adapters.getAdapter(adapter), adapter); 19 | }); 20 | 21 | it('should support loading by name', function () { 22 | const adapter = () => {}; 23 | adapters.adapters['testadapter'] = adapter; 24 | assert.strictEqual(adapters.getAdapter('testAdapter'), adapter); 25 | }); 26 | 27 | it('should detect adapter unavailable status', function () { 28 | adapters.adapters['testadapter'] = null; 29 | assert.throws(()=> adapters.getAdapter('testAdapter'), /is not available in the build/) 30 | }); 31 | 32 | it('should detect adapter unsupported status', function () { 33 | adapters.adapters['testadapter'] = false; 34 | assert.throws(()=> adapters.getAdapter('testAdapter'), /is not supported by the environment/) 35 | }); 36 | 37 | it('should pick suitable adapter from the list', function () { 38 | const adapter = () => {}; 39 | 40 | Object.assign(adapters.adapters, { 41 | foo: false, 42 | bar: null, 43 | baz: adapter 44 | }); 45 | 46 | assert.strictEqual(adapters.getAdapter(['foo', 'bar', 'baz']), adapter); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /test/unit/adapters/axios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KOSASIH/axios/e61a8934d8f94dd429a2f309b48c67307c700df0/test/unit/adapters/axios.png -------------------------------------------------------------------------------- /test/unit/adapters/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICpDCCAYwCCQDbqELLwgbPdDANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls 3 | b2NhbGhvc3QwHhcNMjAwNjI2MjIxMTQ3WhcNNDcxMTExMjIxMTQ3WjAUMRIwEAYD 4 | VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD6 5 | Ogt99/dZ0UgbCuVV1RZ9n28Ov3DzrJCkjperQoXomIq3Fr4RUI1a2rwe3mtl3UzE 6 | 1IVZVvWPGdEsEQHwXfAsP/jFGTwI3HDyOhcqzFQSKsjvqJWYkOOb+2r3SBrFlRZW 7 | 09k/3lC+hx2XtuuG68u4Xgn3AlUvm2vplgCN7eiYcGeNwVuf2eHdOqTRTqiYCZLi 8 | T8GtdYMDXOrwsGZs/jUKd9U0ar/lqwMhmw07yzlVDM2MWM2tyq/asQ7Sf7vuoMFu 9 | oAtDJ3E+bK1k/7SNhdyP4RonhyUCkWG+mzoKDS1qgXroTiQSDUksAvOCTcj8BNIT 10 | ee+Lcn9FaTKNJiKiU9q/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi5ZpaUj+mU 11 | dsgOka+j2/njgNXux3cOjhm7z/N7LeTuDENAOrYa5b+j5JX/YM7RKHrkbXHsQbfs 12 | GB3ufH6QhSiCd/AdsXp/TbCE/8gdq8ykkjwVP1bvBle9oPH7x1aO/WP/odsepYUv 13 | o9aOZW4iNQVmwamU62ezglf3QD7HPeE4LnZueaFtuzRoC+aWT9v0MIeUPJLe3WDQ 14 | FEySwUuthMDJEv92/TeK0YOiunmseCu2mvdiDj6E3C9xa5q2DWgl+msu7+bPgvYO 15 | GuWaoNeQQGk7ebBO3Hk3IyaGx6Cbd8ty+YaZW7dUT+m7KCs1VkxdcDMjZJVWiJy4 16 | 4HcEcKboG4Y= 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /test/unit/adapters/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA+joLfff3WdFIGwrlVdUWfZ9vDr9w86yQpI6Xq0KF6JiKtxa+ 3 | EVCNWtq8Ht5rZd1MxNSFWVb1jxnRLBEB8F3wLD/4xRk8CNxw8joXKsxUEirI76iV 4 | mJDjm/tq90gaxZUWVtPZP95Qvocdl7brhuvLuF4J9wJVL5tr6ZYAje3omHBnjcFb 5 | n9nh3Tqk0U6omAmS4k/BrXWDA1zq8LBmbP41CnfVNGq/5asDIZsNO8s5VQzNjFjN 6 | rcqv2rEO0n+77qDBbqALQydxPmytZP+0jYXcj+EaJ4clApFhvps6Cg0taoF66E4k 7 | Eg1JLALzgk3I/ATSE3nvi3J/RWkyjSYiolPavwIDAQABAoIBAEbMi5ndwjfAlkVI 8 | hPEPNKjgpnymwB/CEL7utY04akkQeBcrsSWXBBfT0exuBDczMVhzxTMs/pe5t0xf 9 | l4vaGG18wDeMV0cukCqJMyrh21u0jVv5+DHNtQjaTz6eQSzsbQCuOkbu8SuncUEO 10 | +X8YUnDc8rbYCyBIOnVCAvAlg201uW0G5G9NEwJOu6cAKMKkogdHqv+FRX96C5hm 11 | gtbGEzpGV2vVClgMwMcX49ucluZvqLvit/yehNVd0VOtW/kuLup4R6q0abHRapDd 12 | 95rJAhPvar4mzP+UgJrGQ9hozqhizDthBjnsmGeMBUiBCkay7OXIZpvLoCpQkti1 13 | WIWuikkCgYEA/oZqq71RT1nPuI7rlcjx3AeWe2EUQtKhQMJBiPx5eLLP6gII8+v2 14 | pD1qlmJM2eyIK0lzuskLIulTAA5Z+ejORDbvmn/DdT0CSvdrUFrcvnrRQnt2M5M2 15 | 9VDRp6nvPE0H4kRZJrtITyLn0dv5ABf2L32i4dPCMePjKjSUygJSHrsCgYEA+61A 16 | cIqch/lrQTk8hG7Y6p0EJzSInFVaKuZoMYpLhlDQcVvSDIQbGgRAN6BKTdxeQ+tK 17 | hSxBSm2mze11aHig8GBGgdBFLaJOZRo6G+2fl+s1t1FCHfsaFhHwheZJONHMpKKd 18 | Qm/7L/V35QV9YG0lPZ01TM6d5lXuKsmUNvBJTc0CgYASYajAgGqn3WeX/5JZ/eoh 19 | ptaiUG+DJ+0HXUAYYYtwQRGs57q3yvnEAL963tyH/IIVBjf6bFyGh+07ms26s6p5 20 | 2LHTKZj3FZHd0iKI6hb5FquYLoxpyx7z9oM9pZMmerWwDJmXp3zgYjf1uvovnItm 21 | AJ/LyVxD+B5GxQdd028U0wKBgG4OllZglxDzJk7wa6FyI9N89Fr8oxzSSkrmVPwN 22 | APfskSpxP8qPXpai8z4gDz47NtG2q/DOqIKWrtHwnF4iGibjwxFzdTz+dA/MR0r9 23 | P8QcbHIMy7/2lbK/B5JWYQDC5h28qs5pz8tqKZLyMqCfOiDWhX9f/zbBrxPw8KqR 24 | q0ylAoGAL/0kemA/Tmxpwmp0S0oCqnA4gbCgS7qnApxB09xTewc/tuvraXc3Mzea 25 | EvqDXLXK0R7O4E3vo0Mr23SodRVlFPevsmUUJLPJMJcxdfnSJgX+qE/UC8Ux+UMi 26 | eYufYRDYSslfL2rt9D7abnnbqSfsHymJKukWpElIgJTklQUru4k= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/unit/core/Axios.js: -------------------------------------------------------------------------------- 1 | import Axios from "../../../lib/core/Axios.js"; 2 | import assert from "assert"; 3 | 4 | describe('Axios', function () { 5 | describe("handle un-writable error stack", function () { 6 | async function testUnwritableErrorStack(stackAttributes) { 7 | const axios = new Axios({}); 8 | // mock axios._request to return an Error with an un-writable stack property 9 | axios._request = () => { 10 | const mockError = new Error("test-error"); 11 | Object.defineProperty(mockError, "stack", stackAttributes); 12 | throw mockError; 13 | } 14 | try { 15 | await axios.request("test-url", {}) 16 | } catch (e) { 17 | assert.strictEqual(e.message, "test-error") 18 | } 19 | } 20 | 21 | it('should support errors with a defined but un-writable stack', async function () { 22 | await testUnwritableErrorStack({value: {}, writable: false}) 23 | }); 24 | 25 | it('should support errors with an undefined and un-writable stack', async function () { 26 | await testUnwritableErrorStack({value: undefined, writable: false}) 27 | }); 28 | 29 | it('should support errors with a custom getter/setter for the stack property', async function () { 30 | await testUnwritableErrorStack({ 31 | get: () => ({}), 32 | set: () => { 33 | throw new Error('read-only'); 34 | } 35 | }) 36 | }); 37 | 38 | it('should support errors with a custom getter/setter for the stack property (null case)', async function () { 39 | await testUnwritableErrorStack({ 40 | get: () => null, 41 | set: () => { 42 | throw new Error('read-only'); 43 | } 44 | }) 45 | }); 46 | }); 47 | 48 | it('should not throw if the config argument is omitted', () => { 49 | const axios = new Axios(); 50 | 51 | assert.deepStrictEqual(axios.defaults, {}); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/defaults/transformReponse.js: -------------------------------------------------------------------------------- 1 | import defaults from '../../../lib/defaults/index.js'; 2 | import transformData from '../../../lib/core/transformData.js'; 3 | import assert from 'assert'; 4 | 5 | describe('transformResponse', function () { 6 | describe('200 request', function () { 7 | it('parses json', function () { 8 | const data = '{"message": "hello, world"}'; 9 | const result = transformData.call({ 10 | data, 11 | response: { 12 | headers: {'content-type': 'application/json'}, 13 | status: 200 14 | } 15 | }, defaults.transformResponse); 16 | assert.strictEqual(result.message, 'hello, world'); 17 | }); 18 | it('ignores XML', function () { 19 | const data = 'hello, world'; 20 | const result = transformData.call({ 21 | data, 22 | response: { 23 | headers: {'content-type': 'text/xml'}, 24 | status: 200 25 | } 26 | }, defaults.transformResponse); 27 | assert.strictEqual(result, data); 28 | }); 29 | }); 30 | describe('204 request', function () { 31 | it('does not parse the empty string', function () { 32 | const data = ''; 33 | const result = transformData.call({ 34 | data, 35 | response: { 36 | headers: {'content-type': undefined}, 37 | status: 204 38 | } 39 | }, defaults.transformResponse); 40 | assert.strictEqual(result, ''); 41 | }); 42 | it('does not parse undefined', function () { 43 | const data = undefined; 44 | const result = transformData.call({ 45 | data, 46 | response: { 47 | headers: {'content-type': undefined}, 48 | status: 200 49 | } 50 | }, defaults.transformResponse); 51 | assert.strictEqual(result, data); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/unit/helpers/composeSignals.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import composeSignals from '../../../lib/helpers/composeSignals.js'; 3 | 4 | describe('helpers::composeSignals', () => { 5 | before(function () { 6 | if (typeof AbortController !== 'function') { 7 | this.skip(); 8 | } 9 | }); 10 | 11 | it('should abort when any of the signals abort', () => { 12 | let called; 13 | 14 | const controllerA = new AbortController(); 15 | const controllerB = new AbortController(); 16 | 17 | const signal = composeSignals([controllerA.signal, controllerB.signal]); 18 | 19 | signal.addEventListener('abort', () => { 20 | called = true; 21 | }); 22 | 23 | controllerA.abort(new Error('test')); 24 | 25 | assert.ok(called); 26 | }); 27 | 28 | it('should abort on timeout', async () => { 29 | const signal = composeSignals([], 100); 30 | 31 | await new Promise(resolve => { 32 | signal.addEventListener('abort', resolve); 33 | }); 34 | 35 | assert.match(String(signal.reason), /timeout 100 of ms exceeded/); 36 | }); 37 | 38 | it('should return undefined if signals and timeout are not provided', async () => { 39 | const signal = composeSignals([]); 40 | 41 | assert.strictEqual(signal, undefined); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/unit/helpers/fromDataURI.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import fromDataURI from '../../../lib/helpers/fromDataURI.js'; 3 | 4 | describe('helpers::fromDataURI', function () { 5 | it('should return buffer from data uri', function () { 6 | const buffer= Buffer.from('123'); 7 | 8 | const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); 9 | 10 | assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/unit/helpers/parseProtocol.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import utils from '../../../lib/utils.js'; 3 | import parseProtocol from '../../../lib/helpers/parseProtocol.js'; 4 | 5 | describe('helpers::parseProtocol', function () { 6 | it('should parse protocol part if it exists', function () { 7 | utils.forEach({ 8 | 'http://username:password@example.com/': 'http', 9 | 'ftp:google.com': 'ftp', 10 | 'sms:+15105550101?body=hello%20there': 'sms', 11 | 'tel:0123456789' : 'tel', 12 | '//google.com': '', 13 | 'google.com': '', 14 | 'admin://etc/default/grub' : 'admin', 15 | 'stratum+tcp://server:port': 'stratum+tcp', 16 | '/api/resource:customVerb': '', 17 | 'https://stackoverflow.com/questions/': 'https', 18 | 'mailto:jsmith@example.com' : 'mailto', 19 | 'chrome-extension://1234/.html' : 'chrome-extension' 20 | }, (expectedProtocol, url) => { 21 | assert.strictEqual(parseProtocol(url), expectedProtocol); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/unit/platform/index.js: -------------------------------------------------------------------------------- 1 | import platform from "../../../lib/platform/index.js"; 2 | import assert from "assert"; 3 | 4 | describe('generateString', function () { 5 | it('should generate a string of the specified length using the default alphabet', function () { 6 | const size = 10; 7 | const str = platform.generateString(size); 8 | 9 | assert.strictEqual(str.length, size); 10 | }); 11 | 12 | it('should generate a string using only characters from the default alphabet', function () { 13 | const size = 10; 14 | const alphabet = platform.ALPHABET.ALPHA_DIGIT; 15 | 16 | const str = platform.generateString(size, alphabet); 17 | 18 | for (let char of str) { 19 | assert.ok(alphabet.includes(char), `Character ${char} is not in the alphabet`); 20 | } 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/unit/regression/SNYK-JS-AXIOS-1038255.js: -------------------------------------------------------------------------------- 1 | // https://snyk.io/vuln/SNYK-JS-AXIOS-1038255 2 | // https://github.com/axios/axios/issues/3407 3 | // https://github.com/axios/axios/issues/3369 4 | 5 | import axios from '../../../index.js'; 6 | import http from 'http'; 7 | import assert from 'assert'; 8 | 9 | const PROXY_PORT = 4777; 10 | const EVIL_PORT = 4666; 11 | 12 | 13 | describe('Server-Side Request Forgery (SSRF)', () => { 14 | let fail = false; 15 | let proxy; 16 | let server; 17 | let location; 18 | beforeEach(() => { 19 | server = http.createServer(function (req, res) { 20 | fail = true; 21 | res.end('rm -rf /'); 22 | }).listen(EVIL_PORT); 23 | 24 | proxy = http.createServer(function (req, res) { 25 | if (new URL(req.url, 'http://' + req.headers.host).toString() === 'http://localhost:' + EVIL_PORT + '/') { 26 | return res.end(JSON.stringify({ 27 | msg: 'Protected', 28 | headers: req.headers, 29 | })); 30 | } 31 | res.writeHead(302, { location }) 32 | res.end() 33 | }).listen(PROXY_PORT); 34 | }); 35 | afterEach(() => { 36 | server.close(); 37 | proxy.close(); 38 | }); 39 | 40 | it('obeys proxy settings when following redirects', async () => { 41 | location = 'http://localhost:' + EVIL_PORT; 42 | 43 | let response = await axios({ 44 | method: "get", 45 | url: "http://www.google.com/", 46 | proxy: { 47 | host: "localhost", 48 | port: PROXY_PORT, 49 | auth: { 50 | username: 'sam', 51 | password: 'password', 52 | } 53 | }, 54 | }); 55 | 56 | assert.strictEqual(fail, false); 57 | assert.strictEqual(response.data.msg, 'Protected'); 58 | assert.strictEqual(response.data.headers.host, 'localhost:' + EVIL_PORT); 59 | assert.strictEqual(response.data.headers['proxy-authorization'], 'Basic ' + Buffer.from('sam:password').toString('base64')); 60 | 61 | return response; 62 | 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/unit/regression/SNYK-JS-AXIOS-7361793.js: -------------------------------------------------------------------------------- 1 | // https://security.snyk.io/vuln/SNYK-JS-AXIOS-7361793 2 | // https://github.com/axios/axios/issues/6463 3 | 4 | import axios from '../../../index.js'; 5 | import http from 'http'; 6 | import assert from 'assert'; 7 | import platform from '../../../lib/platform/index.js'; 8 | 9 | 10 | const GOOD_PORT = 4666; 11 | const BAD_PORT = 4667; 12 | 13 | describe('Server-Side Request Forgery (SSRF)', () => { 14 | let goodServer, badServer; 15 | 16 | beforeEach(() => { 17 | goodServer = http.createServer(function (req, res) { 18 | res.write('good'); 19 | res.end(); 20 | }).listen(GOOD_PORT); 21 | badServer = http.createServer(function (req, res) { 22 | res.write('bad'); 23 | res.end(); 24 | }).listen(BAD_PORT); 25 | }) 26 | 27 | afterEach(() => { 28 | goodServer.close(); 29 | badServer.close(); 30 | }); 31 | 32 | it('should not fetch in server-side mode', async () => { 33 | const ssrfAxios = axios.create({ 34 | baseURL: 'http://localhost:' + String(GOOD_PORT), 35 | }); 36 | 37 | // Good payload would be `userId = '12345'` 38 | // Malicious payload is as below. 39 | const userId = '/localhost:' + String(BAD_PORT); 40 | 41 | try { 42 | await ssrfAxios.get(`/${userId}`); 43 | } catch (error) { 44 | assert.ok(error.message.startsWith('Invalid URL')); 45 | return; 46 | } 47 | assert.fail('Expected an error to be thrown'); 48 | }); 49 | 50 | describe('should fetch in client-side mode', () => { 51 | let hasBrowserEnv, origin; 52 | 53 | before(() => { 54 | assert.ok(platform.hasBrowserEnv !== undefined); 55 | hasBrowserEnv = platform.hasBrowserEnv; 56 | origin = platform.origin; 57 | platform.hasBrowserEnv = true; 58 | platform.origin = 'http://localhost:' + String(GOOD_PORT); 59 | }); 60 | after(() => { 61 | platform.hasBrowserEnv = hasBrowserEnv; 62 | platform.origin = origin; 63 | }); 64 | it('should fetch in client-side mode', async () => { 65 | platform.hasBrowserEnv = true; 66 | const ssrfAxios = axios.create({ 67 | baseURL: 'http://localhost:' + String(GOOD_PORT), 68 | }); 69 | 70 | // Good payload would be `userId = '12345'` 71 | // Malicious payload is as below. 72 | const userId = '/localhost:' + String(BAD_PORT); 73 | 74 | const response = await ssrfAxios.get(`/${userId}`); 75 | assert.strictEqual(response.data, 'bad'); 76 | assert.strictEqual(response.config.baseURL, 'http://localhost:' + String(GOOD_PORT)); 77 | assert.strictEqual(response.config.url, '//localhost:' + String(BAD_PORT)); 78 | assert.strictEqual(response.request.res.responseUrl, 'http://localhost:' + String(BAD_PORT) + '/'); 79 | }); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /test/unit/regression/bugs.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import http from 'http'; 3 | import axios from '../../../index.js'; 4 | 5 | describe('issues', function () { 6 | describe('4999', function () { 7 | it('should not fail with query parsing', async function () { 8 | const {data} = await axios.get('https://postman-echo.com/get?foo1=bar1&foo2=bar2'); 9 | 10 | assert.strictEqual(data.args.foo1, 'bar1'); 11 | assert.strictEqual(data.args.foo2, 'bar2'); 12 | }); 13 | }); 14 | 15 | describe('5028', function () { 16 | it('should handle set-cookie headers as an array', async function () { 17 | const cookie1 = 'something=else; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; 18 | const cookie2 = 'something-ssr.sig=n4MlwVAaxQAxhbdJO5XbUpDw-lA; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; 19 | 20 | const server = http.createServer((req, res) => { 21 | //res.setHeader('Set-Cookie', 'my=value'); 22 | res.setHeader('Set-Cookie', [cookie1, cookie2]); 23 | res.writeHead(200); 24 | res.write('Hi there'); 25 | res.end(); 26 | }).listen(0); 27 | 28 | const request = axios.create(); 29 | 30 | request.interceptors.response.use((res) => { 31 | assert.deepStrictEqual(res.headers['set-cookie'], [ 32 | cookie1, cookie2 33 | ]); 34 | }); 35 | 36 | try { 37 | await request({url: `http://localhost:${server.address().port}`}); 38 | } finally { 39 | server.close() 40 | } 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/unit/utils/utils.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import utils from '../../../lib/utils.js'; 3 | import FormData from 'form-data'; 4 | import stream from 'stream'; 5 | 6 | describe('utils', function (){ 7 | it('should validate Stream', function () { 8 | assert.strictEqual(utils.isStream(new stream.Readable()),true); 9 | assert.strictEqual(utils.isStream({ foo: 'bar' }),false); 10 | }); 11 | 12 | it('should validate Buffer', function () { 13 | assert.strictEqual(utils.isBuffer(Buffer.from('a')),true); 14 | assert.strictEqual(utils.isBuffer(null),false); 15 | assert.strictEqual(utils.isBuffer(undefined),false); 16 | }); 17 | 18 | describe('utils::isFormData', function () { 19 | it('should detect the FormData instance provided by the `form-data` package', function () { 20 | [1, 'str', {}, new RegExp()].forEach(function (thing) { 21 | assert.equal(utils.isFormData(thing), false); 22 | }); 23 | assert.equal(utils.isFormData(new FormData()), true); 24 | }); 25 | 26 | it('should not call toString method on built-in objects instances', () => { 27 | const buf = Buffer.from('123'); 28 | 29 | buf.toString = () => assert.fail('should not be called'); 30 | 31 | assert.equal(utils.isFormData(buf), false); 32 | }); 33 | 34 | it('should not call toString method on built-in objects instances, even if append method exists', () => { 35 | const buf = Buffer.from('123'); 36 | 37 | buf.append = () => {}; 38 | 39 | buf.toString = () => assert.fail('should not be called'); 40 | 41 | assert.equal(utils.isFormData(buf), false); 42 | }); 43 | 44 | it('should detect custom FormData instances by toStringTag signature and append method presence', () => { 45 | class FormData { 46 | append(){ 47 | 48 | } 49 | 50 | get [Symbol.toStringTag]() { 51 | return 'FormData'; 52 | } 53 | } 54 | assert.equal(utils.isFormData(new FormData()), true); 55 | }); 56 | }); 57 | 58 | describe('toJSON', function (){ 59 | it('should convert to a plain object without circular references', function () { 60 | const obj= {a: [0]} 61 | const source = {x:1, y:2, obj}; 62 | source.circular1 = source; 63 | obj.a[1] = obj; 64 | 65 | assert.deepStrictEqual(utils.toJSONObject(source), { 66 | x: 1, y:2, obj: {a: [0]} 67 | }); 68 | }); 69 | 70 | it('should use objects with defined toJSON method without rebuilding', function () { 71 | const objProp = {}; 72 | const obj= {objProp, toJSON(){ 73 | return {ok: 1} 74 | }}; 75 | const source = {x:1, y:2, obj}; 76 | 77 | const jsonObject = utils.toJSONObject(source); 78 | 79 | assert.strictEqual(jsonObject.obj.objProp, objProp); 80 | assert.strictEqual(JSON.stringify(jsonObject), JSON.stringify({x: 1, y:2, obj: {ok: 1}})) 81 | }); 82 | }); 83 | }); 84 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "node16", 4 | "lib": ["dom", "es2015"], 5 | "types": [], 6 | "strict": true, 7 | "noEmit": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "dtslint/dtslint.json", 3 | "rules": { 4 | "no-unnecessary-generics": false 5 | }, 6 | "linterOptions": { 7 | "exclude": [ 8 | "test/module/**" 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var config = {}; 2 | 3 | function generateConfig(name) { 4 | var compress = name.indexOf('min') > -1; 5 | var config = { 6 | entry: './index.js', 7 | output: { 8 | path: __dirname + '/dist/', 9 | filename: name + '.js', 10 | sourceMapFilename: name + '.map', 11 | library: 'axios', 12 | libraryTarget: 'umd', 13 | globalObject: 'this' 14 | }, 15 | node: false, 16 | devtool: 'source-map', 17 | mode: compress ? 'production' : 'development' 18 | }; 19 | return config; 20 | } 21 | 22 | ['axios', 'axios.min'].forEach(function (key) { 23 | config[key] = generateConfig(key); 24 | }); 25 | 26 | module.exports = config; 27 | --------------------------------------------------------------------------------