├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── COLLABORATOR_GUIDE.md ├── COOKBOOK.md ├── ECOSYSTEM.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── UPGRADE_GUIDE.md ├── bower.json ├── dist ├── axios.js ├── axios.map ├── axios.min.js └── axios.min.map ├── examples ├── README.md ├── all │ └── index.html ├── amd │ └── index.html ├── get │ ├── index.html │ └── server.js ├── post │ ├── index.html │ └── server.js ├── server.js ├── transform-response │ └── index.html └── upload │ ├── index.html │ └── server.js ├── index.d.ts ├── index.js ├── karma.conf.js ├── lib ├── adapters │ ├── README.md │ ├── http.js │ └── xhr.js ├── axios.js ├── cancel │ ├── Cancel.js │ ├── CancelToken.js │ └── isCancel.js ├── core │ ├── Axios.js │ ├── InterceptorManager.js │ ├── README.md │ ├── createError.js │ ├── dispatchRequest.js │ ├── enhanceError.js │ ├── jsonp.js │ ├── settle.js │ └── transformData.js ├── defaults.js ├── helpers │ ├── README.md │ ├── bind.js │ ├── btoa.js │ ├── buildURL.js │ ├── combineURLs.js │ ├── cookies.js │ ├── deprecatedMethod.js │ ├── isAbsoluteURL.js │ ├── isURLSameOrigin.js │ ├── normalizeHeaderName.js │ ├── parseHeaders.js │ └── spread.js └── utils.js ├── package.json ├── sandbox ├── client.html ├── client.js └── server.js ├── test ├── manual │ ├── basic.html │ ├── cors.html │ ├── fixture.json │ └── promise.js ├── specs │ ├── __helpers.js │ ├── adapter.spec.js │ ├── api.spec.js │ ├── basicAuth.spec.js │ ├── basicAuthWithPolyfill.spec.js │ ├── cancel.spec.js │ ├── cancel │ │ ├── Cancel.spec.js │ │ ├── CancelToken.spec.js │ │ └── isCancel.spec.js │ ├── core │ │ ├── createError.spec.js │ │ ├── enhanceError.spec.js │ │ ├── settle.spec.js │ │ └── transformData.spec.js │ ├── defaults.spec.js │ ├── headers.spec.js │ ├── helpers │ │ ├── bind.spec.js │ │ ├── btoa.spec.js │ │ ├── buildURL.spec.js │ │ ├── combineURLs.spec.js │ │ ├── cookies.spec.js │ │ ├── isAbsoluteURL.spec.js │ │ ├── isURLSameOrigin.spec.js │ │ ├── normalizeHeaderName.spec.js │ │ ├── parseHeaders.spec.js │ │ └── spread.spec.js │ ├── instance.spec.js │ ├── interceptors.spec.js │ ├── options.spec.js │ ├── progress.spec.js │ ├── promise.spec.js │ ├── requests.spec.js │ ├── transform.spec.js │ ├── utils │ │ ├── extend.spec.js │ │ ├── forEach.spec.js │ │ ├── isX.spec.js │ │ ├── merge.spec.js │ │ └── trim.spec.js │ └── xsrf.spec.js ├── typescript │ └── axios.ts └── unit │ └── adapters │ └── http.js └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "console": true, 4 | "module": true, 5 | "require": true 6 | }, 7 | "env": { 8 | "browser": true, 9 | "node": true 10 | }, 11 | "rules": { 12 | /** 13 | * Strict mode 14 | */ 15 | "strict": [2, "global"], // http://eslint.org/docs/rules/strict 16 | 17 | /** 18 | * Variables 19 | */ 20 | "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow 21 | "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names 22 | "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars 23 | "vars": "local", 24 | "args": "after-used" 25 | }], 26 | "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define 27 | 28 | /** 29 | * Possible errors 30 | */ 31 | "comma-dangle": [2, "never"], // http://eslint.org/docs/rules/comma-dangle 32 | "no-cond-assign": [2, "except-parens"], // http://eslint.org/docs/rules/no-cond-assign 33 | "no-console": 1, // http://eslint.org/docs/rules/no-console 34 | "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger 35 | "no-alert": 1, // http://eslint.org/docs/rules/no-alert 36 | "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition 37 | "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys 38 | "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case 39 | "no-empty": 2, // http://eslint.org/docs/rules/no-empty 40 | "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign 41 | "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast 42 | "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi 43 | "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign 44 | "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations 45 | "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp 46 | "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace 47 | "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls 48 | "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays 49 | "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable 50 | "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan 51 | "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var 52 | 53 | /** 54 | * Best practices 55 | */ 56 | "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return 57 | "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly 58 | "default-case": 2, // http://eslint.org/docs/rules/default-case 59 | "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation 60 | "allowKeywords": true 61 | }], 62 | "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq 63 | "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in 64 | "no-caller": 2, // http://eslint.org/docs/rules/no-caller 65 | "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return 66 | "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null 67 | "no-eval": 2, // http://eslint.org/docs/rules/no-eval 68 | "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native 69 | "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind 70 | "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough 71 | "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal 72 | "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval 73 | "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks 74 | "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func 75 | "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str 76 | "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign 77 | "no-new": 2, // http://eslint.org/docs/rules/no-new 78 | "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func 79 | "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers 80 | "no-octal": 2, // http://eslint.org/docs/rules/no-octal 81 | "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape 82 | "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign 83 | "no-proto": 2, // http://eslint.org/docs/rules/no-proto 84 | "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare 85 | "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign 86 | "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url 87 | "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare 88 | "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences 89 | "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal 90 | "no-with": 2, // http://eslint.org/docs/rules/no-with 91 | "radix": 2, // http://eslint.org/docs/rules/radix 92 | "vars-on-top": 0, // http://eslint.org/docs/rules/vars-on-top 93 | "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife 94 | "yoda": 2, // http://eslint.org/docs/rules/yoda 95 | 96 | /** 97 | * Style 98 | */ 99 | "indent": [2, 2], // http://eslint.org/docs/rules/indent 100 | "brace-style": [2, // http://eslint.org/docs/rules/brace-style 101 | "1tbs", { 102 | "allowSingleLine": true 103 | }], 104 | "quotes": [ 105 | 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes 106 | ], 107 | "camelcase": [2, { // http://eslint.org/docs/rules/camelcase 108 | "properties": "never" 109 | }], 110 | "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing 111 | "before": false, 112 | "after": true 113 | }], 114 | "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style 115 | "eol-last": 2, // http://eslint.org/docs/rules/eol-last 116 | "func-names": 1, // http://eslint.org/docs/rules/func-names 117 | "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing 118 | "beforeColon": false, 119 | "afterColon": true 120 | }], 121 | "new-cap": [2, { // http://eslint.org/docs/rules/new-cap 122 | "newIsCap": true 123 | }], 124 | "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines 125 | "max": 2 126 | }], 127 | "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary 128 | "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object 129 | "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func 130 | "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces 131 | "no-extra-parens": [2, "functions"], // http://eslint.org/docs/rules/no-extra-parens 132 | "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle 133 | "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var 134 | "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks 135 | "semi": [2, "always"], // http://eslint.org/docs/rules/semi 136 | "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing 137 | "before": false, 138 | "after": true 139 | }], 140 | "keyword-spacing": 2, // http://eslint.org/docs/rules/keyword-spacing 141 | "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks 142 | "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren 143 | "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops 144 | "spaced-comment": [2, "always", {// http://eslint.org/docs/rules/spaced-comment 145 | "markers": ["global", "eslint"] 146 | }] 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .tscache 4 | .DS_Store 5 | node_modules/ 6 | typings/ 7 | coverage/ 8 | test/typescript/axios.js* 9 | sauce_connect.log 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | **/.* 2 | *.iml 3 | coverage/ 4 | examples/ 5 | node_modules/ 6 | typings/ 7 | sandbox/ 8 | test/ 9 | bower.json 10 | CODE_OF_CONDUCT.md 11 | COLLABORATOR_GUIDE.md 12 | CONTRIBUTING.md 13 | COOKBOOK.md 14 | ECOSYSTEM.md 15 | Gruntfile.js 16 | karma.conf.js 17 | webpack.*.js 18 | sauce_connect.log 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | email: 5 | on_failure: change 6 | on_success: never 7 | before_script: 8 | - "export DISPLAY=:99.0" 9 | - "sh -e /etc/init.d/xvfb start" 10 | - sleep 3 # give xvfb some time to start 11 | after_success: 12 | - npm run coveralls 13 | env: 14 | global: 15 | - secure: LlXIBEaBLgJznkHWfTV6aftkGoBjH2vik4ZQhKq4k5pvoPLD+n5n28+0bjwlzDIHUdHb+n2YXtyM2PGvGzuqwltV+UY1gu0uG2RNR+5CBsp0pOr0FfGXK6YMXn0BYER6tGYIhaG7ElHBEO0SLcQeQV/xN/m3leyawbKEMBUGizU= 16 | - secure: XbXYzVddHJSVdbJRd/YtsdNu6Wlgx3pXvpuBpg9qBc3TytAF4LzhJNI8u1p4D1Gn8wANlxv1GNgEgkecxbzlTPST+mUrd6KlPLa1+Cmffgajr4oQjsh9ILKMe5Haqx8FOVrPK/leB1mi52liNLlkuo3/BK2r/tC2kMji+2zbses= 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at mzabriskie@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /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/mzabriskie/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 stales 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 | - When fixing a bug: does the PR adequately solve the problem without introducing any regressions? 13 | - When implementing a feature: does the feature fit within the scope of axios? 14 | - When removing functionality: is it properly deprecated with a warning? 15 | - When introducing functionality: is the API predictable? 16 | - Does the new code work for all supported platforms/browsers? 17 | - Do the tests and linting pass CI? 18 | - Are there tests to validate the changes that have been made? 19 | 20 | 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. 21 | 22 | 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. 23 | 24 | -------------------------------------------------------------------------------- /COOKBOOK.md: -------------------------------------------------------------------------------- 1 | # Cookbook 2 | 3 | In an effort to keep axios as light weight as possible, and to avoid a rats nest of code for supporting every possible integration, it is often necessary to say no to feature requests. This doesn't mean that those use cases aren't legitimate, but rather that they are easily supported by augmenting axios with other libraries. 4 | 5 | The following are the recipes for some of the commonly requested features. 6 | 7 | ### Promise.prototype.done 8 | 9 | ```bash 10 | $ npm install axios promise --save 11 | ``` 12 | 13 | ```js 14 | var axios = require('axios'); 15 | require('promise/polyfill-done'); 16 | 17 | axios 18 | .get('http://www.example.com/user') 19 | .then(function (response) { 20 | console.log(response.data); 21 | return response; 22 | }) 23 | .done(); 24 | ``` 25 | 26 | ### Promise.prototype.finally 27 | 28 | ```bash 29 | $ npm install axios promise.prototype.finally --save 30 | ``` 31 | 32 | ```js 33 | var axios = require('axios'); 34 | require('promise.prototype.finally').shim(); 35 | 36 | axios 37 | .get('http://www.example.com/user') 38 | .then(function (response) { 39 | console.log(response.data); 40 | return response; 41 | }) 42 | .finally(function () { 43 | console.log('this will always be called'); 44 | }); 45 | ``` 46 | 47 | ### Inflate/Deflate 48 | 49 | ```bash 50 | $ npm install axios pako --save 51 | ``` 52 | 53 | ```js 54 | // client.js 55 | var axios = require('axios'); 56 | var pako = require('pako'); 57 | 58 | var user = { 59 | firstName: 'Fred', 60 | lastName: 'Flintstone' 61 | }; 62 | 63 | var data = pako.deflate(JSON.stringify(user), { to: 'string' }); 64 | 65 | axios 66 | .post('http://127.0.0.1:3333/user', data) 67 | .then(function (response) { 68 | response.data = JSON.parse(pako.inflate(response.data, { to: 'string' })); 69 | console.log(response.data); 70 | return response; 71 | }); 72 | ``` 73 | 74 | ```js 75 | // server.js 76 | var pako = require('pako'); 77 | var http = require('http'); 78 | var url = require('url'); 79 | var server; 80 | 81 | server = http.createServer(function (req, res) { 82 | req.setEncoding('utf8'); 83 | 84 | var parsed = url.parse(req.url, true); 85 | var pathname = parsed.pathname; 86 | 87 | if (pathname === '/user') { 88 | var data = ''; 89 | req.on('data', function (chunk) { 90 | data += chunk; 91 | }); 92 | 93 | req.on('end', function () { 94 | var user = JSON.parse(pako.inflate(data, { to: 'string' })); 95 | console.log(user); 96 | 97 | res.writeHead(200, { 98 | 'Content-Type': 'application/json' 99 | }); 100 | res.end(pako.deflate(JSON.stringify({result: 'success'}), { to: 'string' })); 101 | }); 102 | } else { 103 | res.writeHead(404); 104 | res.end(pako.deflate(JSON.stringify({result: 'error'}), { to: 'string' })); 105 | } 106 | }); 107 | 108 | server.listen(3333); 109 | ``` 110 | 111 | ### JSONP 112 | 113 | ```bash 114 | $ npm install jsonp --save 115 | ``` 116 | 117 | ```js 118 | var jsonp = require('jsonp'); 119 | 120 | jsonp('http://www.example.com/foo', null, function (err, data) { 121 | if (err) { 122 | console.error(err.message); 123 | } else { 124 | console.log(data); 125 | } 126 | }); 127 | ``` 128 | -------------------------------------------------------------------------------- /ECOSYSTEM.md: -------------------------------------------------------------------------------- 1 | # Ecosystem 2 | 3 | This is a list of axios related libraries and resources. If you have a suggestion on what to add, please don't hesitate to submit a PR. 4 | 5 | ## Libraries 6 | 7 | * [moxios](https://github.com/mzabriskie/moxios) - Mock axios requests for testing 8 | * [axios-response-logger](https://github.com/srph/axios-response-logger) - Axios interceptor which logs responses 9 | * [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) — Axios adapter that allows to easily mock requests 10 | * [redux-axios-middleware](https://github.com/svrcekmichal/redux-axios-middleware) - Redux middleware for fetching data with axios HTTP client 11 | * [axios-vcr](https://github.com/nettofarah/axios-vcr) - 📼 Record and Replay Axios requests 12 | * [@3846masa/axios-cookiejar-support](https://github.com/3846masa/axios-cookiejar-support) - Add tough-cookie support to axios 13 | * [axios-debug-log](https://github.com/Gerhut/axios-debug-log) - Axios interceptor of logging requests & responses by debug. 14 | * [axios-method-override](https://github.com/jacobbuck/axios-method-override) - Axios http request method override plugin 15 | * [mocha-axios](https://github.com/jdrydn/mocha-axios) - Streamlined integration testing with Mocha & Axios 16 | * [axiosist](https://github.com/Gerhut/axiosist) - Axios based supertest: convert node.js request handler to axios adapter, used for node.js server unit test. 17 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | require('load-grunt-tasks')(grunt); 3 | 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | meta: { 7 | banner: '/* <%= pkg.name %> v<%= pkg.version %> | (c) <%= grunt.template.today("yyyy") %> by Matt Zabriskie */\n' 8 | }, 9 | 10 | clean: { 11 | dist: 'dist/**' 12 | }, 13 | 14 | ts: { 15 | test: { 16 | options: { 17 | lib: [ 18 | 'es5', 19 | 'es2015.promise', 20 | 'dom' 21 | ] 22 | }, 23 | src: ['typings/index.d.ts', 'test/typescript/*.ts'] 24 | } 25 | }, 26 | 27 | package2bower: { 28 | all: { 29 | fields: [ 30 | 'name', 31 | 'description', 32 | 'version', 33 | 'homepage', 34 | 'license', 35 | 'keywords' 36 | ] 37 | } 38 | }, 39 | 40 | usebanner: { 41 | all: { 42 | options: { 43 | banner: '<%= meta.banner %>', 44 | linebreak: false 45 | }, 46 | files: { 47 | src: ['dist/*.js'] 48 | } 49 | } 50 | }, 51 | 52 | eslint: { 53 | target: ['lib/**/*.js'] 54 | }, 55 | 56 | karma: { 57 | options: { 58 | configFile: 'karma.conf.js' 59 | }, 60 | single: { 61 | singleRun: true 62 | }, 63 | continuous: { 64 | singleRun: false 65 | } 66 | }, 67 | 68 | nodeunit: { 69 | all: ['test/unit/**/*.js'] 70 | }, 71 | 72 | watch: { 73 | build: { 74 | files: ['lib/**/*.js'], 75 | tasks: ['build'] 76 | }, 77 | test: { 78 | files: ['lib/**/*.js', 'test/**/*.js', '!test/typescript/axios.js', '!test/typescript/out.js'], 79 | tasks: ['test'] 80 | } 81 | }, 82 | 83 | webpack: require('./webpack.config.js') 84 | }); 85 | 86 | grunt.registerMultiTask('package2bower', 'Sync package.json to bower.json', function () { 87 | var npm = grunt.file.readJSON('package.json'); 88 | var bower = grunt.file.readJSON('bower.json'); 89 | var fields = this.data.fields || []; 90 | 91 | for (var i=0, l=fields.length; i 0.16.0 4 | 5 | #### `Promise` Type Declarations 6 | 7 | The `Promise` type declarations have been removed from the axios typings in favor of the built-in type declarations. If you use axios in a TypeScript project that targets `ES5`, please make sure to include the `es2015.promise` lib. Please see [this post](https://blog.mariusschulz.com/2016/11/25/typescript-2-0-built-in-type-declarations) for details. 8 | 9 | ### 0.13.x -> 0.14.0 10 | 11 | #### TypeScript Definitions 12 | 13 | The axios TypeScript definitions have been updated to match the axios API and use the ES2015 module syntax. 14 | 15 | Please use the following `import` statement to import axios in TypeScript: 16 | 17 | ```typescript 18 | import axios from 'axios'; 19 | 20 | axios.get('/foo') 21 | .then(response => console.log(response)) 22 | .catch(error => console.log(error)); 23 | ``` 24 | 25 | #### `agent` Config Option 26 | 27 | The `agent` config option has been replaced with two new options: `httpAgent` and `httpsAgent`. Please use them instead. 28 | 29 | ```js 30 | { 31 | // Define a custom agent for HTTP 32 | httpAgent: new http.Agent({ keepAlive: true }), 33 | // Define a custom agent for HTTPS 34 | httpsAgent: new https.Agent({ keepAlive: true }) 35 | } 36 | ``` 37 | 38 | #### `progress` Config Option 39 | 40 | The `progress` config option has been replaced with the `onUploadProgress` and `onDownloadProgress` options. 41 | 42 | ```js 43 | { 44 | // Define a handler for upload progress events 45 | onUploadProgress: function (progressEvent) { 46 | // ... 47 | }, 48 | 49 | // Define a handler for download progress events 50 | onDownloadProgress: function (progressEvent) { 51 | // ... 52 | } 53 | } 54 | ``` 55 | 56 | ### 0.12.x -> 0.13.0 57 | 58 | The `0.13.0` release contains several changes to custom adapters and error handling. 59 | 60 | #### Error Handling 61 | 62 | Previous to this release an error could either be a server response with bad status code or an actual `Error`. With this release Promise will always reject with an `Error`. In the case that a response was received, the `Error` will also include the response. 63 | 64 | ```js 65 | axios.get('/user/12345') 66 | .catch((error) => { 67 | console.log(error.message); 68 | console.log(error.code); // Not always specified 69 | console.log(error.config); // The config that was used to make the request 70 | console.log(error.response); // Only available if response was received from the server 71 | }); 72 | ``` 73 | 74 | #### Request Adapters 75 | 76 | This release changes a few things about how request adapters work. Please take note if you are using your own custom adapter. 77 | 78 | 1. Response transformer is now called outside of adapter. 79 | 2. Request adapter returns a `Promise`. 80 | 81 | This means that you no longer need to invoke `transformData` on response data. You will also no longer receive `resolve` and `reject` as arguments in your adapter. 82 | 83 | Previous code: 84 | 85 | ```js 86 | function myAdapter(resolve, reject, config) { 87 | var response = { 88 | data: transformData( 89 | responseData, 90 | responseHeaders, 91 | config.transformResponse 92 | ), 93 | status: request.status, 94 | statusText: request.statusText, 95 | headers: responseHeaders 96 | }; 97 | settle(resolve, reject, response); 98 | } 99 | ``` 100 | 101 | New code: 102 | 103 | ```js 104 | function myAdapter(config) { 105 | return new Promise(function (resolve, reject) { 106 | var response = { 107 | data: responseData, 108 | status: request.status, 109 | statusText: request.statusText, 110 | headers: responseHeaders 111 | }; 112 | settle(resolve, reject, response); 113 | }); 114 | } 115 | ``` 116 | 117 | See the related commits for more details: 118 | - [Response transformers](https://github.com/mzabriskie/axios/commit/10eb23865101f9347570552c04e9d6211376e25e) 119 | - [Request adapter Promise](https://github.com/mzabriskie/axios/commit/157efd5615890301824e3121cc6c9d2f9b21f94a) 120 | 121 | ### 0.5.x -> 0.6.0 122 | 123 | The `0.6.0` release contains mostly bug fixes, but there are a couple things to be aware of when upgrading. 124 | 125 | #### ES6 Promise Polyfill 126 | 127 | Up until the `0.6.0` release ES6 `Promise` was being polyfilled using [es6-promise](https://github.com/jakearchibald/es6-promise). With this release, the polyfill has been removed, and you will need to supply it yourself if your environment needs it. 128 | 129 | ```js 130 | require('es6-promise').polyfill(); 131 | var axios = require('axios'); 132 | ``` 133 | 134 | This will polyfill the global environment, and only needs to be done once. 135 | 136 | #### `axios.success`/`axios.error` 137 | 138 | The `success`, and `error` aliases were deprectated in [0.4.0](https://github.com/mzabriskie/axios/blob/master/CHANGELOG.md#040-oct-03-2014). As of this release they have been removed entirely. Instead please use `axios.then`, and `axios.catch` respectively. 139 | 140 | ```js 141 | axios.get('some/url') 142 | .then(function (res) { 143 | /* ... */ 144 | }) 145 | .catch(function (err) { 146 | /* ... */ 147 | }); 148 | ``` 149 | 150 | #### UMD 151 | 152 | Previous versions of axios shipped with an AMD, CommonJS, and Global build. This has all been rolled into a single UMD build. 153 | 154 | ```js 155 | // AMD 156 | require(['bower_components/axios/dist/axios'], function (axios) { 157 | /* ... */ 158 | }); 159 | 160 | // CommonJS 161 | var axios = require('axios/dist/axios'); 162 | ``` 163 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axios", 3 | "main": "./dist/axios.js", 4 | "version": "0.16.2", 5 | "homepage": "https://github.com/mzabriskie/axios", 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/mzabriskie/axios.git` 6 | 2. `cd axios` 7 | 3. `npm install` 8 | 4. `grunt build` 9 | 5. `npm run examples` 10 | 6. [http://localhost:3000](http://localhost:3000) 11 | -------------------------------------------------------------------------------- /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 | var 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 | module.exports = 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 | module.exports = function (req, res) { 2 | var 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/server.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var url = require('url'); 3 | var path = require('path'); 4 | var http = require('http'); 5 | var argv = require('minimist')(process.argv.slice(2)); 6 | var server; 7 | var dirs; 8 | 9 | function listDirs(root) { 10 | var files = fs.readdirSync(root); 11 | var dirs = []; 12 | 13 | for (var i=0, l=files.length; i' + url + ''; 30 | }); 31 | 32 | return ( 33 | '' + 34 | '' + 35 | '' + 36 | 'axios examples' + 37 | '' + 44 | '' + 45 | '' 48 | ); 49 | } 50 | 51 | function sendResponse(res, statusCode, body) { 52 | res.writeHead(statusCode); 53 | res.write(body); 54 | res.end(); 55 | } 56 | 57 | function send200(res, body) { 58 | sendResponse(res, 200, body || '

OK

'); 59 | } 60 | 61 | function send404(res, body) { 62 | sendResponse(res, 404, body || '

Not Found

'); 63 | } 64 | 65 | function pipeFileToResponse(res, file, type) { 66 | if (type) { 67 | res.writeHead(200, { 68 | 'Content-Type': type 69 | }); 70 | } 71 | fs.createReadStream(path.join(__dirname, file)).pipe(res); 72 | } 73 | 74 | 75 | dirs = listDirs(__dirname); 76 | 77 | server = http.createServer(function (req, res) { 78 | var url = req.url; 79 | 80 | // Process axios itself 81 | if (/axios\.min\.js$/.test(url)) { 82 | pipeFileToResponse(res, '../dist/axios.min.js', 'text/javascript'); 83 | return; 84 | } 85 | if (/axios\.min\.map$/.test(url)) { 86 | pipeFileToResponse(res, '../dist/axios.min.map', 'text/javascript'); 87 | return; 88 | } 89 | if (/axios\.amd\.min\.js$/.test(url)) { 90 | pipeFileToResponse(res, '../dist/axios.amd.min.js', 'text/javascript'); 91 | return; 92 | } 93 | if (/axios\.amd\.min\.map$/.test(url)) { 94 | pipeFileToResponse(res, '../dist/axios.amd.min.map', 'text/javascript'); 95 | return; 96 | } 97 | 98 | // Process / 99 | if (url === '/' || url === '/index.html') { 100 | send200(res, getIndexTemplate()); 101 | return; 102 | } 103 | 104 | // Format request */ -> */index.html 105 | if (/\/$/.test(url)) { 106 | url += 'index.html'; 107 | } 108 | 109 | // Format request /get -> /get/index.html 110 | var parts = url.split('/'); 111 | if (dirs.indexOf(parts[parts.length - 1]) > -1) { 112 | url += '/index.html'; 113 | } 114 | 115 | // Process index.html request 116 | if (/index\.html$/.test(url)) { 117 | if (fs.existsSync(path.join(__dirname, url))) { 118 | pipeFileToResponse(res, url, 'text/html'); 119 | } else { 120 | send404(res); 121 | } 122 | } 123 | 124 | // Process server request 125 | else if (new RegExp('(' + dirs.join('|') + ')\/server').test(url)) { 126 | if (fs.existsSync(path.join(__dirname, url + '.js'))) { 127 | require(path.join(__dirname, url + '.js'))(req, res); 128 | } else { 129 | send404(res); 130 | } 131 | } 132 | else { 133 | send404(res); 134 | } 135 | }); 136 | 137 | server.listen(argv.p || 3000); 138 | -------------------------------------------------------------------------------- /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 | module.exports = function (req, res) { 2 | var 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 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export interface AxiosTransformer { 2 | (data: any, headers?: any): any; 3 | } 4 | 5 | export interface AxiosAdapter { 6 | (config: AxiosRequestConfig): AxiosPromise; 7 | } 8 | 9 | export interface AxiosBasicCredentials { 10 | username: string; 11 | password: string; 12 | } 13 | 14 | export interface AxiosProxyConfig { 15 | host: string; 16 | port: number; 17 | auth?: { 18 | username: string; 19 | password: string; 20 | }; 21 | protocol?: string; 22 | } 23 | 24 | export type Method = 25 | | 'get' 26 | | 'GET' 27 | | 'delete' 28 | | 'DELETE' 29 | | 'head' 30 | | 'HEAD' 31 | | 'options' 32 | | 'OPTIONS' 33 | | 'post' 34 | | 'POST' 35 | | 'put' 36 | | 'PUT' 37 | | 'patch' 38 | | 'PATCH' 39 | | 'link' 40 | | 'LINK' 41 | | 'unlink' 42 | | 'UNLINK'; 43 | 44 | export type ResponseType = 45 | | 'arraybuffer' 46 | | 'blob' 47 | | 'document' 48 | | 'json' 49 | | 'text' 50 | | 'stream'; 51 | 52 | export interface AxiosRequestConfig { 53 | url?: string; 54 | method?: Method; 55 | baseURL?: string; 56 | transformRequest?: AxiosTransformer | AxiosTransformer[]; 57 | transformResponse?: AxiosTransformer | AxiosTransformer[]; 58 | headers?: any; 59 | params?: any; 60 | paramsSerializer?: (params: any) => string; 61 | data?: any; 62 | timeout?: number; 63 | timeoutErrorMessage?: string; 64 | withCredentials?: boolean; 65 | adapter?: AxiosAdapter; 66 | auth?: AxiosBasicCredentials; 67 | responseType?: ResponseType; 68 | xsrfCookieName?: string; 69 | xsrfHeaderName?: string; 70 | onUploadProgress?: (progressEvent: any) => void; 71 | onDownloadProgress?: (progressEvent: any) => void; 72 | maxContentLength?: number; 73 | validateStatus?: (status: number) => boolean; 74 | maxRedirects?: number; 75 | socketPath?: string | null; 76 | httpAgent?: any; 77 | httpsAgent?: any; 78 | proxy?: AxiosProxyConfig | false; 79 | cancelToken?: CancelToken; 80 | } 81 | 82 | export interface AxiosResponse { 83 | data: T; 84 | status: number; 85 | statusText: string; 86 | headers: any; 87 | config: AxiosRequestConfig; 88 | request?: any; 89 | } 90 | 91 | export interface AxiosError extends Error { 92 | config: AxiosRequestConfig; 93 | code?: string; 94 | request?: any; 95 | response?: AxiosResponse; 96 | isAxiosError: boolean; 97 | toJSON: () => object; 98 | } 99 | 100 | export interface AxiosPromise extends Promise> {} 101 | 102 | export interface CancelStatic { 103 | new (message?: string): Cancel; 104 | } 105 | 106 | export interface Cancel { 107 | message: string; 108 | } 109 | 110 | export interface Canceler { 111 | (message?: string): void; 112 | } 113 | 114 | export interface CancelTokenStatic { 115 | new (executor: (cancel: Canceler) => void): CancelToken; 116 | source(): CancelTokenSource; 117 | } 118 | 119 | export interface CancelToken { 120 | promise: Promise; 121 | reason?: Cancel; 122 | throwIfRequested(): void; 123 | } 124 | 125 | export interface CancelTokenSource { 126 | token: CancelToken; 127 | cancel: Canceler; 128 | } 129 | 130 | export interface AxiosInterceptorManager { 131 | use( 132 | onFulfilled?: (value: V) => V | Promise, 133 | onRejected?: (error: any) => any 134 | ): number; 135 | eject(id: number): void; 136 | } 137 | 138 | export interface AxiosInstance { 139 | (config: AxiosRequestConfig): AxiosPromise; 140 | (url: string, config?: AxiosRequestConfig): AxiosPromise; 141 | defaults: AxiosRequestConfig; 142 | interceptors: { 143 | request: AxiosInterceptorManager; 144 | response: AxiosInterceptorManager; 145 | }; 146 | getUri(config?: AxiosRequestConfig): string; 147 | request>( 148 | config: AxiosRequestConfig 149 | ): Promise; 150 | get>( 151 | url: string, 152 | config?: AxiosRequestConfig 153 | ): Promise; 154 | jsonp>( 155 | url: string, 156 | config?: AxiosRequestConfig 157 | ): Promise; 158 | delete>( 159 | url: string, 160 | config?: AxiosRequestConfig 161 | ): Promise; 162 | head>( 163 | url: string, 164 | config?: AxiosRequestConfig 165 | ): Promise; 166 | options>( 167 | url: string, 168 | config?: AxiosRequestConfig 169 | ): Promise; 170 | post>( 171 | url: string, 172 | data?: any, 173 | config?: AxiosRequestConfig 174 | ): Promise; 175 | put>( 176 | url: string, 177 | data?: any, 178 | config?: AxiosRequestConfig 179 | ): Promise; 180 | patch>( 181 | url: string, 182 | data?: any, 183 | config?: AxiosRequestConfig 184 | ): Promise; 185 | } 186 | 187 | export interface AxiosStatic extends AxiosInstance { 188 | create(config?: AxiosRequestConfig): AxiosInstance; 189 | Cancel: CancelStatic; 190 | CancelToken: CancelTokenStatic; 191 | isCancel(value: any): boolean; 192 | all(values: (T | Promise)[]): Promise; 193 | spread(callback: (...args: T[]) => R): (array: T[]) => R; 194 | } 195 | 196 | declare const Axios: AxiosStatic; 197 | 198 | export default Axios; 199 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/axios'); -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Aug 15 2014 23:11:13 GMT-0500 (CDT) 3 | 4 | var webpack = require('webpack'); 5 | 6 | function createCustomLauncher(browser, version, platform) { 7 | return { 8 | base: 'SauceLabs', 9 | browserName: browser, 10 | version: version, 11 | platform: platform 12 | }; 13 | } 14 | 15 | module.exports = function(config) { 16 | var customLaunchers = {}; 17 | var browsers = []; 18 | 19 | if (process.env.SAUCE_USERNAME || process.env.SAUCE_ACCESS_KEY) { 20 | customLaunchers = {}; 21 | 22 | var runAll = true; 23 | var options = [ 24 | 'SAUCE_CHROME', 25 | 'SAUCE_FIREFOX', 26 | 'SAUCE_SAFARI', 27 | 'SAUCE_OPERA', 28 | 'SAUCE_IE', 29 | 'SAUCE_EDGE', 30 | 'SAUCE_IOS', 31 | 'SAUCE_ANDROID' 32 | ]; 33 | 34 | options.forEach(function (opt) { 35 | if (process.env[opt]) { 36 | runAll = false; 37 | } 38 | }); 39 | 40 | // Chrome 41 | if (runAll || process.env.SAUCE_CHROME) { 42 | customLaunchers.SL_Chrome = createCustomLauncher('chrome'); 43 | // customLaunchers.SL_ChromeDev = createCustomLauncher('chrome', 'dev'); 44 | // customLaunchers.SL_ChromeBeta = createCustomLauncher('chrome', 'beta'); 45 | } 46 | 47 | // Firefox 48 | if (runAll || process.env.SAUCE_FIREFOX) { 49 | customLaunchers.SL_Firefox = createCustomLauncher('firefox'); 50 | // customLaunchers.SL_FirefoxDev = createCustomLauncher('firefox', 'dev'); 51 | // customLaunchers.SL_FirefoxBeta = createCustomLauncher('firefox', 'beta'); 52 | } 53 | 54 | // Safari 55 | if (runAll || process.env.SAUCE_SAFARI) { 56 | // customLaunchers.SL_Safari7 = createCustomLauncher('safari', 7); 57 | // customLaunchers.SL_Safari8 = createCustomLauncher('safari', 8); 58 | 59 | customLaunchers.SL_Safari9 = createCustomLauncher('safari', 9); 60 | } 61 | 62 | // Opera 63 | if (runAll || process.env.SAUCE_OPERA) { 64 | // TODO The available versions of Opera are too old and lack basic APIs 65 | // customLaunchers.SL_Opera11 = createCustomLauncher('opera', 11, 'Windows XP'); 66 | // customLaunchers.SL_Opera12 = createCustomLauncher('opera', 12, 'Windows 7'); 67 | } 68 | 69 | // IE 70 | if (runAll || process.env.SAUCE_IE) { 71 | // customLaunchers.SL_IE8 = createCustomLauncher('internet explorer', 8, 'Windows 7'); 72 | customLaunchers.SL_IE9 = createCustomLauncher('internet explorer', 9, 'Windows 2008'); 73 | customLaunchers.SL_IE10 = createCustomLauncher('internet explorer', 10, 'Windows 2012'); 74 | customLaunchers.SL_IE11 = createCustomLauncher('internet explorer', 11, 'Windows 8.1'); 75 | } 76 | 77 | // Edge 78 | if (runAll || process.env.SAUCE_EDGE) { 79 | customLaunchers.SL_Edge = createCustomLauncher('microsoftedge', null, 'Windows 10'); 80 | } 81 | 82 | // IOS 83 | if (runAll || process.env.SAUCE_IOS) { 84 | // TODO IOS7 capture always timesout 85 | // customLaunchers.SL_IOS7 = createCustomLauncher('iphone', '7.1', 'OS X 10.10'); 86 | // TODO Mobile browsers are causing failures, possibly from too many concurrent VMs 87 | // customLaunchers.SL_IOS8 = createCustomLauncher('iphone', '8.4', 'OS X 10.10'); 88 | // customLaunchers.SL_IOS9 = createCustomLauncher('iphone', '9.2', 'OS X 10.10'); 89 | } 90 | 91 | // Android 92 | if (runAll || process.env.SAUCE_ANDROID) { 93 | // TODO Mobile browsers are causing failures, possibly from too many concurrent VMs 94 | // customLaunchers.SL_Android4 = createCustomLauncher('android', '4.4', 'Linux'); 95 | // customLaunchers.SL_Android5 = createCustomLauncher('android', '5.1', 'Linux'); 96 | } 97 | 98 | browsers = Object.keys(customLaunchers); 99 | } else if (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false') { 100 | console.log( 101 | 'Cannot run on Sauce Labs as encrypted environment variables are not available to PRs. ' + 102 | 'Running on Travis.' 103 | ); 104 | browsers = ['Firefox']; 105 | } else { 106 | console.log('Running locally since SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are not set.'); 107 | browsers = ['Firefox', 'Chrome', 'Safari', 'Opera']; 108 | } 109 | 110 | config.set({ 111 | // base path that will be used to resolve all patterns (eg. files, exclude) 112 | basePath: '', 113 | 114 | 115 | // frameworks to use 116 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 117 | frameworks: ['jasmine-ajax', 'jasmine', 'sinon'], 118 | 119 | 120 | // list of files / patterns to load in the browser 121 | files: [ 122 | 'test/specs/__helpers.js', 123 | 'test/specs/**/*.spec.js', 124 | ], 125 | 126 | 127 | // list of files to exclude 128 | exclude: [ 129 | 130 | ], 131 | 132 | 133 | // preprocess matching files before serving them to the browser 134 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 135 | preprocessors: { 136 | 'test/specs/__helpers.js': ['webpack', 'sourcemap'], 137 | 'test/specs/**/*.spec.js': ['webpack', 'sourcemap'] 138 | }, 139 | 140 | 141 | // test results reporter to use 142 | // possible values: 'dots', 'progress' 143 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 144 | reporters: ['dots', 'coverage', 'saucelabs'], 145 | 146 | 147 | // web server port 148 | port: 9876, 149 | 150 | 151 | // Increase timeouts to prevent the issue with disconnected tests (https://goo.gl/nstA69) 152 | captureTimeout: 4 * 60 * 1000, 153 | browserDisconnectTimeout: 10000, 154 | browserDisconnectTolerance: 1, 155 | browserNoActivityTimeout: 4 * 60 * 1000, 156 | 157 | 158 | // enable / disable colors in the output (reporters and logs) 159 | colors: true, 160 | 161 | 162 | // level of logging 163 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 164 | logLevel: config.LOG_INFO, 165 | 166 | 167 | // enable / disable watching file and executing tests whenever any file changes 168 | autoWatch: false, 169 | 170 | 171 | // start these browsers 172 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 173 | browsers: browsers, 174 | 175 | 176 | // Continuous Integration mode 177 | // if true, Karma captures browsers, runs the tests and exits 178 | singleRun: false, 179 | 180 | // Webpack config 181 | webpack: { 182 | cache: true, 183 | devtool: 'inline-source-map', 184 | module: { 185 | postLoaders: [ 186 | { 187 | test: /\.js$/, 188 | exclude: /(node_modules|test)/, 189 | loader: 'istanbul-instrumenter' 190 | } 191 | ] 192 | }, 193 | externals: [ 194 | { 195 | './adapters/http': 'var undefined' 196 | } 197 | ], 198 | plugins: [ 199 | new webpack.DefinePlugin({ 200 | 'process.env.NODE_ENV': JSON.stringify('test') 201 | }) 202 | ] 203 | }, 204 | 205 | webpackServer: { 206 | stats: { 207 | colors: true 208 | } 209 | }, 210 | 211 | 212 | // Coverage reporting 213 | coverageReporter: { 214 | type: 'lcov', 215 | dir: 'coverage/', 216 | subdir: '.' 217 | }, 218 | 219 | 220 | // SauceLabs config 221 | sauceLabs: { 222 | recordScreenshots: false, 223 | connectOptions: { 224 | port: 5757, 225 | logfile: 'sauce_connect.log' 226 | }, 227 | public: 'public' 228 | }, 229 | 230 | customLaunchers: customLaunchers 231 | }); 232 | }; 233 | -------------------------------------------------------------------------------- /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/http.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var settle = require('./../core/settle'); 5 | var buildURL = require('./../helpers/buildURL'); 6 | var http = require('http'); 7 | var https = require('https'); 8 | var httpFollow = require('follow-redirects').http; 9 | var httpsFollow = require('follow-redirects').https; 10 | var url = require('url'); 11 | var zlib = require('zlib'); 12 | var pkg = require('./../../package.json'); 13 | var createError = require('../core/createError'); 14 | var enhanceError = require('../core/enhanceError'); 15 | 16 | /*eslint consistent-return:0*/ 17 | module.exports = function httpAdapter(config) { 18 | return new Promise(function dispatchHttpRequest(resolve, reject) { 19 | var data = config.data; 20 | var headers = config.headers; 21 | var timer; 22 | 23 | // Set User-Agent (required by some servers) 24 | // Only set header if it hasn't been set in config 25 | // See https://github.com/mzabriskie/axios/issues/69 26 | if (!headers['User-Agent'] && !headers['user-agent']) { 27 | headers['User-Agent'] = 'axios/' + pkg.version; 28 | } 29 | 30 | if (data && !utils.isStream(data)) { 31 | if (Buffer.isBuffer(data)) { 32 | // Nothing to do... 33 | } else if (utils.isArrayBuffer(data)) { 34 | data = new Buffer(new Uint8Array(data)); 35 | } else if (utils.isString(data)) { 36 | data = new Buffer(data, 'utf-8'); 37 | } else { 38 | return reject(createError( 39 | 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream', 40 | config 41 | )); 42 | } 43 | 44 | // Add Content-Length header if data exists 45 | headers['Content-Length'] = data.length; 46 | } 47 | 48 | // HTTP basic authentication 49 | var auth = undefined; 50 | if (config.auth) { 51 | var username = config.auth.username || ''; 52 | var password = config.auth.password || ''; 53 | auth = username + ':' + password; 54 | } 55 | 56 | // Parse url 57 | var parsed = url.parse(config.url); 58 | var protocol = parsed.protocol || 'http:'; 59 | 60 | if (!auth && parsed.auth) { 61 | var urlAuth = parsed.auth.split(':'); 62 | var urlUsername = urlAuth[0] || ''; 63 | var urlPassword = urlAuth[1] || ''; 64 | auth = urlUsername + ':' + urlPassword; 65 | } 66 | 67 | if (auth) { 68 | delete headers.Authorization; 69 | } 70 | 71 | var isHttps = protocol === 'https:'; 72 | var agent = isHttps ? config.httpsAgent : config.httpAgent; 73 | 74 | var options = { 75 | hostname: parsed.hostname, 76 | port: parsed.port, 77 | path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''), 78 | method: config.method, 79 | headers: headers, 80 | agent: agent, 81 | auth: auth 82 | }; 83 | 84 | var proxy = config.proxy; 85 | if (!proxy && proxy !== false) { 86 | var proxyEnv = protocol.slice(0, -1) + '_proxy'; 87 | var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()]; 88 | if (proxyUrl) { 89 | var parsedProxyUrl = url.parse(proxyUrl); 90 | proxy = { 91 | host: parsedProxyUrl.hostname, 92 | port: parsedProxyUrl.port 93 | }; 94 | 95 | if (parsedProxyUrl.auth) { 96 | var proxyUrlAuth = parsedProxyUrl.auth.split(':'); 97 | proxy.auth = { 98 | username: proxyUrlAuth[0], 99 | password: proxyUrlAuth[1] 100 | }; 101 | } 102 | } 103 | } 104 | 105 | if (proxy) { 106 | options.hostname = proxy.host; 107 | options.host = proxy.host; 108 | options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : ''); 109 | options.port = proxy.port; 110 | options.path = protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path; 111 | 112 | // Basic proxy authorization 113 | if (proxy.auth) { 114 | var base64 = new Buffer(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64'); 115 | options.headers['Proxy-Authorization'] = 'Basic ' + base64; 116 | } 117 | } 118 | 119 | var transport; 120 | if (config.maxRedirects === 0) { 121 | transport = isHttps ? https : http; 122 | } else { 123 | if (config.maxRedirects) { 124 | options.maxRedirects = config.maxRedirects; 125 | } 126 | transport = isHttps ? httpsFollow : httpFollow; 127 | } 128 | 129 | // Create the request 130 | var req = transport.request(options, function handleResponse(res) { 131 | if (req.aborted) return; 132 | 133 | // Response has been received so kill timer that handles request timeout 134 | clearTimeout(timer); 135 | timer = null; 136 | 137 | // uncompress the response body transparently if required 138 | var stream = res; 139 | switch (res.headers['content-encoding']) { 140 | /*eslint default-case:0*/ 141 | case 'gzip': 142 | case 'compress': 143 | case 'deflate': 144 | // add the unzipper to the body stream processing pipeline 145 | stream = stream.pipe(zlib.createUnzip()); 146 | 147 | // remove the content-encoding in order to not confuse downstream operations 148 | delete res.headers['content-encoding']; 149 | break; 150 | } 151 | 152 | // return the last request in case of redirects 153 | var lastRequest = res.req || req; 154 | 155 | var response = { 156 | status: res.statusCode, 157 | statusText: res.statusMessage, 158 | headers: res.headers, 159 | config: config, 160 | request: lastRequest 161 | }; 162 | 163 | if (config.responseType === 'stream') { 164 | response.data = stream; 165 | settle(resolve, reject, response); 166 | } else { 167 | var responseBuffer = []; 168 | stream.on('data', function handleStreamData(chunk) { 169 | responseBuffer.push(chunk); 170 | 171 | // make sure the content length is not over the maxContentLength if specified 172 | if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) { 173 | reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded', 174 | config, null, lastRequest)); 175 | } 176 | }); 177 | 178 | stream.on('error', function handleStreamError(err) { 179 | if (req.aborted) return; 180 | reject(enhanceError(err, config, null, lastRequest)); 181 | }); 182 | 183 | stream.on('end', function handleStreamEnd() { 184 | var responseData = Buffer.concat(responseBuffer); 185 | if (config.responseType !== 'arraybuffer') { 186 | responseData = responseData.toString('utf8'); 187 | } 188 | 189 | response.data = responseData; 190 | settle(resolve, reject, response); 191 | }); 192 | } 193 | }); 194 | 195 | // Handle errors 196 | req.on('error', function handleRequestError(err) { 197 | if (req.aborted) return; 198 | reject(enhanceError(err, config, null, req)); 199 | }); 200 | 201 | // Handle request timeout 202 | if (config.timeout && !timer) { 203 | timer = setTimeout(function handleRequestTimeout() { 204 | req.abort(); 205 | reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req)); 206 | }, config.timeout); 207 | } 208 | 209 | if (config.cancelToken) { 210 | // Handle cancellation 211 | config.cancelToken.promise.then(function onCanceled(cancel) { 212 | if (req.aborted) return; 213 | 214 | req.abort(); 215 | reject(cancel); 216 | }); 217 | } 218 | 219 | // Send the request 220 | if (utils.isStream(data)) { 221 | data.pipe(req); 222 | } else { 223 | req.end(data); 224 | } 225 | }); 226 | }; 227 | -------------------------------------------------------------------------------- /lib/adapters/xhr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var settle = require('./../core/settle'); 5 | var buildURL = require('./../helpers/buildURL'); 6 | var parseHeaders = require('./../helpers/parseHeaders'); 7 | var isURLSameOrigin = require('./../helpers/isURLSameOrigin'); 8 | var createError = require('../core/createError'); 9 | var btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || require('./../helpers/btoa'); 10 | 11 | module.exports = function xhrAdapter(config) { 12 | return new Promise(function dispatchXhrRequest(resolve, reject) { 13 | var requestData = config.data; 14 | var requestHeaders = config.headers; 15 | 16 | if (utils.isFormData(requestData)) { 17 | delete requestHeaders['Content-Type']; // Let the browser set it 18 | } 19 | 20 | var request = new XMLHttpRequest(); 21 | var loadEvent = 'onreadystatechange'; 22 | var xDomain = false; 23 | 24 | // For IE 8/9 CORS support 25 | // Only supports POST and GET calls and doesn't returns the response headers. 26 | // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest. 27 | if (process.env.NODE_ENV !== 'test' && 28 | typeof window !== 'undefined' && 29 | window.XDomainRequest && !('withCredentials' in request) && 30 | !isURLSameOrigin(config.url)) { 31 | request = new window.XDomainRequest(); 32 | loadEvent = 'onload'; 33 | xDomain = true; 34 | request.onprogress = function handleProgress() {}; 35 | request.ontimeout = function handleTimeout() {}; 36 | } 37 | 38 | // HTTP basic authentication 39 | if (config.auth) { 40 | var username = config.auth.username || ''; 41 | var password = config.auth.password || ''; 42 | requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); 43 | } 44 | 45 | request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true); 46 | 47 | // Set the request timeout in MS 48 | request.timeout = config.timeout; 49 | 50 | // Listen for ready state 51 | request[loadEvent] = function handleLoad() { 52 | if (!request || (request.readyState !== 4 && !xDomain)) { 53 | return; 54 | } 55 | 56 | // The request errored out and we didn't get a response, this will be 57 | // handled by onerror instead 58 | // With one exception: request that using file: protocol, most browsers 59 | // will return status as 0 even though it's a successful request 60 | if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { 61 | return; 62 | } 63 | 64 | // Prepare the response 65 | var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; 66 | var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; 67 | var response = { 68 | data: responseData, 69 | // IE sends 1223 instead of 204 (https://github.com/mzabriskie/axios/issues/201) 70 | status: request.status === 1223 ? 204 : request.status, 71 | statusText: request.status === 1223 ? 'No Content' : request.statusText, 72 | headers: responseHeaders, 73 | config: config, 74 | request: request 75 | }; 76 | 77 | settle(resolve, reject, response); 78 | 79 | // Clean up request 80 | request = null; 81 | }; 82 | 83 | // Handle low level network errors 84 | request.onerror = function handleError() { 85 | // Real errors are hidden from us by the browser 86 | // onerror should only fire if it's a network error 87 | reject(createError('Network Error', config, null, request)); 88 | 89 | // Clean up request 90 | request = null; 91 | }; 92 | 93 | // Handle timeout 94 | request.ontimeout = function handleTimeout() { 95 | reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', 96 | request)); 97 | 98 | // Clean up request 99 | request = null; 100 | }; 101 | 102 | // Add xsrf header 103 | // This is only done if running in a standard browser environment. 104 | // Specifically not if we're in a web worker, or react-native. 105 | if (utils.isStandardBrowserEnv()) { 106 | var cookies = require('./../helpers/cookies'); 107 | 108 | // Add xsrf header 109 | var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? 110 | cookies.read(config.xsrfCookieName) : 111 | undefined; 112 | 113 | if (xsrfValue) { 114 | requestHeaders[config.xsrfHeaderName] = xsrfValue; 115 | } 116 | } 117 | 118 | // Add headers to the request 119 | if ('setRequestHeader' in request) { 120 | utils.forEach(requestHeaders, function setRequestHeader(val, key) { 121 | if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { 122 | // Remove Content-Type if data is undefined 123 | delete requestHeaders[key]; 124 | } else { 125 | // Otherwise add header to the request 126 | request.setRequestHeader(key, val); 127 | } 128 | }); 129 | } 130 | 131 | // Add withCredentials to request if needed 132 | if (config.withCredentials) { 133 | request.withCredentials = true; 134 | } 135 | 136 | // Add responseType to request if needed 137 | if (config.responseType) { 138 | try { 139 | request.responseType = config.responseType; 140 | } catch (e) { 141 | // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. 142 | // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. 143 | if (config.responseType !== 'json') { 144 | throw e; 145 | } 146 | } 147 | } 148 | 149 | // Handle progress if needed 150 | if (typeof config.onDownloadProgress === 'function') { 151 | request.addEventListener('progress', config.onDownloadProgress); 152 | } 153 | 154 | // Not all browsers support upload events 155 | if (typeof config.onUploadProgress === 'function' && request.upload) { 156 | request.upload.addEventListener('progress', config.onUploadProgress); 157 | } 158 | 159 | if (config.cancelToken) { 160 | // Handle cancellation 161 | config.cancelToken.promise.then(function onCanceled(cancel) { 162 | if (!request) { 163 | return; 164 | } 165 | 166 | request.abort(); 167 | reject(cancel); 168 | // Clean up request 169 | request = null; 170 | }); 171 | } 172 | 173 | if (requestData === undefined) { 174 | requestData = null; 175 | } 176 | 177 | // Send the request 178 | request.send(requestData); 179 | }); 180 | }; 181 | -------------------------------------------------------------------------------- /lib/axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./utils'); 4 | var bind = require('./helpers/bind'); 5 | var Axios = require('./core/Axios'); 6 | var defaults = require('./defaults'); 7 | 8 | /** 9 | * Create an instance of Axios 10 | * 11 | * @param {Object} defaultConfig The default config for the instance 12 | * @return {Axios} A new instance of Axios 13 | */ 14 | function createInstance(defaultConfig) { 15 | var context = new Axios(defaultConfig); 16 | var instance = bind(Axios.prototype.request, context); 17 | // Copy axios.prototype to instance 18 | utils.extend(instance, Axios.prototype, context); 19 | 20 | // Copy context to instance 21 | utils.extend(instance, context); 22 | 23 | return instance; 24 | } 25 | 26 | // Create the default instance to be exported 27 | var axios = createInstance(defaults); 28 | 29 | // Expose Axios class to allow class inheritance 30 | axios.Axios = Axios; 31 | 32 | // Factory for creating new instances 33 | axios.create = function create(instanceConfig) { 34 | return createInstance(utils.merge(defaults, instanceConfig)); 35 | }; 36 | 37 | // Expose Cancel & CancelToken 38 | axios.Cancel = require('./cancel/Cancel'); 39 | axios.CancelToken = require('./cancel/CancelToken'); 40 | axios.isCancel = require('./cancel/isCancel'); 41 | 42 | // Expose all/spread 43 | axios.all = function all(promises) { 44 | return Promise.all(promises); 45 | }; 46 | axios.spread = require('./helpers/spread'); 47 | 48 | module.exports = axios; 49 | 50 | // Allow use of default import syntax in TypeScript 51 | module.exports.default = axios; 52 | -------------------------------------------------------------------------------- /lib/cancel/Cancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * A `Cancel` is an object that is thrown when an operation is canceled. 5 | * 6 | * @class 7 | * @param {string=} message The message. 8 | */ 9 | function Cancel(message) { 10 | this.message = message; 11 | } 12 | 13 | Cancel.prototype.toString = function toString() { 14 | return 'Cancel' + (this.message ? ': ' + this.message : ''); 15 | }; 16 | 17 | Cancel.prototype.__CANCEL__ = true; 18 | 19 | module.exports = Cancel; 20 | -------------------------------------------------------------------------------- /lib/cancel/CancelToken.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Cancel = require('./Cancel'); 4 | 5 | /** 6 | * A `CancelToken` is an object that can be used to request cancellation of an operation. 7 | * 8 | * @class 9 | * @param {Function} executor The executor function. 10 | */ 11 | function CancelToken(executor) { 12 | if (typeof executor !== 'function') { 13 | throw new TypeError('executor must be a function.'); 14 | } 15 | 16 | var resolvePromise; 17 | this.promise = new Promise(function promiseExecutor(resolve) { 18 | resolvePromise = resolve; 19 | }); 20 | 21 | var token = this; 22 | executor(function cancel(message) { 23 | if (token.reason) { 24 | // Cancellation has already been requested 25 | return; 26 | } 27 | 28 | token.reason = new Cancel(message); 29 | resolvePromise(token.reason); 30 | }); 31 | } 32 | 33 | /** 34 | * Throws a `Cancel` if cancellation has been requested. 35 | */ 36 | CancelToken.prototype.throwIfRequested = function throwIfRequested() { 37 | if (this.reason) { 38 | throw this.reason; 39 | } 40 | }; 41 | 42 | /** 43 | * Returns an object that contains a new `CancelToken` and a function that, when called, 44 | * cancels the `CancelToken`. 45 | */ 46 | CancelToken.source = function source() { 47 | var cancel; 48 | var token = new CancelToken(function executor(c) { 49 | cancel = c; 50 | }); 51 | return { 52 | token: token, 53 | cancel: cancel 54 | }; 55 | }; 56 | 57 | module.exports = CancelToken; 58 | -------------------------------------------------------------------------------- /lib/cancel/isCancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function isCancel(value) { 4 | return !!(value && value.__CANCEL__); 5 | }; 6 | -------------------------------------------------------------------------------- /lib/core/Axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var defaults = require('./../defaults'); 4 | var utils = require('./../utils'); 5 | var InterceptorManager = require('./InterceptorManager'); 6 | var dispatchRequest = require('./dispatchRequest'); 7 | 8 | /** 9 | * Create a new instance of Axios 10 | * 11 | * @param {Object} instanceConfig The default config for the instance 12 | */ 13 | function Axios(instanceConfig) { 14 | this.defaults = instanceConfig; 15 | this.interceptors = { 16 | request: new InterceptorManager(), 17 | response: new InterceptorManager() 18 | }; 19 | } 20 | 21 | /** 22 | * Dispatch a request 23 | * 24 | * @param {Object} config The config specific for this request (merged with this.defaults) 25 | */ 26 | Axios.prototype.request = function request(config) { 27 | /*eslint no-param-reassign:0*/ 28 | // Allow for axios('example/url'[, config]) a la fetch API 29 | if (typeof config === 'string') { 30 | config = utils.merge({ 31 | url: arguments[0] 32 | }, 33 | arguments[1] 34 | ); 35 | } 36 | 37 | config = utils.merge( 38 | defaults, 39 | this.defaults, { 40 | method: 'get' 41 | }, 42 | config 43 | ); 44 | config.method = config.method.toLowerCase(); 45 | 46 | // Hook up interceptors middleware 47 | var chain = [undefined]; 48 | 49 | // var chain = [dispatchRequest, undefined]; 50 | var promise = Promise.resolve(config); 51 | 52 | chain.unshift(dispatchRequest); 53 | 54 | 55 | this.interceptors.request.forEach(function unshiftRequestInterceptors( 56 | interceptor 57 | ) { 58 | chain.unshift(interceptor.fulfilled, interceptor.rejected); 59 | }); 60 | 61 | this.interceptors.response.forEach(function pushResponseInterceptors( 62 | interceptor 63 | ) { 64 | chain.push(interceptor.fulfilled, interceptor.rejected); 65 | }); 66 | 67 | while (chain.length) { 68 | promise = promise.then(chain.shift(), chain.shift()); 69 | } 70 | 71 | return promise; 72 | }; 73 | 74 | // Provide aliases for supported request methods 75 | utils.forEach( 76 | ['delete', 'get', 'head', 'options', 'jsonp'], 77 | function forEachMethodNoData(method) { 78 | /*eslint func-names:0*/ 79 | Axios.prototype[method] = function (url, config) { 80 | return this.request( 81 | utils.merge(config || {}, { 82 | method: method, 83 | url: url 84 | }) 85 | ); 86 | }; 87 | } 88 | ); 89 | 90 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { 91 | /*eslint func-names:0*/ 92 | Axios.prototype[method] = function (url, data, config) { 93 | return this.request( 94 | utils.merge(config || {}, { 95 | method: method, 96 | url: url, 97 | data: data 98 | }) 99 | ); 100 | }; 101 | }); 102 | // add jsonp 103 | // Axios.prototype.jsonp = jsonp; 104 | 105 | module.exports = Axios; -------------------------------------------------------------------------------- /lib/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | function InterceptorManager() { 6 | this.handlers = []; 7 | } 8 | 9 | /** 10 | * Add a new interceptor to the stack 11 | * 12 | * @param {Function} fulfilled The function to handle `then` for a `Promise` 13 | * @param {Function} rejected The function to handle `reject` for a `Promise` 14 | * 15 | * @return {Number} An ID used to remove interceptor later 16 | */ 17 | InterceptorManager.prototype.use = function use(fulfilled, rejected) { 18 | this.handlers.push({ 19 | fulfilled: fulfilled, 20 | rejected: rejected 21 | }); 22 | return this.handlers.length - 1; 23 | }; 24 | 25 | /** 26 | * Remove an interceptor from the stack 27 | * 28 | * @param {Number} id The ID that was returned by `use` 29 | */ 30 | InterceptorManager.prototype.eject = function eject(id) { 31 | if (this.handlers[id]) { 32 | this.handlers[id] = null; 33 | } 34 | }; 35 | 36 | /** 37 | * Iterate over all the registered interceptors 38 | * 39 | * This method is particularly useful for skipping over any 40 | * interceptors that may have become `null` calling `eject`. 41 | * 42 | * @param {Function} fn The function to call for each interceptor 43 | */ 44 | InterceptorManager.prototype.forEach = function forEach(fn) { 45 | utils.forEach(this.handlers, function forEachHandler(h) { 46 | if (h !== null) { 47 | fn(h); 48 | } 49 | }); 50 | }; 51 | 52 | module.exports = InterceptorManager; 53 | -------------------------------------------------------------------------------- /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 | - Managing interceptors 7 | - Handling config 8 | -------------------------------------------------------------------------------- /lib/core/createError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var enhanceError = require('./enhanceError'); 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 {Object} config The config. 10 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 11 | * @param {Object} [request] The request. 12 | * @param {Object} [response] The response. 13 | * @returns {Error} The created error. 14 | */ 15 | module.exports = function createError(message, config, code, request, response) { 16 | var error = new Error(message); 17 | return enhanceError(error, config, code, request, response); 18 | }; 19 | -------------------------------------------------------------------------------- /lib/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var transformData = require('./transformData'); 5 | var isCancel = require('../cancel/isCancel'); 6 | var defaults = require('../defaults'); 7 | var isAbsoluteURL = require('./../helpers/isAbsoluteURL'); 8 | var combineURLs = require('./../helpers/combineURLs'); 9 | var jsonp = require('./jsonp'); 10 | 11 | /** 12 | * Throws a `Cancel` if cancellation has been requested. 13 | */ 14 | function throwIfCancellationRequested(config) { 15 | if (config.cancelToken) { 16 | config.cancelToken.throwIfRequested(); 17 | } 18 | } 19 | 20 | /** 21 | * Dispatch a request to the server using the configured adapter. 22 | * 23 | * @param {object} config The config that is to be used for the request 24 | * @returns {Promise} The Promise to be fulfilled 25 | */ 26 | module.exports = function dispatchRequest(config) { 27 | throwIfCancellationRequested(config); 28 | 29 | // Support baseURL config 30 | if (config.baseURL && !isAbsoluteURL(config.url)) { 31 | config.url = combineURLs(config.baseURL, config.url); 32 | } 33 | 34 | // Ensure headers exist 35 | config.headers = config.headers || {}; 36 | 37 | // Transform request data 38 | config.data = transformData( 39 | config.data, 40 | config.headers, 41 | config.transformRequest 42 | ); 43 | 44 | // Flatten headers 45 | config.headers = utils.merge( 46 | config.headers.common || {}, 47 | config.headers[config.method] || {}, 48 | config.headers || {} 49 | ); 50 | 51 | utils.forEach( 52 | ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], 53 | function cleanHeaderConfig(method) { 54 | delete config.headers[method]; 55 | } 56 | ); 57 | 58 | var adapter = config.adapter || defaults.adapter; 59 | 60 | if (config.method === 'jsonp') { 61 | return jsonp(config); 62 | } 63 | 64 | return adapter(config).then(function onAdapterResolution(response) { 65 | throwIfCancellationRequested(config); 66 | 67 | // Transform response data 68 | response.data = transformData( 69 | response.data, 70 | response.headers, 71 | config.transformResponse 72 | ); 73 | 74 | return response; 75 | }, function onAdapterRejection(reason) { 76 | if (!isCancel(reason)) { 77 | throwIfCancellationRequested(config); 78 | 79 | // Transform response data 80 | if (reason && reason.response) { 81 | reason.response.data = transformData( 82 | reason.response.data, 83 | reason.response.headers, 84 | config.transformResponse 85 | ); 86 | } 87 | } 88 | 89 | return Promise.reject(reason); 90 | }); 91 | }; -------------------------------------------------------------------------------- /lib/core/enhanceError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Update an Error with the specified config, error code, and response. 5 | * 6 | * @param {Error} error The error to update. 7 | * @param {Object} config The config. 8 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 9 | * @param {Object} [request] The request. 10 | * @param {Object} [response] The response. 11 | * @returns {Error} The error. 12 | */ 13 | module.exports = function enhanceError(error, config, code, request, response) { 14 | error.config = config; 15 | if (code) { 16 | error.code = code; 17 | } 18 | error.request = request; 19 | error.response = response; 20 | return error; 21 | }; 22 | -------------------------------------------------------------------------------- /lib/core/jsonp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var buildURL = require("./../helpers/buildURL"); 4 | /** 5 | * Callback index. 6 | */ 7 | 8 | var count = 0; 9 | 10 | /** 11 | * Noop function. 12 | */ 13 | 14 | function noop() {} 15 | 16 | /** 17 | * JSONP handler 18 | * 19 | * Options: 20 | * - param {String} qs parameter (`callback`) 21 | * - prefix {String} qs parameter (`__jp`) 22 | * - name {String} qs parameter (`prefix` + incr) 23 | * - timeout {Number} how long after a timeout error is emitted (`60000`) 24 | * 25 | * @param {String} url 26 | * @param {Object|Function} optional options / callback 27 | */ 28 | 29 | function jsonp(opts) { 30 | var prefix = opts.prefix || "__jp"; 31 | 32 | var callbackName = opts.callback || "callback"; 33 | 34 | // use the callback name that was passed if one was provided. 35 | // otherwise generate a unique name by incrementing our counter. 36 | var id = opts.name || prefix + count++; 37 | 38 | var timeout = opts.timeout || 60000; 39 | var cacheFlag = opts.cache || false; 40 | var enc = encodeURIComponent; 41 | var target = document.getElementsByTagName("script")[0] || document.head; 42 | var script; 43 | var timer; 44 | 45 | function cleanup() { 46 | if (script.parentNode) script.parentNode.removeChild(script); 47 | window[id] = noop; 48 | if (timer) clearTimeout(timer); 49 | } 50 | 51 | if (!opts.url) { 52 | throw new TypeError("url is null or not defined"); 53 | } 54 | 55 | return new Promise(function (resolve, reject) { 56 | try { 57 | if (timeout) { 58 | timer = setTimeout(function () { 59 | cleanup(); 60 | reject(new Error("Request timed out")); 61 | }, timeout); 62 | } 63 | 64 | window[id] = function (data) { 65 | cleanup(); 66 | 67 | //Throws a `Cancel` if cancellation has been requested. 68 | if (opts.cancelToken) { 69 | opts.cancelToken.throwIfRequested(); 70 | } 71 | 72 | resolve(data); 73 | }; 74 | 75 | // add params 76 | opts.url = buildURL(opts.url, opts.params, opts.paramsSerializer); 77 | // add callback 78 | opts.url += 79 | (opts.url.indexOf("?") === -1 ? "?" : "&") + 80 | callbackName + 81 | "=" + 82 | enc(id); 83 | // cache 84 | !cacheFlag && (opts.url += "&_=" + new Date().getTime()); 85 | 86 | // create script 87 | script = document.createElement("script"); 88 | script.src = opts.url; 89 | target.parentNode.insertBefore(script, target); 90 | } catch (e) { 91 | reject(e); 92 | } 93 | }); 94 | } 95 | 96 | module.exports = jsonp; 97 | -------------------------------------------------------------------------------- /lib/core/settle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var createError = require('./createError'); 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 | module.exports = function settle(resolve, reject, response) { 13 | var validateStatus = response.config.validateStatus; 14 | // Note: status is not exposed by XDomainRequest 15 | if (!response.status || !validateStatus || validateStatus(response.status)) { 16 | resolve(response); 17 | } else { 18 | reject(createError( 19 | 'Request failed with status code ' + response.status, 20 | response.config, 21 | null, 22 | response.request, 23 | response 24 | )); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /lib/core/transformData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | /** 6 | * Transform the data for a request or a response 7 | * 8 | * @param {Object|String} data The data to be transformed 9 | * @param {Array} headers The headers for the request or response 10 | * @param {Array|Function} fns A single function or Array of functions 11 | * @returns {*} The resulting transformed data 12 | */ 13 | module.exports = function transformData(data, headers, fns) { 14 | /*eslint no-param-reassign:0*/ 15 | utils.forEach(fns, function transform(fn) { 16 | data = fn(data, headers); 17 | }); 18 | 19 | return data; 20 | }; 21 | -------------------------------------------------------------------------------- /lib/defaults.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./utils'); 4 | var normalizeHeaderName = require('./helpers/normalizeHeaderName'); 5 | 6 | var DEFAULT_CONTENT_TYPE = { 7 | 'Content-Type': 'application/x-www-form-urlencoded' 8 | }; 9 | 10 | function setContentTypeIfUnset(headers, value) { 11 | if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { 12 | headers['Content-Type'] = value; 13 | } 14 | } 15 | 16 | function getDefaultAdapter() { 17 | var adapter; 18 | if (typeof XMLHttpRequest !== 'undefined') { 19 | // For browsers use XHR adapter 20 | adapter = require('./adapters/xhr'); 21 | } else if (typeof process !== 'undefined') { 22 | // For node use HTTP adapter 23 | adapter = require('./adapters/http'); 24 | } 25 | return adapter; 26 | } 27 | 28 | var defaults = { 29 | adapter: getDefaultAdapter(), 30 | 31 | transformRequest: [function transformRequest(data, headers) { 32 | normalizeHeaderName(headers, 'Content-Type'); 33 | if (utils.isFormData(data) || 34 | utils.isArrayBuffer(data) || 35 | utils.isBuffer(data) || 36 | utils.isStream(data) || 37 | utils.isFile(data) || 38 | utils.isBlob(data) 39 | ) { 40 | return data; 41 | } 42 | if (utils.isArrayBufferView(data)) { 43 | return data.buffer; 44 | } 45 | if (utils.isURLSearchParams(data)) { 46 | setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); 47 | return data.toString(); 48 | } 49 | if (utils.isObject(data)) { 50 | setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); 51 | return JSON.stringify(data); 52 | } 53 | return data; 54 | }], 55 | 56 | transformResponse: [function transformResponse(data) { 57 | /*eslint no-param-reassign:0*/ 58 | if (typeof data === 'string') { 59 | try { 60 | data = JSON.parse(data); 61 | } catch (e) { /* Ignore */ } 62 | } 63 | return data; 64 | }], 65 | 66 | timeout: 0, 67 | 68 | xsrfCookieName: 'XSRF-TOKEN', 69 | xsrfHeaderName: 'X-XSRF-TOKEN', 70 | 71 | maxContentLength: -1, 72 | 73 | validateStatus: function validateStatus(status) { 74 | return status >= 200 && status < 300; 75 | } 76 | }; 77 | 78 | defaults.headers = { 79 | common: { 80 | 'Accept': 'application/json, text/plain, */*' 81 | } 82 | }; 83 | 84 | utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { 85 | defaults.headers[method] = {}; 86 | }); 87 | 88 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { 89 | defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); 90 | }); 91 | 92 | module.exports = defaults; 93 | -------------------------------------------------------------------------------- /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/bind.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function bind(fn, thisArg) { 4 | return function wrap() { 5 | var args = new Array(arguments.length); 6 | for (var i = 0; i < args.length; i++) { 7 | args[i] = arguments[i]; 8 | } 9 | return fn.apply(thisArg, args); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /lib/helpers/btoa.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // btoa polyfill for IE<10 courtesy https://github.com/davidchambers/Base64.js 4 | 5 | var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; 6 | 7 | function E() { 8 | this.message = 'String contains an invalid character'; 9 | } 10 | E.prototype = new Error; 11 | E.prototype.code = 5; 12 | E.prototype.name = 'InvalidCharacterError'; 13 | 14 | function btoa(input) { 15 | var str = String(input); 16 | var output = ''; 17 | for ( 18 | // initialize result and counter 19 | var block, charCode, idx = 0, map = chars; 20 | // if the next str index does not exist: 21 | // change the mapping table to "=" 22 | // check if d has no fractional digits 23 | str.charAt(idx | 0) || (map = '=', idx % 1); 24 | // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8 25 | output += map.charAt(63 & block >> 8 - idx % 1 * 8) 26 | ) { 27 | charCode = str.charCodeAt(idx += 3 / 4); 28 | if (charCode > 0xFF) { 29 | throw new E(); 30 | } 31 | block = block << 8 | charCode; 32 | } 33 | return output; 34 | } 35 | 36 | module.exports = btoa; 37 | -------------------------------------------------------------------------------- /lib/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | function encode(val) { 6 | return encodeURIComponent(val). 7 | replace(/%40/gi, '@'). 8 | replace(/%3A/gi, ':'). 9 | replace(/%24/g, '$'). 10 | replace(/%2C/gi, ','). 11 | replace(/%20/g, '+'). 12 | replace(/%5B/gi, '['). 13 | replace(/%5D/gi, ']'); 14 | } 15 | 16 | /** 17 | * Build a URL by appending params to the end 18 | * 19 | * @param {string} url The base of the url (e.g., http://www.google.com) 20 | * @param {object} [params] The params to be appended 21 | * @returns {string} The formatted url 22 | */ 23 | module.exports = function buildURL(url, params, paramsSerializer) { 24 | /*eslint no-param-reassign:0*/ 25 | if (!params) { 26 | return url; 27 | } 28 | 29 | var serializedParams; 30 | if (paramsSerializer) { 31 | serializedParams = paramsSerializer(params); 32 | } else if (utils.isURLSearchParams(params)) { 33 | serializedParams = params.toString(); 34 | } else { 35 | var parts = []; 36 | 37 | utils.forEach(params, function serialize(val, key) { 38 | if (val === null || typeof val === 'undefined') { 39 | return; 40 | } 41 | 42 | if (utils.isArray(val)) { 43 | key = key + '[]'; 44 | } 45 | 46 | if (!utils.isArray(val)) { 47 | val = [val]; 48 | } 49 | 50 | utils.forEach(val, function parseValue(v) { 51 | if (utils.isDate(v)) { 52 | v = v.toISOString(); 53 | } else if (utils.isObject(v)) { 54 | v = JSON.stringify(v); 55 | } 56 | parts.push(encode(key) + '=' + encode(v)); 57 | }); 58 | }); 59 | 60 | serializedParams = parts.join('&'); 61 | } 62 | 63 | if (serializedParams) { 64 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; 65 | } 66 | 67 | return url; 68 | }; 69 | -------------------------------------------------------------------------------- /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 | * @returns {string} The combined URL 9 | */ 10 | module.exports = function combineURLs(baseURL, relativeURL) { 11 | return relativeURL 12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') 13 | : baseURL; 14 | }; 15 | -------------------------------------------------------------------------------- /lib/helpers/cookies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs support document.cookie 9 | (function standardBrowserEnv() { 10 | return { 11 | write: function write(name, value, expires, path, domain, secure) { 12 | var cookie = []; 13 | cookie.push(name + '=' + encodeURIComponent(value)); 14 | 15 | if (utils.isNumber(expires)) { 16 | cookie.push('expires=' + new Date(expires).toGMTString()); 17 | } 18 | 19 | if (utils.isString(path)) { 20 | cookie.push('path=' + path); 21 | } 22 | 23 | if (utils.isString(domain)) { 24 | cookie.push('domain=' + domain); 25 | } 26 | 27 | if (secure === true) { 28 | cookie.push('secure'); 29 | } 30 | 31 | document.cookie = cookie.join('; '); 32 | }, 33 | 34 | read: function read(name) { 35 | var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); 36 | return (match ? decodeURIComponent(match[3]) : null); 37 | }, 38 | 39 | remove: function remove(name) { 40 | this.write(name, '', Date.now() - 86400000); 41 | } 42 | }; 43 | })() : 44 | 45 | // Non standard browser env (web workers, react-native) lack needed support. 46 | (function nonStandardBrowserEnv() { 47 | return { 48 | write: function write() {}, 49 | read: function read() { return null; }, 50 | remove: function remove() {} 51 | }; 52 | })() 53 | ); 54 | -------------------------------------------------------------------------------- /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 | module.exports = function deprecatedMethod(method, instead, docs) { 14 | try { 15 | console.warn( 16 | 'DEPRECATED method `' + method + '`.' + 17 | (instead ? ' Use `' + instead + '` instead.' : '') + 18 | ' This method will be removed in a future release.'); 19 | 20 | if (docs) { 21 | console.warn('For more information about usage see ' + docs); 22 | } 23 | } catch (e) { /* Ignore */ } 24 | }; 25 | -------------------------------------------------------------------------------- /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 | * @returns {boolean} True if the specified URL is absolute, otherwise false 8 | */ 9 | module.exports = function isAbsoluteURL(url) { 10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 12 | // by any combination of letters, digits, plus, period, or hyphen. 13 | return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); 14 | }; 15 | -------------------------------------------------------------------------------- /lib/helpers/isURLSameOrigin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs have full support of the APIs needed to test 9 | // whether the request URL is of the same origin as current location. 10 | (function standardBrowserEnv() { 11 | var msie = /(msie|trident)/i.test(navigator.userAgent); 12 | var urlParsingNode = document.createElement('a'); 13 | var originURL; 14 | 15 | /** 16 | * Parse a URL to discover it's components 17 | * 18 | * @param {String} url The URL to be parsed 19 | * @returns {Object} 20 | */ 21 | function resolveURL(url) { 22 | var href = url; 23 | 24 | if (msie) { 25 | // IE needs attribute set twice to normalize properties 26 | urlParsingNode.setAttribute('href', href); 27 | href = urlParsingNode.href; 28 | } 29 | 30 | urlParsingNode.setAttribute('href', href); 31 | 32 | // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils 33 | return { 34 | href: urlParsingNode.href, 35 | protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', 36 | host: urlParsingNode.host, 37 | search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', 38 | hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', 39 | hostname: urlParsingNode.hostname, 40 | port: urlParsingNode.port, 41 | pathname: (urlParsingNode.pathname.charAt(0) === '/') ? 42 | urlParsingNode.pathname : 43 | '/' + urlParsingNode.pathname 44 | }; 45 | } 46 | 47 | originURL = resolveURL(window.location.href); 48 | 49 | /** 50 | * Determine if a URL shares the same origin as the current location 51 | * 52 | * @param {String} requestURL The URL to test 53 | * @returns {boolean} True if URL shares the same origin, otherwise false 54 | */ 55 | return function isURLSameOrigin(requestURL) { 56 | var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; 57 | return (parsed.protocol === originURL.protocol && 58 | parsed.host === originURL.host); 59 | }; 60 | })() : 61 | 62 | // Non standard browser envs (web workers, react-native) lack needed support. 63 | (function nonStandardBrowserEnv() { 64 | return function isURLSameOrigin() { 65 | return true; 66 | }; 67 | })() 68 | ); 69 | -------------------------------------------------------------------------------- /lib/helpers/normalizeHeaderName.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('../utils'); 4 | 5 | module.exports = function normalizeHeaderName(headers, normalizedName) { 6 | utils.forEach(headers, function processHeader(value, name) { 7 | if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { 8 | headers[normalizedName] = value; 9 | delete headers[name]; 10 | } 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /lib/helpers/parseHeaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | // Headers whose duplicates are ignored by node 6 | // c.f. https://nodejs.org/api/http.html#http_message_headers 7 | var ignoreDuplicateOf = [ 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} headers Headers needing to be parsed 25 | * @returns {Object} Headers parsed into an object 26 | */ 27 | module.exports = function parseHeaders(headers) { 28 | var parsed = {}; 29 | var key; 30 | var val; 31 | var i; 32 | 33 | if (!headers) { return parsed; } 34 | 35 | utils.forEach(headers.split('\n'), function parser(line) { 36 | i = line.indexOf(':'); 37 | key = utils.trim(line.substr(0, i)).toLowerCase(); 38 | val = utils.trim(line.substr(i + 1)); 39 | 40 | if (key) { 41 | if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { 42 | return; 43 | } 44 | if (key === 'set-cookie') { 45 | parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); 46 | } else { 47 | parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; 48 | } 49 | } 50 | }); 51 | 52 | return parsed; 53 | }; 54 | -------------------------------------------------------------------------------- /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 | * @returns {Function} 22 | */ 23 | module.exports = function spread(callback) { 24 | return function wrap(arr) { 25 | return callback.apply(null, arr); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var bind = require('./helpers/bind'); 4 | var isBuffer = require('is-buffer'); 5 | 6 | /*global toString:true*/ 7 | 8 | // utils is a library of generic helper functions non-specific to axios 9 | 10 | var toString = Object.prototype.toString; 11 | 12 | /** 13 | * Determine if a value is an Array 14 | * 15 | * @param {Object} val The value to test 16 | * @returns {boolean} True if value is an Array, otherwise false 17 | */ 18 | function isArray(val) { 19 | return toString.call(val) === '[object Array]'; 20 | } 21 | 22 | /** 23 | * Determine if a value is an ArrayBuffer 24 | * 25 | * @param {Object} val The value to test 26 | * @returns {boolean} True if value is an ArrayBuffer, otherwise false 27 | */ 28 | function isArrayBuffer(val) { 29 | return toString.call(val) === '[object ArrayBuffer]'; 30 | } 31 | 32 | /** 33 | * Determine if a value is a FormData 34 | * 35 | * @param {Object} val The value to test 36 | * @returns {boolean} True if value is an FormData, otherwise false 37 | */ 38 | function isFormData(val) { 39 | return (typeof FormData !== 'undefined') && (val instanceof FormData); 40 | } 41 | 42 | /** 43 | * Determine if a value is a view on an ArrayBuffer 44 | * 45 | * @param {Object} val The value to test 46 | * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false 47 | */ 48 | function isArrayBufferView(val) { 49 | var result; 50 | if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { 51 | result = ArrayBuffer.isView(val); 52 | } else { 53 | result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); 54 | } 55 | return result; 56 | } 57 | 58 | /** 59 | * Determine if a value is a String 60 | * 61 | * @param {Object} val The value to test 62 | * @returns {boolean} True if value is a String, otherwise false 63 | */ 64 | function isString(val) { 65 | return typeof val === 'string'; 66 | } 67 | 68 | /** 69 | * Determine if a value is a Number 70 | * 71 | * @param {Object} val The value to test 72 | * @returns {boolean} True if value is a Number, otherwise false 73 | */ 74 | function isNumber(val) { 75 | return typeof val === 'number'; 76 | } 77 | 78 | /** 79 | * Determine if a value is undefined 80 | * 81 | * @param {Object} val The value to test 82 | * @returns {boolean} True if the value is undefined, otherwise false 83 | */ 84 | function isUndefined(val) { 85 | return typeof val === 'undefined'; 86 | } 87 | 88 | /** 89 | * Determine if a value is an Object 90 | * 91 | * @param {Object} val The value to test 92 | * @returns {boolean} True if value is an Object, otherwise false 93 | */ 94 | function isObject(val) { 95 | return val !== null && typeof val === 'object'; 96 | } 97 | 98 | /** 99 | * Determine if a value is a Date 100 | * 101 | * @param {Object} val The value to test 102 | * @returns {boolean} True if value is a Date, otherwise false 103 | */ 104 | function isDate(val) { 105 | return toString.call(val) === '[object Date]'; 106 | } 107 | 108 | /** 109 | * Determine if a value is a File 110 | * 111 | * @param {Object} val The value to test 112 | * @returns {boolean} True if value is a File, otherwise false 113 | */ 114 | function isFile(val) { 115 | return toString.call(val) === '[object File]'; 116 | } 117 | 118 | /** 119 | * Determine if a value is a Blob 120 | * 121 | * @param {Object} val The value to test 122 | * @returns {boolean} True if value is a Blob, otherwise false 123 | */ 124 | function isBlob(val) { 125 | return toString.call(val) === '[object Blob]'; 126 | } 127 | 128 | /** 129 | * Determine if a value is a Function 130 | * 131 | * @param {Object} val The value to test 132 | * @returns {boolean} True if value is a Function, otherwise false 133 | */ 134 | function isFunction(val) { 135 | return toString.call(val) === '[object Function]'; 136 | } 137 | 138 | /** 139 | * Determine if a value is a Stream 140 | * 141 | * @param {Object} val The value to test 142 | * @returns {boolean} True if value is a Stream, otherwise false 143 | */ 144 | function isStream(val) { 145 | return isObject(val) && isFunction(val.pipe); 146 | } 147 | 148 | /** 149 | * Determine if a value is a URLSearchParams object 150 | * 151 | * @param {Object} val The value to test 152 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false 153 | */ 154 | function isURLSearchParams(val) { 155 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; 156 | } 157 | 158 | /** 159 | * Trim excess whitespace off the beginning and end of a string 160 | * 161 | * @param {String} str The String to trim 162 | * @returns {String} The String freed of excess whitespace 163 | */ 164 | function trim(str) { 165 | return str.replace(/^\s*/, '').replace(/\s*$/, ''); 166 | } 167 | 168 | /** 169 | * Determine if we're running in a standard browser environment 170 | * 171 | * This allows axios to run in a web worker, and react-native. 172 | * Both environments support XMLHttpRequest, but not fully standard globals. 173 | * 174 | * web workers: 175 | * typeof window -> undefined 176 | * typeof document -> undefined 177 | * 178 | * react-native: 179 | * navigator.product -> 'ReactNative' 180 | */ 181 | function isStandardBrowserEnv() { 182 | if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { 183 | return false; 184 | } 185 | return ( 186 | typeof window !== 'undefined' && 187 | typeof document !== 'undefined' 188 | ); 189 | } 190 | 191 | /** 192 | * Iterate over an Array or an Object invoking a function for each item. 193 | * 194 | * If `obj` is an Array callback will be called passing 195 | * the value, index, and complete array for each item. 196 | * 197 | * If 'obj' is an Object callback will be called passing 198 | * the value, key, and complete object for each property. 199 | * 200 | * @param {Object|Array} obj The object to iterate 201 | * @param {Function} fn The callback to invoke for each item 202 | */ 203 | function forEach(obj, fn) { 204 | // Don't bother if no value provided 205 | if (obj === null || typeof obj === 'undefined') { 206 | return; 207 | } 208 | 209 | // Force an array if not already something iterable 210 | if (typeof obj !== 'object' && !isArray(obj)) { 211 | /*eslint no-param-reassign:0*/ 212 | obj = [obj]; 213 | } 214 | 215 | if (isArray(obj)) { 216 | // Iterate over array values 217 | for (var i = 0, l = obj.length; i < l; i++) { 218 | fn.call(null, obj[i], i, obj); 219 | } 220 | } else { 221 | // Iterate over object keys 222 | for (var key in obj) { 223 | if (Object.prototype.hasOwnProperty.call(obj, key)) { 224 | fn.call(null, obj[key], key, obj); 225 | } 226 | } 227 | } 228 | } 229 | 230 | /** 231 | * Accepts varargs expecting each argument to be an object, then 232 | * immutably merges the properties of each object and returns result. 233 | * 234 | * When multiple objects contain the same key the later object in 235 | * the arguments list will take precedence. 236 | * 237 | * Example: 238 | * 239 | * ```js 240 | * var result = merge({foo: 123}, {foo: 456}); 241 | * console.log(result.foo); // outputs 456 242 | * ``` 243 | * 244 | * @param {Object} obj1 Object to merge 245 | * @returns {Object} Result of all merge properties 246 | */ 247 | function merge(/* obj1, obj2, obj3, ... */) { 248 | var result = {}; 249 | function assignValue(val, key) { 250 | if (typeof result[key] === 'object' && typeof val === 'object') { 251 | result[key] = merge(result[key], val); 252 | } else { 253 | result[key] = val; 254 | } 255 | } 256 | 257 | for (var i = 0, l = arguments.length; i < l; i++) { 258 | forEach(arguments[i], assignValue); 259 | } 260 | return result; 261 | } 262 | 263 | /** 264 | * Extends object a by mutably adding to it the properties of object b. 265 | * 266 | * @param {Object} a The object to be extended 267 | * @param {Object} b The object to copy properties from 268 | * @param {Object} thisArg The object to bind function to 269 | * @return {Object} The resulting value of object a 270 | */ 271 | function extend(a, b, thisArg) { 272 | forEach(b, function assignValue(val, key) { 273 | if (thisArg && typeof val === 'function') { 274 | a[key] = bind(val, thisArg); 275 | } else { 276 | a[key] = val; 277 | } 278 | }); 279 | return a; 280 | } 281 | 282 | module.exports = { 283 | isArray: isArray, 284 | isArrayBuffer: isArrayBuffer, 285 | isBuffer: isBuffer, 286 | isFormData: isFormData, 287 | isArrayBufferView: isArrayBufferView, 288 | isString: isString, 289 | isNumber: isNumber, 290 | isObject: isObject, 291 | isUndefined: isUndefined, 292 | isDate: isDate, 293 | isFile: isFile, 294 | isBlob: isBlob, 295 | isFunction: isFunction, 296 | isStream: isStream, 297 | isURLSearchParams: isURLSearchParams, 298 | isStandardBrowserEnv: isStandardBrowserEnv, 299 | forEach: forEach, 300 | merge: merge, 301 | extend: extend, 302 | trim: trim 303 | }; 304 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axios-jsonp-pro", 3 | "version": "1.1.8", 4 | "description": "Promise based HTTP client for the browser and node.js", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "grunt test", 8 | "start": "node ./sandbox/server.js", 9 | "build": "NODE_ENV=production grunt build", 10 | "preversion": "npm test", 11 | "version": "npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json", 12 | "postversion": "git push && git push --tags", 13 | "examples": "node ./examples/server.js", 14 | "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/RekingZhang/axios-jsonp.git" 19 | }, 20 | "keywords": [ 21 | "xhr", 22 | "http", 23 | "ajax", 24 | "promise", 25 | "node", 26 | "jsonp" 27 | ], 28 | "author": "Reking Zhang", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/RekingZhang/axios-jsonp/issues" 32 | }, 33 | "homepage": "https://github.com/RekingZhang/axios-jsonp", 34 | "devDependencies": { 35 | "coveralls": "^2.11.9", 36 | "es6-promise": "^4.0.5", 37 | "grunt": "^1.0.1", 38 | "grunt-banner": "^0.6.0", 39 | "grunt-cli": "^1.2.0", 40 | "grunt-contrib-clean": "^1.0.0", 41 | "grunt-contrib-nodeunit": "^1.0.0", 42 | "grunt-contrib-watch": "^1.0.0", 43 | "grunt-eslint": "^19.0.0", 44 | "grunt-karma": "^2.0.0", 45 | "grunt-ts": "^6.0.0-beta.3", 46 | "grunt-webpack": "^1.0.18", 47 | "istanbul-instrumenter-loader": "^1.0.0", 48 | "jasmine-core": "^2.4.1", 49 | "karma": "^1.3.0", 50 | "karma-chrome-launcher": "^2.0.0", 51 | "karma-coverage": "^1.0.0", 52 | "karma-firefox-launcher": "^1.0.0", 53 | "karma-jasmine": "^1.0.2", 54 | "karma-jasmine-ajax": "^0.1.13", 55 | "karma-opera-launcher": "^1.0.0", 56 | "karma-phantomjs-launcher": "^1.0.0", 57 | "karma-safari-launcher": "^1.0.0", 58 | "karma-sauce-launcher": "^1.1.0", 59 | "karma-sinon": "^1.0.5", 60 | "karma-sourcemap-loader": "^0.3.7", 61 | "karma-webpack": "^1.7.0", 62 | "load-grunt-tasks": "^3.5.2", 63 | "minimist": "^1.2.0", 64 | "phantomjs-prebuilt": "^2.1.7", 65 | "sinon": "^1.17.4", 66 | "webpack": "^1.13.1", 67 | "webpack-dev-server": "^1.14.1", 68 | "url-search-params": "^0.6.1", 69 | "typescript": "^2.0.3" 70 | }, 71 | "browser": { 72 | "./lib/adapters/http.js": "./lib/adapters/xhr.js" 73 | }, 74 | "typings": "./index.d.ts", 75 | "dependencies": { 76 | "follow-redirects": "^1.2.3", 77 | "is-buffer": "^1.1.5" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /sandbox/client.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | axios 5 | 6 | 13 | 14 | 15 |

axios

16 | 17 |
18 |

Input

19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 34 |
35 |
36 | 37 | 38 |
39 | 43 |
44 | 45 | 46 |
47 | 48 |
49 |
50 | 51 |
52 |

Request

53 |
No Data
54 |
55 | 56 |
57 |

Response

58 |
No Data
59 |
60 | 61 | 62 | 172 | 173 | -------------------------------------------------------------------------------- /sandbox/client.js: -------------------------------------------------------------------------------- 1 | var axios = require('../index'); 2 | 3 | var URL = 'http://127.0.0.1:3000/api'; 4 | var 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); -------------------------------------------------------------------------------- /sandbox/server.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var url = require('url'); 3 | var path = require('path'); 4 | var http = require('http'); 5 | var 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(__dirname, file)).pipe(res); 15 | } 16 | 17 | server = http.createServer(function (req, res) { 18 | req.setEncoding('utf8'); 19 | 20 | var parsed = url.parse(req.url, true); 21 | var 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'); 31 | } else if (pathname === '/axios.js') { 32 | pipeFileToResponse(res, '../dist/axios.js', 'text/javascript'); 33 | } else if (pathname === '/axios.map') { 34 | pipeFileToResponse(res, '../dist/axios.map', 'text/javascript'); 35 | } else if (pathname === '/api') { 36 | var status; 37 | var result; 38 | var 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 | server.listen(3000); -------------------------------------------------------------------------------- /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/specs/__helpers.js: -------------------------------------------------------------------------------- 1 | // Polyfill ES6 Promise 2 | require('es6-promise').polyfill(); 3 | 4 | // Polyfill URLSearchParams 5 | URLSearchParams = require('url-search-params'); 6 | 7 | // Import axios 8 | axios = require('../../index'); 9 | 10 | // Jasmine config 11 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; 12 | jasmine.getEnv().defaultTimeoutInterval = 20000; 13 | 14 | // Is this an old version of IE that lacks standard objects like DataView, ArrayBuffer, FormData, etc. 15 | isOldIE = /MSIE (8|9)\.0/.test(navigator.userAgent); 16 | 17 | // Get Ajax request using an increasing timeout to retry 18 | getAjaxRequest = (function () { 19 | var attempts = 0; 20 | var MAX_ATTEMPTS = 5; 21 | var ATTEMPT_DELAY_FACTOR = 5; 22 | 23 | function getAjaxRequest() { 24 | return new Promise(function (resolve, reject) { 25 | attempts = 0; 26 | attemptGettingAjaxRequest(resolve, reject); 27 | }); 28 | } 29 | 30 | function attemptGettingAjaxRequest(resolve, reject) { 31 | var delay = attempts * attempts * ATTEMPT_DELAY_FACTOR; 32 | 33 | if (attempts++ > MAX_ATTEMPTS) { 34 | reject(new Error('No request was found')); 35 | return; 36 | } 37 | 38 | setTimeout(function () { 39 | var request = jasmine.Ajax.requests.mostRecent(); 40 | if (request) { 41 | resolve(request); 42 | } else { 43 | attemptGettingAjaxRequest(resolve, reject); 44 | } 45 | }, delay); 46 | } 47 | 48 | return getAjaxRequest; 49 | })(); 50 | 51 | // Validate an invalid character error 52 | validateInvalidCharacterError = function validateInvalidCharacterError(error) { 53 | expect(/character/i.test(error.message)).toEqual(true); 54 | }; 55 | 56 | // Setup basic auth tests 57 | setupBasicAuthTest = function setupBasicAuthTest() { 58 | beforeEach(function () { 59 | jasmine.Ajax.install(); 60 | }); 61 | 62 | afterEach(function () { 63 | jasmine.Ajax.uninstall(); 64 | }); 65 | 66 | it('should accept HTTP Basic auth with username/password', function (done) { 67 | axios('/foo', { 68 | auth: { 69 | username: 'Aladdin', 70 | password: 'open sesame' 71 | } 72 | }); 73 | 74 | setTimeout(function () { 75 | var request = jasmine.Ajax.requests.mostRecent(); 76 | 77 | expect(request.requestHeaders['Authorization']).toEqual('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='); 78 | done(); 79 | }, 100); 80 | }); 81 | 82 | it('should fail to encode HTTP Basic auth credentials with non-Latin1 characters', function (done) { 83 | axios('/foo', { 84 | auth: { 85 | username: 'Aladßç£☃din', 86 | password: 'open sesame' 87 | } 88 | }).then(function(response) { 89 | done(new Error('Should not succeed to make a HTTP Basic auth request with non-latin1 chars in credentials.')); 90 | }).catch(function(error) { 91 | validateInvalidCharacterError(error); 92 | done(); 93 | }); 94 | }); 95 | }; 96 | -------------------------------------------------------------------------------- /test/specs/adapter.spec.js: -------------------------------------------------------------------------------- 1 | var axios = require('../../index'); 2 | 3 | describe('adapter', function () { 4 | it('should support custom adapter', function (done) { 5 | var called = false; 6 | 7 | axios('/foo', { 8 | adapter: function (config) { 9 | called = true; 10 | } 11 | }); 12 | 13 | setTimeout(function () { 14 | expect(called).toBe(true); 15 | done(); 16 | }, 100); 17 | }); 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /test/specs/api.spec.js: -------------------------------------------------------------------------------- 1 | describe('static api', function () { 2 | it('should have request method helpers', function () { 3 | expect(typeof axios.request).toEqual('function'); 4 | expect(typeof axios.get).toEqual('function'); 5 | expect(typeof axios.head).toEqual('function'); 6 | expect(typeof axios.options).toEqual('function'); 7 | expect(typeof axios.delete).toEqual('function'); 8 | expect(typeof axios.post).toEqual('function'); 9 | expect(typeof axios.put).toEqual('function'); 10 | expect(typeof axios.patch).toEqual('function'); 11 | }); 12 | 13 | it('should have promise method helpers', function () { 14 | var promise = axios(); 15 | 16 | expect(typeof promise.then).toEqual('function'); 17 | expect(typeof promise.catch).toEqual('function'); 18 | }); 19 | 20 | it('should have defaults', function () { 21 | expect(typeof axios.defaults).toEqual('object'); 22 | expect(typeof axios.defaults.headers).toEqual('object'); 23 | }); 24 | 25 | it('should have interceptors', function () { 26 | expect(typeof axios.interceptors.request).toEqual('object'); 27 | expect(typeof axios.interceptors.response).toEqual('object'); 28 | }); 29 | 30 | it('should have all/spread helpers', function () { 31 | expect(typeof axios.all).toEqual('function'); 32 | expect(typeof axios.spread).toEqual('function'); 33 | }); 34 | 35 | it('should have factory method', function () { 36 | expect(typeof axios.create).toEqual('function'); 37 | }); 38 | 39 | it('should have Cancel, CancelToken, and isCancel properties', function () { 40 | expect(typeof axios.Cancel).toEqual('function'); 41 | expect(typeof axios.CancelToken).toEqual('function'); 42 | expect(typeof axios.isCancel).toEqual('function'); 43 | }); 44 | }); 45 | 46 | describe('instance api', function () { 47 | var instance = axios.create(); 48 | 49 | it('should have request methods', function () { 50 | expect(typeof instance.request).toEqual('function'); 51 | expect(typeof instance.get).toEqual('function'); 52 | expect(typeof instance.options).toEqual('function'); 53 | expect(typeof instance.head).toEqual('function'); 54 | expect(typeof instance.delete).toEqual('function'); 55 | expect(typeof instance.post).toEqual('function'); 56 | expect(typeof instance.put).toEqual('function'); 57 | expect(typeof instance.patch).toEqual('function'); 58 | }); 59 | 60 | it('should have interceptors', function () { 61 | expect(typeof instance.interceptors.request).toEqual('object'); 62 | expect(typeof instance.interceptors.response).toEqual('object'); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/specs/basicAuth.spec.js: -------------------------------------------------------------------------------- 1 | describe('basicAuth without btoa polyfill', function () { 2 | setupBasicAuthTest(); 3 | }); 4 | -------------------------------------------------------------------------------- /test/specs/basicAuthWithPolyfill.spec.js: -------------------------------------------------------------------------------- 1 | var window_btoa; 2 | 3 | describe('basicAuth with btoa polyfill', function () { 4 | beforeAll(function() { 5 | window_btoa = window.btoa; 6 | window.btoa = undefined; 7 | }); 8 | 9 | afterAll(function() { 10 | window.btoa = window_btoa; 11 | window_btoa = undefined; 12 | }); 13 | 14 | it('should not have native window.btoa', function () { 15 | expect(window.btoa).toEqual(undefined); 16 | }); 17 | 18 | setupBasicAuthTest(); 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /test/specs/cancel.spec.js: -------------------------------------------------------------------------------- 1 | var Cancel = axios.Cancel; 2 | var CancelToken = axios.CancelToken; 3 | 4 | describe('cancel', function() { 5 | beforeEach(function() { 6 | jasmine.Ajax.install(); 7 | }); 8 | 9 | afterEach(function() { 10 | jasmine.Ajax.uninstall(); 11 | }); 12 | 13 | describe('when called before sending request', function() { 14 | it('rejects Promise with a Cancel object', function (done) { 15 | var source = CancelToken.source(); 16 | source.cancel('Operation has been canceled.'); 17 | axios.get('/foo', { 18 | cancelToken: source.token 19 | }).catch(function (thrown) { 20 | expect(thrown).toEqual(jasmine.any(Cancel)); 21 | expect(thrown.message).toBe('Operation has been canceled.'); 22 | done(); 23 | }); 24 | }); 25 | }); 26 | 27 | describe('when called after request has been sent', function() { 28 | it('rejects Promise with a Cancel object', function (done) { 29 | var source = CancelToken.source(); 30 | axios.get('/foo/bar', { 31 | cancelToken: source.token 32 | }).catch(function (thrown) { 33 | expect(thrown).toEqual(jasmine.any(Cancel)); 34 | expect(thrown.message).toBe('Operation has been canceled.'); 35 | done(); 36 | }); 37 | 38 | getAjaxRequest().then(function (request) { 39 | // call cancel() when the request has been sent, but a response has not been received 40 | source.cancel('Operation has been canceled.'); 41 | request.respondWith({ 42 | status: 200, 43 | responseText: 'OK' 44 | }); 45 | }); 46 | }); 47 | 48 | it('calls abort on request object', function (done) { 49 | var source = CancelToken.source(); 50 | var request; 51 | axios.get('/foo/bar', { 52 | cancelToken: source.token 53 | }).catch(function() { 54 | // jasmine-ajax sets statusText to 'abort' when request.abort() is called 55 | expect(request.statusText).toBe('abort'); 56 | done(); 57 | }); 58 | 59 | getAjaxRequest().then(function (req) { 60 | // call cancel() when the request has been sent, but a response has not been received 61 | source.cancel(); 62 | request = req; 63 | }); 64 | }); 65 | }); 66 | 67 | describe('when called after response has been received', function() { 68 | // https://github.com/mzabriskie/axios/issues/482 69 | it('does not cause unhandled rejection', function (done) { 70 | var source = CancelToken.source(); 71 | axios.get('/foo', { 72 | cancelToken: source.token 73 | }).then(function () { 74 | window.addEventListener('unhandledrejection', function () { 75 | done.fail('Unhandled rejection.'); 76 | }); 77 | source.cancel(); 78 | setTimeout(done, 100); 79 | }); 80 | 81 | getAjaxRequest().then(function (request) { 82 | request.respondWith({ 83 | status: 200, 84 | responseText: 'OK' 85 | }); 86 | }); 87 | }); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /test/specs/cancel/Cancel.spec.js: -------------------------------------------------------------------------------- 1 | var Cancel = require('../../../lib/cancel/Cancel'); 2 | 3 | describe('Cancel', function() { 4 | describe('toString', function() { 5 | it('returns correct result when message is not specified', function() { 6 | var cancel = new Cancel(); 7 | expect(cancel.toString()).toBe('Cancel'); 8 | }); 9 | 10 | it('returns correct result when message is specified', function() { 11 | var cancel = new Cancel('Operation has been canceled.'); 12 | expect(cancel.toString()).toBe('Cancel: Operation has been canceled.'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/specs/cancel/CancelToken.spec.js: -------------------------------------------------------------------------------- 1 | var CancelToken = require('../../../lib/cancel/CancelToken'); 2 | var Cancel = require('../../../lib/cancel/Cancel'); 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 Cancel if cancellation has been requested', function() { 21 | var cancel; 22 | var token = new CancelToken(function(c) { 23 | cancel = c; 24 | }); 25 | cancel('Operation has been canceled.'); 26 | expect(token.reason).toEqual(jasmine.any(Cancel)); 27 | expect(token.reason.message).toBe('Operation has been canceled.'); 28 | }); 29 | 30 | it('returns undefined if cancellation has not been requested', function() { 31 | var 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 | var cancel; 39 | var token = new CancelToken(function(c) { 40 | cancel = c; 41 | }); 42 | token.promise.then(function onFulfilled(value) { 43 | expect(value).toEqual(jasmine.any(Cancel)); 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 Cancel does not inherit from Error 54 | var cancel; 55 | var 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 Cancel)) { 64 | fail('Expected throwIfRequested to throw a Cancel, 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 | var 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 | var 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(Cancel)); 84 | expect(source.token.reason.message).toBe('Operation has been canceled.'); 85 | }); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /test/specs/cancel/isCancel.spec.js: -------------------------------------------------------------------------------- 1 | var isCancel = require('../../../lib/cancel/isCancel'); 2 | var Cancel = require('../../../lib/cancel/Cancel'); 3 | 4 | describe('isCancel', function() { 5 | it('returns true if value is a Cancel', function() { 6 | expect(isCancel(new Cancel())).toBe(true); 7 | }); 8 | 9 | it('returns false if value is not a Cancel', function() { 10 | expect(isCancel({ foo: 'bar' })).toBe(false); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/core/createError.spec.js: -------------------------------------------------------------------------------- 1 | var createError = require('../../../lib/core/createError'); 2 | 3 | describe('core::createError', function() { 4 | it('should create an Error with message, config, code, request and response', function() { 5 | var request = { path: '/foo' }; 6 | var response = { status: 200, data: { foo: 'bar' } }; 7 | var error = createError('Boom!', { foo: 'bar' }, 'ESOMETHING', 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 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/specs/core/enhanceError.spec.js: -------------------------------------------------------------------------------- 1 | var enhanceError = require('../../../lib/core/enhanceError'); 2 | 3 | describe('core::enhanceError', function() { 4 | it('should add config, config, request and response to error', function() { 5 | var error = new Error('Boom!'); 6 | var request = { path: '/foo' }; 7 | var response = { status: 200, data: { foo: 'bar' } }; 8 | 9 | enhanceError(error, { foo: 'bar' }, 'ESOMETHING', request, response); 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 | }); 15 | 16 | it('should return error', function() { 17 | var error = new Error('Boom!'); 18 | expect(enhanceError(error, { foo: 'bar' }, 'ESOMETHING')).toBe(error); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/specs/core/settle.spec.js: -------------------------------------------------------------------------------- 1 | var settle = require('../../../lib/core/settle'); 2 | 3 | describe('core::settle', function() { 4 | var resolve; 5 | var 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 | var 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 | var 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 | var 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 | var req = { 52 | path: '/foo' 53 | }; 54 | var 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 | var 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 | var validateStatus = jasmine.createSpy('validateStatus'); 76 | var 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 | var transformData = require('../../../lib/core/transformData'); 2 | 3 | describe('core::transformData', function () { 4 | it('should support a single transformer', function () { 5 | var data; 6 | data = transformData(data, null, function (data) { 7 | data = 'foo'; 8 | return data; 9 | }); 10 | 11 | expect(data).toEqual('foo'); 12 | }); 13 | 14 | it('should support an array of transformers', function () { 15 | var data = ''; 16 | data = transformData(data, null, [function (data) { 17 | data += 'f'; 18 | return data; 19 | }, function (data) { 20 | data += 'o'; 21 | return data; 22 | }, function (data) { 23 | data += 'o'; 24 | return data; 25 | }]); 26 | 27 | expect(data).toEqual('foo'); 28 | }); 29 | }); 30 | 31 | -------------------------------------------------------------------------------- /test/specs/defaults.spec.js: -------------------------------------------------------------------------------- 1 | var defaults = require('../../lib/defaults'); 2 | var utils = require('../../lib/utils'); 3 | 4 | describe('defaults', function () { 5 | var XSRF_COOKIE_NAME = 'CUSTOM-XSRF-TOKEN'; 6 | 7 | beforeEach(function () { 8 | jasmine.Ajax.install(); 9 | }); 10 | 11 | afterEach(function () { 12 | jasmine.Ajax.uninstall(); 13 | delete axios.defaults.baseURL; 14 | delete axios.defaults.headers.get['X-CUSTOM-HEADER']; 15 | delete axios.defaults.headers.post['X-CUSTOM-HEADER']; 16 | document.cookie = XSRF_COOKIE_NAME + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); 17 | }); 18 | 19 | it('should transform request json', function () { 20 | expect(defaults.transformRequest[0]({foo: 'bar'})).toEqual('{"foo":"bar"}'); 21 | }); 22 | 23 | it('should do nothing to request string', function () { 24 | expect(defaults.transformRequest[0]('foo=bar')).toEqual('foo=bar'); 25 | }); 26 | 27 | it('should transform response json', function () { 28 | var data = defaults.transformResponse[0]('{"foo":"bar"}'); 29 | 30 | expect(typeof data).toEqual('object'); 31 | expect(data.foo).toEqual('bar'); 32 | }); 33 | 34 | it('should do nothing to response string', function () { 35 | expect(defaults.transformResponse[0]('foo=bar')).toEqual('foo=bar'); 36 | }); 37 | 38 | it('should use global defaults config', function (done) { 39 | axios('/foo'); 40 | 41 | getAjaxRequest().then(function (request) { 42 | expect(request.url).toBe('/foo'); 43 | done(); 44 | }); 45 | }); 46 | 47 | it('should use modified defaults config', function (done) { 48 | axios.defaults.baseURL = 'http://example.com/'; 49 | 50 | axios('/foo'); 51 | 52 | getAjaxRequest().then(function (request) { 53 | expect(request.url).toBe('http://example.com/foo'); 54 | done(); 55 | }); 56 | }); 57 | 58 | it('should use request config', function (done) { 59 | axios('/foo', { 60 | baseURL: 'http://www.example.com' 61 | }); 62 | 63 | getAjaxRequest().then(function (request) { 64 | expect(request.url).toBe('http://www.example.com/foo'); 65 | done(); 66 | }); 67 | }); 68 | 69 | it('should use default config for custom instance', function (done) { 70 | var instance = axios.create({ 71 | xsrfCookieName: XSRF_COOKIE_NAME, 72 | xsrfHeaderName: 'X-CUSTOM-XSRF-TOKEN' 73 | }); 74 | document.cookie = instance.defaults.xsrfCookieName + '=foobarbaz'; 75 | 76 | instance.get('/foo'); 77 | 78 | getAjaxRequest().then(function (request) { 79 | expect(request.requestHeaders[instance.defaults.xsrfHeaderName]).toEqual('foobarbaz'); 80 | done(); 81 | }); 82 | }); 83 | 84 | it('should use GET headers', function (done) { 85 | axios.defaults.headers.get['X-CUSTOM-HEADER'] = 'foo'; 86 | axios.get('/foo'); 87 | 88 | getAjaxRequest().then(function (request) { 89 | expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); 90 | done(); 91 | }); 92 | }); 93 | 94 | it('should use POST headers', function (done) { 95 | axios.defaults.headers.post['X-CUSTOM-HEADER'] = 'foo'; 96 | axios.post('/foo', {}); 97 | 98 | getAjaxRequest().then(function (request) { 99 | expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); 100 | done(); 101 | }); 102 | }); 103 | 104 | it('should use header config', function (done) { 105 | var instance = axios.create({ 106 | headers: { 107 | common: { 108 | 'X-COMMON-HEADER': 'commonHeaderValue' 109 | }, 110 | get: { 111 | 'X-GET-HEADER': 'getHeaderValue' 112 | }, 113 | post: { 114 | 'X-POST-HEADER': 'postHeaderValue' 115 | } 116 | } 117 | }); 118 | 119 | instance.get('/foo', { 120 | headers: { 121 | 'X-FOO-HEADER': 'fooHeaderValue', 122 | 'X-BAR-HEADER': 'barHeaderValue' 123 | } 124 | }); 125 | 126 | getAjaxRequest().then(function (request) { 127 | expect(request.requestHeaders).toEqual( 128 | utils.merge(defaults.headers.common, defaults.headers.get, { 129 | 'X-COMMON-HEADER': 'commonHeaderValue', 130 | 'X-GET-HEADER': 'getHeaderValue', 131 | 'X-FOO-HEADER': 'fooHeaderValue', 132 | 'X-BAR-HEADER': 'barHeaderValue' 133 | }) 134 | ); 135 | done(); 136 | }); 137 | }); 138 | 139 | it('should be used by custom instance if set before instance created', function (done) { 140 | axios.defaults.baseURL = 'http://example.org/'; 141 | var instance = axios.create(); 142 | 143 | instance.get('/foo'); 144 | 145 | getAjaxRequest().then(function (request) { 146 | expect(request.url).toBe('http://example.org/foo'); 147 | done(); 148 | }); 149 | }); 150 | 151 | it('should be used by custom instance if set after instance created', function (done) { 152 | var instance = axios.create(); 153 | axios.defaults.baseURL = 'http://example.org/'; 154 | 155 | instance.get('/foo'); 156 | 157 | getAjaxRequest().then(function (request) { 158 | expect(request.url).toBe('http://example.org/foo'); 159 | done(); 160 | }); 161 | }); 162 | }); 163 | -------------------------------------------------------------------------------- /test/specs/headers.spec.js: -------------------------------------------------------------------------------- 1 | function testHeaderValue(headers, key, val) { 2 | var found = false; 3 | 4 | for (var k in headers) { 5 | if (k.toLowerCase() === key.toLowerCase()) { 6 | found = true; 7 | expect(headers[k]).toEqual(val); 8 | break; 9 | } 10 | } 11 | 12 | if (!found) { 13 | if (typeof val === 'undefined') { 14 | expect(headers.hasOwnProperty(key)).toEqual(false); 15 | } else { 16 | throw new Error(key + ' was not found in headers'); 17 | } 18 | } 19 | } 20 | 21 | describe('headers', function () { 22 | beforeEach(function () { 23 | jasmine.Ajax.install(); 24 | }); 25 | 26 | afterEach(function () { 27 | jasmine.Ajax.uninstall(); 28 | }); 29 | 30 | it('should default common headers', function (done) { 31 | var headers = axios.defaults.headers.common; 32 | 33 | axios('/foo'); 34 | 35 | getAjaxRequest().then(function (request) { 36 | for (var key in headers) { 37 | if (headers.hasOwnProperty(key)) { 38 | expect(request.requestHeaders[key]).toEqual(headers[key]); 39 | } 40 | } 41 | done(); 42 | }); 43 | }); 44 | 45 | it('should add extra headers for post', function (done) { 46 | var headers = axios.defaults.headers.common; 47 | 48 | axios.post('/foo', 'fizz=buzz'); 49 | 50 | getAjaxRequest().then(function (request) { 51 | for (var key in headers) { 52 | if (headers.hasOwnProperty(key)) { 53 | expect(request.requestHeaders[key]).toEqual(headers[key]); 54 | } 55 | } 56 | done(); 57 | }); 58 | }); 59 | 60 | it('should use application/json when posting an object', function (done) { 61 | axios.post('/foo/bar', { 62 | firstName: 'foo', 63 | lastName: 'bar' 64 | }); 65 | 66 | getAjaxRequest().then(function (request) { 67 | testHeaderValue(request.requestHeaders, 'Content-Type', 'application/json;charset=utf-8'); 68 | done(); 69 | }); 70 | }); 71 | 72 | it('should remove content-type if data is empty', function (done) { 73 | axios.post('/foo'); 74 | 75 | getAjaxRequest().then(function (request) { 76 | testHeaderValue(request.requestHeaders, 'Content-Type', undefined); 77 | done(); 78 | }); 79 | }); 80 | 81 | it('should preserve content-type if data is false', function (done) { 82 | axios.post('/foo', false); 83 | 84 | getAjaxRequest().then(function (request) { 85 | testHeaderValue(request.requestHeaders, 'Content-Type', 'application/x-www-form-urlencoded'); 86 | done(); 87 | }); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /test/specs/helpers/bind.spec.js: -------------------------------------------------------------------------------- 1 | var bind = require('../../../lib/helpers/bind'); 2 | 3 | describe('bind', function () { 4 | it('should bind an object to a function', function () { 5 | var o = { val: 123 }; 6 | var f = bind(function (num) { 7 | return this.val * num; 8 | }, o); 9 | 10 | expect(f(2)).toEqual(246); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/specs/helpers/btoa.spec.js: -------------------------------------------------------------------------------- 1 | var __btoa = require('../../../lib/helpers/btoa'); 2 | 3 | describe('btoa polyfill', function () { 4 | it('should behave the same as native window.btoa', function () { 5 | // btoa doesn't exist in IE8/9 6 | if (isOldIE && typeof Int8Array === 'undefined') { 7 | return; 8 | } 9 | 10 | var data = 'Hello, world'; 11 | expect(__btoa(data)).toEqual(window.btoa(data)); 12 | }); 13 | 14 | it('should throw an error if char is out of range 0xFF', function () { 15 | var err; 16 | var data = 'I ♡ Unicode!'; 17 | 18 | try { 19 | __btoa(data); 20 | } catch (e) { 21 | err = e; 22 | } 23 | 24 | validateInvalidCharacterError(err); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/specs/helpers/buildURL.spec.js: -------------------------------------------------------------------------------- 1 | var buildURL = require('../../../lib/helpers/buildURL'); 2 | var URLSearchParams = require('url-search-params'); 3 | 4 | describe('helpers::buildURL', function () { 5 | it('should support null params', function () { 6 | expect(buildURL('/foo')).toEqual('/foo'); 7 | }); 8 | 9 | it('should support params', function () { 10 | expect(buildURL('/foo', { 11 | foo: 'bar' 12 | })).toEqual('/foo?foo=bar'); 13 | }); 14 | 15 | it('should support object params', function () { 16 | expect(buildURL('/foo', { 17 | foo: { 18 | bar: 'baz' 19 | } 20 | })).toEqual('/foo?foo=' + encodeURI('{"bar":"baz"}')); 21 | }); 22 | 23 | it('should support date params', function () { 24 | var date = new Date(); 25 | 26 | expect(buildURL('/foo', { 27 | date: date 28 | })).toEqual('/foo?date=' + date.toISOString()); 29 | }); 30 | 31 | it('should support array params', function () { 32 | expect(buildURL('/foo', { 33 | foo: ['bar', 'baz'] 34 | })).toEqual('/foo?foo[]=bar&foo[]=baz'); 35 | }); 36 | 37 | it('should support special char params', function () { 38 | expect(buildURL('/foo', { 39 | foo: '@:$, ' 40 | })).toEqual('/foo?foo=@:$,+'); 41 | }); 42 | 43 | it('should support existing params', function () { 44 | expect(buildURL('/foo?foo=bar', { 45 | bar: 'baz' 46 | })).toEqual('/foo?foo=bar&bar=baz'); 47 | }); 48 | 49 | it('should support "length" parameter', function () { 50 | expect(buildURL('/foo', { 51 | query: 'bar', 52 | start: 0, 53 | length: 5 54 | })).toEqual('/foo?query=bar&start=0&length=5'); 55 | }); 56 | 57 | it('should use serializer if provided', function () { 58 | serializer = sinon.stub(); 59 | params = {foo: 'bar'}; 60 | serializer.returns('foo=bar'); 61 | expect(buildURL('/foo', params, serializer)).toEqual('/foo?foo=bar'); 62 | expect(serializer.calledOnce).toBe(true); 63 | expect(serializer.calledWith(params)).toBe(true); 64 | }); 65 | 66 | it('should support URLSearchParams', function () { 67 | expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz'); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/specs/helpers/combineURLs.spec.js: -------------------------------------------------------------------------------- 1 | var combineURLs = require('../../../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 | var cookies = require('../../../lib/helpers/cookies'); 2 | 3 | describe('helpers::cookies', function () { 4 | afterEach(function () { 5 | // Remove all the cookies 6 | var 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/isAbsoluteURL.spec.js: -------------------------------------------------------------------------------- 1 | var isAbsoluteURL = require('../../../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/isURLSameOrigin.spec.js: -------------------------------------------------------------------------------- 1 | var isURLSameOrigin = require('../../../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/mzabriskie/axios')).toEqual(false); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/specs/helpers/normalizeHeaderName.spec.js: -------------------------------------------------------------------------------- 1 | var normalizeHeaderName = require('../../../lib/helpers/normalizeHeaderName'); 2 | 3 | describe('helpers::normalizeHeaderName', function () { 4 | it('should normalize matching header name', function () { 5 | var headers = { 6 | 'conTenT-Type': 'foo/bar', 7 | }; 8 | normalizeHeaderName(headers, 'Content-Type'); 9 | expect(headers['Content-Type']).toBe('foo/bar'); 10 | expect(headers['conTenT-Type']).toBeUndefined(); 11 | }); 12 | 13 | it('should not change non-matching header name', function () { 14 | var headers = { 15 | 'content-type': 'foo/bar', 16 | }; 17 | normalizeHeaderName(headers, 'Content-Length'); 18 | expect(headers['content-type']).toBe('foo/bar'); 19 | expect(headers['Content-Length']).toBeUndefined(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/specs/helpers/parseHeaders.spec.js: -------------------------------------------------------------------------------- 1 | var parseHeaders = require('../../../lib/helpers/parseHeaders'); 2 | 3 | describe('helpers::parseHeaders', function () { 4 | it('should parse headers', function () { 5 | var date = new Date(); 6 | var 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 | var parsedZero = parseHeaders(''); 21 | var parsedSingle = parseHeaders( 22 | 'Set-Cookie: key=val;' 23 | ); 24 | var 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 | var parsed = parseHeaders( 36 | 'Age: age-a\n' + // age is in ignore duplicates blacklist 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 | var spread = require('../../../lib/helpers/spread'); 2 | 3 | describe('helpers::spread', function () { 4 | it('should spread array to arguments', function () { 5 | var 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 | var value = spread(function (a, b) { 15 | return a * b; 16 | })([5, 10]); 17 | 18 | expect(value).toEqual(50); 19 | }); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /test/specs/instance.spec.js: -------------------------------------------------------------------------------- 1 | describe('instance', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | }); 9 | 10 | it('should have the same methods as default instance', function () { 11 | var instance = axios.create(); 12 | 13 | for (var prop in axios) { 14 | if ([ 15 | 'Axios', 16 | 'create', 17 | 'Cancel', 18 | 'CancelToken', 19 | 'isCancel', 20 | 'all', 21 | 'spread', 22 | 'default'].indexOf(prop) > -1) { 23 | continue; 24 | } 25 | expect(typeof instance[prop]).toBe(typeof axios[prop]); 26 | } 27 | }); 28 | 29 | it('should make an http request without verb helper', function (done) { 30 | var instance = axios.create(); 31 | 32 | instance('/foo'); 33 | 34 | getAjaxRequest().then(function (request) { 35 | expect(request.url).toBe('/foo'); 36 | done(); 37 | }); 38 | }); 39 | 40 | it('should make an http request', function (done) { 41 | var instance = axios.create(); 42 | 43 | instance.get('/foo'); 44 | 45 | getAjaxRequest().then(function (request) { 46 | expect(request.url).toBe('/foo'); 47 | done(); 48 | }); 49 | }); 50 | 51 | it('should use instance options', function (done) { 52 | var instance = axios.create({ timeout: 1000 }); 53 | 54 | instance.get('/foo'); 55 | 56 | getAjaxRequest().then(function (request) { 57 | expect(request.timeout).toBe(1000); 58 | done(); 59 | }); 60 | }); 61 | 62 | it('should have defaults.headers', function () { 63 | var instance = axios.create({ 64 | baseURL: 'https://api.example.com' 65 | }); 66 | 67 | expect(typeof instance.defaults.headers, 'object'); 68 | expect(typeof instance.defaults.headers.common, 'object'); 69 | }); 70 | 71 | it('should have interceptors on the instance', function (done) { 72 | axios.interceptors.request.use(function (config) { 73 | config.foo = true; 74 | return config; 75 | }); 76 | 77 | var instance = axios.create(); 78 | instance.interceptors.request.use(function (config) { 79 | config.bar = true; 80 | return config; 81 | }); 82 | 83 | var response; 84 | instance.get('/foo').then(function (res) { 85 | response = res; 86 | }); 87 | 88 | getAjaxRequest().then(function (request) { 89 | request.respondWith({ 90 | status: 200 91 | }); 92 | 93 | setTimeout(function () { 94 | expect(response.config.foo).toEqual(undefined); 95 | expect(response.config.bar).toEqual(true); 96 | done(); 97 | }, 100); 98 | }); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /test/specs/interceptors.spec.js: -------------------------------------------------------------------------------- 1 | describe('interceptors', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | axios.interceptors.request.handlers = []; 9 | axios.interceptors.response.handlers = []; 10 | }); 11 | 12 | it('should add a request interceptor', function (done) { 13 | axios.interceptors.request.use(function (config) { 14 | config.headers.test = 'added by interceptor'; 15 | return config; 16 | }); 17 | 18 | axios('/foo'); 19 | 20 | getAjaxRequest().then(function (request) { 21 | request.respondWith({ 22 | status: 200, 23 | responseText: 'OK' 24 | }); 25 | 26 | expect(request.requestHeaders.test).toBe('added by interceptor'); 27 | done(); 28 | }); 29 | }); 30 | 31 | it('should add a request interceptor that returns a new config object', function (done) { 32 | axios.interceptors.request.use(function () { 33 | return { 34 | url: '/bar', 35 | method: 'post' 36 | }; 37 | }); 38 | 39 | axios('/foo'); 40 | 41 | getAjaxRequest().then(function (request) { 42 | expect(request.method).toBe('POST'); 43 | expect(request.url).toBe('/bar'); 44 | done(); 45 | }); 46 | }); 47 | 48 | it('should add a request interceptor that returns a promise', function (done) { 49 | axios.interceptors.request.use(function (config) { 50 | return new Promise(function (resolve) { 51 | // do something async 52 | setTimeout(function () { 53 | config.headers.async = 'promise'; 54 | resolve(config); 55 | }, 100); 56 | }); 57 | }); 58 | 59 | axios('/foo'); 60 | 61 | getAjaxRequest().then(function (request) { 62 | expect(request.requestHeaders.async).toBe('promise'); 63 | done(); 64 | }); 65 | }); 66 | 67 | it('should add multiple request interceptors', function (done) { 68 | axios.interceptors.request.use(function (config) { 69 | config.headers.test1 = '1'; 70 | return config; 71 | }); 72 | axios.interceptors.request.use(function (config) { 73 | config.headers.test2 = '2'; 74 | return config; 75 | }); 76 | axios.interceptors.request.use(function (config) { 77 | config.headers.test3 = '3'; 78 | return config; 79 | }); 80 | 81 | axios('/foo'); 82 | 83 | getAjaxRequest().then(function (request) { 84 | expect(request.requestHeaders.test1).toBe('1'); 85 | expect(request.requestHeaders.test2).toBe('2'); 86 | expect(request.requestHeaders.test3).toBe('3'); 87 | done(); 88 | }); 89 | }); 90 | 91 | it('should add a response interceptor', function (done) { 92 | var response; 93 | 94 | axios.interceptors.response.use(function (data) { 95 | data.data = data.data + ' - modified by interceptor'; 96 | return data; 97 | }); 98 | 99 | axios('/foo').then(function (data) { 100 | response = data; 101 | }); 102 | 103 | getAjaxRequest().then(function (request) { 104 | request.respondWith({ 105 | status: 200, 106 | responseText: 'OK' 107 | }); 108 | 109 | setTimeout(function () { 110 | expect(response.data).toBe('OK - modified by interceptor'); 111 | done(); 112 | }, 100); 113 | }); 114 | }); 115 | 116 | it('should add a response interceptor that returns a new data object', function (done) { 117 | var response; 118 | 119 | axios.interceptors.response.use(function () { 120 | return { 121 | data: 'stuff' 122 | }; 123 | }); 124 | 125 | axios('/foo').then(function (data) { 126 | response = data; 127 | }); 128 | 129 | getAjaxRequest().then(function (request) { 130 | request.respondWith({ 131 | status: 200, 132 | responseText: 'OK' 133 | }); 134 | 135 | setTimeout(function () { 136 | expect(response.data).toBe('stuff'); 137 | done(); 138 | }, 100); 139 | }); 140 | }); 141 | 142 | it('should add a response interceptor that returns a promise', function (done) { 143 | var response; 144 | 145 | axios.interceptors.response.use(function (data) { 146 | return new Promise(function (resolve) { 147 | // do something async 148 | setTimeout(function () { 149 | data.data = 'you have been promised!'; 150 | resolve(data); 151 | }, 10); 152 | }); 153 | }); 154 | 155 | axios('/foo').then(function (data) { 156 | response = data; 157 | }); 158 | 159 | getAjaxRequest().then(function (request) { 160 | request.respondWith({ 161 | status: 200, 162 | responseText: 'OK' 163 | }); 164 | 165 | setTimeout(function () { 166 | expect(response.data).toBe('you have been promised!'); 167 | done(); 168 | }, 100); 169 | }); 170 | }); 171 | 172 | it('should add multiple response interceptors', function (done) { 173 | var response; 174 | 175 | axios.interceptors.response.use(function (data) { 176 | data.data = data.data + '1'; 177 | return data; 178 | }); 179 | axios.interceptors.response.use(function (data) { 180 | data.data = data.data + '2'; 181 | return data; 182 | }); 183 | axios.interceptors.response.use(function (data) { 184 | data.data = data.data + '3'; 185 | return data; 186 | }); 187 | 188 | axios('/foo').then(function (data) { 189 | response = data; 190 | }); 191 | 192 | getAjaxRequest().then(function (request) { 193 | request.respondWith({ 194 | status: 200, 195 | responseText: 'OK' 196 | }); 197 | 198 | setTimeout(function () { 199 | expect(response.data).toBe('OK123'); 200 | done(); 201 | }, 100); 202 | }); 203 | }); 204 | 205 | it('should allow removing interceptors', function (done) { 206 | var response, intercept; 207 | 208 | axios.interceptors.response.use(function (data) { 209 | data.data = data.data + '1'; 210 | return data; 211 | }); 212 | intercept = axios.interceptors.response.use(function (data) { 213 | data.data = data.data + '2'; 214 | return data; 215 | }); 216 | axios.interceptors.response.use(function (data) { 217 | data.data = data.data + '3'; 218 | return data; 219 | }); 220 | 221 | axios.interceptors.response.eject(intercept); 222 | 223 | axios('/foo').then(function (data) { 224 | response = data; 225 | }); 226 | 227 | getAjaxRequest().then(function (request) { 228 | request.respondWith({ 229 | status: 200, 230 | responseText: 'OK' 231 | }); 232 | 233 | setTimeout(function () { 234 | expect(response.data).toBe('OK13'); 235 | done(); 236 | }, 100); 237 | }); 238 | }); 239 | 240 | it('should execute interceptors before transformers', function (done) { 241 | axios.interceptors.request.use(function (config) { 242 | config.data.baz = 'qux'; 243 | return config; 244 | }); 245 | 246 | axios.post('/foo', { 247 | foo: 'bar' 248 | }); 249 | 250 | getAjaxRequest().then(function (request) { 251 | expect(request.params).toEqual('{"foo":"bar","baz":"qux"}'); 252 | done(); 253 | }); 254 | }); 255 | 256 | it('should modify base URL in request interceptor', function (done) { 257 | var instance = axios.create({ 258 | baseURL: 'http://test.com/' 259 | }); 260 | 261 | instance.interceptors.request.use(function (config) { 262 | config.baseURL = 'http://rebase.com/'; 263 | return config; 264 | }); 265 | 266 | instance.get('/foo'); 267 | 268 | getAjaxRequest().then(function (request) { 269 | expect(request.url).toBe('http://rebase.com/foo'); 270 | done(); 271 | }); 272 | }); 273 | }); 274 | -------------------------------------------------------------------------------- /test/specs/options.spec.js: -------------------------------------------------------------------------------- 1 | describe('options', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | }); 9 | 10 | it('should default method to get', function (done) { 11 | axios('/foo'); 12 | 13 | getAjaxRequest().then(function (request) { 14 | expect(request.method).toBe('GET'); 15 | done(); 16 | }); 17 | }); 18 | 19 | it('should accept headers', function (done) { 20 | axios('/foo', { 21 | headers: { 22 | 'X-Requested-With': 'XMLHttpRequest' 23 | } 24 | }); 25 | 26 | getAjaxRequest().then(function (request) { 27 | expect(request.requestHeaders['X-Requested-With']).toEqual('XMLHttpRequest'); 28 | done(); 29 | }); 30 | }); 31 | 32 | it('should accept params', function (done) { 33 | axios('/foo', { 34 | params: { 35 | foo: 123, 36 | bar: 456 37 | } 38 | }); 39 | 40 | getAjaxRequest().then(function (request) { 41 | expect(request.url).toBe('/foo?foo=123&bar=456'); 42 | done(); 43 | }); 44 | }); 45 | 46 | it('should allow overriding default headers', function (done) { 47 | axios('/foo', { 48 | headers: { 49 | 'Accept': 'foo/bar' 50 | } 51 | }); 52 | 53 | getAjaxRequest().then(function (request) { 54 | expect(request.requestHeaders['Accept']).toEqual('foo/bar'); 55 | done(); 56 | }); 57 | }); 58 | 59 | it('should accept base URL', function (done) { 60 | var instance = axios.create({ 61 | baseURL: 'http://test.com/' 62 | }); 63 | 64 | instance.get('/foo'); 65 | 66 | getAjaxRequest().then(function (request) { 67 | expect(request.url).toBe('http://test.com/foo'); 68 | done(); 69 | }); 70 | }); 71 | 72 | it('should ignore base URL if request URL is absolute', function (done) { 73 | var instance = axios.create({ 74 | baseURL: 'http://someurl.com/' 75 | }); 76 | 77 | instance.get('http://someotherurl.com/'); 78 | 79 | getAjaxRequest().then(function (request) { 80 | expect(request.url).toBe('http://someotherurl.com/'); 81 | done(); 82 | }); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/specs/progress.spec.js: -------------------------------------------------------------------------------- 1 | describe('progress events', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | }); 9 | 10 | it('should add a download progress handler', function (done) { 11 | var progressSpy = jasmine.createSpy('progress'); 12 | 13 | axios('/foo', { onDownloadProgress: progressSpy } ); 14 | 15 | getAjaxRequest().then(function (request) { 16 | request.respondWith({ 17 | status: 200, 18 | responseText: '{"foo": "bar"}' 19 | }); 20 | expect(progressSpy).toHaveBeenCalled(); 21 | done(); 22 | }); 23 | }); 24 | 25 | it('should add a upload progress handler', function (done) { 26 | var progressSpy = jasmine.createSpy('progress'); 27 | 28 | axios('/foo', { onUploadProgress: progressSpy } ); 29 | 30 | getAjaxRequest().then(function (request) { 31 | // Jasmine AJAX doesn't trigger upload events. Waiting for upstream fix 32 | // expect(progressSpy).toHaveBeenCalled(); 33 | done(); 34 | }); 35 | }); 36 | 37 | it('should add both upload and download progress handlers', function (done) { 38 | var downloadProgressSpy = jasmine.createSpy('downloadProgress'); 39 | var uploadProgressSpy = jasmine.createSpy('uploadProgress'); 40 | 41 | axios('/foo', { onDownloadProgress: downloadProgressSpy, onUploadProgress: uploadProgressSpy }); 42 | 43 | getAjaxRequest().then(function (request) { 44 | // expect(uploadProgressSpy).toHaveBeenCalled(); 45 | expect(downloadProgressSpy).not.toHaveBeenCalled(); 46 | request.respondWith({ 47 | status: 200, 48 | responseText: '{"foo": "bar"}' 49 | }); 50 | expect(downloadProgressSpy).toHaveBeenCalled(); 51 | done(); 52 | }); 53 | }); 54 | 55 | it('should add a download progress handler from instance config', function (done) { 56 | var progressSpy = jasmine.createSpy('progress'); 57 | 58 | var instance = axios.create({ 59 | onDownloadProgress: progressSpy, 60 | }); 61 | 62 | instance.get('/foo'); 63 | 64 | getAjaxRequest().then(function (request) { 65 | request.respondWith({ 66 | status: 200, 67 | responseText: '{"foo": "bar"}' 68 | }); 69 | expect(progressSpy).toHaveBeenCalled(); 70 | done(); 71 | }); 72 | }); 73 | 74 | it('should add a upload progress handler from instance config', function (done) { 75 | var progressSpy = jasmine.createSpy('progress'); 76 | 77 | var instance = axios.create({ 78 | onUploadProgress: progressSpy, 79 | }); 80 | 81 | instance.get('/foo'); 82 | 83 | getAjaxRequest().then(function (request) { 84 | // expect(progressSpy).toHaveBeenCalled(); 85 | done(); 86 | }); 87 | }); 88 | 89 | it('should add upload and download progress handlers from instance config', function (done) { 90 | var downloadProgressSpy = jasmine.createSpy('downloadProgress'); 91 | var uploadProgressSpy = jasmine.createSpy('uploadProgress'); 92 | 93 | var instance = axios.create({ 94 | onDownloadProgress: downloadProgressSpy, 95 | onUploadProgress: uploadProgressSpy, 96 | }); 97 | 98 | instance.get('/foo'); 99 | 100 | getAjaxRequest().then(function (request) { 101 | // expect(uploadProgressSpy).toHaveBeenCalled(); 102 | expect(downloadProgressSpy).not.toHaveBeenCalled(); 103 | request.respondWith({ 104 | status: 200, 105 | responseText: '{"foo": "bar"}' 106 | }); 107 | expect(downloadProgressSpy).toHaveBeenCalled(); 108 | done(); 109 | }); 110 | }); 111 | }); 112 | -------------------------------------------------------------------------------- /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 | var 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 | var 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 | var sum = 0; 49 | var fulfilled = false; 50 | var 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 | }); 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/requests.spec.js: -------------------------------------------------------------------------------- 1 | describe('requests', function () { 2 | beforeEach(function () { 3 | jasmine.Ajax.install(); 4 | }); 5 | 6 | afterEach(function () { 7 | jasmine.Ajax.uninstall(); 8 | }); 9 | 10 | it('should treat single string arg as url', function (done) { 11 | axios('/foo'); 12 | 13 | getAjaxRequest().then(function (request) { 14 | expect(request.url).toBe('/foo'); 15 | expect(request.method).toBe('GET'); 16 | done(); 17 | }); 18 | }); 19 | 20 | it('should treat method value as lowercase string', function (done) { 21 | axios({ 22 | url: '/foo', 23 | method: 'POST' 24 | }).then(function (response) { 25 | expect(response.config.method).toBe('post'); 26 | done(); 27 | }); 28 | 29 | getAjaxRequest().then(function (request) { 30 | request.respondWith({ 31 | status: 200 32 | }); 33 | }); 34 | }); 35 | 36 | it('should allow string arg as url, and config arg', function (done) { 37 | axios.post('/foo'); 38 | 39 | getAjaxRequest().then(function (request) { 40 | expect(request.url).toBe('/foo'); 41 | expect(request.method).toBe('POST'); 42 | done(); 43 | }); 44 | }); 45 | 46 | it('should make an http request', function (done) { 47 | axios('/foo'); 48 | 49 | getAjaxRequest().then(function (request) { 50 | expect(request.url).toBe('/foo'); 51 | done(); 52 | }); 53 | }); 54 | 55 | it('should reject on network errors', function (done) { 56 | // disable jasmine.Ajax since we're hitting a non-existant server anyway 57 | jasmine.Ajax.uninstall(); 58 | 59 | var resolveSpy = jasmine.createSpy('resolve'); 60 | var rejectSpy = jasmine.createSpy('reject'); 61 | 62 | var finish = function () { 63 | expect(resolveSpy).not.toHaveBeenCalled(); 64 | expect(rejectSpy).toHaveBeenCalled(); 65 | var reason = rejectSpy.calls.first().args[0]; 66 | expect(reason instanceof Error).toBe(true); 67 | expect(reason.config.method).toBe('get'); 68 | expect(reason.config.url).toBe('http://thisisnotaserver/foo'); 69 | expect(reason.request).toEqual(jasmine.any(XMLHttpRequest)); 70 | 71 | // re-enable jasmine.Ajax 72 | jasmine.Ajax.install(); 73 | 74 | done(); 75 | }; 76 | 77 | axios('http://thisisnotaserver/foo') 78 | .then(resolveSpy, rejectSpy) 79 | .then(finish, finish); 80 | }); 81 | 82 | it('should reject when validateStatus returns false', function (done) { 83 | var resolveSpy = jasmine.createSpy('resolve'); 84 | var rejectSpy = jasmine.createSpy('reject'); 85 | 86 | axios('/foo', { 87 | validateStatus: function (status) { 88 | return status !== 500; 89 | } 90 | }).then(resolveSpy) 91 | .catch(rejectSpy) 92 | .then(function () { 93 | expect(resolveSpy).not.toHaveBeenCalled(); 94 | expect(rejectSpy).toHaveBeenCalled(); 95 | var reason = rejectSpy.calls.first().args[0]; 96 | expect(reason instanceof Error).toBe(true); 97 | expect(reason.message).toBe('Request failed with status code 500'); 98 | expect(reason.config.method).toBe('get'); 99 | expect(reason.config.url).toBe('/foo'); 100 | expect(reason.response.status).toBe(500); 101 | 102 | done(); 103 | }); 104 | 105 | getAjaxRequest().then(function (request) { 106 | request.respondWith({ 107 | status: 500 108 | }); 109 | }); 110 | }); 111 | 112 | it('should resolve when validateStatus returns true', function (done) { 113 | var resolveSpy = jasmine.createSpy('resolve'); 114 | var rejectSpy = jasmine.createSpy('reject'); 115 | 116 | axios('/foo', { 117 | validateStatus: function (status) { 118 | return status === 500; 119 | } 120 | }).then(resolveSpy) 121 | .catch(rejectSpy) 122 | .then(function () { 123 | expect(resolveSpy).toHaveBeenCalled(); 124 | expect(rejectSpy).not.toHaveBeenCalled(); 125 | done(); 126 | }); 127 | 128 | getAjaxRequest().then(function (request) { 129 | request.respondWith({ 130 | status: 500 131 | }); 132 | }); 133 | }); 134 | 135 | // https://github.com/mzabriskie/axios/issues/378 136 | it('should return JSON when rejecting', function (done) { 137 | var response; 138 | 139 | axios('/api/account/signup', { 140 | username: null, 141 | password: null 142 | }, { 143 | method: 'post', 144 | headers: { 145 | 'Accept': 'application/json' 146 | } 147 | }) 148 | .catch(function (error) { 149 | response = error.response; 150 | }); 151 | 152 | getAjaxRequest().then(function (request) { 153 | request.respondWith({ 154 | status: 400, 155 | statusText: 'Bad Request', 156 | responseText: '{"error": "BAD USERNAME", "code": 1}' 157 | }); 158 | 159 | setTimeout(function () { 160 | expect(typeof response.data).toEqual('object'); 161 | expect(response.data.error).toEqual('BAD USERNAME'); 162 | expect(response.data.code).toEqual(1); 163 | done(); 164 | }, 100); 165 | }); 166 | }); 167 | 168 | it('should make cross domian http request', function (done) { 169 | var response; 170 | 171 | axios.post('www.someurl.com/foo').then(function(res){ 172 | response = res; 173 | }); 174 | 175 | getAjaxRequest().then(function (request) { 176 | request.respondWith({ 177 | status: 200, 178 | statusText: 'OK', 179 | responseText: '{"foo": "bar"}', 180 | headers: { 181 | 'Content-Type': 'application/json' 182 | } 183 | }); 184 | 185 | setTimeout(function () { 186 | expect(response.data.foo).toEqual('bar'); 187 | expect(response.status).toEqual(200); 188 | expect(response.statusText).toEqual('OK'); 189 | expect(response.headers['content-type']).toEqual('application/json'); 190 | done(); 191 | }, 100); 192 | }); 193 | }); 194 | 195 | 196 | it('should supply correct response', function (done) { 197 | var response; 198 | 199 | axios.post('/foo').then(function (res) { 200 | response = res; 201 | }); 202 | 203 | getAjaxRequest().then(function (request) { 204 | request.respondWith({ 205 | status: 200, 206 | statusText: 'OK', 207 | responseText: '{"foo": "bar"}', 208 | headers: { 209 | 'Content-Type': 'application/json' 210 | } 211 | }); 212 | 213 | setTimeout(function () { 214 | expect(response.data.foo).toEqual('bar'); 215 | expect(response.status).toEqual(200); 216 | expect(response.statusText).toEqual('OK'); 217 | expect(response.headers['content-type']).toEqual('application/json'); 218 | done(); 219 | }, 100); 220 | }); 221 | }); 222 | 223 | // https://github.com/mzabriskie/axios/issues/201 224 | it('should fix IE no content error', function (done) { 225 | var response; 226 | 227 | axios('/foo').then(function (res) { 228 | response = res 229 | }); 230 | 231 | getAjaxRequest().then(function (request) { 232 | request.respondWith({ 233 | status: 1223, 234 | statusText: 'Unknown' 235 | }); 236 | 237 | setTimeout(function () { 238 | expect(response.status).toEqual(204); 239 | expect(response.statusText).toEqual('No Content'); 240 | done(); 241 | }, 100); 242 | }); 243 | }); 244 | 245 | it('should allow overriding Content-Type header case-insensitive', function (done) { 246 | var response; 247 | var contentType = 'application/vnd.myapp.type+json'; 248 | 249 | axios.post('/foo', { prop: 'value' }, { 250 | headers: { 251 | 'content-type': contentType 252 | } 253 | }).then(function (res) { 254 | response = res; 255 | }); 256 | 257 | getAjaxRequest().then(function (request) { 258 | expect(request.requestHeaders['Content-Type']).toEqual(contentType); 259 | done(); 260 | }); 261 | }); 262 | 263 | it('should support binary data as array buffer', function (done) { 264 | // Int8Array doesn't exist in IE8/9 265 | if (isOldIE && typeof Int8Array === 'undefined') { 266 | done(); 267 | return; 268 | } 269 | 270 | var input = new Int8Array(2); 271 | input[0] = 1; 272 | input[1] = 2; 273 | 274 | axios.post('/foo', input.buffer); 275 | 276 | getAjaxRequest().then(function (request) { 277 | var output = new Int8Array(request.params); 278 | expect(output.length).toEqual(2); 279 | expect(output[0]).toEqual(1); 280 | expect(output[1]).toEqual(2); 281 | done(); 282 | }); 283 | }); 284 | 285 | it('should support binary data as array buffer view', function (done) { 286 | // Int8Array doesn't exist in IE8/9 287 | if (isOldIE && typeof Int8Array === 'undefined') { 288 | done(); 289 | return; 290 | } 291 | 292 | var input = new Int8Array(2); 293 | input[0] = 1; 294 | input[1] = 2; 295 | 296 | axios.post('/foo', input); 297 | 298 | getAjaxRequest().then(function (request) { 299 | var output = new Int8Array(request.params); 300 | expect(output.length).toEqual(2); 301 | expect(output[0]).toEqual(1); 302 | expect(output[1]).toEqual(2); 303 | done(); 304 | }); 305 | }); 306 | 307 | it('should support array buffer response', function (done) { 308 | // ArrayBuffer doesn't exist in IE8/9 309 | if (isOldIE && typeof ArrayBuffer === 'undefined') { 310 | done(); 311 | return; 312 | } 313 | 314 | var response; 315 | 316 | function str2ab(str) { 317 | var buff = new ArrayBuffer(str.length * 2); 318 | var view = new Uint16Array(buff); 319 | for ( var i=0, l=str.length; i '{"foo":"bar"}', 18 | transformResponse: [(data: any) => ({ baz: 'qux' })], 19 | headers: { 'X-FOO': 'bar' }, 20 | params: { id: 12345 }, 21 | paramsSerializer: (params: any) => 'id=12345', 22 | data: { foo: 'bar' }, 23 | timeout: 10000, 24 | withCredentials: true, 25 | auth: { 26 | username: 'janedoe', 27 | password: 's00pers3cret' 28 | }, 29 | responseType: 'json', 30 | xsrfCookieName: 'XSRF-TOKEN', 31 | xsrfHeaderName: 'X-XSRF-TOKEN', 32 | onUploadProgress: (progressEvent: any) => {}, 33 | onDownloadProgress: (progressEvent: any) => {}, 34 | maxContentLength: 2000, 35 | validateStatus: (status: number) => status >= 200 && status < 300, 36 | maxRedirects: 5, 37 | proxy: { 38 | host: '127.0.0.1', 39 | port: 9000 40 | }, 41 | cancelToken: new axios.CancelToken((cancel: Canceler) => {}) 42 | }; 43 | 44 | const handleResponse = (response: AxiosResponse) => { 45 | console.log(response.data); 46 | console.log(response.status); 47 | console.log(response.statusText); 48 | console.log(response.headers); 49 | console.log(response.config); 50 | }; 51 | 52 | const handleError = (error: AxiosError) => { 53 | if (error.response) { 54 | console.log(error.response.data); 55 | console.log(error.response.status); 56 | console.log(error.response.headers); 57 | } else { 58 | console.log(error.message); 59 | } 60 | }; 61 | 62 | axios(config) 63 | .then(handleResponse) 64 | .catch(handleError); 65 | 66 | axios 67 | .get('/user?id=12345') 68 | .then(handleResponse) 69 | .catch(handleError); 70 | 71 | axios 72 | .get('/user', { params: { id: 12345 } }) 73 | .then(handleResponse) 74 | .catch(handleError); 75 | 76 | axios 77 | .jsonp('/user', { 78 | timeout: 1000, 79 | params: { id: 12345 } 80 | }) 81 | .then(handleResponse) 82 | .catch(handleError); 83 | 84 | axios 85 | .head('/user') 86 | .then(handleResponse) 87 | .catch(handleError); 88 | 89 | axios 90 | .delete('/user') 91 | .then(handleResponse) 92 | .catch(handleError); 93 | 94 | axios 95 | .post('/user', { foo: 'bar' }) 96 | .then(handleResponse) 97 | .catch(handleError); 98 | 99 | axios 100 | .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) 101 | .then(handleResponse) 102 | .catch(handleError); 103 | 104 | axios 105 | .put('/user', { foo: 'bar' }) 106 | .then(handleResponse) 107 | .catch(handleError); 108 | 109 | axios 110 | .patch('/user', { foo: 'bar' }) 111 | .then(handleResponse) 112 | .catch(handleError); 113 | 114 | // Instances 115 | 116 | const instance1: AxiosInstance = axios.create(); 117 | const instance2: AxiosInstance = axios.create(config); 118 | 119 | instance1 120 | .request(config) 121 | .then(handleResponse) 122 | .catch(handleError); 123 | 124 | instance1 125 | .get('/user?id=12345') 126 | .then(handleResponse) 127 | .catch(handleError); 128 | 129 | instance1 130 | .get('/user', { params: { id: 12345 } }) 131 | .then(handleResponse) 132 | .catch(handleError); 133 | 134 | instance1 135 | .post('/user', { foo: 'bar' }) 136 | .then(handleResponse) 137 | .catch(handleError); 138 | 139 | instance1 140 | .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) 141 | .then(handleResponse) 142 | .catch(handleError); 143 | 144 | // Defaults 145 | 146 | axios.defaults.baseURL = 'https://api.example.com/'; 147 | axios.defaults.headers.common['Authorization'] = 'token'; 148 | axios.defaults.headers.post['X-FOO'] = 'bar'; 149 | axios.defaults.timeout = 2500; 150 | 151 | instance1.defaults.baseURL = 'https://api.example.com/'; 152 | instance1.defaults.headers.common['Authorization'] = 'token'; 153 | instance1.defaults.headers.post['X-FOO'] = 'bar'; 154 | instance1.defaults.timeout = 2500; 155 | 156 | // Interceptors 157 | 158 | const requestInterceptorId: number = axios.interceptors.request.use( 159 | (config: AxiosRequestConfig) => config, 160 | (error: any) => Promise.reject(error) 161 | ); 162 | 163 | axios.interceptors.request.eject(requestInterceptorId); 164 | 165 | axios.interceptors.request.use( 166 | (config: AxiosRequestConfig) => Promise.resolve(config), 167 | (error: any) => Promise.reject(error) 168 | ); 169 | 170 | axios.interceptors.request.use((config: AxiosRequestConfig) => config); 171 | axios.interceptors.request.use((config: AxiosRequestConfig) => 172 | Promise.resolve(config) 173 | ); 174 | 175 | const responseInterceptorId: number = axios.interceptors.response.use( 176 | (response: AxiosResponse) => response, 177 | (error: any) => Promise.reject(error) 178 | ); 179 | 180 | axios.interceptors.response.eject(responseInterceptorId); 181 | 182 | axios.interceptors.response.use( 183 | (response: AxiosResponse) => Promise.resolve(response), 184 | (error: any) => Promise.reject(error) 185 | ); 186 | 187 | axios.interceptors.response.use((response: AxiosResponse) => response); 188 | axios.interceptors.response.use((response: AxiosResponse) => 189 | Promise.resolve(response) 190 | ); 191 | 192 | // Adapters 193 | 194 | const adapter: AxiosAdapter = (config: AxiosRequestConfig) => { 195 | const response: AxiosResponse = { 196 | data: { foo: 'bar' }, 197 | status: 200, 198 | statusText: 'OK', 199 | headers: { 'X-FOO': 'bar' }, 200 | config 201 | }; 202 | return Promise.resolve(response); 203 | }; 204 | 205 | axios.defaults.adapter = adapter; 206 | 207 | // axios.all 208 | 209 | const promises = [Promise.resolve(1), Promise.resolve(2)]; 210 | 211 | const promise: Promise = axios.all(promises); 212 | 213 | // axios.spread 214 | 215 | const fn1 = (a: number, b: number, c: number) => `${a}-${b}-${c}`; 216 | const fn2: (arr: number[]) => string = axios.spread(fn1); 217 | 218 | // Promises 219 | 220 | axios 221 | .get('/user') 222 | .then((response: AxiosResponse) => 'foo') 223 | .then((value: string) => {}); 224 | 225 | axios 226 | .get('/user') 227 | .then((response: AxiosResponse) => Promise.resolve('foo')) 228 | .then((value: string) => {}); 229 | 230 | axios 231 | .get('/user') 232 | .then((response: AxiosResponse) => 'foo', (error: any) => 'bar') 233 | .then((value: string) => {}); 234 | 235 | axios 236 | .get('/user') 237 | .then((response: AxiosResponse) => 'foo', (error: any) => 123) 238 | .then((value: string | number) => {}); 239 | 240 | axios 241 | .get('/user') 242 | .catch((error: any) => 'foo') 243 | .then((value: string) => {}); 244 | 245 | axios 246 | .get('/user') 247 | .catch((error: any) => Promise.resolve('foo')) 248 | .then((value: string) => {}); 249 | 250 | // Cancellation 251 | 252 | const source: CancelTokenSource = axios.CancelToken.source(); 253 | 254 | axios 255 | .get('/user', { 256 | cancelToken: source.token 257 | }) 258 | .catch((thrown: AxiosError | Cancel) => { 259 | if (axios.isCancel(thrown)) { 260 | const cancel: Cancel = thrown; 261 | console.log(cancel.message); 262 | } 263 | }); 264 | 265 | source.cancel('Operation has been canceled.'); 266 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var config = {}; 3 | 4 | function generateConfig(name) { 5 | var uglify = name.indexOf('min') > -1; 6 | var config = { 7 | entry: './index.js', 8 | output: { 9 | path: 'dist/', 10 | filename: name + '.js', 11 | sourceMapFilename: name + '.map', 12 | library: 'axios', 13 | libraryTarget: 'umd' 14 | }, 15 | node: { 16 | process: false 17 | }, 18 | devtool: 'source-map' 19 | }; 20 | 21 | config.plugins = [ 22 | new webpack.DefinePlugin({ 23 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) 24 | }) 25 | ]; 26 | 27 | if (uglify) { 28 | config.plugins.push( 29 | new webpack.optimize.UglifyJsPlugin({ 30 | compressor: { 31 | warnings: false 32 | } 33 | }) 34 | ); 35 | } 36 | 37 | return config; 38 | } 39 | 40 | ['axios', 'axios.min'].forEach(function (key) { 41 | config[key] = generateConfig(key); 42 | }); 43 | 44 | module.exports = config; 45 | --------------------------------------------------------------------------------