Spaces:
Sleeping
Sleeping
Upload 95 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- credentials.json +13 -0
- dropbox_plans/2301 BMW job1 external.pdf +0 -0
- dropbox_plans/2301 BMW job1 foundation.pdf +0 -0
- dropbox_plans/2301 BMW job1 pc2.pdf +0 -0
- dropbox_plans/2301 BMW job1 pc3.pdf +0 -0
- dropbox_plans/2301 BMW job1 piles.pdf +0 -0
- dropbox_plans/2301 BMW job2 external.pdf +0 -0
- dropbox_plans/2301 BMW job2 interior.pdf +0 -0
- dropbox_plans/2301 BMW job2 pc5.pdf +0 -0
- dropbox_plans/2301 BMW job2 pc7.pdf +0 -0
- dropbox_plans/2301BMWfoundation.pdf +0 -0
- dropbox_plans/2301BMWpc2.pdf +0 -0
- dropbox_plans/2301BMWpc3.pdf +0 -0
- dropbox_plans/BMW job1 23-HRW-01-BG-DR-S-110_P.02_FN.pdf +0 -0
- dropbox_plans/foundation.pdf +0 -0
- dropbox_plans/foundation2023.pdf +0 -0
- dropbox_plans/pc2-2023.pdf +0 -0
- dropbox_plans/pc2.pdf +0 -0
- dropbox_plans/pc3-2023.pdf +0 -0
- dropbox_plans/pc3.pdf +0 -0
- dropbox_plans/pc5 2023.pdf +0 -0
- dropbox_plans/pc5.pdf +0 -0
- dropbox_plans/pc7 2023.pdf +0 -0
- dropbox_plans/pc7.pdf +0 -0
- dropbox_plans/piles_origCountSummary.csv +2 -0
- node_modules/node-fetch/LICENSE.md +22 -0
- node_modules/node-fetch/README.md +633 -0
- node_modules/node-fetch/browser.js +25 -0
- node_modules/node-fetch/lib/index.es.js +1778 -0
- node_modules/node-fetch/lib/index.js +1787 -0
- node_modules/node-fetch/lib/index.mjs +1776 -0
- node_modules/node-fetch/package.json +116 -0
- node_modules/tr46/.npmignore +4 -0
- node_modules/tr46/dropbox/CODE_OF_CONDUCT.md +5 -0
- node_modules/tr46/dropbox/CONTRIBUTING.md +62 -0
- node_modules/tr46/dropbox/LICENSE +20 -0
- node_modules/tr46/dropbox/README.md +70 -0
- node_modules/tr46/dropbox/UPGRADING.md +163 -0
- node_modules/tr46/dropbox/cjs/index.js +41 -0
- node_modules/tr46/dropbox/cjs/lib/routes.js +0 -0
- node_modules/tr46/dropbox/cjs/lib/types.js +0 -0
- node_modules/tr46/dropbox/cjs/src/auth.js +492 -0
- node_modules/tr46/dropbox/cjs/src/constants.js +20 -0
- node_modules/tr46/dropbox/cjs/src/dropbox.js +247 -0
- node_modules/tr46/dropbox/cjs/src/error.js +58 -0
- node_modules/tr46/dropbox/cjs/src/response.js +82 -0
- node_modules/tr46/dropbox/cjs/src/utils.js +87 -0
- node_modules/tr46/dropbox/dist/Dropbox-sdk.js +0 -0
- node_modules/tr46/dropbox/dist/Dropbox-sdk.js.map +0 -0
- node_modules/tr46/dropbox/dist/Dropbox-sdk.min.js +1 -0
credentials.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"type": "service_account",
|
| 3 |
+
"project_id": "adr-demo1",
|
| 4 |
+
"private_key_id": "4cc6ab0f41bd07b7458c4ac31001a58da494e701",
|
| 5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCkXzEvAM42FL15\ngkRvnJMxi6bcNxWTE96UJYJ+Y+WaHkXr3v4BrWV3sJnYOI3HFiUpcG/BbKZUzoxJ\nL1vTtzZIhA/OrEl9xDF9Ta4xxDiwaZWBQnwbtCZIIqk8Al5UvjHcP8ZpR3dZ3luf\nql/M+o8Wh1pllejrHtq/rrXDhuFYEuyBh/Oft8wpqIoPwKLW51I3jn42Q0u9hOJO\n56lHultNfCPzGzRd6H0XpbCi5S0Doo8m1mOMjHdrHUAk2/4CQ39wepeyB/77LXhD\n51/9PIaSKHo7tY4GMfIhAmAPuOF2718EY8xJWjkOdzbs9kXheW7OFTBq5zyrNLwm\nRaDUFXmBAgMBAAECggEAAQ9hcH1/gaHInGFWslGUMXGbyzfKZSnE+bee4SnLxUla\nB2y8vqNbpYCiErRAAH9dZf2vpX5fOZTLcCgPXjeERhtz7qVLJAsr4TRVt0RzXnqP\n2Ebm01bqGEpWRRN5gEUUapM5YwcZofQT1d0cw7mp9T885K1+1GVdNndDUiuAheI2\ntrAca4JApH6uRy6rbeEm0pPnIsvwIDA/6YuaQJvPuBclN44aLanAO/M2UhtXnuYI\nfXCMdV0EG3dwTmQGpjPWJxEjXO8pQn67pqJfBej0x8ZZ/qJCR0P8hGhPOrZcu+db\nZ6XxeKHMX0t95tuonMAx+0XaUnKXfG0VorJ3EDsbQQKBgQDSYWc9jK043hJk588F\ndPmRavuSQCjJbEShVtbf1bIhW6vlemqCnkkGg5X8OfLprf+eikzLbx2ToVPx6x+j\nMzEYXr5ZsWmXhN8MXY+wka5bl+V1XI7bekTB+dKjUauF22SFvEv2XPVvi/5m7S3L\nCrjfIYSAzTtjv0Q9W2NAOwHvhQKBgQDIA8RhgnuLK7GJyBOQ77WbAdaG/r17x7yP\nBhaP+uB09OyGUyWMvgzzh3m8fo0T8hxyJGNL2lG77MlxdUt49FRoin4z3SwD73JF\nHaXSyHBF/gSSaEje2OOg+XY3Ry7Nt8CRM+UWlZ5S8TEFfaBsDfxIH1cwpTGKX+JT\nUOFPnwe8zQKBgQCRrk1Ve8K/7FeEdFkRCE2Bezm1rqQPxt9HceDdoxb0row8Hib/\nSCh9UEVeIaqqUoj9+frvrIQopMCCdzSzSFGo9IKPjaD3AVWLNIa52EeKuYZ1XKC4\nLtTKFfrciUNjL+dODHP1p611jtWd5IOfZE9cg9NDddq4WcwhSNVTtwjCGQKBgDIA\nvxehh0FDqx7G5h1V0BDwZLFa/gPz6y/WVc2o6nRSxs7N+pU07gfz1ntJJ/vUi0f9\n0NUlv0k76SB0MmoKqw93kBVnNZnGQssEnnATq/3Tg1EWwSD1F/MmamdnZEwJpBqo\n3pzGys3xfk/hGDnrRSbCrwl6QuhVED/D+I/vMgABAoGBAMyMz38hTbEnp/qePGJy\nUwIcJrgd0GexJBayR29zFcUIeJRX7bq11/LRu+bFYJ5wuCem72QndfEneU5T1l1F\nwIPBhJsK1XP9m0sLIR3TWNywRX+1omfK0V9rxoAm22Tq9t/CXwQuXjHBqUyvoE3c\nvFo3c3iTC+cUM7XnlDzOQDsV\n-----END PRIVATE KEY-----\n",
|
| 6 |
+
"client_email": "adrgooglesheet@adr-demo1.iam.gserviceaccount.com",
|
| 7 |
+
"client_id": "114059569575086599132",
|
| 8 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 9 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
| 10 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 11 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/adrgooglesheet%40adr-demo1.iam.gserviceaccount.com",
|
| 12 |
+
"universe_domain": "googleapis.com"
|
| 13 |
+
}
|
dropbox_plans/2301 BMW job1 external.pdf
ADDED
|
Binary file (396 kB). View file
|
|
|
dropbox_plans/2301 BMW job1 foundation.pdf
ADDED
|
Binary file (173 kB). View file
|
|
|
dropbox_plans/2301 BMW job1 pc2.pdf
ADDED
|
Binary file (445 kB). View file
|
|
|
dropbox_plans/2301 BMW job1 pc3.pdf
ADDED
|
Binary file (396 kB). View file
|
|
|
dropbox_plans/2301 BMW job1 piles.pdf
ADDED
|
Binary file (445 kB). View file
|
|
|
dropbox_plans/2301 BMW job2 external.pdf
ADDED
|
Binary file (330 kB). View file
|
|
|
dropbox_plans/2301 BMW job2 interior.pdf
ADDED
|
Binary file (265 kB). View file
|
|
|
dropbox_plans/2301 BMW job2 pc5.pdf
ADDED
|
Binary file (330 kB). View file
|
|
|
dropbox_plans/2301 BMW job2 pc7.pdf
ADDED
|
Binary file (265 kB). View file
|
|
|
dropbox_plans/2301BMWfoundation.pdf
ADDED
|
File without changes
|
dropbox_plans/2301BMWpc2.pdf
ADDED
|
File without changes
|
dropbox_plans/2301BMWpc3.pdf
ADDED
|
File without changes
|
dropbox_plans/BMW job1 23-HRW-01-BG-DR-S-110_P.02_FN.pdf
ADDED
|
Binary file (504 kB). View file
|
|
|
dropbox_plans/foundation.pdf
ADDED
|
Binary file (173 kB). View file
|
|
|
dropbox_plans/foundation2023.pdf
ADDED
|
Binary file (173 kB). View file
|
|
|
dropbox_plans/pc2-2023.pdf
ADDED
|
Binary file (445 kB). View file
|
|
|
dropbox_plans/pc2.pdf
ADDED
|
Binary file (445 kB). View file
|
|
|
dropbox_plans/pc3-2023.pdf
ADDED
|
Binary file (396 kB). View file
|
|
|
dropbox_plans/pc3.pdf
ADDED
|
Binary file (396 kB). View file
|
|
|
dropbox_plans/pc5 2023.pdf
ADDED
|
Binary file (330 kB). View file
|
|
|
dropbox_plans/pc5.pdf
ADDED
|
Binary file (330 kB). View file
|
|
|
dropbox_plans/pc7 2023.pdf
ADDED
|
Binary file (265 kB). View file
|
|
|
dropbox_plans/pc7.pdf
ADDED
|
Binary file (265 kB). View file
|
|
|
dropbox_plans/piles_origCountSummary.csv
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Plan_Name,Matched items,Sensitivity
|
| 2 |
+
piles_orig.pdf,8,70
|
node_modules/node-fetch/LICENSE.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The MIT License (MIT)
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2016 David Frank
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
| 22 |
+
|
node_modules/node-fetch/README.md
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node-fetch
|
| 2 |
+
==========
|
| 3 |
+
|
| 4 |
+
[![npm version][npm-image]][npm-url]
|
| 5 |
+
[![build status][travis-image]][travis-url]
|
| 6 |
+
[![coverage status][codecov-image]][codecov-url]
|
| 7 |
+
[![install size][install-size-image]][install-size-url]
|
| 8 |
+
[![Discord][discord-image]][discord-url]
|
| 9 |
+
|
| 10 |
+
A light-weight module that brings `window.fetch` to Node.js
|
| 11 |
+
|
| 12 |
+
(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567))
|
| 13 |
+
|
| 14 |
+
[![Backers][opencollective-image]][opencollective-url]
|
| 15 |
+
|
| 16 |
+
<!-- TOC -->
|
| 17 |
+
|
| 18 |
+
- [Motivation](#motivation)
|
| 19 |
+
- [Features](#features)
|
| 20 |
+
- [Difference from client-side fetch](#difference-from-client-side-fetch)
|
| 21 |
+
- [Installation](#installation)
|
| 22 |
+
- [Loading and configuring the module](#loading-and-configuring-the-module)
|
| 23 |
+
- [Common Usage](#common-usage)
|
| 24 |
+
- [Plain text or HTML](#plain-text-or-html)
|
| 25 |
+
- [JSON](#json)
|
| 26 |
+
- [Simple Post](#simple-post)
|
| 27 |
+
- [Post with JSON](#post-with-json)
|
| 28 |
+
- [Post with form parameters](#post-with-form-parameters)
|
| 29 |
+
- [Handling exceptions](#handling-exceptions)
|
| 30 |
+
- [Handling client and server errors](#handling-client-and-server-errors)
|
| 31 |
+
- [Advanced Usage](#advanced-usage)
|
| 32 |
+
- [Streams](#streams)
|
| 33 |
+
- [Buffer](#buffer)
|
| 34 |
+
- [Accessing Headers and other Meta data](#accessing-headers-and-other-meta-data)
|
| 35 |
+
- [Extract Set-Cookie Header](#extract-set-cookie-header)
|
| 36 |
+
- [Post data using a file stream](#post-data-using-a-file-stream)
|
| 37 |
+
- [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart)
|
| 38 |
+
- [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)
|
| 39 |
+
- [API](#api)
|
| 40 |
+
- [fetch(url[, options])](#fetchurl-options)
|
| 41 |
+
- [Options](#options)
|
| 42 |
+
- [Class: Request](#class-request)
|
| 43 |
+
- [Class: Response](#class-response)
|
| 44 |
+
- [Class: Headers](#class-headers)
|
| 45 |
+
- [Interface: Body](#interface-body)
|
| 46 |
+
- [Class: FetchError](#class-fetcherror)
|
| 47 |
+
- [License](#license)
|
| 48 |
+
- [Acknowledgement](#acknowledgement)
|
| 49 |
+
|
| 50 |
+
<!-- /TOC -->
|
| 51 |
+
|
| 52 |
+
## Motivation
|
| 53 |
+
|
| 54 |
+
Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime.
|
| 55 |
+
|
| 56 |
+
See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side).
|
| 57 |
+
|
| 58 |
+
## Features
|
| 59 |
+
|
| 60 |
+
- Stay consistent with `window.fetch` API.
|
| 61 |
+
- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences.
|
| 62 |
+
- Use native promise but allow substituting it with [insert your favorite promise library].
|
| 63 |
+
- Use native Node streams for body on both request and response.
|
| 64 |
+
- Decode content encoding (gzip/deflate) properly and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically.
|
| 65 |
+
- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](ERROR-HANDLING.md) for troubleshooting.
|
| 66 |
+
|
| 67 |
+
## Difference from client-side fetch
|
| 68 |
+
|
| 69 |
+
- See [Known Differences](LIMITS.md) for details.
|
| 70 |
+
- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue.
|
| 71 |
+
- Pull requests are welcomed too!
|
| 72 |
+
|
| 73 |
+
## Installation
|
| 74 |
+
|
| 75 |
+
Current stable release (`2.x`)
|
| 76 |
+
|
| 77 |
+
```sh
|
| 78 |
+
$ npm install node-fetch
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
## Loading and configuring the module
|
| 82 |
+
We suggest you load the module via `require` until the stabilization of ES modules in node:
|
| 83 |
+
```js
|
| 84 |
+
const fetch = require('node-fetch');
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
If you are using a Promise library other than native, set it through `fetch.Promise`:
|
| 88 |
+
```js
|
| 89 |
+
const Bluebird = require('bluebird');
|
| 90 |
+
|
| 91 |
+
fetch.Promise = Bluebird;
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
## Common Usage
|
| 95 |
+
|
| 96 |
+
NOTE: The documentation below is up-to-date with `2.x` releases; see the [`1.x` readme](https://github.com/bitinn/node-fetch/blob/1.x/README.md), [changelog](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) and [2.x upgrade guide](UPGRADE-GUIDE.md) for the differences.
|
| 97 |
+
|
| 98 |
+
#### Plain text or HTML
|
| 99 |
+
```js
|
| 100 |
+
fetch('https://github.com/')
|
| 101 |
+
.then(res => res.text())
|
| 102 |
+
.then(body => console.log(body));
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
#### JSON
|
| 106 |
+
|
| 107 |
+
```js
|
| 108 |
+
|
| 109 |
+
fetch('https://api.github.com/users/github')
|
| 110 |
+
.then(res => res.json())
|
| 111 |
+
.then(json => console.log(json));
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
#### Simple Post
|
| 115 |
+
```js
|
| 116 |
+
fetch('https://httpbin.org/post', { method: 'POST', body: 'a=1' })
|
| 117 |
+
.then(res => res.json()) // expecting a json response
|
| 118 |
+
.then(json => console.log(json));
|
| 119 |
+
```
|
| 120 |
+
|
| 121 |
+
#### Post with JSON
|
| 122 |
+
|
| 123 |
+
```js
|
| 124 |
+
const body = { a: 1 };
|
| 125 |
+
|
| 126 |
+
fetch('https://httpbin.org/post', {
|
| 127 |
+
method: 'post',
|
| 128 |
+
body: JSON.stringify(body),
|
| 129 |
+
headers: { 'Content-Type': 'application/json' },
|
| 130 |
+
})
|
| 131 |
+
.then(res => res.json())
|
| 132 |
+
.then(json => console.log(json));
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
#### Post with form parameters
|
| 136 |
+
`URLSearchParams` is available in Node.js as of v7.5.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods.
|
| 137 |
+
|
| 138 |
+
NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such:
|
| 139 |
+
|
| 140 |
+
```js
|
| 141 |
+
const { URLSearchParams } = require('url');
|
| 142 |
+
|
| 143 |
+
const params = new URLSearchParams();
|
| 144 |
+
params.append('a', 1);
|
| 145 |
+
|
| 146 |
+
fetch('https://httpbin.org/post', { method: 'POST', body: params })
|
| 147 |
+
.then(res => res.json())
|
| 148 |
+
.then(json => console.log(json));
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
#### Handling exceptions
|
| 152 |
+
NOTE: 3xx-5xx responses are *NOT* exceptions and should be handled in `then()`; see the next section for more information.
|
| 153 |
+
|
| 154 |
+
Adding a catch to the fetch promise chain will catch *all* exceptions, such as errors originating from node core libraries, network errors and operational errors, which are instances of FetchError. See the [error handling document](ERROR-HANDLING.md) for more details.
|
| 155 |
+
|
| 156 |
+
```js
|
| 157 |
+
fetch('https://domain.invalid/')
|
| 158 |
+
.catch(err => console.error(err));
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
#### Handling client and server errors
|
| 162 |
+
It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses:
|
| 163 |
+
|
| 164 |
+
```js
|
| 165 |
+
function checkStatus(res) {
|
| 166 |
+
if (res.ok) { // res.status >= 200 && res.status < 300
|
| 167 |
+
return res;
|
| 168 |
+
} else {
|
| 169 |
+
throw MyCustomError(res.statusText);
|
| 170 |
+
}
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
fetch('https://httpbin.org/status/400')
|
| 174 |
+
.then(checkStatus)
|
| 175 |
+
.then(res => console.log('will not get here...'))
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
## Advanced Usage
|
| 179 |
+
|
| 180 |
+
#### Streams
|
| 181 |
+
The "Node.js way" is to use streams when possible:
|
| 182 |
+
|
| 183 |
+
```js
|
| 184 |
+
fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png')
|
| 185 |
+
.then(res => {
|
| 186 |
+
const dest = fs.createWriteStream('./octocat.png');
|
| 187 |
+
res.body.pipe(dest);
|
| 188 |
+
});
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch
|
| 192 |
+
errors -- the longer a response runs, the more likely it is to encounter an error.
|
| 193 |
+
|
| 194 |
+
```js
|
| 195 |
+
const fetch = require('node-fetch');
|
| 196 |
+
const response = await fetch('https://httpbin.org/stream/3');
|
| 197 |
+
try {
|
| 198 |
+
for await (const chunk of response.body) {
|
| 199 |
+
console.dir(JSON.parse(chunk.toString()));
|
| 200 |
+
}
|
| 201 |
+
} catch (err) {
|
| 202 |
+
console.error(err.stack);
|
| 203 |
+
}
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams
|
| 207 |
+
did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors
|
| 208 |
+
directly from the stream and wait on it response to fully close.
|
| 209 |
+
|
| 210 |
+
```js
|
| 211 |
+
const fetch = require('node-fetch');
|
| 212 |
+
const read = async body => {
|
| 213 |
+
let error;
|
| 214 |
+
body.on('error', err => {
|
| 215 |
+
error = err;
|
| 216 |
+
});
|
| 217 |
+
for await (const chunk of body) {
|
| 218 |
+
console.dir(JSON.parse(chunk.toString()));
|
| 219 |
+
}
|
| 220 |
+
return new Promise((resolve, reject) => {
|
| 221 |
+
body.on('close', () => {
|
| 222 |
+
error ? reject(error) : resolve();
|
| 223 |
+
});
|
| 224 |
+
});
|
| 225 |
+
};
|
| 226 |
+
try {
|
| 227 |
+
const response = await fetch('https://httpbin.org/stream/3');
|
| 228 |
+
await read(response.body);
|
| 229 |
+
} catch (err) {
|
| 230 |
+
console.error(err.stack);
|
| 231 |
+
}
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
#### Buffer
|
| 235 |
+
If you prefer to cache binary data in full, use buffer(). (NOTE: `buffer()` is a `node-fetch`-only API)
|
| 236 |
+
|
| 237 |
+
```js
|
| 238 |
+
const fileType = require('file-type');
|
| 239 |
+
|
| 240 |
+
fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png')
|
| 241 |
+
.then(res => res.buffer())
|
| 242 |
+
.then(buffer => fileType(buffer))
|
| 243 |
+
.then(type => { /* ... */ });
|
| 244 |
+
```
|
| 245 |
+
|
| 246 |
+
#### Accessing Headers and other Meta data
|
| 247 |
+
```js
|
| 248 |
+
fetch('https://github.com/')
|
| 249 |
+
.then(res => {
|
| 250 |
+
console.log(res.ok);
|
| 251 |
+
console.log(res.status);
|
| 252 |
+
console.log(res.statusText);
|
| 253 |
+
console.log(res.headers.raw());
|
| 254 |
+
console.log(res.headers.get('content-type'));
|
| 255 |
+
});
|
| 256 |
+
```
|
| 257 |
+
|
| 258 |
+
#### Extract Set-Cookie Header
|
| 259 |
+
|
| 260 |
+
Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API.
|
| 261 |
+
|
| 262 |
+
```js
|
| 263 |
+
fetch(url).then(res => {
|
| 264 |
+
// returns an array of values, instead of a string of comma-separated values
|
| 265 |
+
console.log(res.headers.raw()['set-cookie']);
|
| 266 |
+
});
|
| 267 |
+
```
|
| 268 |
+
|
| 269 |
+
#### Post data using a file stream
|
| 270 |
+
|
| 271 |
+
```js
|
| 272 |
+
const { createReadStream } = require('fs');
|
| 273 |
+
|
| 274 |
+
const stream = createReadStream('input.txt');
|
| 275 |
+
|
| 276 |
+
fetch('https://httpbin.org/post', { method: 'POST', body: stream })
|
| 277 |
+
.then(res => res.json())
|
| 278 |
+
.then(json => console.log(json));
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
#### Post with form-data (detect multipart)
|
| 282 |
+
|
| 283 |
+
```js
|
| 284 |
+
const FormData = require('form-data');
|
| 285 |
+
|
| 286 |
+
const form = new FormData();
|
| 287 |
+
form.append('a', 1);
|
| 288 |
+
|
| 289 |
+
fetch('https://httpbin.org/post', { method: 'POST', body: form })
|
| 290 |
+
.then(res => res.json())
|
| 291 |
+
.then(json => console.log(json));
|
| 292 |
+
|
| 293 |
+
// OR, using custom headers
|
| 294 |
+
// NOTE: getHeaders() is non-standard API
|
| 295 |
+
|
| 296 |
+
const form = new FormData();
|
| 297 |
+
form.append('a', 1);
|
| 298 |
+
|
| 299 |
+
const options = {
|
| 300 |
+
method: 'POST',
|
| 301 |
+
body: form,
|
| 302 |
+
headers: form.getHeaders()
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
fetch('https://httpbin.org/post', options)
|
| 306 |
+
.then(res => res.json())
|
| 307 |
+
.then(json => console.log(json));
|
| 308 |
+
```
|
| 309 |
+
|
| 310 |
+
#### Request cancellation with AbortSignal
|
| 311 |
+
|
| 312 |
+
> NOTE: You may cancel streamed requests only on Node >= v8.0.0
|
| 313 |
+
|
| 314 |
+
You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller).
|
| 315 |
+
|
| 316 |
+
An example of timing out a request after 150ms could be achieved as the following:
|
| 317 |
+
|
| 318 |
+
```js
|
| 319 |
+
import AbortController from 'abort-controller';
|
| 320 |
+
|
| 321 |
+
const controller = new AbortController();
|
| 322 |
+
const timeout = setTimeout(
|
| 323 |
+
() => { controller.abort(); },
|
| 324 |
+
150,
|
| 325 |
+
);
|
| 326 |
+
|
| 327 |
+
fetch(url, { signal: controller.signal })
|
| 328 |
+
.then(res => res.json())
|
| 329 |
+
.then(
|
| 330 |
+
data => {
|
| 331 |
+
useData(data)
|
| 332 |
+
},
|
| 333 |
+
err => {
|
| 334 |
+
if (err.name === 'AbortError') {
|
| 335 |
+
// request was aborted
|
| 336 |
+
}
|
| 337 |
+
},
|
| 338 |
+
)
|
| 339 |
+
.finally(() => {
|
| 340 |
+
clearTimeout(timeout);
|
| 341 |
+
});
|
| 342 |
+
```
|
| 343 |
+
|
| 344 |
+
See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples.
|
| 345 |
+
|
| 346 |
+
|
| 347 |
+
## API
|
| 348 |
+
|
| 349 |
+
### fetch(url[, options])
|
| 350 |
+
|
| 351 |
+
- `url` A string representing the URL for fetching
|
| 352 |
+
- `options` [Options](#fetch-options) for the HTTP(S) request
|
| 353 |
+
- Returns: <code>Promise<[Response](#class-response)></code>
|
| 354 |
+
|
| 355 |
+
Perform an HTTP(S) fetch.
|
| 356 |
+
|
| 357 |
+
`url` should be an absolute url, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`.
|
| 358 |
+
|
| 359 |
+
<a id="fetch-options"></a>
|
| 360 |
+
### Options
|
| 361 |
+
|
| 362 |
+
The default values are shown after each option key.
|
| 363 |
+
|
| 364 |
+
```js
|
| 365 |
+
{
|
| 366 |
+
// These properties are part of the Fetch Standard
|
| 367 |
+
method: 'GET',
|
| 368 |
+
headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below)
|
| 369 |
+
body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
|
| 370 |
+
redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
|
| 371 |
+
signal: null, // pass an instance of AbortSignal to optionally abort requests
|
| 372 |
+
|
| 373 |
+
// The following properties are node-fetch extensions
|
| 374 |
+
follow: 20, // maximum redirect count. 0 to not follow redirect
|
| 375 |
+
timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
|
| 376 |
+
compress: true, // support gzip/deflate content encoding. false to disable
|
| 377 |
+
size: 0, // maximum response body size in bytes. 0 to disable
|
| 378 |
+
agent: null // http(s).Agent instance or function that returns an instance (see below)
|
| 379 |
+
}
|
| 380 |
+
```
|
| 381 |
+
|
| 382 |
+
##### Default Headers
|
| 383 |
+
|
| 384 |
+
If no values are set, the following request headers will be sent automatically:
|
| 385 |
+
|
| 386 |
+
Header | Value
|
| 387 |
+
------------------- | --------------------------------------------------------
|
| 388 |
+
`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_
|
| 389 |
+
`Accept` | `*/*`
|
| 390 |
+
`Connection` | `close` _(when no `options.agent` is present)_
|
| 391 |
+
`Content-Length` | _(automatically calculated, if possible)_
|
| 392 |
+
`Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_
|
| 393 |
+
`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)`
|
| 394 |
+
|
| 395 |
+
Note: when `body` is a `Stream`, `Content-Length` is not set automatically.
|
| 396 |
+
|
| 397 |
+
##### Custom Agent
|
| 398 |
+
|
| 399 |
+
The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following:
|
| 400 |
+
|
| 401 |
+
- Support self-signed certificate
|
| 402 |
+
- Use only IPv4 or IPv6
|
| 403 |
+
- Custom DNS Lookup
|
| 404 |
+
|
| 405 |
+
See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information.
|
| 406 |
+
|
| 407 |
+
In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol.
|
| 408 |
+
|
| 409 |
+
```js
|
| 410 |
+
const httpAgent = new http.Agent({
|
| 411 |
+
keepAlive: true
|
| 412 |
+
});
|
| 413 |
+
const httpsAgent = new https.Agent({
|
| 414 |
+
keepAlive: true
|
| 415 |
+
});
|
| 416 |
+
|
| 417 |
+
const options = {
|
| 418 |
+
agent: function (_parsedURL) {
|
| 419 |
+
if (_parsedURL.protocol == 'http:') {
|
| 420 |
+
return httpAgent;
|
| 421 |
+
} else {
|
| 422 |
+
return httpsAgent;
|
| 423 |
+
}
|
| 424 |
+
}
|
| 425 |
+
}
|
| 426 |
+
```
|
| 427 |
+
|
| 428 |
+
<a id="class-request"></a>
|
| 429 |
+
### Class: Request
|
| 430 |
+
|
| 431 |
+
An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface.
|
| 432 |
+
|
| 433 |
+
Due to the nature of Node.js, the following properties are not implemented at this moment:
|
| 434 |
+
|
| 435 |
+
- `type`
|
| 436 |
+
- `destination`
|
| 437 |
+
- `referrer`
|
| 438 |
+
- `referrerPolicy`
|
| 439 |
+
- `mode`
|
| 440 |
+
- `credentials`
|
| 441 |
+
- `cache`
|
| 442 |
+
- `integrity`
|
| 443 |
+
- `keepalive`
|
| 444 |
+
|
| 445 |
+
The following node-fetch extension properties are provided:
|
| 446 |
+
|
| 447 |
+
- `follow`
|
| 448 |
+
- `compress`
|
| 449 |
+
- `counter`
|
| 450 |
+
- `agent`
|
| 451 |
+
|
| 452 |
+
See [options](#fetch-options) for exact meaning of these extensions.
|
| 453 |
+
|
| 454 |
+
#### new Request(input[, options])
|
| 455 |
+
|
| 456 |
+
<small>*(spec-compliant)*</small>
|
| 457 |
+
|
| 458 |
+
- `input` A string representing a URL, or another `Request` (which will be cloned)
|
| 459 |
+
- `options` [Options][#fetch-options] for the HTTP(S) request
|
| 460 |
+
|
| 461 |
+
Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request).
|
| 462 |
+
|
| 463 |
+
In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object.
|
| 464 |
+
|
| 465 |
+
<a id="class-response"></a>
|
| 466 |
+
### Class: Response
|
| 467 |
+
|
| 468 |
+
An HTTP(S) response. This class implements the [Body](#iface-body) interface.
|
| 469 |
+
|
| 470 |
+
The following properties are not implemented in node-fetch at this moment:
|
| 471 |
+
|
| 472 |
+
- `Response.error()`
|
| 473 |
+
- `Response.redirect()`
|
| 474 |
+
- `type`
|
| 475 |
+
- `trailer`
|
| 476 |
+
|
| 477 |
+
#### new Response([body[, options]])
|
| 478 |
+
|
| 479 |
+
<small>*(spec-compliant)*</small>
|
| 480 |
+
|
| 481 |
+
- `body` A `String` or [`Readable` stream][node-readable]
|
| 482 |
+
- `options` A [`ResponseInit`][response-init] options dictionary
|
| 483 |
+
|
| 484 |
+
Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
|
| 485 |
+
|
| 486 |
+
Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly.
|
| 487 |
+
|
| 488 |
+
#### response.ok
|
| 489 |
+
|
| 490 |
+
<small>*(spec-compliant)*</small>
|
| 491 |
+
|
| 492 |
+
Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300.
|
| 493 |
+
|
| 494 |
+
#### response.redirected
|
| 495 |
+
|
| 496 |
+
<small>*(spec-compliant)*</small>
|
| 497 |
+
|
| 498 |
+
Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0.
|
| 499 |
+
|
| 500 |
+
<a id="class-headers"></a>
|
| 501 |
+
### Class: Headers
|
| 502 |
+
|
| 503 |
+
This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented.
|
| 504 |
+
|
| 505 |
+
#### new Headers([init])
|
| 506 |
+
|
| 507 |
+
<small>*(spec-compliant)*</small>
|
| 508 |
+
|
| 509 |
+
- `init` Optional argument to pre-fill the `Headers` object
|
| 510 |
+
|
| 511 |
+
Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object.
|
| 512 |
+
|
| 513 |
+
```js
|
| 514 |
+
// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
|
| 515 |
+
|
| 516 |
+
const meta = {
|
| 517 |
+
'Content-Type': 'text/xml',
|
| 518 |
+
'Breaking-Bad': '<3'
|
| 519 |
+
};
|
| 520 |
+
const headers = new Headers(meta);
|
| 521 |
+
|
| 522 |
+
// The above is equivalent to
|
| 523 |
+
const meta = [
|
| 524 |
+
[ 'Content-Type', 'text/xml' ],
|
| 525 |
+
[ 'Breaking-Bad', '<3' ]
|
| 526 |
+
];
|
| 527 |
+
const headers = new Headers(meta);
|
| 528 |
+
|
| 529 |
+
// You can in fact use any iterable objects, like a Map or even another Headers
|
| 530 |
+
const meta = new Map();
|
| 531 |
+
meta.set('Content-Type', 'text/xml');
|
| 532 |
+
meta.set('Breaking-Bad', '<3');
|
| 533 |
+
const headers = new Headers(meta);
|
| 534 |
+
const copyOfHeaders = new Headers(headers);
|
| 535 |
+
```
|
| 536 |
+
|
| 537 |
+
<a id="iface-body"></a>
|
| 538 |
+
### Interface: Body
|
| 539 |
+
|
| 540 |
+
`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes.
|
| 541 |
+
|
| 542 |
+
The following methods are not yet implemented in node-fetch at this moment:
|
| 543 |
+
|
| 544 |
+
- `formData()`
|
| 545 |
+
|
| 546 |
+
#### body.body
|
| 547 |
+
|
| 548 |
+
<small>*(deviation from spec)*</small>
|
| 549 |
+
|
| 550 |
+
* Node.js [`Readable` stream][node-readable]
|
| 551 |
+
|
| 552 |
+
Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable].
|
| 553 |
+
|
| 554 |
+
#### body.bodyUsed
|
| 555 |
+
|
| 556 |
+
<small>*(spec-compliant)*</small>
|
| 557 |
+
|
| 558 |
+
* `Boolean`
|
| 559 |
+
|
| 560 |
+
A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again.
|
| 561 |
+
|
| 562 |
+
#### body.arrayBuffer()
|
| 563 |
+
#### body.blob()
|
| 564 |
+
#### body.json()
|
| 565 |
+
#### body.text()
|
| 566 |
+
|
| 567 |
+
<small>*(spec-compliant)*</small>
|
| 568 |
+
|
| 569 |
+
* Returns: <code>Promise</code>
|
| 570 |
+
|
| 571 |
+
Consume the body and return a promise that will resolve to one of these formats.
|
| 572 |
+
|
| 573 |
+
#### body.buffer()
|
| 574 |
+
|
| 575 |
+
<small>*(node-fetch extension)*</small>
|
| 576 |
+
|
| 577 |
+
* Returns: <code>Promise<Buffer></code>
|
| 578 |
+
|
| 579 |
+
Consume the body and return a promise that will resolve to a Buffer.
|
| 580 |
+
|
| 581 |
+
#### body.textConverted()
|
| 582 |
+
|
| 583 |
+
<small>*(node-fetch extension)*</small>
|
| 584 |
+
|
| 585 |
+
* Returns: <code>Promise<String></code>
|
| 586 |
+
|
| 587 |
+
Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8 if possible.
|
| 588 |
+
|
| 589 |
+
(This API requires an optional dependency of the npm package [encoding](https://www.npmjs.com/package/encoding), which you need to install manually. `webpack` users may see [a warning message](https://github.com/bitinn/node-fetch/issues/412#issuecomment-379007792) due to this optional dependency.)
|
| 590 |
+
|
| 591 |
+
<a id="class-fetcherror"></a>
|
| 592 |
+
### Class: FetchError
|
| 593 |
+
|
| 594 |
+
<small>*(node-fetch extension)*</small>
|
| 595 |
+
|
| 596 |
+
An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info.
|
| 597 |
+
|
| 598 |
+
<a id="class-aborterror"></a>
|
| 599 |
+
### Class: AbortError
|
| 600 |
+
|
| 601 |
+
<small>*(node-fetch extension)*</small>
|
| 602 |
+
|
| 603 |
+
An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info.
|
| 604 |
+
|
| 605 |
+
## Acknowledgement
|
| 606 |
+
|
| 607 |
+
Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.
|
| 608 |
+
|
| 609 |
+
`node-fetch` v1 was maintained by [@bitinn](https://github.com/bitinn); v2 was maintained by [@TimothyGu](https://github.com/timothygu), [@bitinn](https://github.com/bitinn) and [@jimmywarting](https://github.com/jimmywarting); v2 readme is written by [@jkantr](https://github.com/jkantr).
|
| 610 |
+
|
| 611 |
+
## License
|
| 612 |
+
|
| 613 |
+
MIT
|
| 614 |
+
|
| 615 |
+
[npm-image]: https://flat.badgen.net/npm/v/node-fetch
|
| 616 |
+
[npm-url]: https://www.npmjs.com/package/node-fetch
|
| 617 |
+
[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch
|
| 618 |
+
[travis-url]: https://travis-ci.org/bitinn/node-fetch
|
| 619 |
+
[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master
|
| 620 |
+
[codecov-url]: https://codecov.io/gh/bitinn/node-fetch
|
| 621 |
+
[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch
|
| 622 |
+
[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch
|
| 623 |
+
[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square
|
| 624 |
+
[discord-url]: https://discord.gg/Zxbndcm
|
| 625 |
+
[opencollective-image]: https://opencollective.com/node-fetch/backers.svg
|
| 626 |
+
[opencollective-url]: https://opencollective.com/node-fetch
|
| 627 |
+
[whatwg-fetch]: https://fetch.spec.whatwg.org/
|
| 628 |
+
[response-init]: https://fetch.spec.whatwg.org/#responseinit
|
| 629 |
+
[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
|
| 630 |
+
[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
| 631 |
+
[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md
|
| 632 |
+
[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md
|
| 633 |
+
[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md
|
node_modules/node-fetch/browser.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
// ref: https://github.com/tc39/proposal-global
|
| 4 |
+
var getGlobal = function () {
|
| 5 |
+
// the only reliable means to get the global object is
|
| 6 |
+
// `Function('return this')()`
|
| 7 |
+
// However, this causes CSP violations in Chrome apps.
|
| 8 |
+
if (typeof self !== 'undefined') { return self; }
|
| 9 |
+
if (typeof window !== 'undefined') { return window; }
|
| 10 |
+
if (typeof global !== 'undefined') { return global; }
|
| 11 |
+
throw new Error('unable to locate global object');
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
var globalObject = getGlobal();
|
| 15 |
+
|
| 16 |
+
module.exports = exports = globalObject.fetch;
|
| 17 |
+
|
| 18 |
+
// Needed for TypeScript and Webpack.
|
| 19 |
+
if (globalObject.fetch) {
|
| 20 |
+
exports.default = globalObject.fetch.bind(globalObject);
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
exports.Headers = globalObject.Headers;
|
| 24 |
+
exports.Request = globalObject.Request;
|
| 25 |
+
exports.Response = globalObject.Response;
|
node_modules/node-fetch/lib/index.es.js
ADDED
|
@@ -0,0 +1,1778 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
process.emitWarning("The .es.js file is deprecated. Use .mjs instead.");
|
| 2 |
+
|
| 3 |
+
import Stream from 'stream';
|
| 4 |
+
import http from 'http';
|
| 5 |
+
import Url from 'url';
|
| 6 |
+
import whatwgUrl from 'whatwg-url';
|
| 7 |
+
import https from 'https';
|
| 8 |
+
import zlib from 'zlib';
|
| 9 |
+
|
| 10 |
+
// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
|
| 11 |
+
|
| 12 |
+
// fix for "Readable" isn't a named export issue
|
| 13 |
+
const Readable = Stream.Readable;
|
| 14 |
+
|
| 15 |
+
const BUFFER = Symbol('buffer');
|
| 16 |
+
const TYPE = Symbol('type');
|
| 17 |
+
|
| 18 |
+
class Blob {
|
| 19 |
+
constructor() {
|
| 20 |
+
this[TYPE] = '';
|
| 21 |
+
|
| 22 |
+
const blobParts = arguments[0];
|
| 23 |
+
const options = arguments[1];
|
| 24 |
+
|
| 25 |
+
const buffers = [];
|
| 26 |
+
let size = 0;
|
| 27 |
+
|
| 28 |
+
if (blobParts) {
|
| 29 |
+
const a = blobParts;
|
| 30 |
+
const length = Number(a.length);
|
| 31 |
+
for (let i = 0; i < length; i++) {
|
| 32 |
+
const element = a[i];
|
| 33 |
+
let buffer;
|
| 34 |
+
if (element instanceof Buffer) {
|
| 35 |
+
buffer = element;
|
| 36 |
+
} else if (ArrayBuffer.isView(element)) {
|
| 37 |
+
buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
|
| 38 |
+
} else if (element instanceof ArrayBuffer) {
|
| 39 |
+
buffer = Buffer.from(element);
|
| 40 |
+
} else if (element instanceof Blob) {
|
| 41 |
+
buffer = element[BUFFER];
|
| 42 |
+
} else {
|
| 43 |
+
buffer = Buffer.from(typeof element === 'string' ? element : String(element));
|
| 44 |
+
}
|
| 45 |
+
size += buffer.length;
|
| 46 |
+
buffers.push(buffer);
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
this[BUFFER] = Buffer.concat(buffers);
|
| 51 |
+
|
| 52 |
+
let type = options && options.type !== undefined && String(options.type).toLowerCase();
|
| 53 |
+
if (type && !/[^\u0020-\u007E]/.test(type)) {
|
| 54 |
+
this[TYPE] = type;
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
get size() {
|
| 58 |
+
return this[BUFFER].length;
|
| 59 |
+
}
|
| 60 |
+
get type() {
|
| 61 |
+
return this[TYPE];
|
| 62 |
+
}
|
| 63 |
+
text() {
|
| 64 |
+
return Promise.resolve(this[BUFFER].toString());
|
| 65 |
+
}
|
| 66 |
+
arrayBuffer() {
|
| 67 |
+
const buf = this[BUFFER];
|
| 68 |
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 69 |
+
return Promise.resolve(ab);
|
| 70 |
+
}
|
| 71 |
+
stream() {
|
| 72 |
+
const readable = new Readable();
|
| 73 |
+
readable._read = function () {};
|
| 74 |
+
readable.push(this[BUFFER]);
|
| 75 |
+
readable.push(null);
|
| 76 |
+
return readable;
|
| 77 |
+
}
|
| 78 |
+
toString() {
|
| 79 |
+
return '[object Blob]';
|
| 80 |
+
}
|
| 81 |
+
slice() {
|
| 82 |
+
const size = this.size;
|
| 83 |
+
|
| 84 |
+
const start = arguments[0];
|
| 85 |
+
const end = arguments[1];
|
| 86 |
+
let relativeStart, relativeEnd;
|
| 87 |
+
if (start === undefined) {
|
| 88 |
+
relativeStart = 0;
|
| 89 |
+
} else if (start < 0) {
|
| 90 |
+
relativeStart = Math.max(size + start, 0);
|
| 91 |
+
} else {
|
| 92 |
+
relativeStart = Math.min(start, size);
|
| 93 |
+
}
|
| 94 |
+
if (end === undefined) {
|
| 95 |
+
relativeEnd = size;
|
| 96 |
+
} else if (end < 0) {
|
| 97 |
+
relativeEnd = Math.max(size + end, 0);
|
| 98 |
+
} else {
|
| 99 |
+
relativeEnd = Math.min(end, size);
|
| 100 |
+
}
|
| 101 |
+
const span = Math.max(relativeEnd - relativeStart, 0);
|
| 102 |
+
|
| 103 |
+
const buffer = this[BUFFER];
|
| 104 |
+
const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
|
| 105 |
+
const blob = new Blob([], { type: arguments[2] });
|
| 106 |
+
blob[BUFFER] = slicedBuffer;
|
| 107 |
+
return blob;
|
| 108 |
+
}
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
Object.defineProperties(Blob.prototype, {
|
| 112 |
+
size: { enumerable: true },
|
| 113 |
+
type: { enumerable: true },
|
| 114 |
+
slice: { enumerable: true }
|
| 115 |
+
});
|
| 116 |
+
|
| 117 |
+
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
|
| 118 |
+
value: 'Blob',
|
| 119 |
+
writable: false,
|
| 120 |
+
enumerable: false,
|
| 121 |
+
configurable: true
|
| 122 |
+
});
|
| 123 |
+
|
| 124 |
+
/**
|
| 125 |
+
* fetch-error.js
|
| 126 |
+
*
|
| 127 |
+
* FetchError interface for operational errors
|
| 128 |
+
*/
|
| 129 |
+
|
| 130 |
+
/**
|
| 131 |
+
* Create FetchError instance
|
| 132 |
+
*
|
| 133 |
+
* @param String message Error message for human
|
| 134 |
+
* @param String type Error type for machine
|
| 135 |
+
* @param String systemError For Node.js system error
|
| 136 |
+
* @return FetchError
|
| 137 |
+
*/
|
| 138 |
+
function FetchError(message, type, systemError) {
|
| 139 |
+
Error.call(this, message);
|
| 140 |
+
|
| 141 |
+
this.message = message;
|
| 142 |
+
this.type = type;
|
| 143 |
+
|
| 144 |
+
// when err.type is `system`, err.code contains system error code
|
| 145 |
+
if (systemError) {
|
| 146 |
+
this.code = this.errno = systemError.code;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
// hide custom error implementation details from end-users
|
| 150 |
+
Error.captureStackTrace(this, this.constructor);
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
FetchError.prototype = Object.create(Error.prototype);
|
| 154 |
+
FetchError.prototype.constructor = FetchError;
|
| 155 |
+
FetchError.prototype.name = 'FetchError';
|
| 156 |
+
|
| 157 |
+
let convert;
|
| 158 |
+
try {
|
| 159 |
+
convert = require('encoding').convert;
|
| 160 |
+
} catch (e) {}
|
| 161 |
+
|
| 162 |
+
const INTERNALS = Symbol('Body internals');
|
| 163 |
+
|
| 164 |
+
// fix an issue where "PassThrough" isn't a named export for node <10
|
| 165 |
+
const PassThrough = Stream.PassThrough;
|
| 166 |
+
|
| 167 |
+
/**
|
| 168 |
+
* Body mixin
|
| 169 |
+
*
|
| 170 |
+
* Ref: https://fetch.spec.whatwg.org/#body
|
| 171 |
+
*
|
| 172 |
+
* @param Stream body Readable stream
|
| 173 |
+
* @param Object opts Response options
|
| 174 |
+
* @return Void
|
| 175 |
+
*/
|
| 176 |
+
function Body(body) {
|
| 177 |
+
var _this = this;
|
| 178 |
+
|
| 179 |
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
| 180 |
+
_ref$size = _ref.size;
|
| 181 |
+
|
| 182 |
+
let size = _ref$size === undefined ? 0 : _ref$size;
|
| 183 |
+
var _ref$timeout = _ref.timeout;
|
| 184 |
+
let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
|
| 185 |
+
|
| 186 |
+
if (body == null) {
|
| 187 |
+
// body is undefined or null
|
| 188 |
+
body = null;
|
| 189 |
+
} else if (isURLSearchParams(body)) {
|
| 190 |
+
// body is a URLSearchParams
|
| 191 |
+
body = Buffer.from(body.toString());
|
| 192 |
+
} else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 193 |
+
// body is ArrayBuffer
|
| 194 |
+
body = Buffer.from(body);
|
| 195 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 196 |
+
// body is ArrayBufferView
|
| 197 |
+
body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
| 198 |
+
} else if (body instanceof Stream) ; else {
|
| 199 |
+
// none of the above
|
| 200 |
+
// coerce to string then buffer
|
| 201 |
+
body = Buffer.from(String(body));
|
| 202 |
+
}
|
| 203 |
+
this[INTERNALS] = {
|
| 204 |
+
body,
|
| 205 |
+
disturbed: false,
|
| 206 |
+
error: null
|
| 207 |
+
};
|
| 208 |
+
this.size = size;
|
| 209 |
+
this.timeout = timeout;
|
| 210 |
+
|
| 211 |
+
if (body instanceof Stream) {
|
| 212 |
+
body.on('error', function (err) {
|
| 213 |
+
const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
|
| 214 |
+
_this[INTERNALS].error = error;
|
| 215 |
+
});
|
| 216 |
+
}
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
Body.prototype = {
|
| 220 |
+
get body() {
|
| 221 |
+
return this[INTERNALS].body;
|
| 222 |
+
},
|
| 223 |
+
|
| 224 |
+
get bodyUsed() {
|
| 225 |
+
return this[INTERNALS].disturbed;
|
| 226 |
+
},
|
| 227 |
+
|
| 228 |
+
/**
|
| 229 |
+
* Decode response as ArrayBuffer
|
| 230 |
+
*
|
| 231 |
+
* @return Promise
|
| 232 |
+
*/
|
| 233 |
+
arrayBuffer() {
|
| 234 |
+
return consumeBody.call(this).then(function (buf) {
|
| 235 |
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 236 |
+
});
|
| 237 |
+
},
|
| 238 |
+
|
| 239 |
+
/**
|
| 240 |
+
* Return raw response as Blob
|
| 241 |
+
*
|
| 242 |
+
* @return Promise
|
| 243 |
+
*/
|
| 244 |
+
blob() {
|
| 245 |
+
let ct = this.headers && this.headers.get('content-type') || '';
|
| 246 |
+
return consumeBody.call(this).then(function (buf) {
|
| 247 |
+
return Object.assign(
|
| 248 |
+
// Prevent copying
|
| 249 |
+
new Blob([], {
|
| 250 |
+
type: ct.toLowerCase()
|
| 251 |
+
}), {
|
| 252 |
+
[BUFFER]: buf
|
| 253 |
+
});
|
| 254 |
+
});
|
| 255 |
+
},
|
| 256 |
+
|
| 257 |
+
/**
|
| 258 |
+
* Decode response as json
|
| 259 |
+
*
|
| 260 |
+
* @return Promise
|
| 261 |
+
*/
|
| 262 |
+
json() {
|
| 263 |
+
var _this2 = this;
|
| 264 |
+
|
| 265 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 266 |
+
try {
|
| 267 |
+
return JSON.parse(buffer.toString());
|
| 268 |
+
} catch (err) {
|
| 269 |
+
return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
|
| 270 |
+
}
|
| 271 |
+
});
|
| 272 |
+
},
|
| 273 |
+
|
| 274 |
+
/**
|
| 275 |
+
* Decode response as text
|
| 276 |
+
*
|
| 277 |
+
* @return Promise
|
| 278 |
+
*/
|
| 279 |
+
text() {
|
| 280 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 281 |
+
return buffer.toString();
|
| 282 |
+
});
|
| 283 |
+
},
|
| 284 |
+
|
| 285 |
+
/**
|
| 286 |
+
* Decode response as buffer (non-spec api)
|
| 287 |
+
*
|
| 288 |
+
* @return Promise
|
| 289 |
+
*/
|
| 290 |
+
buffer() {
|
| 291 |
+
return consumeBody.call(this);
|
| 292 |
+
},
|
| 293 |
+
|
| 294 |
+
/**
|
| 295 |
+
* Decode response as text, while automatically detecting the encoding and
|
| 296 |
+
* trying to decode to UTF-8 (non-spec api)
|
| 297 |
+
*
|
| 298 |
+
* @return Promise
|
| 299 |
+
*/
|
| 300 |
+
textConverted() {
|
| 301 |
+
var _this3 = this;
|
| 302 |
+
|
| 303 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 304 |
+
return convertBody(buffer, _this3.headers);
|
| 305 |
+
});
|
| 306 |
+
}
|
| 307 |
+
};
|
| 308 |
+
|
| 309 |
+
// In browsers, all properties are enumerable.
|
| 310 |
+
Object.defineProperties(Body.prototype, {
|
| 311 |
+
body: { enumerable: true },
|
| 312 |
+
bodyUsed: { enumerable: true },
|
| 313 |
+
arrayBuffer: { enumerable: true },
|
| 314 |
+
blob: { enumerable: true },
|
| 315 |
+
json: { enumerable: true },
|
| 316 |
+
text: { enumerable: true }
|
| 317 |
+
});
|
| 318 |
+
|
| 319 |
+
Body.mixIn = function (proto) {
|
| 320 |
+
for (const name of Object.getOwnPropertyNames(Body.prototype)) {
|
| 321 |
+
// istanbul ignore else: future proof
|
| 322 |
+
if (!(name in proto)) {
|
| 323 |
+
const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
|
| 324 |
+
Object.defineProperty(proto, name, desc);
|
| 325 |
+
}
|
| 326 |
+
}
|
| 327 |
+
};
|
| 328 |
+
|
| 329 |
+
/**
|
| 330 |
+
* Consume and convert an entire Body to a Buffer.
|
| 331 |
+
*
|
| 332 |
+
* Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
|
| 333 |
+
*
|
| 334 |
+
* @return Promise
|
| 335 |
+
*/
|
| 336 |
+
function consumeBody() {
|
| 337 |
+
var _this4 = this;
|
| 338 |
+
|
| 339 |
+
if (this[INTERNALS].disturbed) {
|
| 340 |
+
return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
this[INTERNALS].disturbed = true;
|
| 344 |
+
|
| 345 |
+
if (this[INTERNALS].error) {
|
| 346 |
+
return Body.Promise.reject(this[INTERNALS].error);
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
let body = this.body;
|
| 350 |
+
|
| 351 |
+
// body is null
|
| 352 |
+
if (body === null) {
|
| 353 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
// body is blob
|
| 357 |
+
if (isBlob(body)) {
|
| 358 |
+
body = body.stream();
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
// body is buffer
|
| 362 |
+
if (Buffer.isBuffer(body)) {
|
| 363 |
+
return Body.Promise.resolve(body);
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
// istanbul ignore if: should never happen
|
| 367 |
+
if (!(body instanceof Stream)) {
|
| 368 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
// body is stream
|
| 372 |
+
// get ready to actually consume the body
|
| 373 |
+
let accum = [];
|
| 374 |
+
let accumBytes = 0;
|
| 375 |
+
let abort = false;
|
| 376 |
+
|
| 377 |
+
return new Body.Promise(function (resolve, reject) {
|
| 378 |
+
let resTimeout;
|
| 379 |
+
|
| 380 |
+
// allow timeout on slow response body
|
| 381 |
+
if (_this4.timeout) {
|
| 382 |
+
resTimeout = setTimeout(function () {
|
| 383 |
+
abort = true;
|
| 384 |
+
reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
|
| 385 |
+
}, _this4.timeout);
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
// handle stream errors
|
| 389 |
+
body.on('error', function (err) {
|
| 390 |
+
if (err.name === 'AbortError') {
|
| 391 |
+
// if the request was aborted, reject with this Error
|
| 392 |
+
abort = true;
|
| 393 |
+
reject(err);
|
| 394 |
+
} else {
|
| 395 |
+
// other errors, such as incorrect content-encoding
|
| 396 |
+
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
|
| 397 |
+
}
|
| 398 |
+
});
|
| 399 |
+
|
| 400 |
+
body.on('data', function (chunk) {
|
| 401 |
+
if (abort || chunk === null) {
|
| 402 |
+
return;
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
if (_this4.size && accumBytes + chunk.length > _this4.size) {
|
| 406 |
+
abort = true;
|
| 407 |
+
reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
|
| 408 |
+
return;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
accumBytes += chunk.length;
|
| 412 |
+
accum.push(chunk);
|
| 413 |
+
});
|
| 414 |
+
|
| 415 |
+
body.on('end', function () {
|
| 416 |
+
if (abort) {
|
| 417 |
+
return;
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
clearTimeout(resTimeout);
|
| 421 |
+
|
| 422 |
+
try {
|
| 423 |
+
resolve(Buffer.concat(accum, accumBytes));
|
| 424 |
+
} catch (err) {
|
| 425 |
+
// handle streams that have accumulated too much data (issue #414)
|
| 426 |
+
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
|
| 427 |
+
}
|
| 428 |
+
});
|
| 429 |
+
});
|
| 430 |
+
}
|
| 431 |
+
|
| 432 |
+
/**
|
| 433 |
+
* Detect buffer encoding and convert to target encoding
|
| 434 |
+
* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
|
| 435 |
+
*
|
| 436 |
+
* @param Buffer buffer Incoming buffer
|
| 437 |
+
* @param String encoding Target encoding
|
| 438 |
+
* @return String
|
| 439 |
+
*/
|
| 440 |
+
function convertBody(buffer, headers) {
|
| 441 |
+
if (typeof convert !== 'function') {
|
| 442 |
+
throw new Error('The package `encoding` must be installed to use the textConverted() function');
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
const ct = headers.get('content-type');
|
| 446 |
+
let charset = 'utf-8';
|
| 447 |
+
let res, str;
|
| 448 |
+
|
| 449 |
+
// header
|
| 450 |
+
if (ct) {
|
| 451 |
+
res = /charset=([^;]*)/i.exec(ct);
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
// no charset in content type, peek at response body for at most 1024 bytes
|
| 455 |
+
str = buffer.slice(0, 1024).toString();
|
| 456 |
+
|
| 457 |
+
// html5
|
| 458 |
+
if (!res && str) {
|
| 459 |
+
res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
// html4
|
| 463 |
+
if (!res && str) {
|
| 464 |
+
res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
|
| 465 |
+
if (!res) {
|
| 466 |
+
res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
|
| 467 |
+
if (res) {
|
| 468 |
+
res.pop(); // drop last quote
|
| 469 |
+
}
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
if (res) {
|
| 473 |
+
res = /charset=(.*)/i.exec(res.pop());
|
| 474 |
+
}
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
// xml
|
| 478 |
+
if (!res && str) {
|
| 479 |
+
res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
// found charset
|
| 483 |
+
if (res) {
|
| 484 |
+
charset = res.pop();
|
| 485 |
+
|
| 486 |
+
// prevent decode issues when sites use incorrect encoding
|
| 487 |
+
// ref: https://hsivonen.fi/encoding-menu/
|
| 488 |
+
if (charset === 'gb2312' || charset === 'gbk') {
|
| 489 |
+
charset = 'gb18030';
|
| 490 |
+
}
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
// turn raw buffers into a single utf-8 buffer
|
| 494 |
+
return convert(buffer, 'UTF-8', charset).toString();
|
| 495 |
+
}
|
| 496 |
+
|
| 497 |
+
/**
|
| 498 |
+
* Detect a URLSearchParams object
|
| 499 |
+
* ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
|
| 500 |
+
*
|
| 501 |
+
* @param Object obj Object to detect by type or brand
|
| 502 |
+
* @return String
|
| 503 |
+
*/
|
| 504 |
+
function isURLSearchParams(obj) {
|
| 505 |
+
// Duck-typing as a necessary condition.
|
| 506 |
+
if (typeof obj !== 'object' || typeof obj.append !== 'function' || typeof obj.delete !== 'function' || typeof obj.get !== 'function' || typeof obj.getAll !== 'function' || typeof obj.has !== 'function' || typeof obj.set !== 'function') {
|
| 507 |
+
return false;
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
// Brand-checking and more duck-typing as optional condition.
|
| 511 |
+
return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
/**
|
| 515 |
+
* Check if `obj` is a W3C `Blob` object (which `File` inherits from)
|
| 516 |
+
* @param {*} obj
|
| 517 |
+
* @return {boolean}
|
| 518 |
+
*/
|
| 519 |
+
function isBlob(obj) {
|
| 520 |
+
return typeof obj === 'object' && typeof obj.arrayBuffer === 'function' && typeof obj.type === 'string' && typeof obj.stream === 'function' && typeof obj.constructor === 'function' && typeof obj.constructor.name === 'string' && /^(Blob|File)$/.test(obj.constructor.name) && /^(Blob|File)$/.test(obj[Symbol.toStringTag]);
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
/**
|
| 524 |
+
* Clone body given Res/Req instance
|
| 525 |
+
*
|
| 526 |
+
* @param Mixed instance Response or Request instance
|
| 527 |
+
* @return Mixed
|
| 528 |
+
*/
|
| 529 |
+
function clone(instance) {
|
| 530 |
+
let p1, p2;
|
| 531 |
+
let body = instance.body;
|
| 532 |
+
|
| 533 |
+
// don't allow cloning a used body
|
| 534 |
+
if (instance.bodyUsed) {
|
| 535 |
+
throw new Error('cannot clone body after it is used');
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
// check that body is a stream and not form-data object
|
| 539 |
+
// note: we can't clone the form-data object without having it as a dependency
|
| 540 |
+
if (body instanceof Stream && typeof body.getBoundary !== 'function') {
|
| 541 |
+
// tee instance body
|
| 542 |
+
p1 = new PassThrough();
|
| 543 |
+
p2 = new PassThrough();
|
| 544 |
+
body.pipe(p1);
|
| 545 |
+
body.pipe(p2);
|
| 546 |
+
// set instance body to teed body and return the other teed body
|
| 547 |
+
instance[INTERNALS].body = p1;
|
| 548 |
+
body = p2;
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
return body;
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
/**
|
| 555 |
+
* Performs the operation "extract a `Content-Type` value from |object|" as
|
| 556 |
+
* specified in the specification:
|
| 557 |
+
* https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
| 558 |
+
*
|
| 559 |
+
* This function assumes that instance.body is present.
|
| 560 |
+
*
|
| 561 |
+
* @param Mixed instance Any options.body input
|
| 562 |
+
*/
|
| 563 |
+
function extractContentType(body) {
|
| 564 |
+
if (body === null) {
|
| 565 |
+
// body is null
|
| 566 |
+
return null;
|
| 567 |
+
} else if (typeof body === 'string') {
|
| 568 |
+
// body is string
|
| 569 |
+
return 'text/plain;charset=UTF-8';
|
| 570 |
+
} else if (isURLSearchParams(body)) {
|
| 571 |
+
// body is a URLSearchParams
|
| 572 |
+
return 'application/x-www-form-urlencoded;charset=UTF-8';
|
| 573 |
+
} else if (isBlob(body)) {
|
| 574 |
+
// body is blob
|
| 575 |
+
return body.type || null;
|
| 576 |
+
} else if (Buffer.isBuffer(body)) {
|
| 577 |
+
// body is buffer
|
| 578 |
+
return null;
|
| 579 |
+
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 580 |
+
// body is ArrayBuffer
|
| 581 |
+
return null;
|
| 582 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 583 |
+
// body is ArrayBufferView
|
| 584 |
+
return null;
|
| 585 |
+
} else if (typeof body.getBoundary === 'function') {
|
| 586 |
+
// detect form data input from form-data module
|
| 587 |
+
return `multipart/form-data;boundary=${body.getBoundary()}`;
|
| 588 |
+
} else if (body instanceof Stream) {
|
| 589 |
+
// body is stream
|
| 590 |
+
// can't really do much about this
|
| 591 |
+
return null;
|
| 592 |
+
} else {
|
| 593 |
+
// Body constructor defaults other things to string
|
| 594 |
+
return 'text/plain;charset=UTF-8';
|
| 595 |
+
}
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
/**
|
| 599 |
+
* The Fetch Standard treats this as if "total bytes" is a property on the body.
|
| 600 |
+
* For us, we have to explicitly get it with a function.
|
| 601 |
+
*
|
| 602 |
+
* ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
|
| 603 |
+
*
|
| 604 |
+
* @param Body instance Instance of Body
|
| 605 |
+
* @return Number? Number of bytes, or null if not possible
|
| 606 |
+
*/
|
| 607 |
+
function getTotalBytes(instance) {
|
| 608 |
+
const body = instance.body;
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
if (body === null) {
|
| 612 |
+
// body is null
|
| 613 |
+
return 0;
|
| 614 |
+
} else if (isBlob(body)) {
|
| 615 |
+
return body.size;
|
| 616 |
+
} else if (Buffer.isBuffer(body)) {
|
| 617 |
+
// body is buffer
|
| 618 |
+
return body.length;
|
| 619 |
+
} else if (body && typeof body.getLengthSync === 'function') {
|
| 620 |
+
// detect form data input from form-data module
|
| 621 |
+
if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
|
| 622 |
+
body.hasKnownLength && body.hasKnownLength()) {
|
| 623 |
+
// 2.x
|
| 624 |
+
return body.getLengthSync();
|
| 625 |
+
}
|
| 626 |
+
return null;
|
| 627 |
+
} else {
|
| 628 |
+
// body is stream
|
| 629 |
+
return null;
|
| 630 |
+
}
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
/**
|
| 634 |
+
* Write a Body to a Node.js WritableStream (e.g. http.Request) object.
|
| 635 |
+
*
|
| 636 |
+
* @param Body instance Instance of Body
|
| 637 |
+
* @return Void
|
| 638 |
+
*/
|
| 639 |
+
function writeToStream(dest, instance) {
|
| 640 |
+
const body = instance.body;
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
if (body === null) {
|
| 644 |
+
// body is null
|
| 645 |
+
dest.end();
|
| 646 |
+
} else if (isBlob(body)) {
|
| 647 |
+
body.stream().pipe(dest);
|
| 648 |
+
} else if (Buffer.isBuffer(body)) {
|
| 649 |
+
// body is buffer
|
| 650 |
+
dest.write(body);
|
| 651 |
+
dest.end();
|
| 652 |
+
} else {
|
| 653 |
+
// body is stream
|
| 654 |
+
body.pipe(dest);
|
| 655 |
+
}
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
// expose Promise
|
| 659 |
+
Body.Promise = global.Promise;
|
| 660 |
+
|
| 661 |
+
/**
|
| 662 |
+
* headers.js
|
| 663 |
+
*
|
| 664 |
+
* Headers class offers convenient helpers
|
| 665 |
+
*/
|
| 666 |
+
|
| 667 |
+
const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
|
| 668 |
+
const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
|
| 669 |
+
|
| 670 |
+
function validateName(name) {
|
| 671 |
+
name = `${name}`;
|
| 672 |
+
if (invalidTokenRegex.test(name) || name === '') {
|
| 673 |
+
throw new TypeError(`${name} is not a legal HTTP header name`);
|
| 674 |
+
}
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
function validateValue(value) {
|
| 678 |
+
value = `${value}`;
|
| 679 |
+
if (invalidHeaderCharRegex.test(value)) {
|
| 680 |
+
throw new TypeError(`${value} is not a legal HTTP header value`);
|
| 681 |
+
}
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
/**
|
| 685 |
+
* Find the key in the map object given a header name.
|
| 686 |
+
*
|
| 687 |
+
* Returns undefined if not found.
|
| 688 |
+
*
|
| 689 |
+
* @param String name Header name
|
| 690 |
+
* @return String|Undefined
|
| 691 |
+
*/
|
| 692 |
+
function find(map, name) {
|
| 693 |
+
name = name.toLowerCase();
|
| 694 |
+
for (const key in map) {
|
| 695 |
+
if (key.toLowerCase() === name) {
|
| 696 |
+
return key;
|
| 697 |
+
}
|
| 698 |
+
}
|
| 699 |
+
return undefined;
|
| 700 |
+
}
|
| 701 |
+
|
| 702 |
+
const MAP = Symbol('map');
|
| 703 |
+
class Headers {
|
| 704 |
+
/**
|
| 705 |
+
* Headers class
|
| 706 |
+
*
|
| 707 |
+
* @param Object headers Response headers
|
| 708 |
+
* @return Void
|
| 709 |
+
*/
|
| 710 |
+
constructor() {
|
| 711 |
+
let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
|
| 712 |
+
|
| 713 |
+
this[MAP] = Object.create(null);
|
| 714 |
+
|
| 715 |
+
if (init instanceof Headers) {
|
| 716 |
+
const rawHeaders = init.raw();
|
| 717 |
+
const headerNames = Object.keys(rawHeaders);
|
| 718 |
+
|
| 719 |
+
for (const headerName of headerNames) {
|
| 720 |
+
for (const value of rawHeaders[headerName]) {
|
| 721 |
+
this.append(headerName, value);
|
| 722 |
+
}
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
return;
|
| 726 |
+
}
|
| 727 |
+
|
| 728 |
+
// We don't worry about converting prop to ByteString here as append()
|
| 729 |
+
// will handle it.
|
| 730 |
+
if (init == null) ; else if (typeof init === 'object') {
|
| 731 |
+
const method = init[Symbol.iterator];
|
| 732 |
+
if (method != null) {
|
| 733 |
+
if (typeof method !== 'function') {
|
| 734 |
+
throw new TypeError('Header pairs must be iterable');
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
// sequence<sequence<ByteString>>
|
| 738 |
+
// Note: per spec we have to first exhaust the lists then process them
|
| 739 |
+
const pairs = [];
|
| 740 |
+
for (const pair of init) {
|
| 741 |
+
if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
|
| 742 |
+
throw new TypeError('Each header pair must be iterable');
|
| 743 |
+
}
|
| 744 |
+
pairs.push(Array.from(pair));
|
| 745 |
+
}
|
| 746 |
+
|
| 747 |
+
for (const pair of pairs) {
|
| 748 |
+
if (pair.length !== 2) {
|
| 749 |
+
throw new TypeError('Each header pair must be a name/value tuple');
|
| 750 |
+
}
|
| 751 |
+
this.append(pair[0], pair[1]);
|
| 752 |
+
}
|
| 753 |
+
} else {
|
| 754 |
+
// record<ByteString, ByteString>
|
| 755 |
+
for (const key of Object.keys(init)) {
|
| 756 |
+
const value = init[key];
|
| 757 |
+
this.append(key, value);
|
| 758 |
+
}
|
| 759 |
+
}
|
| 760 |
+
} else {
|
| 761 |
+
throw new TypeError('Provided initializer must be an object');
|
| 762 |
+
}
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
/**
|
| 766 |
+
* Return combined header value given name
|
| 767 |
+
*
|
| 768 |
+
* @param String name Header name
|
| 769 |
+
* @return Mixed
|
| 770 |
+
*/
|
| 771 |
+
get(name) {
|
| 772 |
+
name = `${name}`;
|
| 773 |
+
validateName(name);
|
| 774 |
+
const key = find(this[MAP], name);
|
| 775 |
+
if (key === undefined) {
|
| 776 |
+
return null;
|
| 777 |
+
}
|
| 778 |
+
|
| 779 |
+
return this[MAP][key].join(', ');
|
| 780 |
+
}
|
| 781 |
+
|
| 782 |
+
/**
|
| 783 |
+
* Iterate over all headers
|
| 784 |
+
*
|
| 785 |
+
* @param Function callback Executed for each item with parameters (value, name, thisArg)
|
| 786 |
+
* @param Boolean thisArg `this` context for callback function
|
| 787 |
+
* @return Void
|
| 788 |
+
*/
|
| 789 |
+
forEach(callback) {
|
| 790 |
+
let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
| 791 |
+
|
| 792 |
+
let pairs = getHeaders(this);
|
| 793 |
+
let i = 0;
|
| 794 |
+
while (i < pairs.length) {
|
| 795 |
+
var _pairs$i = pairs[i];
|
| 796 |
+
const name = _pairs$i[0],
|
| 797 |
+
value = _pairs$i[1];
|
| 798 |
+
|
| 799 |
+
callback.call(thisArg, value, name, this);
|
| 800 |
+
pairs = getHeaders(this);
|
| 801 |
+
i++;
|
| 802 |
+
}
|
| 803 |
+
}
|
| 804 |
+
|
| 805 |
+
/**
|
| 806 |
+
* Overwrite header values given name
|
| 807 |
+
*
|
| 808 |
+
* @param String name Header name
|
| 809 |
+
* @param String value Header value
|
| 810 |
+
* @return Void
|
| 811 |
+
*/
|
| 812 |
+
set(name, value) {
|
| 813 |
+
name = `${name}`;
|
| 814 |
+
value = `${value}`;
|
| 815 |
+
validateName(name);
|
| 816 |
+
validateValue(value);
|
| 817 |
+
const key = find(this[MAP], name);
|
| 818 |
+
this[MAP][key !== undefined ? key : name] = [value];
|
| 819 |
+
}
|
| 820 |
+
|
| 821 |
+
/**
|
| 822 |
+
* Append a value onto existing header
|
| 823 |
+
*
|
| 824 |
+
* @param String name Header name
|
| 825 |
+
* @param String value Header value
|
| 826 |
+
* @return Void
|
| 827 |
+
*/
|
| 828 |
+
append(name, value) {
|
| 829 |
+
name = `${name}`;
|
| 830 |
+
value = `${value}`;
|
| 831 |
+
validateName(name);
|
| 832 |
+
validateValue(value);
|
| 833 |
+
const key = find(this[MAP], name);
|
| 834 |
+
if (key !== undefined) {
|
| 835 |
+
this[MAP][key].push(value);
|
| 836 |
+
} else {
|
| 837 |
+
this[MAP][name] = [value];
|
| 838 |
+
}
|
| 839 |
+
}
|
| 840 |
+
|
| 841 |
+
/**
|
| 842 |
+
* Check for header name existence
|
| 843 |
+
*
|
| 844 |
+
* @param String name Header name
|
| 845 |
+
* @return Boolean
|
| 846 |
+
*/
|
| 847 |
+
has(name) {
|
| 848 |
+
name = `${name}`;
|
| 849 |
+
validateName(name);
|
| 850 |
+
return find(this[MAP], name) !== undefined;
|
| 851 |
+
}
|
| 852 |
+
|
| 853 |
+
/**
|
| 854 |
+
* Delete all header values given name
|
| 855 |
+
*
|
| 856 |
+
* @param String name Header name
|
| 857 |
+
* @return Void
|
| 858 |
+
*/
|
| 859 |
+
delete(name) {
|
| 860 |
+
name = `${name}`;
|
| 861 |
+
validateName(name);
|
| 862 |
+
const key = find(this[MAP], name);
|
| 863 |
+
if (key !== undefined) {
|
| 864 |
+
delete this[MAP][key];
|
| 865 |
+
}
|
| 866 |
+
}
|
| 867 |
+
|
| 868 |
+
/**
|
| 869 |
+
* Return raw headers (non-spec api)
|
| 870 |
+
*
|
| 871 |
+
* @return Object
|
| 872 |
+
*/
|
| 873 |
+
raw() {
|
| 874 |
+
return this[MAP];
|
| 875 |
+
}
|
| 876 |
+
|
| 877 |
+
/**
|
| 878 |
+
* Get an iterator on keys.
|
| 879 |
+
*
|
| 880 |
+
* @return Iterator
|
| 881 |
+
*/
|
| 882 |
+
keys() {
|
| 883 |
+
return createHeadersIterator(this, 'key');
|
| 884 |
+
}
|
| 885 |
+
|
| 886 |
+
/**
|
| 887 |
+
* Get an iterator on values.
|
| 888 |
+
*
|
| 889 |
+
* @return Iterator
|
| 890 |
+
*/
|
| 891 |
+
values() {
|
| 892 |
+
return createHeadersIterator(this, 'value');
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
/**
|
| 896 |
+
* Get an iterator on entries.
|
| 897 |
+
*
|
| 898 |
+
* This is the default iterator of the Headers object.
|
| 899 |
+
*
|
| 900 |
+
* @return Iterator
|
| 901 |
+
*/
|
| 902 |
+
[Symbol.iterator]() {
|
| 903 |
+
return createHeadersIterator(this, 'key+value');
|
| 904 |
+
}
|
| 905 |
+
}
|
| 906 |
+
Headers.prototype.entries = Headers.prototype[Symbol.iterator];
|
| 907 |
+
|
| 908 |
+
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
|
| 909 |
+
value: 'Headers',
|
| 910 |
+
writable: false,
|
| 911 |
+
enumerable: false,
|
| 912 |
+
configurable: true
|
| 913 |
+
});
|
| 914 |
+
|
| 915 |
+
Object.defineProperties(Headers.prototype, {
|
| 916 |
+
get: { enumerable: true },
|
| 917 |
+
forEach: { enumerable: true },
|
| 918 |
+
set: { enumerable: true },
|
| 919 |
+
append: { enumerable: true },
|
| 920 |
+
has: { enumerable: true },
|
| 921 |
+
delete: { enumerable: true },
|
| 922 |
+
keys: { enumerable: true },
|
| 923 |
+
values: { enumerable: true },
|
| 924 |
+
entries: { enumerable: true }
|
| 925 |
+
});
|
| 926 |
+
|
| 927 |
+
function getHeaders(headers) {
|
| 928 |
+
let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
|
| 929 |
+
|
| 930 |
+
const keys = Object.keys(headers[MAP]).sort();
|
| 931 |
+
return keys.map(kind === 'key' ? function (k) {
|
| 932 |
+
return k.toLowerCase();
|
| 933 |
+
} : kind === 'value' ? function (k) {
|
| 934 |
+
return headers[MAP][k].join(', ');
|
| 935 |
+
} : function (k) {
|
| 936 |
+
return [k.toLowerCase(), headers[MAP][k].join(', ')];
|
| 937 |
+
});
|
| 938 |
+
}
|
| 939 |
+
|
| 940 |
+
const INTERNAL = Symbol('internal');
|
| 941 |
+
|
| 942 |
+
function createHeadersIterator(target, kind) {
|
| 943 |
+
const iterator = Object.create(HeadersIteratorPrototype);
|
| 944 |
+
iterator[INTERNAL] = {
|
| 945 |
+
target,
|
| 946 |
+
kind,
|
| 947 |
+
index: 0
|
| 948 |
+
};
|
| 949 |
+
return iterator;
|
| 950 |
+
}
|
| 951 |
+
|
| 952 |
+
const HeadersIteratorPrototype = Object.setPrototypeOf({
|
| 953 |
+
next() {
|
| 954 |
+
// istanbul ignore if
|
| 955 |
+
if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
|
| 956 |
+
throw new TypeError('Value of `this` is not a HeadersIterator');
|
| 957 |
+
}
|
| 958 |
+
|
| 959 |
+
var _INTERNAL = this[INTERNAL];
|
| 960 |
+
const target = _INTERNAL.target,
|
| 961 |
+
kind = _INTERNAL.kind,
|
| 962 |
+
index = _INTERNAL.index;
|
| 963 |
+
|
| 964 |
+
const values = getHeaders(target, kind);
|
| 965 |
+
const len = values.length;
|
| 966 |
+
if (index >= len) {
|
| 967 |
+
return {
|
| 968 |
+
value: undefined,
|
| 969 |
+
done: true
|
| 970 |
+
};
|
| 971 |
+
}
|
| 972 |
+
|
| 973 |
+
this[INTERNAL].index = index + 1;
|
| 974 |
+
|
| 975 |
+
return {
|
| 976 |
+
value: values[index],
|
| 977 |
+
done: false
|
| 978 |
+
};
|
| 979 |
+
}
|
| 980 |
+
}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
|
| 981 |
+
|
| 982 |
+
Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
|
| 983 |
+
value: 'HeadersIterator',
|
| 984 |
+
writable: false,
|
| 985 |
+
enumerable: false,
|
| 986 |
+
configurable: true
|
| 987 |
+
});
|
| 988 |
+
|
| 989 |
+
/**
|
| 990 |
+
* Export the Headers object in a form that Node.js can consume.
|
| 991 |
+
*
|
| 992 |
+
* @param Headers headers
|
| 993 |
+
* @return Object
|
| 994 |
+
*/
|
| 995 |
+
function exportNodeCompatibleHeaders(headers) {
|
| 996 |
+
const obj = Object.assign({ __proto__: null }, headers[MAP]);
|
| 997 |
+
|
| 998 |
+
// http.request() only supports string as Host header. This hack makes
|
| 999 |
+
// specifying custom Host header possible.
|
| 1000 |
+
const hostHeaderKey = find(headers[MAP], 'Host');
|
| 1001 |
+
if (hostHeaderKey !== undefined) {
|
| 1002 |
+
obj[hostHeaderKey] = obj[hostHeaderKey][0];
|
| 1003 |
+
}
|
| 1004 |
+
|
| 1005 |
+
return obj;
|
| 1006 |
+
}
|
| 1007 |
+
|
| 1008 |
+
/**
|
| 1009 |
+
* Create a Headers object from an object of headers, ignoring those that do
|
| 1010 |
+
* not conform to HTTP grammar productions.
|
| 1011 |
+
*
|
| 1012 |
+
* @param Object obj Object of headers
|
| 1013 |
+
* @return Headers
|
| 1014 |
+
*/
|
| 1015 |
+
function createHeadersLenient(obj) {
|
| 1016 |
+
const headers = new Headers();
|
| 1017 |
+
for (const name of Object.keys(obj)) {
|
| 1018 |
+
if (invalidTokenRegex.test(name)) {
|
| 1019 |
+
continue;
|
| 1020 |
+
}
|
| 1021 |
+
if (Array.isArray(obj[name])) {
|
| 1022 |
+
for (const val of obj[name]) {
|
| 1023 |
+
if (invalidHeaderCharRegex.test(val)) {
|
| 1024 |
+
continue;
|
| 1025 |
+
}
|
| 1026 |
+
if (headers[MAP][name] === undefined) {
|
| 1027 |
+
headers[MAP][name] = [val];
|
| 1028 |
+
} else {
|
| 1029 |
+
headers[MAP][name].push(val);
|
| 1030 |
+
}
|
| 1031 |
+
}
|
| 1032 |
+
} else if (!invalidHeaderCharRegex.test(obj[name])) {
|
| 1033 |
+
headers[MAP][name] = [obj[name]];
|
| 1034 |
+
}
|
| 1035 |
+
}
|
| 1036 |
+
return headers;
|
| 1037 |
+
}
|
| 1038 |
+
|
| 1039 |
+
const INTERNALS$1 = Symbol('Response internals');
|
| 1040 |
+
|
| 1041 |
+
// fix an issue where "STATUS_CODES" aren't a named export for node <10
|
| 1042 |
+
const STATUS_CODES = http.STATUS_CODES;
|
| 1043 |
+
|
| 1044 |
+
/**
|
| 1045 |
+
* Response class
|
| 1046 |
+
*
|
| 1047 |
+
* @param Stream body Readable stream
|
| 1048 |
+
* @param Object opts Response options
|
| 1049 |
+
* @return Void
|
| 1050 |
+
*/
|
| 1051 |
+
class Response {
|
| 1052 |
+
constructor() {
|
| 1053 |
+
let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
| 1054 |
+
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1055 |
+
|
| 1056 |
+
Body.call(this, body, opts);
|
| 1057 |
+
|
| 1058 |
+
const status = opts.status || 200;
|
| 1059 |
+
const headers = new Headers(opts.headers);
|
| 1060 |
+
|
| 1061 |
+
if (body != null && !headers.has('Content-Type')) {
|
| 1062 |
+
const contentType = extractContentType(body);
|
| 1063 |
+
if (contentType) {
|
| 1064 |
+
headers.append('Content-Type', contentType);
|
| 1065 |
+
}
|
| 1066 |
+
}
|
| 1067 |
+
|
| 1068 |
+
this[INTERNALS$1] = {
|
| 1069 |
+
url: opts.url,
|
| 1070 |
+
status,
|
| 1071 |
+
statusText: opts.statusText || STATUS_CODES[status],
|
| 1072 |
+
headers,
|
| 1073 |
+
counter: opts.counter
|
| 1074 |
+
};
|
| 1075 |
+
}
|
| 1076 |
+
|
| 1077 |
+
get url() {
|
| 1078 |
+
return this[INTERNALS$1].url || '';
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
get status() {
|
| 1082 |
+
return this[INTERNALS$1].status;
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
+
/**
|
| 1086 |
+
* Convenience property representing if the request ended normally
|
| 1087 |
+
*/
|
| 1088 |
+
get ok() {
|
| 1089 |
+
return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
|
| 1090 |
+
}
|
| 1091 |
+
|
| 1092 |
+
get redirected() {
|
| 1093 |
+
return this[INTERNALS$1].counter > 0;
|
| 1094 |
+
}
|
| 1095 |
+
|
| 1096 |
+
get statusText() {
|
| 1097 |
+
return this[INTERNALS$1].statusText;
|
| 1098 |
+
}
|
| 1099 |
+
|
| 1100 |
+
get headers() {
|
| 1101 |
+
return this[INTERNALS$1].headers;
|
| 1102 |
+
}
|
| 1103 |
+
|
| 1104 |
+
/**
|
| 1105 |
+
* Clone this response
|
| 1106 |
+
*
|
| 1107 |
+
* @return Response
|
| 1108 |
+
*/
|
| 1109 |
+
clone() {
|
| 1110 |
+
return new Response(clone(this), {
|
| 1111 |
+
url: this.url,
|
| 1112 |
+
status: this.status,
|
| 1113 |
+
statusText: this.statusText,
|
| 1114 |
+
headers: this.headers,
|
| 1115 |
+
ok: this.ok,
|
| 1116 |
+
redirected: this.redirected
|
| 1117 |
+
});
|
| 1118 |
+
}
|
| 1119 |
+
}
|
| 1120 |
+
|
| 1121 |
+
Body.mixIn(Response.prototype);
|
| 1122 |
+
|
| 1123 |
+
Object.defineProperties(Response.prototype, {
|
| 1124 |
+
url: { enumerable: true },
|
| 1125 |
+
status: { enumerable: true },
|
| 1126 |
+
ok: { enumerable: true },
|
| 1127 |
+
redirected: { enumerable: true },
|
| 1128 |
+
statusText: { enumerable: true },
|
| 1129 |
+
headers: { enumerable: true },
|
| 1130 |
+
clone: { enumerable: true }
|
| 1131 |
+
});
|
| 1132 |
+
|
| 1133 |
+
Object.defineProperty(Response.prototype, Symbol.toStringTag, {
|
| 1134 |
+
value: 'Response',
|
| 1135 |
+
writable: false,
|
| 1136 |
+
enumerable: false,
|
| 1137 |
+
configurable: true
|
| 1138 |
+
});
|
| 1139 |
+
|
| 1140 |
+
const INTERNALS$2 = Symbol('Request internals');
|
| 1141 |
+
const URL = Url.URL || whatwgUrl.URL;
|
| 1142 |
+
|
| 1143 |
+
// fix an issue where "format", "parse" aren't a named export for node <10
|
| 1144 |
+
const parse_url = Url.parse;
|
| 1145 |
+
const format_url = Url.format;
|
| 1146 |
+
|
| 1147 |
+
/**
|
| 1148 |
+
* Wrapper around `new URL` to handle arbitrary URLs
|
| 1149 |
+
*
|
| 1150 |
+
* @param {string} urlStr
|
| 1151 |
+
* @return {void}
|
| 1152 |
+
*/
|
| 1153 |
+
function parseURL(urlStr) {
|
| 1154 |
+
/*
|
| 1155 |
+
Check whether the URL is absolute or not
|
| 1156 |
+
Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
|
| 1157 |
+
Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
|
| 1158 |
+
*/
|
| 1159 |
+
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
|
| 1160 |
+
urlStr = new URL(urlStr).toString();
|
| 1161 |
+
}
|
| 1162 |
+
|
| 1163 |
+
// Fallback to old implementation for arbitrary URLs
|
| 1164 |
+
return parse_url(urlStr);
|
| 1165 |
+
}
|
| 1166 |
+
|
| 1167 |
+
const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
|
| 1168 |
+
|
| 1169 |
+
/**
|
| 1170 |
+
* Check if a value is an instance of Request.
|
| 1171 |
+
*
|
| 1172 |
+
* @param Mixed input
|
| 1173 |
+
* @return Boolean
|
| 1174 |
+
*/
|
| 1175 |
+
function isRequest(input) {
|
| 1176 |
+
return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
|
| 1177 |
+
}
|
| 1178 |
+
|
| 1179 |
+
function isAbortSignal(signal) {
|
| 1180 |
+
const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
|
| 1181 |
+
return !!(proto && proto.constructor.name === 'AbortSignal');
|
| 1182 |
+
}
|
| 1183 |
+
|
| 1184 |
+
/**
|
| 1185 |
+
* Request class
|
| 1186 |
+
*
|
| 1187 |
+
* @param Mixed input Url or Request instance
|
| 1188 |
+
* @param Object init Custom options
|
| 1189 |
+
* @return Void
|
| 1190 |
+
*/
|
| 1191 |
+
class Request {
|
| 1192 |
+
constructor(input) {
|
| 1193 |
+
let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1194 |
+
|
| 1195 |
+
let parsedURL;
|
| 1196 |
+
|
| 1197 |
+
// normalize input
|
| 1198 |
+
if (!isRequest(input)) {
|
| 1199 |
+
if (input && input.href) {
|
| 1200 |
+
// in order to support Node.js' Url objects; though WHATWG's URL objects
|
| 1201 |
+
// will fall into this branch also (since their `toString()` will return
|
| 1202 |
+
// `href` property anyway)
|
| 1203 |
+
parsedURL = parseURL(input.href);
|
| 1204 |
+
} else {
|
| 1205 |
+
// coerce input to a string before attempting to parse
|
| 1206 |
+
parsedURL = parseURL(`${input}`);
|
| 1207 |
+
}
|
| 1208 |
+
input = {};
|
| 1209 |
+
} else {
|
| 1210 |
+
parsedURL = parseURL(input.url);
|
| 1211 |
+
}
|
| 1212 |
+
|
| 1213 |
+
let method = init.method || input.method || 'GET';
|
| 1214 |
+
method = method.toUpperCase();
|
| 1215 |
+
|
| 1216 |
+
if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
|
| 1217 |
+
throw new TypeError('Request with GET/HEAD method cannot have body');
|
| 1218 |
+
}
|
| 1219 |
+
|
| 1220 |
+
let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
|
| 1221 |
+
|
| 1222 |
+
Body.call(this, inputBody, {
|
| 1223 |
+
timeout: init.timeout || input.timeout || 0,
|
| 1224 |
+
size: init.size || input.size || 0
|
| 1225 |
+
});
|
| 1226 |
+
|
| 1227 |
+
const headers = new Headers(init.headers || input.headers || {});
|
| 1228 |
+
|
| 1229 |
+
if (inputBody != null && !headers.has('Content-Type')) {
|
| 1230 |
+
const contentType = extractContentType(inputBody);
|
| 1231 |
+
if (contentType) {
|
| 1232 |
+
headers.append('Content-Type', contentType);
|
| 1233 |
+
}
|
| 1234 |
+
}
|
| 1235 |
+
|
| 1236 |
+
let signal = isRequest(input) ? input.signal : null;
|
| 1237 |
+
if ('signal' in init) signal = init.signal;
|
| 1238 |
+
|
| 1239 |
+
if (signal != null && !isAbortSignal(signal)) {
|
| 1240 |
+
throw new TypeError('Expected signal to be an instanceof AbortSignal');
|
| 1241 |
+
}
|
| 1242 |
+
|
| 1243 |
+
this[INTERNALS$2] = {
|
| 1244 |
+
method,
|
| 1245 |
+
redirect: init.redirect || input.redirect || 'follow',
|
| 1246 |
+
headers,
|
| 1247 |
+
parsedURL,
|
| 1248 |
+
signal
|
| 1249 |
+
};
|
| 1250 |
+
|
| 1251 |
+
// node-fetch-only options
|
| 1252 |
+
this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
|
| 1253 |
+
this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
|
| 1254 |
+
this.counter = init.counter || input.counter || 0;
|
| 1255 |
+
this.agent = init.agent || input.agent;
|
| 1256 |
+
}
|
| 1257 |
+
|
| 1258 |
+
get method() {
|
| 1259 |
+
return this[INTERNALS$2].method;
|
| 1260 |
+
}
|
| 1261 |
+
|
| 1262 |
+
get url() {
|
| 1263 |
+
return format_url(this[INTERNALS$2].parsedURL);
|
| 1264 |
+
}
|
| 1265 |
+
|
| 1266 |
+
get headers() {
|
| 1267 |
+
return this[INTERNALS$2].headers;
|
| 1268 |
+
}
|
| 1269 |
+
|
| 1270 |
+
get redirect() {
|
| 1271 |
+
return this[INTERNALS$2].redirect;
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
get signal() {
|
| 1275 |
+
return this[INTERNALS$2].signal;
|
| 1276 |
+
}
|
| 1277 |
+
|
| 1278 |
+
/**
|
| 1279 |
+
* Clone this request
|
| 1280 |
+
*
|
| 1281 |
+
* @return Request
|
| 1282 |
+
*/
|
| 1283 |
+
clone() {
|
| 1284 |
+
return new Request(this);
|
| 1285 |
+
}
|
| 1286 |
+
}
|
| 1287 |
+
|
| 1288 |
+
Body.mixIn(Request.prototype);
|
| 1289 |
+
|
| 1290 |
+
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
|
| 1291 |
+
value: 'Request',
|
| 1292 |
+
writable: false,
|
| 1293 |
+
enumerable: false,
|
| 1294 |
+
configurable: true
|
| 1295 |
+
});
|
| 1296 |
+
|
| 1297 |
+
Object.defineProperties(Request.prototype, {
|
| 1298 |
+
method: { enumerable: true },
|
| 1299 |
+
url: { enumerable: true },
|
| 1300 |
+
headers: { enumerable: true },
|
| 1301 |
+
redirect: { enumerable: true },
|
| 1302 |
+
clone: { enumerable: true },
|
| 1303 |
+
signal: { enumerable: true }
|
| 1304 |
+
});
|
| 1305 |
+
|
| 1306 |
+
/**
|
| 1307 |
+
* Convert a Request to Node.js http request options.
|
| 1308 |
+
*
|
| 1309 |
+
* @param Request A Request instance
|
| 1310 |
+
* @return Object The options object to be passed to http.request
|
| 1311 |
+
*/
|
| 1312 |
+
function getNodeRequestOptions(request) {
|
| 1313 |
+
const parsedURL = request[INTERNALS$2].parsedURL;
|
| 1314 |
+
const headers = new Headers(request[INTERNALS$2].headers);
|
| 1315 |
+
|
| 1316 |
+
// fetch step 1.3
|
| 1317 |
+
if (!headers.has('Accept')) {
|
| 1318 |
+
headers.set('Accept', '*/*');
|
| 1319 |
+
}
|
| 1320 |
+
|
| 1321 |
+
// Basic fetch
|
| 1322 |
+
if (!parsedURL.protocol || !parsedURL.hostname) {
|
| 1323 |
+
throw new TypeError('Only absolute URLs are supported');
|
| 1324 |
+
}
|
| 1325 |
+
|
| 1326 |
+
if (!/^https?:$/.test(parsedURL.protocol)) {
|
| 1327 |
+
throw new TypeError('Only HTTP(S) protocols are supported');
|
| 1328 |
+
}
|
| 1329 |
+
|
| 1330 |
+
if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
|
| 1331 |
+
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
|
| 1332 |
+
}
|
| 1333 |
+
|
| 1334 |
+
// HTTP-network-or-cache fetch steps 2.4-2.7
|
| 1335 |
+
let contentLengthValue = null;
|
| 1336 |
+
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
|
| 1337 |
+
contentLengthValue = '0';
|
| 1338 |
+
}
|
| 1339 |
+
if (request.body != null) {
|
| 1340 |
+
const totalBytes = getTotalBytes(request);
|
| 1341 |
+
if (typeof totalBytes === 'number') {
|
| 1342 |
+
contentLengthValue = String(totalBytes);
|
| 1343 |
+
}
|
| 1344 |
+
}
|
| 1345 |
+
if (contentLengthValue) {
|
| 1346 |
+
headers.set('Content-Length', contentLengthValue);
|
| 1347 |
+
}
|
| 1348 |
+
|
| 1349 |
+
// HTTP-network-or-cache fetch step 2.11
|
| 1350 |
+
if (!headers.has('User-Agent')) {
|
| 1351 |
+
headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
|
| 1352 |
+
}
|
| 1353 |
+
|
| 1354 |
+
// HTTP-network-or-cache fetch step 2.15
|
| 1355 |
+
if (request.compress && !headers.has('Accept-Encoding')) {
|
| 1356 |
+
headers.set('Accept-Encoding', 'gzip,deflate');
|
| 1357 |
+
}
|
| 1358 |
+
|
| 1359 |
+
let agent = request.agent;
|
| 1360 |
+
if (typeof agent === 'function') {
|
| 1361 |
+
agent = agent(parsedURL);
|
| 1362 |
+
}
|
| 1363 |
+
|
| 1364 |
+
if (!headers.has('Connection') && !agent) {
|
| 1365 |
+
headers.set('Connection', 'close');
|
| 1366 |
+
}
|
| 1367 |
+
|
| 1368 |
+
// HTTP-network fetch step 4.2
|
| 1369 |
+
// chunked encoding is handled by Node.js
|
| 1370 |
+
|
| 1371 |
+
return Object.assign({}, parsedURL, {
|
| 1372 |
+
method: request.method,
|
| 1373 |
+
headers: exportNodeCompatibleHeaders(headers),
|
| 1374 |
+
agent
|
| 1375 |
+
});
|
| 1376 |
+
}
|
| 1377 |
+
|
| 1378 |
+
/**
|
| 1379 |
+
* abort-error.js
|
| 1380 |
+
*
|
| 1381 |
+
* AbortError interface for cancelled requests
|
| 1382 |
+
*/
|
| 1383 |
+
|
| 1384 |
+
/**
|
| 1385 |
+
* Create AbortError instance
|
| 1386 |
+
*
|
| 1387 |
+
* @param String message Error message for human
|
| 1388 |
+
* @return AbortError
|
| 1389 |
+
*/
|
| 1390 |
+
function AbortError(message) {
|
| 1391 |
+
Error.call(this, message);
|
| 1392 |
+
|
| 1393 |
+
this.type = 'aborted';
|
| 1394 |
+
this.message = message;
|
| 1395 |
+
|
| 1396 |
+
// hide custom error implementation details from end-users
|
| 1397 |
+
Error.captureStackTrace(this, this.constructor);
|
| 1398 |
+
}
|
| 1399 |
+
|
| 1400 |
+
AbortError.prototype = Object.create(Error.prototype);
|
| 1401 |
+
AbortError.prototype.constructor = AbortError;
|
| 1402 |
+
AbortError.prototype.name = 'AbortError';
|
| 1403 |
+
|
| 1404 |
+
const URL$1 = Url.URL || whatwgUrl.URL;
|
| 1405 |
+
|
| 1406 |
+
// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
|
| 1407 |
+
const PassThrough$1 = Stream.PassThrough;
|
| 1408 |
+
|
| 1409 |
+
const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
|
| 1410 |
+
const orig = new URL$1(original).hostname;
|
| 1411 |
+
const dest = new URL$1(destination).hostname;
|
| 1412 |
+
|
| 1413 |
+
return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
|
| 1414 |
+
};
|
| 1415 |
+
|
| 1416 |
+
/**
|
| 1417 |
+
* isSameProtocol reports whether the two provided URLs use the same protocol.
|
| 1418 |
+
*
|
| 1419 |
+
* Both domains must already be in canonical form.
|
| 1420 |
+
* @param {string|URL} original
|
| 1421 |
+
* @param {string|URL} destination
|
| 1422 |
+
*/
|
| 1423 |
+
const isSameProtocol = function isSameProtocol(destination, original) {
|
| 1424 |
+
const orig = new URL$1(original).protocol;
|
| 1425 |
+
const dest = new URL$1(destination).protocol;
|
| 1426 |
+
|
| 1427 |
+
return orig === dest;
|
| 1428 |
+
};
|
| 1429 |
+
|
| 1430 |
+
/**
|
| 1431 |
+
* Fetch function
|
| 1432 |
+
*
|
| 1433 |
+
* @param Mixed url Absolute url or Request instance
|
| 1434 |
+
* @param Object opts Fetch options
|
| 1435 |
+
* @return Promise
|
| 1436 |
+
*/
|
| 1437 |
+
function fetch(url, opts) {
|
| 1438 |
+
|
| 1439 |
+
// allow custom promise
|
| 1440 |
+
if (!fetch.Promise) {
|
| 1441 |
+
throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
|
| 1442 |
+
}
|
| 1443 |
+
|
| 1444 |
+
Body.Promise = fetch.Promise;
|
| 1445 |
+
|
| 1446 |
+
// wrap http.request into fetch
|
| 1447 |
+
return new fetch.Promise(function (resolve, reject) {
|
| 1448 |
+
// build request object
|
| 1449 |
+
const request = new Request(url, opts);
|
| 1450 |
+
const options = getNodeRequestOptions(request);
|
| 1451 |
+
|
| 1452 |
+
const send = (options.protocol === 'https:' ? https : http).request;
|
| 1453 |
+
const signal = request.signal;
|
| 1454 |
+
|
| 1455 |
+
let response = null;
|
| 1456 |
+
|
| 1457 |
+
const abort = function abort() {
|
| 1458 |
+
let error = new AbortError('The user aborted a request.');
|
| 1459 |
+
reject(error);
|
| 1460 |
+
if (request.body && request.body instanceof Stream.Readable) {
|
| 1461 |
+
destroyStream(request.body, error);
|
| 1462 |
+
}
|
| 1463 |
+
if (!response || !response.body) return;
|
| 1464 |
+
response.body.emit('error', error);
|
| 1465 |
+
};
|
| 1466 |
+
|
| 1467 |
+
if (signal && signal.aborted) {
|
| 1468 |
+
abort();
|
| 1469 |
+
return;
|
| 1470 |
+
}
|
| 1471 |
+
|
| 1472 |
+
const abortAndFinalize = function abortAndFinalize() {
|
| 1473 |
+
abort();
|
| 1474 |
+
finalize();
|
| 1475 |
+
};
|
| 1476 |
+
|
| 1477 |
+
// send request
|
| 1478 |
+
const req = send(options);
|
| 1479 |
+
let reqTimeout;
|
| 1480 |
+
|
| 1481 |
+
if (signal) {
|
| 1482 |
+
signal.addEventListener('abort', abortAndFinalize);
|
| 1483 |
+
}
|
| 1484 |
+
|
| 1485 |
+
function finalize() {
|
| 1486 |
+
req.abort();
|
| 1487 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1488 |
+
clearTimeout(reqTimeout);
|
| 1489 |
+
}
|
| 1490 |
+
|
| 1491 |
+
if (request.timeout) {
|
| 1492 |
+
req.once('socket', function (socket) {
|
| 1493 |
+
reqTimeout = setTimeout(function () {
|
| 1494 |
+
reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
|
| 1495 |
+
finalize();
|
| 1496 |
+
}, request.timeout);
|
| 1497 |
+
});
|
| 1498 |
+
}
|
| 1499 |
+
|
| 1500 |
+
req.on('error', function (err) {
|
| 1501 |
+
reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
|
| 1502 |
+
|
| 1503 |
+
if (response && response.body) {
|
| 1504 |
+
destroyStream(response.body, err);
|
| 1505 |
+
}
|
| 1506 |
+
|
| 1507 |
+
finalize();
|
| 1508 |
+
});
|
| 1509 |
+
|
| 1510 |
+
fixResponseChunkedTransferBadEnding(req, function (err) {
|
| 1511 |
+
if (signal && signal.aborted) {
|
| 1512 |
+
return;
|
| 1513 |
+
}
|
| 1514 |
+
|
| 1515 |
+
if (response && response.body) {
|
| 1516 |
+
destroyStream(response.body, err);
|
| 1517 |
+
}
|
| 1518 |
+
});
|
| 1519 |
+
|
| 1520 |
+
/* c8 ignore next 18 */
|
| 1521 |
+
if (parseInt(process.version.substring(1)) < 14) {
|
| 1522 |
+
// Before Node.js 14, pipeline() does not fully support async iterators and does not always
|
| 1523 |
+
// properly handle when the socket close/end events are out of order.
|
| 1524 |
+
req.on('socket', function (s) {
|
| 1525 |
+
s.addListener('close', function (hadError) {
|
| 1526 |
+
// if a data listener is still present we didn't end cleanly
|
| 1527 |
+
const hasDataListener = s.listenerCount('data') > 0;
|
| 1528 |
+
|
| 1529 |
+
// if end happened before close but the socket didn't emit an error, do it now
|
| 1530 |
+
if (response && hasDataListener && !hadError && !(signal && signal.aborted)) {
|
| 1531 |
+
const err = new Error('Premature close');
|
| 1532 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1533 |
+
response.body.emit('error', err);
|
| 1534 |
+
}
|
| 1535 |
+
});
|
| 1536 |
+
});
|
| 1537 |
+
}
|
| 1538 |
+
|
| 1539 |
+
req.on('response', function (res) {
|
| 1540 |
+
clearTimeout(reqTimeout);
|
| 1541 |
+
|
| 1542 |
+
const headers = createHeadersLenient(res.headers);
|
| 1543 |
+
|
| 1544 |
+
// HTTP fetch step 5
|
| 1545 |
+
if (fetch.isRedirect(res.statusCode)) {
|
| 1546 |
+
// HTTP fetch step 5.2
|
| 1547 |
+
const location = headers.get('Location');
|
| 1548 |
+
|
| 1549 |
+
// HTTP fetch step 5.3
|
| 1550 |
+
let locationURL = null;
|
| 1551 |
+
try {
|
| 1552 |
+
locationURL = location === null ? null : new URL$1(location, request.url).toString();
|
| 1553 |
+
} catch (err) {
|
| 1554 |
+
// error here can only be invalid URL in Location: header
|
| 1555 |
+
// do not throw when options.redirect == manual
|
| 1556 |
+
// let the user extract the errorneous redirect URL
|
| 1557 |
+
if (request.redirect !== 'manual') {
|
| 1558 |
+
reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
|
| 1559 |
+
finalize();
|
| 1560 |
+
return;
|
| 1561 |
+
}
|
| 1562 |
+
}
|
| 1563 |
+
|
| 1564 |
+
// HTTP fetch step 5.5
|
| 1565 |
+
switch (request.redirect) {
|
| 1566 |
+
case 'error':
|
| 1567 |
+
reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
|
| 1568 |
+
finalize();
|
| 1569 |
+
return;
|
| 1570 |
+
case 'manual':
|
| 1571 |
+
// node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
|
| 1572 |
+
if (locationURL !== null) {
|
| 1573 |
+
// handle corrupted header
|
| 1574 |
+
try {
|
| 1575 |
+
headers.set('Location', locationURL);
|
| 1576 |
+
} catch (err) {
|
| 1577 |
+
// istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
|
| 1578 |
+
reject(err);
|
| 1579 |
+
}
|
| 1580 |
+
}
|
| 1581 |
+
break;
|
| 1582 |
+
case 'follow':
|
| 1583 |
+
// HTTP-redirect fetch step 2
|
| 1584 |
+
if (locationURL === null) {
|
| 1585 |
+
break;
|
| 1586 |
+
}
|
| 1587 |
+
|
| 1588 |
+
// HTTP-redirect fetch step 5
|
| 1589 |
+
if (request.counter >= request.follow) {
|
| 1590 |
+
reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
|
| 1591 |
+
finalize();
|
| 1592 |
+
return;
|
| 1593 |
+
}
|
| 1594 |
+
|
| 1595 |
+
// HTTP-redirect fetch step 6 (counter increment)
|
| 1596 |
+
// Create a new Request object.
|
| 1597 |
+
const requestOpts = {
|
| 1598 |
+
headers: new Headers(request.headers),
|
| 1599 |
+
follow: request.follow,
|
| 1600 |
+
counter: request.counter + 1,
|
| 1601 |
+
agent: request.agent,
|
| 1602 |
+
compress: request.compress,
|
| 1603 |
+
method: request.method,
|
| 1604 |
+
body: request.body,
|
| 1605 |
+
signal: request.signal,
|
| 1606 |
+
timeout: request.timeout,
|
| 1607 |
+
size: request.size
|
| 1608 |
+
};
|
| 1609 |
+
|
| 1610 |
+
if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) {
|
| 1611 |
+
for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
|
| 1612 |
+
requestOpts.headers.delete(name);
|
| 1613 |
+
}
|
| 1614 |
+
}
|
| 1615 |
+
|
| 1616 |
+
// HTTP-redirect fetch step 9
|
| 1617 |
+
if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
|
| 1618 |
+
reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
|
| 1619 |
+
finalize();
|
| 1620 |
+
return;
|
| 1621 |
+
}
|
| 1622 |
+
|
| 1623 |
+
// HTTP-redirect fetch step 11
|
| 1624 |
+
if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
|
| 1625 |
+
requestOpts.method = 'GET';
|
| 1626 |
+
requestOpts.body = undefined;
|
| 1627 |
+
requestOpts.headers.delete('content-length');
|
| 1628 |
+
}
|
| 1629 |
+
|
| 1630 |
+
// HTTP-redirect fetch step 15
|
| 1631 |
+
resolve(fetch(new Request(locationURL, requestOpts)));
|
| 1632 |
+
finalize();
|
| 1633 |
+
return;
|
| 1634 |
+
}
|
| 1635 |
+
}
|
| 1636 |
+
|
| 1637 |
+
// prepare response
|
| 1638 |
+
res.once('end', function () {
|
| 1639 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1640 |
+
});
|
| 1641 |
+
let body = res.pipe(new PassThrough$1());
|
| 1642 |
+
|
| 1643 |
+
const response_options = {
|
| 1644 |
+
url: request.url,
|
| 1645 |
+
status: res.statusCode,
|
| 1646 |
+
statusText: res.statusMessage,
|
| 1647 |
+
headers: headers,
|
| 1648 |
+
size: request.size,
|
| 1649 |
+
timeout: request.timeout,
|
| 1650 |
+
counter: request.counter
|
| 1651 |
+
};
|
| 1652 |
+
|
| 1653 |
+
// HTTP-network fetch step 12.1.1.3
|
| 1654 |
+
const codings = headers.get('Content-Encoding');
|
| 1655 |
+
|
| 1656 |
+
// HTTP-network fetch step 12.1.1.4: handle content codings
|
| 1657 |
+
|
| 1658 |
+
// in following scenarios we ignore compression support
|
| 1659 |
+
// 1. compression support is disabled
|
| 1660 |
+
// 2. HEAD request
|
| 1661 |
+
// 3. no Content-Encoding header
|
| 1662 |
+
// 4. no content response (204)
|
| 1663 |
+
// 5. content not modified response (304)
|
| 1664 |
+
if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
| 1665 |
+
response = new Response(body, response_options);
|
| 1666 |
+
resolve(response);
|
| 1667 |
+
return;
|
| 1668 |
+
}
|
| 1669 |
+
|
| 1670 |
+
// For Node v6+
|
| 1671 |
+
// Be less strict when decoding compressed responses, since sometimes
|
| 1672 |
+
// servers send slightly invalid responses that are still accepted
|
| 1673 |
+
// by common browsers.
|
| 1674 |
+
// Always using Z_SYNC_FLUSH is what cURL does.
|
| 1675 |
+
const zlibOptions = {
|
| 1676 |
+
flush: zlib.Z_SYNC_FLUSH,
|
| 1677 |
+
finishFlush: zlib.Z_SYNC_FLUSH
|
| 1678 |
+
};
|
| 1679 |
+
|
| 1680 |
+
// for gzip
|
| 1681 |
+
if (codings == 'gzip' || codings == 'x-gzip') {
|
| 1682 |
+
body = body.pipe(zlib.createGunzip(zlibOptions));
|
| 1683 |
+
response = new Response(body, response_options);
|
| 1684 |
+
resolve(response);
|
| 1685 |
+
return;
|
| 1686 |
+
}
|
| 1687 |
+
|
| 1688 |
+
// for deflate
|
| 1689 |
+
if (codings == 'deflate' || codings == 'x-deflate') {
|
| 1690 |
+
// handle the infamous raw deflate response from old servers
|
| 1691 |
+
// a hack for old IIS and Apache servers
|
| 1692 |
+
const raw = res.pipe(new PassThrough$1());
|
| 1693 |
+
raw.once('data', function (chunk) {
|
| 1694 |
+
// see http://stackoverflow.com/questions/37519828
|
| 1695 |
+
if ((chunk[0] & 0x0F) === 0x08) {
|
| 1696 |
+
body = body.pipe(zlib.createInflate());
|
| 1697 |
+
} else {
|
| 1698 |
+
body = body.pipe(zlib.createInflateRaw());
|
| 1699 |
+
}
|
| 1700 |
+
response = new Response(body, response_options);
|
| 1701 |
+
resolve(response);
|
| 1702 |
+
});
|
| 1703 |
+
raw.on('end', function () {
|
| 1704 |
+
// some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted.
|
| 1705 |
+
if (!response) {
|
| 1706 |
+
response = new Response(body, response_options);
|
| 1707 |
+
resolve(response);
|
| 1708 |
+
}
|
| 1709 |
+
});
|
| 1710 |
+
return;
|
| 1711 |
+
}
|
| 1712 |
+
|
| 1713 |
+
// for br
|
| 1714 |
+
if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
|
| 1715 |
+
body = body.pipe(zlib.createBrotliDecompress());
|
| 1716 |
+
response = new Response(body, response_options);
|
| 1717 |
+
resolve(response);
|
| 1718 |
+
return;
|
| 1719 |
+
}
|
| 1720 |
+
|
| 1721 |
+
// otherwise, use response as-is
|
| 1722 |
+
response = new Response(body, response_options);
|
| 1723 |
+
resolve(response);
|
| 1724 |
+
});
|
| 1725 |
+
|
| 1726 |
+
writeToStream(req, request);
|
| 1727 |
+
});
|
| 1728 |
+
}
|
| 1729 |
+
function fixResponseChunkedTransferBadEnding(request, errorCallback) {
|
| 1730 |
+
let socket;
|
| 1731 |
+
|
| 1732 |
+
request.on('socket', function (s) {
|
| 1733 |
+
socket = s;
|
| 1734 |
+
});
|
| 1735 |
+
|
| 1736 |
+
request.on('response', function (response) {
|
| 1737 |
+
const headers = response.headers;
|
| 1738 |
+
|
| 1739 |
+
if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) {
|
| 1740 |
+
response.once('close', function (hadError) {
|
| 1741 |
+
// if a data listener is still present we didn't end cleanly
|
| 1742 |
+
const hasDataListener = socket.listenerCount('data') > 0;
|
| 1743 |
+
|
| 1744 |
+
if (hasDataListener && !hadError) {
|
| 1745 |
+
const err = new Error('Premature close');
|
| 1746 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1747 |
+
errorCallback(err);
|
| 1748 |
+
}
|
| 1749 |
+
});
|
| 1750 |
+
}
|
| 1751 |
+
});
|
| 1752 |
+
}
|
| 1753 |
+
|
| 1754 |
+
function destroyStream(stream, err) {
|
| 1755 |
+
if (stream.destroy) {
|
| 1756 |
+
stream.destroy(err);
|
| 1757 |
+
} else {
|
| 1758 |
+
// node < 8
|
| 1759 |
+
stream.emit('error', err);
|
| 1760 |
+
stream.end();
|
| 1761 |
+
}
|
| 1762 |
+
}
|
| 1763 |
+
|
| 1764 |
+
/**
|
| 1765 |
+
* Redirect code matching
|
| 1766 |
+
*
|
| 1767 |
+
* @param Number code Status code
|
| 1768 |
+
* @return Boolean
|
| 1769 |
+
*/
|
| 1770 |
+
fetch.isRedirect = function (code) {
|
| 1771 |
+
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
|
| 1772 |
+
};
|
| 1773 |
+
|
| 1774 |
+
// expose Promise
|
| 1775 |
+
fetch.Promise = global.Promise;
|
| 1776 |
+
|
| 1777 |
+
export default fetch;
|
| 1778 |
+
export { Headers, Request, Response, FetchError };
|
node_modules/node-fetch/lib/index.js
ADDED
|
@@ -0,0 +1,1787 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use strict';
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, '__esModule', { value: true });
|
| 4 |
+
|
| 5 |
+
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
| 6 |
+
|
| 7 |
+
var Stream = _interopDefault(require('stream'));
|
| 8 |
+
var http = _interopDefault(require('http'));
|
| 9 |
+
var Url = _interopDefault(require('url'));
|
| 10 |
+
var whatwgUrl = _interopDefault(require('whatwg-url'));
|
| 11 |
+
var https = _interopDefault(require('https'));
|
| 12 |
+
var zlib = _interopDefault(require('zlib'));
|
| 13 |
+
|
| 14 |
+
// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
|
| 15 |
+
|
| 16 |
+
// fix for "Readable" isn't a named export issue
|
| 17 |
+
const Readable = Stream.Readable;
|
| 18 |
+
|
| 19 |
+
const BUFFER = Symbol('buffer');
|
| 20 |
+
const TYPE = Symbol('type');
|
| 21 |
+
|
| 22 |
+
class Blob {
|
| 23 |
+
constructor() {
|
| 24 |
+
this[TYPE] = '';
|
| 25 |
+
|
| 26 |
+
const blobParts = arguments[0];
|
| 27 |
+
const options = arguments[1];
|
| 28 |
+
|
| 29 |
+
const buffers = [];
|
| 30 |
+
let size = 0;
|
| 31 |
+
|
| 32 |
+
if (blobParts) {
|
| 33 |
+
const a = blobParts;
|
| 34 |
+
const length = Number(a.length);
|
| 35 |
+
for (let i = 0; i < length; i++) {
|
| 36 |
+
const element = a[i];
|
| 37 |
+
let buffer;
|
| 38 |
+
if (element instanceof Buffer) {
|
| 39 |
+
buffer = element;
|
| 40 |
+
} else if (ArrayBuffer.isView(element)) {
|
| 41 |
+
buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
|
| 42 |
+
} else if (element instanceof ArrayBuffer) {
|
| 43 |
+
buffer = Buffer.from(element);
|
| 44 |
+
} else if (element instanceof Blob) {
|
| 45 |
+
buffer = element[BUFFER];
|
| 46 |
+
} else {
|
| 47 |
+
buffer = Buffer.from(typeof element === 'string' ? element : String(element));
|
| 48 |
+
}
|
| 49 |
+
size += buffer.length;
|
| 50 |
+
buffers.push(buffer);
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
this[BUFFER] = Buffer.concat(buffers);
|
| 55 |
+
|
| 56 |
+
let type = options && options.type !== undefined && String(options.type).toLowerCase();
|
| 57 |
+
if (type && !/[^\u0020-\u007E]/.test(type)) {
|
| 58 |
+
this[TYPE] = type;
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
get size() {
|
| 62 |
+
return this[BUFFER].length;
|
| 63 |
+
}
|
| 64 |
+
get type() {
|
| 65 |
+
return this[TYPE];
|
| 66 |
+
}
|
| 67 |
+
text() {
|
| 68 |
+
return Promise.resolve(this[BUFFER].toString());
|
| 69 |
+
}
|
| 70 |
+
arrayBuffer() {
|
| 71 |
+
const buf = this[BUFFER];
|
| 72 |
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 73 |
+
return Promise.resolve(ab);
|
| 74 |
+
}
|
| 75 |
+
stream() {
|
| 76 |
+
const readable = new Readable();
|
| 77 |
+
readable._read = function () {};
|
| 78 |
+
readable.push(this[BUFFER]);
|
| 79 |
+
readable.push(null);
|
| 80 |
+
return readable;
|
| 81 |
+
}
|
| 82 |
+
toString() {
|
| 83 |
+
return '[object Blob]';
|
| 84 |
+
}
|
| 85 |
+
slice() {
|
| 86 |
+
const size = this.size;
|
| 87 |
+
|
| 88 |
+
const start = arguments[0];
|
| 89 |
+
const end = arguments[1];
|
| 90 |
+
let relativeStart, relativeEnd;
|
| 91 |
+
if (start === undefined) {
|
| 92 |
+
relativeStart = 0;
|
| 93 |
+
} else if (start < 0) {
|
| 94 |
+
relativeStart = Math.max(size + start, 0);
|
| 95 |
+
} else {
|
| 96 |
+
relativeStart = Math.min(start, size);
|
| 97 |
+
}
|
| 98 |
+
if (end === undefined) {
|
| 99 |
+
relativeEnd = size;
|
| 100 |
+
} else if (end < 0) {
|
| 101 |
+
relativeEnd = Math.max(size + end, 0);
|
| 102 |
+
} else {
|
| 103 |
+
relativeEnd = Math.min(end, size);
|
| 104 |
+
}
|
| 105 |
+
const span = Math.max(relativeEnd - relativeStart, 0);
|
| 106 |
+
|
| 107 |
+
const buffer = this[BUFFER];
|
| 108 |
+
const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
|
| 109 |
+
const blob = new Blob([], { type: arguments[2] });
|
| 110 |
+
blob[BUFFER] = slicedBuffer;
|
| 111 |
+
return blob;
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
Object.defineProperties(Blob.prototype, {
|
| 116 |
+
size: { enumerable: true },
|
| 117 |
+
type: { enumerable: true },
|
| 118 |
+
slice: { enumerable: true }
|
| 119 |
+
});
|
| 120 |
+
|
| 121 |
+
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
|
| 122 |
+
value: 'Blob',
|
| 123 |
+
writable: false,
|
| 124 |
+
enumerable: false,
|
| 125 |
+
configurable: true
|
| 126 |
+
});
|
| 127 |
+
|
| 128 |
+
/**
|
| 129 |
+
* fetch-error.js
|
| 130 |
+
*
|
| 131 |
+
* FetchError interface for operational errors
|
| 132 |
+
*/
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* Create FetchError instance
|
| 136 |
+
*
|
| 137 |
+
* @param String message Error message for human
|
| 138 |
+
* @param String type Error type for machine
|
| 139 |
+
* @param String systemError For Node.js system error
|
| 140 |
+
* @return FetchError
|
| 141 |
+
*/
|
| 142 |
+
function FetchError(message, type, systemError) {
|
| 143 |
+
Error.call(this, message);
|
| 144 |
+
|
| 145 |
+
this.message = message;
|
| 146 |
+
this.type = type;
|
| 147 |
+
|
| 148 |
+
// when err.type is `system`, err.code contains system error code
|
| 149 |
+
if (systemError) {
|
| 150 |
+
this.code = this.errno = systemError.code;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
// hide custom error implementation details from end-users
|
| 154 |
+
Error.captureStackTrace(this, this.constructor);
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
FetchError.prototype = Object.create(Error.prototype);
|
| 158 |
+
FetchError.prototype.constructor = FetchError;
|
| 159 |
+
FetchError.prototype.name = 'FetchError';
|
| 160 |
+
|
| 161 |
+
let convert;
|
| 162 |
+
try {
|
| 163 |
+
convert = require('encoding').convert;
|
| 164 |
+
} catch (e) {}
|
| 165 |
+
|
| 166 |
+
const INTERNALS = Symbol('Body internals');
|
| 167 |
+
|
| 168 |
+
// fix an issue where "PassThrough" isn't a named export for node <10
|
| 169 |
+
const PassThrough = Stream.PassThrough;
|
| 170 |
+
|
| 171 |
+
/**
|
| 172 |
+
* Body mixin
|
| 173 |
+
*
|
| 174 |
+
* Ref: https://fetch.spec.whatwg.org/#body
|
| 175 |
+
*
|
| 176 |
+
* @param Stream body Readable stream
|
| 177 |
+
* @param Object opts Response options
|
| 178 |
+
* @return Void
|
| 179 |
+
*/
|
| 180 |
+
function Body(body) {
|
| 181 |
+
var _this = this;
|
| 182 |
+
|
| 183 |
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
| 184 |
+
_ref$size = _ref.size;
|
| 185 |
+
|
| 186 |
+
let size = _ref$size === undefined ? 0 : _ref$size;
|
| 187 |
+
var _ref$timeout = _ref.timeout;
|
| 188 |
+
let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
|
| 189 |
+
|
| 190 |
+
if (body == null) {
|
| 191 |
+
// body is undefined or null
|
| 192 |
+
body = null;
|
| 193 |
+
} else if (isURLSearchParams(body)) {
|
| 194 |
+
// body is a URLSearchParams
|
| 195 |
+
body = Buffer.from(body.toString());
|
| 196 |
+
} else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 197 |
+
// body is ArrayBuffer
|
| 198 |
+
body = Buffer.from(body);
|
| 199 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 200 |
+
// body is ArrayBufferView
|
| 201 |
+
body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
| 202 |
+
} else if (body instanceof Stream) ; else {
|
| 203 |
+
// none of the above
|
| 204 |
+
// coerce to string then buffer
|
| 205 |
+
body = Buffer.from(String(body));
|
| 206 |
+
}
|
| 207 |
+
this[INTERNALS] = {
|
| 208 |
+
body,
|
| 209 |
+
disturbed: false,
|
| 210 |
+
error: null
|
| 211 |
+
};
|
| 212 |
+
this.size = size;
|
| 213 |
+
this.timeout = timeout;
|
| 214 |
+
|
| 215 |
+
if (body instanceof Stream) {
|
| 216 |
+
body.on('error', function (err) {
|
| 217 |
+
const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
|
| 218 |
+
_this[INTERNALS].error = error;
|
| 219 |
+
});
|
| 220 |
+
}
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
Body.prototype = {
|
| 224 |
+
get body() {
|
| 225 |
+
return this[INTERNALS].body;
|
| 226 |
+
},
|
| 227 |
+
|
| 228 |
+
get bodyUsed() {
|
| 229 |
+
return this[INTERNALS].disturbed;
|
| 230 |
+
},
|
| 231 |
+
|
| 232 |
+
/**
|
| 233 |
+
* Decode response as ArrayBuffer
|
| 234 |
+
*
|
| 235 |
+
* @return Promise
|
| 236 |
+
*/
|
| 237 |
+
arrayBuffer() {
|
| 238 |
+
return consumeBody.call(this).then(function (buf) {
|
| 239 |
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 240 |
+
});
|
| 241 |
+
},
|
| 242 |
+
|
| 243 |
+
/**
|
| 244 |
+
* Return raw response as Blob
|
| 245 |
+
*
|
| 246 |
+
* @return Promise
|
| 247 |
+
*/
|
| 248 |
+
blob() {
|
| 249 |
+
let ct = this.headers && this.headers.get('content-type') || '';
|
| 250 |
+
return consumeBody.call(this).then(function (buf) {
|
| 251 |
+
return Object.assign(
|
| 252 |
+
// Prevent copying
|
| 253 |
+
new Blob([], {
|
| 254 |
+
type: ct.toLowerCase()
|
| 255 |
+
}), {
|
| 256 |
+
[BUFFER]: buf
|
| 257 |
+
});
|
| 258 |
+
});
|
| 259 |
+
},
|
| 260 |
+
|
| 261 |
+
/**
|
| 262 |
+
* Decode response as json
|
| 263 |
+
*
|
| 264 |
+
* @return Promise
|
| 265 |
+
*/
|
| 266 |
+
json() {
|
| 267 |
+
var _this2 = this;
|
| 268 |
+
|
| 269 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 270 |
+
try {
|
| 271 |
+
return JSON.parse(buffer.toString());
|
| 272 |
+
} catch (err) {
|
| 273 |
+
return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
|
| 274 |
+
}
|
| 275 |
+
});
|
| 276 |
+
},
|
| 277 |
+
|
| 278 |
+
/**
|
| 279 |
+
* Decode response as text
|
| 280 |
+
*
|
| 281 |
+
* @return Promise
|
| 282 |
+
*/
|
| 283 |
+
text() {
|
| 284 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 285 |
+
return buffer.toString();
|
| 286 |
+
});
|
| 287 |
+
},
|
| 288 |
+
|
| 289 |
+
/**
|
| 290 |
+
* Decode response as buffer (non-spec api)
|
| 291 |
+
*
|
| 292 |
+
* @return Promise
|
| 293 |
+
*/
|
| 294 |
+
buffer() {
|
| 295 |
+
return consumeBody.call(this);
|
| 296 |
+
},
|
| 297 |
+
|
| 298 |
+
/**
|
| 299 |
+
* Decode response as text, while automatically detecting the encoding and
|
| 300 |
+
* trying to decode to UTF-8 (non-spec api)
|
| 301 |
+
*
|
| 302 |
+
* @return Promise
|
| 303 |
+
*/
|
| 304 |
+
textConverted() {
|
| 305 |
+
var _this3 = this;
|
| 306 |
+
|
| 307 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 308 |
+
return convertBody(buffer, _this3.headers);
|
| 309 |
+
});
|
| 310 |
+
}
|
| 311 |
+
};
|
| 312 |
+
|
| 313 |
+
// In browsers, all properties are enumerable.
|
| 314 |
+
Object.defineProperties(Body.prototype, {
|
| 315 |
+
body: { enumerable: true },
|
| 316 |
+
bodyUsed: { enumerable: true },
|
| 317 |
+
arrayBuffer: { enumerable: true },
|
| 318 |
+
blob: { enumerable: true },
|
| 319 |
+
json: { enumerable: true },
|
| 320 |
+
text: { enumerable: true }
|
| 321 |
+
});
|
| 322 |
+
|
| 323 |
+
Body.mixIn = function (proto) {
|
| 324 |
+
for (const name of Object.getOwnPropertyNames(Body.prototype)) {
|
| 325 |
+
// istanbul ignore else: future proof
|
| 326 |
+
if (!(name in proto)) {
|
| 327 |
+
const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
|
| 328 |
+
Object.defineProperty(proto, name, desc);
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
};
|
| 332 |
+
|
| 333 |
+
/**
|
| 334 |
+
* Consume and convert an entire Body to a Buffer.
|
| 335 |
+
*
|
| 336 |
+
* Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
|
| 337 |
+
*
|
| 338 |
+
* @return Promise
|
| 339 |
+
*/
|
| 340 |
+
function consumeBody() {
|
| 341 |
+
var _this4 = this;
|
| 342 |
+
|
| 343 |
+
if (this[INTERNALS].disturbed) {
|
| 344 |
+
return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
this[INTERNALS].disturbed = true;
|
| 348 |
+
|
| 349 |
+
if (this[INTERNALS].error) {
|
| 350 |
+
return Body.Promise.reject(this[INTERNALS].error);
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
let body = this.body;
|
| 354 |
+
|
| 355 |
+
// body is null
|
| 356 |
+
if (body === null) {
|
| 357 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
// body is blob
|
| 361 |
+
if (isBlob(body)) {
|
| 362 |
+
body = body.stream();
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
// body is buffer
|
| 366 |
+
if (Buffer.isBuffer(body)) {
|
| 367 |
+
return Body.Promise.resolve(body);
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
// istanbul ignore if: should never happen
|
| 371 |
+
if (!(body instanceof Stream)) {
|
| 372 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
// body is stream
|
| 376 |
+
// get ready to actually consume the body
|
| 377 |
+
let accum = [];
|
| 378 |
+
let accumBytes = 0;
|
| 379 |
+
let abort = false;
|
| 380 |
+
|
| 381 |
+
return new Body.Promise(function (resolve, reject) {
|
| 382 |
+
let resTimeout;
|
| 383 |
+
|
| 384 |
+
// allow timeout on slow response body
|
| 385 |
+
if (_this4.timeout) {
|
| 386 |
+
resTimeout = setTimeout(function () {
|
| 387 |
+
abort = true;
|
| 388 |
+
reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
|
| 389 |
+
}, _this4.timeout);
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
// handle stream errors
|
| 393 |
+
body.on('error', function (err) {
|
| 394 |
+
if (err.name === 'AbortError') {
|
| 395 |
+
// if the request was aborted, reject with this Error
|
| 396 |
+
abort = true;
|
| 397 |
+
reject(err);
|
| 398 |
+
} else {
|
| 399 |
+
// other errors, such as incorrect content-encoding
|
| 400 |
+
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
|
| 401 |
+
}
|
| 402 |
+
});
|
| 403 |
+
|
| 404 |
+
body.on('data', function (chunk) {
|
| 405 |
+
if (abort || chunk === null) {
|
| 406 |
+
return;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
if (_this4.size && accumBytes + chunk.length > _this4.size) {
|
| 410 |
+
abort = true;
|
| 411 |
+
reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
|
| 412 |
+
return;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
accumBytes += chunk.length;
|
| 416 |
+
accum.push(chunk);
|
| 417 |
+
});
|
| 418 |
+
|
| 419 |
+
body.on('end', function () {
|
| 420 |
+
if (abort) {
|
| 421 |
+
return;
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
clearTimeout(resTimeout);
|
| 425 |
+
|
| 426 |
+
try {
|
| 427 |
+
resolve(Buffer.concat(accum, accumBytes));
|
| 428 |
+
} catch (err) {
|
| 429 |
+
// handle streams that have accumulated too much data (issue #414)
|
| 430 |
+
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
|
| 431 |
+
}
|
| 432 |
+
});
|
| 433 |
+
});
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
/**
|
| 437 |
+
* Detect buffer encoding and convert to target encoding
|
| 438 |
+
* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
|
| 439 |
+
*
|
| 440 |
+
* @param Buffer buffer Incoming buffer
|
| 441 |
+
* @param String encoding Target encoding
|
| 442 |
+
* @return String
|
| 443 |
+
*/
|
| 444 |
+
function convertBody(buffer, headers) {
|
| 445 |
+
if (typeof convert !== 'function') {
|
| 446 |
+
throw new Error('The package `encoding` must be installed to use the textConverted() function');
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
const ct = headers.get('content-type');
|
| 450 |
+
let charset = 'utf-8';
|
| 451 |
+
let res, str;
|
| 452 |
+
|
| 453 |
+
// header
|
| 454 |
+
if (ct) {
|
| 455 |
+
res = /charset=([^;]*)/i.exec(ct);
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
// no charset in content type, peek at response body for at most 1024 bytes
|
| 459 |
+
str = buffer.slice(0, 1024).toString();
|
| 460 |
+
|
| 461 |
+
// html5
|
| 462 |
+
if (!res && str) {
|
| 463 |
+
res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
// html4
|
| 467 |
+
if (!res && str) {
|
| 468 |
+
res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
|
| 469 |
+
if (!res) {
|
| 470 |
+
res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
|
| 471 |
+
if (res) {
|
| 472 |
+
res.pop(); // drop last quote
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
if (res) {
|
| 477 |
+
res = /charset=(.*)/i.exec(res.pop());
|
| 478 |
+
}
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
// xml
|
| 482 |
+
if (!res && str) {
|
| 483 |
+
res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
|
| 484 |
+
}
|
| 485 |
+
|
| 486 |
+
// found charset
|
| 487 |
+
if (res) {
|
| 488 |
+
charset = res.pop();
|
| 489 |
+
|
| 490 |
+
// prevent decode issues when sites use incorrect encoding
|
| 491 |
+
// ref: https://hsivonen.fi/encoding-menu/
|
| 492 |
+
if (charset === 'gb2312' || charset === 'gbk') {
|
| 493 |
+
charset = 'gb18030';
|
| 494 |
+
}
|
| 495 |
+
}
|
| 496 |
+
|
| 497 |
+
// turn raw buffers into a single utf-8 buffer
|
| 498 |
+
return convert(buffer, 'UTF-8', charset).toString();
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
/**
|
| 502 |
+
* Detect a URLSearchParams object
|
| 503 |
+
* ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
|
| 504 |
+
*
|
| 505 |
+
* @param Object obj Object to detect by type or brand
|
| 506 |
+
* @return String
|
| 507 |
+
*/
|
| 508 |
+
function isURLSearchParams(obj) {
|
| 509 |
+
// Duck-typing as a necessary condition.
|
| 510 |
+
if (typeof obj !== 'object' || typeof obj.append !== 'function' || typeof obj.delete !== 'function' || typeof obj.get !== 'function' || typeof obj.getAll !== 'function' || typeof obj.has !== 'function' || typeof obj.set !== 'function') {
|
| 511 |
+
return false;
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
// Brand-checking and more duck-typing as optional condition.
|
| 515 |
+
return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
/**
|
| 519 |
+
* Check if `obj` is a W3C `Blob` object (which `File` inherits from)
|
| 520 |
+
* @param {*} obj
|
| 521 |
+
* @return {boolean}
|
| 522 |
+
*/
|
| 523 |
+
function isBlob(obj) {
|
| 524 |
+
return typeof obj === 'object' && typeof obj.arrayBuffer === 'function' && typeof obj.type === 'string' && typeof obj.stream === 'function' && typeof obj.constructor === 'function' && typeof obj.constructor.name === 'string' && /^(Blob|File)$/.test(obj.constructor.name) && /^(Blob|File)$/.test(obj[Symbol.toStringTag]);
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
/**
|
| 528 |
+
* Clone body given Res/Req instance
|
| 529 |
+
*
|
| 530 |
+
* @param Mixed instance Response or Request instance
|
| 531 |
+
* @return Mixed
|
| 532 |
+
*/
|
| 533 |
+
function clone(instance) {
|
| 534 |
+
let p1, p2;
|
| 535 |
+
let body = instance.body;
|
| 536 |
+
|
| 537 |
+
// don't allow cloning a used body
|
| 538 |
+
if (instance.bodyUsed) {
|
| 539 |
+
throw new Error('cannot clone body after it is used');
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
// check that body is a stream and not form-data object
|
| 543 |
+
// note: we can't clone the form-data object without having it as a dependency
|
| 544 |
+
if (body instanceof Stream && typeof body.getBoundary !== 'function') {
|
| 545 |
+
// tee instance body
|
| 546 |
+
p1 = new PassThrough();
|
| 547 |
+
p2 = new PassThrough();
|
| 548 |
+
body.pipe(p1);
|
| 549 |
+
body.pipe(p2);
|
| 550 |
+
// set instance body to teed body and return the other teed body
|
| 551 |
+
instance[INTERNALS].body = p1;
|
| 552 |
+
body = p2;
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
return body;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
/**
|
| 559 |
+
* Performs the operation "extract a `Content-Type` value from |object|" as
|
| 560 |
+
* specified in the specification:
|
| 561 |
+
* https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
| 562 |
+
*
|
| 563 |
+
* This function assumes that instance.body is present.
|
| 564 |
+
*
|
| 565 |
+
* @param Mixed instance Any options.body input
|
| 566 |
+
*/
|
| 567 |
+
function extractContentType(body) {
|
| 568 |
+
if (body === null) {
|
| 569 |
+
// body is null
|
| 570 |
+
return null;
|
| 571 |
+
} else if (typeof body === 'string') {
|
| 572 |
+
// body is string
|
| 573 |
+
return 'text/plain;charset=UTF-8';
|
| 574 |
+
} else if (isURLSearchParams(body)) {
|
| 575 |
+
// body is a URLSearchParams
|
| 576 |
+
return 'application/x-www-form-urlencoded;charset=UTF-8';
|
| 577 |
+
} else if (isBlob(body)) {
|
| 578 |
+
// body is blob
|
| 579 |
+
return body.type || null;
|
| 580 |
+
} else if (Buffer.isBuffer(body)) {
|
| 581 |
+
// body is buffer
|
| 582 |
+
return null;
|
| 583 |
+
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 584 |
+
// body is ArrayBuffer
|
| 585 |
+
return null;
|
| 586 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 587 |
+
// body is ArrayBufferView
|
| 588 |
+
return null;
|
| 589 |
+
} else if (typeof body.getBoundary === 'function') {
|
| 590 |
+
// detect form data input from form-data module
|
| 591 |
+
return `multipart/form-data;boundary=${body.getBoundary()}`;
|
| 592 |
+
} else if (body instanceof Stream) {
|
| 593 |
+
// body is stream
|
| 594 |
+
// can't really do much about this
|
| 595 |
+
return null;
|
| 596 |
+
} else {
|
| 597 |
+
// Body constructor defaults other things to string
|
| 598 |
+
return 'text/plain;charset=UTF-8';
|
| 599 |
+
}
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
/**
|
| 603 |
+
* The Fetch Standard treats this as if "total bytes" is a property on the body.
|
| 604 |
+
* For us, we have to explicitly get it with a function.
|
| 605 |
+
*
|
| 606 |
+
* ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
|
| 607 |
+
*
|
| 608 |
+
* @param Body instance Instance of Body
|
| 609 |
+
* @return Number? Number of bytes, or null if not possible
|
| 610 |
+
*/
|
| 611 |
+
function getTotalBytes(instance) {
|
| 612 |
+
const body = instance.body;
|
| 613 |
+
|
| 614 |
+
|
| 615 |
+
if (body === null) {
|
| 616 |
+
// body is null
|
| 617 |
+
return 0;
|
| 618 |
+
} else if (isBlob(body)) {
|
| 619 |
+
return body.size;
|
| 620 |
+
} else if (Buffer.isBuffer(body)) {
|
| 621 |
+
// body is buffer
|
| 622 |
+
return body.length;
|
| 623 |
+
} else if (body && typeof body.getLengthSync === 'function') {
|
| 624 |
+
// detect form data input from form-data module
|
| 625 |
+
if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
|
| 626 |
+
body.hasKnownLength && body.hasKnownLength()) {
|
| 627 |
+
// 2.x
|
| 628 |
+
return body.getLengthSync();
|
| 629 |
+
}
|
| 630 |
+
return null;
|
| 631 |
+
} else {
|
| 632 |
+
// body is stream
|
| 633 |
+
return null;
|
| 634 |
+
}
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
/**
|
| 638 |
+
* Write a Body to a Node.js WritableStream (e.g. http.Request) object.
|
| 639 |
+
*
|
| 640 |
+
* @param Body instance Instance of Body
|
| 641 |
+
* @return Void
|
| 642 |
+
*/
|
| 643 |
+
function writeToStream(dest, instance) {
|
| 644 |
+
const body = instance.body;
|
| 645 |
+
|
| 646 |
+
|
| 647 |
+
if (body === null) {
|
| 648 |
+
// body is null
|
| 649 |
+
dest.end();
|
| 650 |
+
} else if (isBlob(body)) {
|
| 651 |
+
body.stream().pipe(dest);
|
| 652 |
+
} else if (Buffer.isBuffer(body)) {
|
| 653 |
+
// body is buffer
|
| 654 |
+
dest.write(body);
|
| 655 |
+
dest.end();
|
| 656 |
+
} else {
|
| 657 |
+
// body is stream
|
| 658 |
+
body.pipe(dest);
|
| 659 |
+
}
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
// expose Promise
|
| 663 |
+
Body.Promise = global.Promise;
|
| 664 |
+
|
| 665 |
+
/**
|
| 666 |
+
* headers.js
|
| 667 |
+
*
|
| 668 |
+
* Headers class offers convenient helpers
|
| 669 |
+
*/
|
| 670 |
+
|
| 671 |
+
const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
|
| 672 |
+
const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
|
| 673 |
+
|
| 674 |
+
function validateName(name) {
|
| 675 |
+
name = `${name}`;
|
| 676 |
+
if (invalidTokenRegex.test(name) || name === '') {
|
| 677 |
+
throw new TypeError(`${name} is not a legal HTTP header name`);
|
| 678 |
+
}
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
function validateValue(value) {
|
| 682 |
+
value = `${value}`;
|
| 683 |
+
if (invalidHeaderCharRegex.test(value)) {
|
| 684 |
+
throw new TypeError(`${value} is not a legal HTTP header value`);
|
| 685 |
+
}
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
/**
|
| 689 |
+
* Find the key in the map object given a header name.
|
| 690 |
+
*
|
| 691 |
+
* Returns undefined if not found.
|
| 692 |
+
*
|
| 693 |
+
* @param String name Header name
|
| 694 |
+
* @return String|Undefined
|
| 695 |
+
*/
|
| 696 |
+
function find(map, name) {
|
| 697 |
+
name = name.toLowerCase();
|
| 698 |
+
for (const key in map) {
|
| 699 |
+
if (key.toLowerCase() === name) {
|
| 700 |
+
return key;
|
| 701 |
+
}
|
| 702 |
+
}
|
| 703 |
+
return undefined;
|
| 704 |
+
}
|
| 705 |
+
|
| 706 |
+
const MAP = Symbol('map');
|
| 707 |
+
class Headers {
|
| 708 |
+
/**
|
| 709 |
+
* Headers class
|
| 710 |
+
*
|
| 711 |
+
* @param Object headers Response headers
|
| 712 |
+
* @return Void
|
| 713 |
+
*/
|
| 714 |
+
constructor() {
|
| 715 |
+
let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
|
| 716 |
+
|
| 717 |
+
this[MAP] = Object.create(null);
|
| 718 |
+
|
| 719 |
+
if (init instanceof Headers) {
|
| 720 |
+
const rawHeaders = init.raw();
|
| 721 |
+
const headerNames = Object.keys(rawHeaders);
|
| 722 |
+
|
| 723 |
+
for (const headerName of headerNames) {
|
| 724 |
+
for (const value of rawHeaders[headerName]) {
|
| 725 |
+
this.append(headerName, value);
|
| 726 |
+
}
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
return;
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
// We don't worry about converting prop to ByteString here as append()
|
| 733 |
+
// will handle it.
|
| 734 |
+
if (init == null) ; else if (typeof init === 'object') {
|
| 735 |
+
const method = init[Symbol.iterator];
|
| 736 |
+
if (method != null) {
|
| 737 |
+
if (typeof method !== 'function') {
|
| 738 |
+
throw new TypeError('Header pairs must be iterable');
|
| 739 |
+
}
|
| 740 |
+
|
| 741 |
+
// sequence<sequence<ByteString>>
|
| 742 |
+
// Note: per spec we have to first exhaust the lists then process them
|
| 743 |
+
const pairs = [];
|
| 744 |
+
for (const pair of init) {
|
| 745 |
+
if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
|
| 746 |
+
throw new TypeError('Each header pair must be iterable');
|
| 747 |
+
}
|
| 748 |
+
pairs.push(Array.from(pair));
|
| 749 |
+
}
|
| 750 |
+
|
| 751 |
+
for (const pair of pairs) {
|
| 752 |
+
if (pair.length !== 2) {
|
| 753 |
+
throw new TypeError('Each header pair must be a name/value tuple');
|
| 754 |
+
}
|
| 755 |
+
this.append(pair[0], pair[1]);
|
| 756 |
+
}
|
| 757 |
+
} else {
|
| 758 |
+
// record<ByteString, ByteString>
|
| 759 |
+
for (const key of Object.keys(init)) {
|
| 760 |
+
const value = init[key];
|
| 761 |
+
this.append(key, value);
|
| 762 |
+
}
|
| 763 |
+
}
|
| 764 |
+
} else {
|
| 765 |
+
throw new TypeError('Provided initializer must be an object');
|
| 766 |
+
}
|
| 767 |
+
}
|
| 768 |
+
|
| 769 |
+
/**
|
| 770 |
+
* Return combined header value given name
|
| 771 |
+
*
|
| 772 |
+
* @param String name Header name
|
| 773 |
+
* @return Mixed
|
| 774 |
+
*/
|
| 775 |
+
get(name) {
|
| 776 |
+
name = `${name}`;
|
| 777 |
+
validateName(name);
|
| 778 |
+
const key = find(this[MAP], name);
|
| 779 |
+
if (key === undefined) {
|
| 780 |
+
return null;
|
| 781 |
+
}
|
| 782 |
+
|
| 783 |
+
return this[MAP][key].join(', ');
|
| 784 |
+
}
|
| 785 |
+
|
| 786 |
+
/**
|
| 787 |
+
* Iterate over all headers
|
| 788 |
+
*
|
| 789 |
+
* @param Function callback Executed for each item with parameters (value, name, thisArg)
|
| 790 |
+
* @param Boolean thisArg `this` context for callback function
|
| 791 |
+
* @return Void
|
| 792 |
+
*/
|
| 793 |
+
forEach(callback) {
|
| 794 |
+
let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
| 795 |
+
|
| 796 |
+
let pairs = getHeaders(this);
|
| 797 |
+
let i = 0;
|
| 798 |
+
while (i < pairs.length) {
|
| 799 |
+
var _pairs$i = pairs[i];
|
| 800 |
+
const name = _pairs$i[0],
|
| 801 |
+
value = _pairs$i[1];
|
| 802 |
+
|
| 803 |
+
callback.call(thisArg, value, name, this);
|
| 804 |
+
pairs = getHeaders(this);
|
| 805 |
+
i++;
|
| 806 |
+
}
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
/**
|
| 810 |
+
* Overwrite header values given name
|
| 811 |
+
*
|
| 812 |
+
* @param String name Header name
|
| 813 |
+
* @param String value Header value
|
| 814 |
+
* @return Void
|
| 815 |
+
*/
|
| 816 |
+
set(name, value) {
|
| 817 |
+
name = `${name}`;
|
| 818 |
+
value = `${value}`;
|
| 819 |
+
validateName(name);
|
| 820 |
+
validateValue(value);
|
| 821 |
+
const key = find(this[MAP], name);
|
| 822 |
+
this[MAP][key !== undefined ? key : name] = [value];
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
/**
|
| 826 |
+
* Append a value onto existing header
|
| 827 |
+
*
|
| 828 |
+
* @param String name Header name
|
| 829 |
+
* @param String value Header value
|
| 830 |
+
* @return Void
|
| 831 |
+
*/
|
| 832 |
+
append(name, value) {
|
| 833 |
+
name = `${name}`;
|
| 834 |
+
value = `${value}`;
|
| 835 |
+
validateName(name);
|
| 836 |
+
validateValue(value);
|
| 837 |
+
const key = find(this[MAP], name);
|
| 838 |
+
if (key !== undefined) {
|
| 839 |
+
this[MAP][key].push(value);
|
| 840 |
+
} else {
|
| 841 |
+
this[MAP][name] = [value];
|
| 842 |
+
}
|
| 843 |
+
}
|
| 844 |
+
|
| 845 |
+
/**
|
| 846 |
+
* Check for header name existence
|
| 847 |
+
*
|
| 848 |
+
* @param String name Header name
|
| 849 |
+
* @return Boolean
|
| 850 |
+
*/
|
| 851 |
+
has(name) {
|
| 852 |
+
name = `${name}`;
|
| 853 |
+
validateName(name);
|
| 854 |
+
return find(this[MAP], name) !== undefined;
|
| 855 |
+
}
|
| 856 |
+
|
| 857 |
+
/**
|
| 858 |
+
* Delete all header values given name
|
| 859 |
+
*
|
| 860 |
+
* @param String name Header name
|
| 861 |
+
* @return Void
|
| 862 |
+
*/
|
| 863 |
+
delete(name) {
|
| 864 |
+
name = `${name}`;
|
| 865 |
+
validateName(name);
|
| 866 |
+
const key = find(this[MAP], name);
|
| 867 |
+
if (key !== undefined) {
|
| 868 |
+
delete this[MAP][key];
|
| 869 |
+
}
|
| 870 |
+
}
|
| 871 |
+
|
| 872 |
+
/**
|
| 873 |
+
* Return raw headers (non-spec api)
|
| 874 |
+
*
|
| 875 |
+
* @return Object
|
| 876 |
+
*/
|
| 877 |
+
raw() {
|
| 878 |
+
return this[MAP];
|
| 879 |
+
}
|
| 880 |
+
|
| 881 |
+
/**
|
| 882 |
+
* Get an iterator on keys.
|
| 883 |
+
*
|
| 884 |
+
* @return Iterator
|
| 885 |
+
*/
|
| 886 |
+
keys() {
|
| 887 |
+
return createHeadersIterator(this, 'key');
|
| 888 |
+
}
|
| 889 |
+
|
| 890 |
+
/**
|
| 891 |
+
* Get an iterator on values.
|
| 892 |
+
*
|
| 893 |
+
* @return Iterator
|
| 894 |
+
*/
|
| 895 |
+
values() {
|
| 896 |
+
return createHeadersIterator(this, 'value');
|
| 897 |
+
}
|
| 898 |
+
|
| 899 |
+
/**
|
| 900 |
+
* Get an iterator on entries.
|
| 901 |
+
*
|
| 902 |
+
* This is the default iterator of the Headers object.
|
| 903 |
+
*
|
| 904 |
+
* @return Iterator
|
| 905 |
+
*/
|
| 906 |
+
[Symbol.iterator]() {
|
| 907 |
+
return createHeadersIterator(this, 'key+value');
|
| 908 |
+
}
|
| 909 |
+
}
|
| 910 |
+
Headers.prototype.entries = Headers.prototype[Symbol.iterator];
|
| 911 |
+
|
| 912 |
+
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
|
| 913 |
+
value: 'Headers',
|
| 914 |
+
writable: false,
|
| 915 |
+
enumerable: false,
|
| 916 |
+
configurable: true
|
| 917 |
+
});
|
| 918 |
+
|
| 919 |
+
Object.defineProperties(Headers.prototype, {
|
| 920 |
+
get: { enumerable: true },
|
| 921 |
+
forEach: { enumerable: true },
|
| 922 |
+
set: { enumerable: true },
|
| 923 |
+
append: { enumerable: true },
|
| 924 |
+
has: { enumerable: true },
|
| 925 |
+
delete: { enumerable: true },
|
| 926 |
+
keys: { enumerable: true },
|
| 927 |
+
values: { enumerable: true },
|
| 928 |
+
entries: { enumerable: true }
|
| 929 |
+
});
|
| 930 |
+
|
| 931 |
+
function getHeaders(headers) {
|
| 932 |
+
let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
|
| 933 |
+
|
| 934 |
+
const keys = Object.keys(headers[MAP]).sort();
|
| 935 |
+
return keys.map(kind === 'key' ? function (k) {
|
| 936 |
+
return k.toLowerCase();
|
| 937 |
+
} : kind === 'value' ? function (k) {
|
| 938 |
+
return headers[MAP][k].join(', ');
|
| 939 |
+
} : function (k) {
|
| 940 |
+
return [k.toLowerCase(), headers[MAP][k].join(', ')];
|
| 941 |
+
});
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
const INTERNAL = Symbol('internal');
|
| 945 |
+
|
| 946 |
+
function createHeadersIterator(target, kind) {
|
| 947 |
+
const iterator = Object.create(HeadersIteratorPrototype);
|
| 948 |
+
iterator[INTERNAL] = {
|
| 949 |
+
target,
|
| 950 |
+
kind,
|
| 951 |
+
index: 0
|
| 952 |
+
};
|
| 953 |
+
return iterator;
|
| 954 |
+
}
|
| 955 |
+
|
| 956 |
+
const HeadersIteratorPrototype = Object.setPrototypeOf({
|
| 957 |
+
next() {
|
| 958 |
+
// istanbul ignore if
|
| 959 |
+
if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
|
| 960 |
+
throw new TypeError('Value of `this` is not a HeadersIterator');
|
| 961 |
+
}
|
| 962 |
+
|
| 963 |
+
var _INTERNAL = this[INTERNAL];
|
| 964 |
+
const target = _INTERNAL.target,
|
| 965 |
+
kind = _INTERNAL.kind,
|
| 966 |
+
index = _INTERNAL.index;
|
| 967 |
+
|
| 968 |
+
const values = getHeaders(target, kind);
|
| 969 |
+
const len = values.length;
|
| 970 |
+
if (index >= len) {
|
| 971 |
+
return {
|
| 972 |
+
value: undefined,
|
| 973 |
+
done: true
|
| 974 |
+
};
|
| 975 |
+
}
|
| 976 |
+
|
| 977 |
+
this[INTERNAL].index = index + 1;
|
| 978 |
+
|
| 979 |
+
return {
|
| 980 |
+
value: values[index],
|
| 981 |
+
done: false
|
| 982 |
+
};
|
| 983 |
+
}
|
| 984 |
+
}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
|
| 985 |
+
|
| 986 |
+
Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
|
| 987 |
+
value: 'HeadersIterator',
|
| 988 |
+
writable: false,
|
| 989 |
+
enumerable: false,
|
| 990 |
+
configurable: true
|
| 991 |
+
});
|
| 992 |
+
|
| 993 |
+
/**
|
| 994 |
+
* Export the Headers object in a form that Node.js can consume.
|
| 995 |
+
*
|
| 996 |
+
* @param Headers headers
|
| 997 |
+
* @return Object
|
| 998 |
+
*/
|
| 999 |
+
function exportNodeCompatibleHeaders(headers) {
|
| 1000 |
+
const obj = Object.assign({ __proto__: null }, headers[MAP]);
|
| 1001 |
+
|
| 1002 |
+
// http.request() only supports string as Host header. This hack makes
|
| 1003 |
+
// specifying custom Host header possible.
|
| 1004 |
+
const hostHeaderKey = find(headers[MAP], 'Host');
|
| 1005 |
+
if (hostHeaderKey !== undefined) {
|
| 1006 |
+
obj[hostHeaderKey] = obj[hostHeaderKey][0];
|
| 1007 |
+
}
|
| 1008 |
+
|
| 1009 |
+
return obj;
|
| 1010 |
+
}
|
| 1011 |
+
|
| 1012 |
+
/**
|
| 1013 |
+
* Create a Headers object from an object of headers, ignoring those that do
|
| 1014 |
+
* not conform to HTTP grammar productions.
|
| 1015 |
+
*
|
| 1016 |
+
* @param Object obj Object of headers
|
| 1017 |
+
* @return Headers
|
| 1018 |
+
*/
|
| 1019 |
+
function createHeadersLenient(obj) {
|
| 1020 |
+
const headers = new Headers();
|
| 1021 |
+
for (const name of Object.keys(obj)) {
|
| 1022 |
+
if (invalidTokenRegex.test(name)) {
|
| 1023 |
+
continue;
|
| 1024 |
+
}
|
| 1025 |
+
if (Array.isArray(obj[name])) {
|
| 1026 |
+
for (const val of obj[name]) {
|
| 1027 |
+
if (invalidHeaderCharRegex.test(val)) {
|
| 1028 |
+
continue;
|
| 1029 |
+
}
|
| 1030 |
+
if (headers[MAP][name] === undefined) {
|
| 1031 |
+
headers[MAP][name] = [val];
|
| 1032 |
+
} else {
|
| 1033 |
+
headers[MAP][name].push(val);
|
| 1034 |
+
}
|
| 1035 |
+
}
|
| 1036 |
+
} else if (!invalidHeaderCharRegex.test(obj[name])) {
|
| 1037 |
+
headers[MAP][name] = [obj[name]];
|
| 1038 |
+
}
|
| 1039 |
+
}
|
| 1040 |
+
return headers;
|
| 1041 |
+
}
|
| 1042 |
+
|
| 1043 |
+
const INTERNALS$1 = Symbol('Response internals');
|
| 1044 |
+
|
| 1045 |
+
// fix an issue where "STATUS_CODES" aren't a named export for node <10
|
| 1046 |
+
const STATUS_CODES = http.STATUS_CODES;
|
| 1047 |
+
|
| 1048 |
+
/**
|
| 1049 |
+
* Response class
|
| 1050 |
+
*
|
| 1051 |
+
* @param Stream body Readable stream
|
| 1052 |
+
* @param Object opts Response options
|
| 1053 |
+
* @return Void
|
| 1054 |
+
*/
|
| 1055 |
+
class Response {
|
| 1056 |
+
constructor() {
|
| 1057 |
+
let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
| 1058 |
+
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1059 |
+
|
| 1060 |
+
Body.call(this, body, opts);
|
| 1061 |
+
|
| 1062 |
+
const status = opts.status || 200;
|
| 1063 |
+
const headers = new Headers(opts.headers);
|
| 1064 |
+
|
| 1065 |
+
if (body != null && !headers.has('Content-Type')) {
|
| 1066 |
+
const contentType = extractContentType(body);
|
| 1067 |
+
if (contentType) {
|
| 1068 |
+
headers.append('Content-Type', contentType);
|
| 1069 |
+
}
|
| 1070 |
+
}
|
| 1071 |
+
|
| 1072 |
+
this[INTERNALS$1] = {
|
| 1073 |
+
url: opts.url,
|
| 1074 |
+
status,
|
| 1075 |
+
statusText: opts.statusText || STATUS_CODES[status],
|
| 1076 |
+
headers,
|
| 1077 |
+
counter: opts.counter
|
| 1078 |
+
};
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
get url() {
|
| 1082 |
+
return this[INTERNALS$1].url || '';
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
+
get status() {
|
| 1086 |
+
return this[INTERNALS$1].status;
|
| 1087 |
+
}
|
| 1088 |
+
|
| 1089 |
+
/**
|
| 1090 |
+
* Convenience property representing if the request ended normally
|
| 1091 |
+
*/
|
| 1092 |
+
get ok() {
|
| 1093 |
+
return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
|
| 1094 |
+
}
|
| 1095 |
+
|
| 1096 |
+
get redirected() {
|
| 1097 |
+
return this[INTERNALS$1].counter > 0;
|
| 1098 |
+
}
|
| 1099 |
+
|
| 1100 |
+
get statusText() {
|
| 1101 |
+
return this[INTERNALS$1].statusText;
|
| 1102 |
+
}
|
| 1103 |
+
|
| 1104 |
+
get headers() {
|
| 1105 |
+
return this[INTERNALS$1].headers;
|
| 1106 |
+
}
|
| 1107 |
+
|
| 1108 |
+
/**
|
| 1109 |
+
* Clone this response
|
| 1110 |
+
*
|
| 1111 |
+
* @return Response
|
| 1112 |
+
*/
|
| 1113 |
+
clone() {
|
| 1114 |
+
return new Response(clone(this), {
|
| 1115 |
+
url: this.url,
|
| 1116 |
+
status: this.status,
|
| 1117 |
+
statusText: this.statusText,
|
| 1118 |
+
headers: this.headers,
|
| 1119 |
+
ok: this.ok,
|
| 1120 |
+
redirected: this.redirected
|
| 1121 |
+
});
|
| 1122 |
+
}
|
| 1123 |
+
}
|
| 1124 |
+
|
| 1125 |
+
Body.mixIn(Response.prototype);
|
| 1126 |
+
|
| 1127 |
+
Object.defineProperties(Response.prototype, {
|
| 1128 |
+
url: { enumerable: true },
|
| 1129 |
+
status: { enumerable: true },
|
| 1130 |
+
ok: { enumerable: true },
|
| 1131 |
+
redirected: { enumerable: true },
|
| 1132 |
+
statusText: { enumerable: true },
|
| 1133 |
+
headers: { enumerable: true },
|
| 1134 |
+
clone: { enumerable: true }
|
| 1135 |
+
});
|
| 1136 |
+
|
| 1137 |
+
Object.defineProperty(Response.prototype, Symbol.toStringTag, {
|
| 1138 |
+
value: 'Response',
|
| 1139 |
+
writable: false,
|
| 1140 |
+
enumerable: false,
|
| 1141 |
+
configurable: true
|
| 1142 |
+
});
|
| 1143 |
+
|
| 1144 |
+
const INTERNALS$2 = Symbol('Request internals');
|
| 1145 |
+
const URL = Url.URL || whatwgUrl.URL;
|
| 1146 |
+
|
| 1147 |
+
// fix an issue where "format", "parse" aren't a named export for node <10
|
| 1148 |
+
const parse_url = Url.parse;
|
| 1149 |
+
const format_url = Url.format;
|
| 1150 |
+
|
| 1151 |
+
/**
|
| 1152 |
+
* Wrapper around `new URL` to handle arbitrary URLs
|
| 1153 |
+
*
|
| 1154 |
+
* @param {string} urlStr
|
| 1155 |
+
* @return {void}
|
| 1156 |
+
*/
|
| 1157 |
+
function parseURL(urlStr) {
|
| 1158 |
+
/*
|
| 1159 |
+
Check whether the URL is absolute or not
|
| 1160 |
+
Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
|
| 1161 |
+
Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
|
| 1162 |
+
*/
|
| 1163 |
+
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
|
| 1164 |
+
urlStr = new URL(urlStr).toString();
|
| 1165 |
+
}
|
| 1166 |
+
|
| 1167 |
+
// Fallback to old implementation for arbitrary URLs
|
| 1168 |
+
return parse_url(urlStr);
|
| 1169 |
+
}
|
| 1170 |
+
|
| 1171 |
+
const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
|
| 1172 |
+
|
| 1173 |
+
/**
|
| 1174 |
+
* Check if a value is an instance of Request.
|
| 1175 |
+
*
|
| 1176 |
+
* @param Mixed input
|
| 1177 |
+
* @return Boolean
|
| 1178 |
+
*/
|
| 1179 |
+
function isRequest(input) {
|
| 1180 |
+
return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
|
| 1181 |
+
}
|
| 1182 |
+
|
| 1183 |
+
function isAbortSignal(signal) {
|
| 1184 |
+
const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
|
| 1185 |
+
return !!(proto && proto.constructor.name === 'AbortSignal');
|
| 1186 |
+
}
|
| 1187 |
+
|
| 1188 |
+
/**
|
| 1189 |
+
* Request class
|
| 1190 |
+
*
|
| 1191 |
+
* @param Mixed input Url or Request instance
|
| 1192 |
+
* @param Object init Custom options
|
| 1193 |
+
* @return Void
|
| 1194 |
+
*/
|
| 1195 |
+
class Request {
|
| 1196 |
+
constructor(input) {
|
| 1197 |
+
let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1198 |
+
|
| 1199 |
+
let parsedURL;
|
| 1200 |
+
|
| 1201 |
+
// normalize input
|
| 1202 |
+
if (!isRequest(input)) {
|
| 1203 |
+
if (input && input.href) {
|
| 1204 |
+
// in order to support Node.js' Url objects; though WHATWG's URL objects
|
| 1205 |
+
// will fall into this branch also (since their `toString()` will return
|
| 1206 |
+
// `href` property anyway)
|
| 1207 |
+
parsedURL = parseURL(input.href);
|
| 1208 |
+
} else {
|
| 1209 |
+
// coerce input to a string before attempting to parse
|
| 1210 |
+
parsedURL = parseURL(`${input}`);
|
| 1211 |
+
}
|
| 1212 |
+
input = {};
|
| 1213 |
+
} else {
|
| 1214 |
+
parsedURL = parseURL(input.url);
|
| 1215 |
+
}
|
| 1216 |
+
|
| 1217 |
+
let method = init.method || input.method || 'GET';
|
| 1218 |
+
method = method.toUpperCase();
|
| 1219 |
+
|
| 1220 |
+
if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
|
| 1221 |
+
throw new TypeError('Request with GET/HEAD method cannot have body');
|
| 1222 |
+
}
|
| 1223 |
+
|
| 1224 |
+
let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
|
| 1225 |
+
|
| 1226 |
+
Body.call(this, inputBody, {
|
| 1227 |
+
timeout: init.timeout || input.timeout || 0,
|
| 1228 |
+
size: init.size || input.size || 0
|
| 1229 |
+
});
|
| 1230 |
+
|
| 1231 |
+
const headers = new Headers(init.headers || input.headers || {});
|
| 1232 |
+
|
| 1233 |
+
if (inputBody != null && !headers.has('Content-Type')) {
|
| 1234 |
+
const contentType = extractContentType(inputBody);
|
| 1235 |
+
if (contentType) {
|
| 1236 |
+
headers.append('Content-Type', contentType);
|
| 1237 |
+
}
|
| 1238 |
+
}
|
| 1239 |
+
|
| 1240 |
+
let signal = isRequest(input) ? input.signal : null;
|
| 1241 |
+
if ('signal' in init) signal = init.signal;
|
| 1242 |
+
|
| 1243 |
+
if (signal != null && !isAbortSignal(signal)) {
|
| 1244 |
+
throw new TypeError('Expected signal to be an instanceof AbortSignal');
|
| 1245 |
+
}
|
| 1246 |
+
|
| 1247 |
+
this[INTERNALS$2] = {
|
| 1248 |
+
method,
|
| 1249 |
+
redirect: init.redirect || input.redirect || 'follow',
|
| 1250 |
+
headers,
|
| 1251 |
+
parsedURL,
|
| 1252 |
+
signal
|
| 1253 |
+
};
|
| 1254 |
+
|
| 1255 |
+
// node-fetch-only options
|
| 1256 |
+
this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
|
| 1257 |
+
this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
|
| 1258 |
+
this.counter = init.counter || input.counter || 0;
|
| 1259 |
+
this.agent = init.agent || input.agent;
|
| 1260 |
+
}
|
| 1261 |
+
|
| 1262 |
+
get method() {
|
| 1263 |
+
return this[INTERNALS$2].method;
|
| 1264 |
+
}
|
| 1265 |
+
|
| 1266 |
+
get url() {
|
| 1267 |
+
return format_url(this[INTERNALS$2].parsedURL);
|
| 1268 |
+
}
|
| 1269 |
+
|
| 1270 |
+
get headers() {
|
| 1271 |
+
return this[INTERNALS$2].headers;
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
get redirect() {
|
| 1275 |
+
return this[INTERNALS$2].redirect;
|
| 1276 |
+
}
|
| 1277 |
+
|
| 1278 |
+
get signal() {
|
| 1279 |
+
return this[INTERNALS$2].signal;
|
| 1280 |
+
}
|
| 1281 |
+
|
| 1282 |
+
/**
|
| 1283 |
+
* Clone this request
|
| 1284 |
+
*
|
| 1285 |
+
* @return Request
|
| 1286 |
+
*/
|
| 1287 |
+
clone() {
|
| 1288 |
+
return new Request(this);
|
| 1289 |
+
}
|
| 1290 |
+
}
|
| 1291 |
+
|
| 1292 |
+
Body.mixIn(Request.prototype);
|
| 1293 |
+
|
| 1294 |
+
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
|
| 1295 |
+
value: 'Request',
|
| 1296 |
+
writable: false,
|
| 1297 |
+
enumerable: false,
|
| 1298 |
+
configurable: true
|
| 1299 |
+
});
|
| 1300 |
+
|
| 1301 |
+
Object.defineProperties(Request.prototype, {
|
| 1302 |
+
method: { enumerable: true },
|
| 1303 |
+
url: { enumerable: true },
|
| 1304 |
+
headers: { enumerable: true },
|
| 1305 |
+
redirect: { enumerable: true },
|
| 1306 |
+
clone: { enumerable: true },
|
| 1307 |
+
signal: { enumerable: true }
|
| 1308 |
+
});
|
| 1309 |
+
|
| 1310 |
+
/**
|
| 1311 |
+
* Convert a Request to Node.js http request options.
|
| 1312 |
+
*
|
| 1313 |
+
* @param Request A Request instance
|
| 1314 |
+
* @return Object The options object to be passed to http.request
|
| 1315 |
+
*/
|
| 1316 |
+
function getNodeRequestOptions(request) {
|
| 1317 |
+
const parsedURL = request[INTERNALS$2].parsedURL;
|
| 1318 |
+
const headers = new Headers(request[INTERNALS$2].headers);
|
| 1319 |
+
|
| 1320 |
+
// fetch step 1.3
|
| 1321 |
+
if (!headers.has('Accept')) {
|
| 1322 |
+
headers.set('Accept', '*/*');
|
| 1323 |
+
}
|
| 1324 |
+
|
| 1325 |
+
// Basic fetch
|
| 1326 |
+
if (!parsedURL.protocol || !parsedURL.hostname) {
|
| 1327 |
+
throw new TypeError('Only absolute URLs are supported');
|
| 1328 |
+
}
|
| 1329 |
+
|
| 1330 |
+
if (!/^https?:$/.test(parsedURL.protocol)) {
|
| 1331 |
+
throw new TypeError('Only HTTP(S) protocols are supported');
|
| 1332 |
+
}
|
| 1333 |
+
|
| 1334 |
+
if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
|
| 1335 |
+
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
|
| 1336 |
+
}
|
| 1337 |
+
|
| 1338 |
+
// HTTP-network-or-cache fetch steps 2.4-2.7
|
| 1339 |
+
let contentLengthValue = null;
|
| 1340 |
+
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
|
| 1341 |
+
contentLengthValue = '0';
|
| 1342 |
+
}
|
| 1343 |
+
if (request.body != null) {
|
| 1344 |
+
const totalBytes = getTotalBytes(request);
|
| 1345 |
+
if (typeof totalBytes === 'number') {
|
| 1346 |
+
contentLengthValue = String(totalBytes);
|
| 1347 |
+
}
|
| 1348 |
+
}
|
| 1349 |
+
if (contentLengthValue) {
|
| 1350 |
+
headers.set('Content-Length', contentLengthValue);
|
| 1351 |
+
}
|
| 1352 |
+
|
| 1353 |
+
// HTTP-network-or-cache fetch step 2.11
|
| 1354 |
+
if (!headers.has('User-Agent')) {
|
| 1355 |
+
headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
|
| 1356 |
+
}
|
| 1357 |
+
|
| 1358 |
+
// HTTP-network-or-cache fetch step 2.15
|
| 1359 |
+
if (request.compress && !headers.has('Accept-Encoding')) {
|
| 1360 |
+
headers.set('Accept-Encoding', 'gzip,deflate');
|
| 1361 |
+
}
|
| 1362 |
+
|
| 1363 |
+
let agent = request.agent;
|
| 1364 |
+
if (typeof agent === 'function') {
|
| 1365 |
+
agent = agent(parsedURL);
|
| 1366 |
+
}
|
| 1367 |
+
|
| 1368 |
+
if (!headers.has('Connection') && !agent) {
|
| 1369 |
+
headers.set('Connection', 'close');
|
| 1370 |
+
}
|
| 1371 |
+
|
| 1372 |
+
// HTTP-network fetch step 4.2
|
| 1373 |
+
// chunked encoding is handled by Node.js
|
| 1374 |
+
|
| 1375 |
+
return Object.assign({}, parsedURL, {
|
| 1376 |
+
method: request.method,
|
| 1377 |
+
headers: exportNodeCompatibleHeaders(headers),
|
| 1378 |
+
agent
|
| 1379 |
+
});
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
+
/**
|
| 1383 |
+
* abort-error.js
|
| 1384 |
+
*
|
| 1385 |
+
* AbortError interface for cancelled requests
|
| 1386 |
+
*/
|
| 1387 |
+
|
| 1388 |
+
/**
|
| 1389 |
+
* Create AbortError instance
|
| 1390 |
+
*
|
| 1391 |
+
* @param String message Error message for human
|
| 1392 |
+
* @return AbortError
|
| 1393 |
+
*/
|
| 1394 |
+
function AbortError(message) {
|
| 1395 |
+
Error.call(this, message);
|
| 1396 |
+
|
| 1397 |
+
this.type = 'aborted';
|
| 1398 |
+
this.message = message;
|
| 1399 |
+
|
| 1400 |
+
// hide custom error implementation details from end-users
|
| 1401 |
+
Error.captureStackTrace(this, this.constructor);
|
| 1402 |
+
}
|
| 1403 |
+
|
| 1404 |
+
AbortError.prototype = Object.create(Error.prototype);
|
| 1405 |
+
AbortError.prototype.constructor = AbortError;
|
| 1406 |
+
AbortError.prototype.name = 'AbortError';
|
| 1407 |
+
|
| 1408 |
+
const URL$1 = Url.URL || whatwgUrl.URL;
|
| 1409 |
+
|
| 1410 |
+
// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
|
| 1411 |
+
const PassThrough$1 = Stream.PassThrough;
|
| 1412 |
+
|
| 1413 |
+
const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
|
| 1414 |
+
const orig = new URL$1(original).hostname;
|
| 1415 |
+
const dest = new URL$1(destination).hostname;
|
| 1416 |
+
|
| 1417 |
+
return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
|
| 1418 |
+
};
|
| 1419 |
+
|
| 1420 |
+
/**
|
| 1421 |
+
* isSameProtocol reports whether the two provided URLs use the same protocol.
|
| 1422 |
+
*
|
| 1423 |
+
* Both domains must already be in canonical form.
|
| 1424 |
+
* @param {string|URL} original
|
| 1425 |
+
* @param {string|URL} destination
|
| 1426 |
+
*/
|
| 1427 |
+
const isSameProtocol = function isSameProtocol(destination, original) {
|
| 1428 |
+
const orig = new URL$1(original).protocol;
|
| 1429 |
+
const dest = new URL$1(destination).protocol;
|
| 1430 |
+
|
| 1431 |
+
return orig === dest;
|
| 1432 |
+
};
|
| 1433 |
+
|
| 1434 |
+
/**
|
| 1435 |
+
* Fetch function
|
| 1436 |
+
*
|
| 1437 |
+
* @param Mixed url Absolute url or Request instance
|
| 1438 |
+
* @param Object opts Fetch options
|
| 1439 |
+
* @return Promise
|
| 1440 |
+
*/
|
| 1441 |
+
function fetch(url, opts) {
|
| 1442 |
+
|
| 1443 |
+
// allow custom promise
|
| 1444 |
+
if (!fetch.Promise) {
|
| 1445 |
+
throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
|
| 1446 |
+
}
|
| 1447 |
+
|
| 1448 |
+
Body.Promise = fetch.Promise;
|
| 1449 |
+
|
| 1450 |
+
// wrap http.request into fetch
|
| 1451 |
+
return new fetch.Promise(function (resolve, reject) {
|
| 1452 |
+
// build request object
|
| 1453 |
+
const request = new Request(url, opts);
|
| 1454 |
+
const options = getNodeRequestOptions(request);
|
| 1455 |
+
|
| 1456 |
+
const send = (options.protocol === 'https:' ? https : http).request;
|
| 1457 |
+
const signal = request.signal;
|
| 1458 |
+
|
| 1459 |
+
let response = null;
|
| 1460 |
+
|
| 1461 |
+
const abort = function abort() {
|
| 1462 |
+
let error = new AbortError('The user aborted a request.');
|
| 1463 |
+
reject(error);
|
| 1464 |
+
if (request.body && request.body instanceof Stream.Readable) {
|
| 1465 |
+
destroyStream(request.body, error);
|
| 1466 |
+
}
|
| 1467 |
+
if (!response || !response.body) return;
|
| 1468 |
+
response.body.emit('error', error);
|
| 1469 |
+
};
|
| 1470 |
+
|
| 1471 |
+
if (signal && signal.aborted) {
|
| 1472 |
+
abort();
|
| 1473 |
+
return;
|
| 1474 |
+
}
|
| 1475 |
+
|
| 1476 |
+
const abortAndFinalize = function abortAndFinalize() {
|
| 1477 |
+
abort();
|
| 1478 |
+
finalize();
|
| 1479 |
+
};
|
| 1480 |
+
|
| 1481 |
+
// send request
|
| 1482 |
+
const req = send(options);
|
| 1483 |
+
let reqTimeout;
|
| 1484 |
+
|
| 1485 |
+
if (signal) {
|
| 1486 |
+
signal.addEventListener('abort', abortAndFinalize);
|
| 1487 |
+
}
|
| 1488 |
+
|
| 1489 |
+
function finalize() {
|
| 1490 |
+
req.abort();
|
| 1491 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1492 |
+
clearTimeout(reqTimeout);
|
| 1493 |
+
}
|
| 1494 |
+
|
| 1495 |
+
if (request.timeout) {
|
| 1496 |
+
req.once('socket', function (socket) {
|
| 1497 |
+
reqTimeout = setTimeout(function () {
|
| 1498 |
+
reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
|
| 1499 |
+
finalize();
|
| 1500 |
+
}, request.timeout);
|
| 1501 |
+
});
|
| 1502 |
+
}
|
| 1503 |
+
|
| 1504 |
+
req.on('error', function (err) {
|
| 1505 |
+
reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
|
| 1506 |
+
|
| 1507 |
+
if (response && response.body) {
|
| 1508 |
+
destroyStream(response.body, err);
|
| 1509 |
+
}
|
| 1510 |
+
|
| 1511 |
+
finalize();
|
| 1512 |
+
});
|
| 1513 |
+
|
| 1514 |
+
fixResponseChunkedTransferBadEnding(req, function (err) {
|
| 1515 |
+
if (signal && signal.aborted) {
|
| 1516 |
+
return;
|
| 1517 |
+
}
|
| 1518 |
+
|
| 1519 |
+
if (response && response.body) {
|
| 1520 |
+
destroyStream(response.body, err);
|
| 1521 |
+
}
|
| 1522 |
+
});
|
| 1523 |
+
|
| 1524 |
+
/* c8 ignore next 18 */
|
| 1525 |
+
if (parseInt(process.version.substring(1)) < 14) {
|
| 1526 |
+
// Before Node.js 14, pipeline() does not fully support async iterators and does not always
|
| 1527 |
+
// properly handle when the socket close/end events are out of order.
|
| 1528 |
+
req.on('socket', function (s) {
|
| 1529 |
+
s.addListener('close', function (hadError) {
|
| 1530 |
+
// if a data listener is still present we didn't end cleanly
|
| 1531 |
+
const hasDataListener = s.listenerCount('data') > 0;
|
| 1532 |
+
|
| 1533 |
+
// if end happened before close but the socket didn't emit an error, do it now
|
| 1534 |
+
if (response && hasDataListener && !hadError && !(signal && signal.aborted)) {
|
| 1535 |
+
const err = new Error('Premature close');
|
| 1536 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1537 |
+
response.body.emit('error', err);
|
| 1538 |
+
}
|
| 1539 |
+
});
|
| 1540 |
+
});
|
| 1541 |
+
}
|
| 1542 |
+
|
| 1543 |
+
req.on('response', function (res) {
|
| 1544 |
+
clearTimeout(reqTimeout);
|
| 1545 |
+
|
| 1546 |
+
const headers = createHeadersLenient(res.headers);
|
| 1547 |
+
|
| 1548 |
+
// HTTP fetch step 5
|
| 1549 |
+
if (fetch.isRedirect(res.statusCode)) {
|
| 1550 |
+
// HTTP fetch step 5.2
|
| 1551 |
+
const location = headers.get('Location');
|
| 1552 |
+
|
| 1553 |
+
// HTTP fetch step 5.3
|
| 1554 |
+
let locationURL = null;
|
| 1555 |
+
try {
|
| 1556 |
+
locationURL = location === null ? null : new URL$1(location, request.url).toString();
|
| 1557 |
+
} catch (err) {
|
| 1558 |
+
// error here can only be invalid URL in Location: header
|
| 1559 |
+
// do not throw when options.redirect == manual
|
| 1560 |
+
// let the user extract the errorneous redirect URL
|
| 1561 |
+
if (request.redirect !== 'manual') {
|
| 1562 |
+
reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
|
| 1563 |
+
finalize();
|
| 1564 |
+
return;
|
| 1565 |
+
}
|
| 1566 |
+
}
|
| 1567 |
+
|
| 1568 |
+
// HTTP fetch step 5.5
|
| 1569 |
+
switch (request.redirect) {
|
| 1570 |
+
case 'error':
|
| 1571 |
+
reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
|
| 1572 |
+
finalize();
|
| 1573 |
+
return;
|
| 1574 |
+
case 'manual':
|
| 1575 |
+
// node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
|
| 1576 |
+
if (locationURL !== null) {
|
| 1577 |
+
// handle corrupted header
|
| 1578 |
+
try {
|
| 1579 |
+
headers.set('Location', locationURL);
|
| 1580 |
+
} catch (err) {
|
| 1581 |
+
// istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
|
| 1582 |
+
reject(err);
|
| 1583 |
+
}
|
| 1584 |
+
}
|
| 1585 |
+
break;
|
| 1586 |
+
case 'follow':
|
| 1587 |
+
// HTTP-redirect fetch step 2
|
| 1588 |
+
if (locationURL === null) {
|
| 1589 |
+
break;
|
| 1590 |
+
}
|
| 1591 |
+
|
| 1592 |
+
// HTTP-redirect fetch step 5
|
| 1593 |
+
if (request.counter >= request.follow) {
|
| 1594 |
+
reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
|
| 1595 |
+
finalize();
|
| 1596 |
+
return;
|
| 1597 |
+
}
|
| 1598 |
+
|
| 1599 |
+
// HTTP-redirect fetch step 6 (counter increment)
|
| 1600 |
+
// Create a new Request object.
|
| 1601 |
+
const requestOpts = {
|
| 1602 |
+
headers: new Headers(request.headers),
|
| 1603 |
+
follow: request.follow,
|
| 1604 |
+
counter: request.counter + 1,
|
| 1605 |
+
agent: request.agent,
|
| 1606 |
+
compress: request.compress,
|
| 1607 |
+
method: request.method,
|
| 1608 |
+
body: request.body,
|
| 1609 |
+
signal: request.signal,
|
| 1610 |
+
timeout: request.timeout,
|
| 1611 |
+
size: request.size
|
| 1612 |
+
};
|
| 1613 |
+
|
| 1614 |
+
if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) {
|
| 1615 |
+
for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
|
| 1616 |
+
requestOpts.headers.delete(name);
|
| 1617 |
+
}
|
| 1618 |
+
}
|
| 1619 |
+
|
| 1620 |
+
// HTTP-redirect fetch step 9
|
| 1621 |
+
if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
|
| 1622 |
+
reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
|
| 1623 |
+
finalize();
|
| 1624 |
+
return;
|
| 1625 |
+
}
|
| 1626 |
+
|
| 1627 |
+
// HTTP-redirect fetch step 11
|
| 1628 |
+
if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
|
| 1629 |
+
requestOpts.method = 'GET';
|
| 1630 |
+
requestOpts.body = undefined;
|
| 1631 |
+
requestOpts.headers.delete('content-length');
|
| 1632 |
+
}
|
| 1633 |
+
|
| 1634 |
+
// HTTP-redirect fetch step 15
|
| 1635 |
+
resolve(fetch(new Request(locationURL, requestOpts)));
|
| 1636 |
+
finalize();
|
| 1637 |
+
return;
|
| 1638 |
+
}
|
| 1639 |
+
}
|
| 1640 |
+
|
| 1641 |
+
// prepare response
|
| 1642 |
+
res.once('end', function () {
|
| 1643 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1644 |
+
});
|
| 1645 |
+
let body = res.pipe(new PassThrough$1());
|
| 1646 |
+
|
| 1647 |
+
const response_options = {
|
| 1648 |
+
url: request.url,
|
| 1649 |
+
status: res.statusCode,
|
| 1650 |
+
statusText: res.statusMessage,
|
| 1651 |
+
headers: headers,
|
| 1652 |
+
size: request.size,
|
| 1653 |
+
timeout: request.timeout,
|
| 1654 |
+
counter: request.counter
|
| 1655 |
+
};
|
| 1656 |
+
|
| 1657 |
+
// HTTP-network fetch step 12.1.1.3
|
| 1658 |
+
const codings = headers.get('Content-Encoding');
|
| 1659 |
+
|
| 1660 |
+
// HTTP-network fetch step 12.1.1.4: handle content codings
|
| 1661 |
+
|
| 1662 |
+
// in following scenarios we ignore compression support
|
| 1663 |
+
// 1. compression support is disabled
|
| 1664 |
+
// 2. HEAD request
|
| 1665 |
+
// 3. no Content-Encoding header
|
| 1666 |
+
// 4. no content response (204)
|
| 1667 |
+
// 5. content not modified response (304)
|
| 1668 |
+
if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
| 1669 |
+
response = new Response(body, response_options);
|
| 1670 |
+
resolve(response);
|
| 1671 |
+
return;
|
| 1672 |
+
}
|
| 1673 |
+
|
| 1674 |
+
// For Node v6+
|
| 1675 |
+
// Be less strict when decoding compressed responses, since sometimes
|
| 1676 |
+
// servers send slightly invalid responses that are still accepted
|
| 1677 |
+
// by common browsers.
|
| 1678 |
+
// Always using Z_SYNC_FLUSH is what cURL does.
|
| 1679 |
+
const zlibOptions = {
|
| 1680 |
+
flush: zlib.Z_SYNC_FLUSH,
|
| 1681 |
+
finishFlush: zlib.Z_SYNC_FLUSH
|
| 1682 |
+
};
|
| 1683 |
+
|
| 1684 |
+
// for gzip
|
| 1685 |
+
if (codings == 'gzip' || codings == 'x-gzip') {
|
| 1686 |
+
body = body.pipe(zlib.createGunzip(zlibOptions));
|
| 1687 |
+
response = new Response(body, response_options);
|
| 1688 |
+
resolve(response);
|
| 1689 |
+
return;
|
| 1690 |
+
}
|
| 1691 |
+
|
| 1692 |
+
// for deflate
|
| 1693 |
+
if (codings == 'deflate' || codings == 'x-deflate') {
|
| 1694 |
+
// handle the infamous raw deflate response from old servers
|
| 1695 |
+
// a hack for old IIS and Apache servers
|
| 1696 |
+
const raw = res.pipe(new PassThrough$1());
|
| 1697 |
+
raw.once('data', function (chunk) {
|
| 1698 |
+
// see http://stackoverflow.com/questions/37519828
|
| 1699 |
+
if ((chunk[0] & 0x0F) === 0x08) {
|
| 1700 |
+
body = body.pipe(zlib.createInflate());
|
| 1701 |
+
} else {
|
| 1702 |
+
body = body.pipe(zlib.createInflateRaw());
|
| 1703 |
+
}
|
| 1704 |
+
response = new Response(body, response_options);
|
| 1705 |
+
resolve(response);
|
| 1706 |
+
});
|
| 1707 |
+
raw.on('end', function () {
|
| 1708 |
+
// some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted.
|
| 1709 |
+
if (!response) {
|
| 1710 |
+
response = new Response(body, response_options);
|
| 1711 |
+
resolve(response);
|
| 1712 |
+
}
|
| 1713 |
+
});
|
| 1714 |
+
return;
|
| 1715 |
+
}
|
| 1716 |
+
|
| 1717 |
+
// for br
|
| 1718 |
+
if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
|
| 1719 |
+
body = body.pipe(zlib.createBrotliDecompress());
|
| 1720 |
+
response = new Response(body, response_options);
|
| 1721 |
+
resolve(response);
|
| 1722 |
+
return;
|
| 1723 |
+
}
|
| 1724 |
+
|
| 1725 |
+
// otherwise, use response as-is
|
| 1726 |
+
response = new Response(body, response_options);
|
| 1727 |
+
resolve(response);
|
| 1728 |
+
});
|
| 1729 |
+
|
| 1730 |
+
writeToStream(req, request);
|
| 1731 |
+
});
|
| 1732 |
+
}
|
| 1733 |
+
function fixResponseChunkedTransferBadEnding(request, errorCallback) {
|
| 1734 |
+
let socket;
|
| 1735 |
+
|
| 1736 |
+
request.on('socket', function (s) {
|
| 1737 |
+
socket = s;
|
| 1738 |
+
});
|
| 1739 |
+
|
| 1740 |
+
request.on('response', function (response) {
|
| 1741 |
+
const headers = response.headers;
|
| 1742 |
+
|
| 1743 |
+
if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) {
|
| 1744 |
+
response.once('close', function (hadError) {
|
| 1745 |
+
// if a data listener is still present we didn't end cleanly
|
| 1746 |
+
const hasDataListener = socket.listenerCount('data') > 0;
|
| 1747 |
+
|
| 1748 |
+
if (hasDataListener && !hadError) {
|
| 1749 |
+
const err = new Error('Premature close');
|
| 1750 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1751 |
+
errorCallback(err);
|
| 1752 |
+
}
|
| 1753 |
+
});
|
| 1754 |
+
}
|
| 1755 |
+
});
|
| 1756 |
+
}
|
| 1757 |
+
|
| 1758 |
+
function destroyStream(stream, err) {
|
| 1759 |
+
if (stream.destroy) {
|
| 1760 |
+
stream.destroy(err);
|
| 1761 |
+
} else {
|
| 1762 |
+
// node < 8
|
| 1763 |
+
stream.emit('error', err);
|
| 1764 |
+
stream.end();
|
| 1765 |
+
}
|
| 1766 |
+
}
|
| 1767 |
+
|
| 1768 |
+
/**
|
| 1769 |
+
* Redirect code matching
|
| 1770 |
+
*
|
| 1771 |
+
* @param Number code Status code
|
| 1772 |
+
* @return Boolean
|
| 1773 |
+
*/
|
| 1774 |
+
fetch.isRedirect = function (code) {
|
| 1775 |
+
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
|
| 1776 |
+
};
|
| 1777 |
+
|
| 1778 |
+
// expose Promise
|
| 1779 |
+
fetch.Promise = global.Promise;
|
| 1780 |
+
|
| 1781 |
+
module.exports = exports = fetch;
|
| 1782 |
+
Object.defineProperty(exports, "__esModule", { value: true });
|
| 1783 |
+
exports.default = exports;
|
| 1784 |
+
exports.Headers = Headers;
|
| 1785 |
+
exports.Request = Request;
|
| 1786 |
+
exports.Response = Response;
|
| 1787 |
+
exports.FetchError = FetchError;
|
node_modules/node-fetch/lib/index.mjs
ADDED
|
@@ -0,0 +1,1776 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Stream from 'stream';
|
| 2 |
+
import http from 'http';
|
| 3 |
+
import Url from 'url';
|
| 4 |
+
import whatwgUrl from 'whatwg-url';
|
| 5 |
+
import https from 'https';
|
| 6 |
+
import zlib from 'zlib';
|
| 7 |
+
|
| 8 |
+
// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
|
| 9 |
+
|
| 10 |
+
// fix for "Readable" isn't a named export issue
|
| 11 |
+
const Readable = Stream.Readable;
|
| 12 |
+
|
| 13 |
+
const BUFFER = Symbol('buffer');
|
| 14 |
+
const TYPE = Symbol('type');
|
| 15 |
+
|
| 16 |
+
class Blob {
|
| 17 |
+
constructor() {
|
| 18 |
+
this[TYPE] = '';
|
| 19 |
+
|
| 20 |
+
const blobParts = arguments[0];
|
| 21 |
+
const options = arguments[1];
|
| 22 |
+
|
| 23 |
+
const buffers = [];
|
| 24 |
+
let size = 0;
|
| 25 |
+
|
| 26 |
+
if (blobParts) {
|
| 27 |
+
const a = blobParts;
|
| 28 |
+
const length = Number(a.length);
|
| 29 |
+
for (let i = 0; i < length; i++) {
|
| 30 |
+
const element = a[i];
|
| 31 |
+
let buffer;
|
| 32 |
+
if (element instanceof Buffer) {
|
| 33 |
+
buffer = element;
|
| 34 |
+
} else if (ArrayBuffer.isView(element)) {
|
| 35 |
+
buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
|
| 36 |
+
} else if (element instanceof ArrayBuffer) {
|
| 37 |
+
buffer = Buffer.from(element);
|
| 38 |
+
} else if (element instanceof Blob) {
|
| 39 |
+
buffer = element[BUFFER];
|
| 40 |
+
} else {
|
| 41 |
+
buffer = Buffer.from(typeof element === 'string' ? element : String(element));
|
| 42 |
+
}
|
| 43 |
+
size += buffer.length;
|
| 44 |
+
buffers.push(buffer);
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
this[BUFFER] = Buffer.concat(buffers);
|
| 49 |
+
|
| 50 |
+
let type = options && options.type !== undefined && String(options.type).toLowerCase();
|
| 51 |
+
if (type && !/[^\u0020-\u007E]/.test(type)) {
|
| 52 |
+
this[TYPE] = type;
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
get size() {
|
| 56 |
+
return this[BUFFER].length;
|
| 57 |
+
}
|
| 58 |
+
get type() {
|
| 59 |
+
return this[TYPE];
|
| 60 |
+
}
|
| 61 |
+
text() {
|
| 62 |
+
return Promise.resolve(this[BUFFER].toString());
|
| 63 |
+
}
|
| 64 |
+
arrayBuffer() {
|
| 65 |
+
const buf = this[BUFFER];
|
| 66 |
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 67 |
+
return Promise.resolve(ab);
|
| 68 |
+
}
|
| 69 |
+
stream() {
|
| 70 |
+
const readable = new Readable();
|
| 71 |
+
readable._read = function () {};
|
| 72 |
+
readable.push(this[BUFFER]);
|
| 73 |
+
readable.push(null);
|
| 74 |
+
return readable;
|
| 75 |
+
}
|
| 76 |
+
toString() {
|
| 77 |
+
return '[object Blob]';
|
| 78 |
+
}
|
| 79 |
+
slice() {
|
| 80 |
+
const size = this.size;
|
| 81 |
+
|
| 82 |
+
const start = arguments[0];
|
| 83 |
+
const end = arguments[1];
|
| 84 |
+
let relativeStart, relativeEnd;
|
| 85 |
+
if (start === undefined) {
|
| 86 |
+
relativeStart = 0;
|
| 87 |
+
} else if (start < 0) {
|
| 88 |
+
relativeStart = Math.max(size + start, 0);
|
| 89 |
+
} else {
|
| 90 |
+
relativeStart = Math.min(start, size);
|
| 91 |
+
}
|
| 92 |
+
if (end === undefined) {
|
| 93 |
+
relativeEnd = size;
|
| 94 |
+
} else if (end < 0) {
|
| 95 |
+
relativeEnd = Math.max(size + end, 0);
|
| 96 |
+
} else {
|
| 97 |
+
relativeEnd = Math.min(end, size);
|
| 98 |
+
}
|
| 99 |
+
const span = Math.max(relativeEnd - relativeStart, 0);
|
| 100 |
+
|
| 101 |
+
const buffer = this[BUFFER];
|
| 102 |
+
const slicedBuffer = buffer.slice(relativeStart, relativeStart + span);
|
| 103 |
+
const blob = new Blob([], { type: arguments[2] });
|
| 104 |
+
blob[BUFFER] = slicedBuffer;
|
| 105 |
+
return blob;
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
Object.defineProperties(Blob.prototype, {
|
| 110 |
+
size: { enumerable: true },
|
| 111 |
+
type: { enumerable: true },
|
| 112 |
+
slice: { enumerable: true }
|
| 113 |
+
});
|
| 114 |
+
|
| 115 |
+
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
|
| 116 |
+
value: 'Blob',
|
| 117 |
+
writable: false,
|
| 118 |
+
enumerable: false,
|
| 119 |
+
configurable: true
|
| 120 |
+
});
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* fetch-error.js
|
| 124 |
+
*
|
| 125 |
+
* FetchError interface for operational errors
|
| 126 |
+
*/
|
| 127 |
+
|
| 128 |
+
/**
|
| 129 |
+
* Create FetchError instance
|
| 130 |
+
*
|
| 131 |
+
* @param String message Error message for human
|
| 132 |
+
* @param String type Error type for machine
|
| 133 |
+
* @param String systemError For Node.js system error
|
| 134 |
+
* @return FetchError
|
| 135 |
+
*/
|
| 136 |
+
function FetchError(message, type, systemError) {
|
| 137 |
+
Error.call(this, message);
|
| 138 |
+
|
| 139 |
+
this.message = message;
|
| 140 |
+
this.type = type;
|
| 141 |
+
|
| 142 |
+
// when err.type is `system`, err.code contains system error code
|
| 143 |
+
if (systemError) {
|
| 144 |
+
this.code = this.errno = systemError.code;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
// hide custom error implementation details from end-users
|
| 148 |
+
Error.captureStackTrace(this, this.constructor);
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
FetchError.prototype = Object.create(Error.prototype);
|
| 152 |
+
FetchError.prototype.constructor = FetchError;
|
| 153 |
+
FetchError.prototype.name = 'FetchError';
|
| 154 |
+
|
| 155 |
+
let convert;
|
| 156 |
+
try {
|
| 157 |
+
convert = require('encoding').convert;
|
| 158 |
+
} catch (e) {}
|
| 159 |
+
|
| 160 |
+
const INTERNALS = Symbol('Body internals');
|
| 161 |
+
|
| 162 |
+
// fix an issue where "PassThrough" isn't a named export for node <10
|
| 163 |
+
const PassThrough = Stream.PassThrough;
|
| 164 |
+
|
| 165 |
+
/**
|
| 166 |
+
* Body mixin
|
| 167 |
+
*
|
| 168 |
+
* Ref: https://fetch.spec.whatwg.org/#body
|
| 169 |
+
*
|
| 170 |
+
* @param Stream body Readable stream
|
| 171 |
+
* @param Object opts Response options
|
| 172 |
+
* @return Void
|
| 173 |
+
*/
|
| 174 |
+
function Body(body) {
|
| 175 |
+
var _this = this;
|
| 176 |
+
|
| 177 |
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
| 178 |
+
_ref$size = _ref.size;
|
| 179 |
+
|
| 180 |
+
let size = _ref$size === undefined ? 0 : _ref$size;
|
| 181 |
+
var _ref$timeout = _ref.timeout;
|
| 182 |
+
let timeout = _ref$timeout === undefined ? 0 : _ref$timeout;
|
| 183 |
+
|
| 184 |
+
if (body == null) {
|
| 185 |
+
// body is undefined or null
|
| 186 |
+
body = null;
|
| 187 |
+
} else if (isURLSearchParams(body)) {
|
| 188 |
+
// body is a URLSearchParams
|
| 189 |
+
body = Buffer.from(body.toString());
|
| 190 |
+
} else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 191 |
+
// body is ArrayBuffer
|
| 192 |
+
body = Buffer.from(body);
|
| 193 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 194 |
+
// body is ArrayBufferView
|
| 195 |
+
body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
| 196 |
+
} else if (body instanceof Stream) ; else {
|
| 197 |
+
// none of the above
|
| 198 |
+
// coerce to string then buffer
|
| 199 |
+
body = Buffer.from(String(body));
|
| 200 |
+
}
|
| 201 |
+
this[INTERNALS] = {
|
| 202 |
+
body,
|
| 203 |
+
disturbed: false,
|
| 204 |
+
error: null
|
| 205 |
+
};
|
| 206 |
+
this.size = size;
|
| 207 |
+
this.timeout = timeout;
|
| 208 |
+
|
| 209 |
+
if (body instanceof Stream) {
|
| 210 |
+
body.on('error', function (err) {
|
| 211 |
+
const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
|
| 212 |
+
_this[INTERNALS].error = error;
|
| 213 |
+
});
|
| 214 |
+
}
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
Body.prototype = {
|
| 218 |
+
get body() {
|
| 219 |
+
return this[INTERNALS].body;
|
| 220 |
+
},
|
| 221 |
+
|
| 222 |
+
get bodyUsed() {
|
| 223 |
+
return this[INTERNALS].disturbed;
|
| 224 |
+
},
|
| 225 |
+
|
| 226 |
+
/**
|
| 227 |
+
* Decode response as ArrayBuffer
|
| 228 |
+
*
|
| 229 |
+
* @return Promise
|
| 230 |
+
*/
|
| 231 |
+
arrayBuffer() {
|
| 232 |
+
return consumeBody.call(this).then(function (buf) {
|
| 233 |
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
| 234 |
+
});
|
| 235 |
+
},
|
| 236 |
+
|
| 237 |
+
/**
|
| 238 |
+
* Return raw response as Blob
|
| 239 |
+
*
|
| 240 |
+
* @return Promise
|
| 241 |
+
*/
|
| 242 |
+
blob() {
|
| 243 |
+
let ct = this.headers && this.headers.get('content-type') || '';
|
| 244 |
+
return consumeBody.call(this).then(function (buf) {
|
| 245 |
+
return Object.assign(
|
| 246 |
+
// Prevent copying
|
| 247 |
+
new Blob([], {
|
| 248 |
+
type: ct.toLowerCase()
|
| 249 |
+
}), {
|
| 250 |
+
[BUFFER]: buf
|
| 251 |
+
});
|
| 252 |
+
});
|
| 253 |
+
},
|
| 254 |
+
|
| 255 |
+
/**
|
| 256 |
+
* Decode response as json
|
| 257 |
+
*
|
| 258 |
+
* @return Promise
|
| 259 |
+
*/
|
| 260 |
+
json() {
|
| 261 |
+
var _this2 = this;
|
| 262 |
+
|
| 263 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 264 |
+
try {
|
| 265 |
+
return JSON.parse(buffer.toString());
|
| 266 |
+
} catch (err) {
|
| 267 |
+
return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
|
| 268 |
+
}
|
| 269 |
+
});
|
| 270 |
+
},
|
| 271 |
+
|
| 272 |
+
/**
|
| 273 |
+
* Decode response as text
|
| 274 |
+
*
|
| 275 |
+
* @return Promise
|
| 276 |
+
*/
|
| 277 |
+
text() {
|
| 278 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 279 |
+
return buffer.toString();
|
| 280 |
+
});
|
| 281 |
+
},
|
| 282 |
+
|
| 283 |
+
/**
|
| 284 |
+
* Decode response as buffer (non-spec api)
|
| 285 |
+
*
|
| 286 |
+
* @return Promise
|
| 287 |
+
*/
|
| 288 |
+
buffer() {
|
| 289 |
+
return consumeBody.call(this);
|
| 290 |
+
},
|
| 291 |
+
|
| 292 |
+
/**
|
| 293 |
+
* Decode response as text, while automatically detecting the encoding and
|
| 294 |
+
* trying to decode to UTF-8 (non-spec api)
|
| 295 |
+
*
|
| 296 |
+
* @return Promise
|
| 297 |
+
*/
|
| 298 |
+
textConverted() {
|
| 299 |
+
var _this3 = this;
|
| 300 |
+
|
| 301 |
+
return consumeBody.call(this).then(function (buffer) {
|
| 302 |
+
return convertBody(buffer, _this3.headers);
|
| 303 |
+
});
|
| 304 |
+
}
|
| 305 |
+
};
|
| 306 |
+
|
| 307 |
+
// In browsers, all properties are enumerable.
|
| 308 |
+
Object.defineProperties(Body.prototype, {
|
| 309 |
+
body: { enumerable: true },
|
| 310 |
+
bodyUsed: { enumerable: true },
|
| 311 |
+
arrayBuffer: { enumerable: true },
|
| 312 |
+
blob: { enumerable: true },
|
| 313 |
+
json: { enumerable: true },
|
| 314 |
+
text: { enumerable: true }
|
| 315 |
+
});
|
| 316 |
+
|
| 317 |
+
Body.mixIn = function (proto) {
|
| 318 |
+
for (const name of Object.getOwnPropertyNames(Body.prototype)) {
|
| 319 |
+
// istanbul ignore else: future proof
|
| 320 |
+
if (!(name in proto)) {
|
| 321 |
+
const desc = Object.getOwnPropertyDescriptor(Body.prototype, name);
|
| 322 |
+
Object.defineProperty(proto, name, desc);
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
};
|
| 326 |
+
|
| 327 |
+
/**
|
| 328 |
+
* Consume and convert an entire Body to a Buffer.
|
| 329 |
+
*
|
| 330 |
+
* Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body
|
| 331 |
+
*
|
| 332 |
+
* @return Promise
|
| 333 |
+
*/
|
| 334 |
+
function consumeBody() {
|
| 335 |
+
var _this4 = this;
|
| 336 |
+
|
| 337 |
+
if (this[INTERNALS].disturbed) {
|
| 338 |
+
return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`));
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
this[INTERNALS].disturbed = true;
|
| 342 |
+
|
| 343 |
+
if (this[INTERNALS].error) {
|
| 344 |
+
return Body.Promise.reject(this[INTERNALS].error);
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
let body = this.body;
|
| 348 |
+
|
| 349 |
+
// body is null
|
| 350 |
+
if (body === null) {
|
| 351 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
// body is blob
|
| 355 |
+
if (isBlob(body)) {
|
| 356 |
+
body = body.stream();
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
// body is buffer
|
| 360 |
+
if (Buffer.isBuffer(body)) {
|
| 361 |
+
return Body.Promise.resolve(body);
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
// istanbul ignore if: should never happen
|
| 365 |
+
if (!(body instanceof Stream)) {
|
| 366 |
+
return Body.Promise.resolve(Buffer.alloc(0));
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
// body is stream
|
| 370 |
+
// get ready to actually consume the body
|
| 371 |
+
let accum = [];
|
| 372 |
+
let accumBytes = 0;
|
| 373 |
+
let abort = false;
|
| 374 |
+
|
| 375 |
+
return new Body.Promise(function (resolve, reject) {
|
| 376 |
+
let resTimeout;
|
| 377 |
+
|
| 378 |
+
// allow timeout on slow response body
|
| 379 |
+
if (_this4.timeout) {
|
| 380 |
+
resTimeout = setTimeout(function () {
|
| 381 |
+
abort = true;
|
| 382 |
+
reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout'));
|
| 383 |
+
}, _this4.timeout);
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
// handle stream errors
|
| 387 |
+
body.on('error', function (err) {
|
| 388 |
+
if (err.name === 'AbortError') {
|
| 389 |
+
// if the request was aborted, reject with this Error
|
| 390 |
+
abort = true;
|
| 391 |
+
reject(err);
|
| 392 |
+
} else {
|
| 393 |
+
// other errors, such as incorrect content-encoding
|
| 394 |
+
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
|
| 395 |
+
}
|
| 396 |
+
});
|
| 397 |
+
|
| 398 |
+
body.on('data', function (chunk) {
|
| 399 |
+
if (abort || chunk === null) {
|
| 400 |
+
return;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
if (_this4.size && accumBytes + chunk.length > _this4.size) {
|
| 404 |
+
abort = true;
|
| 405 |
+
reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size'));
|
| 406 |
+
return;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
accumBytes += chunk.length;
|
| 410 |
+
accum.push(chunk);
|
| 411 |
+
});
|
| 412 |
+
|
| 413 |
+
body.on('end', function () {
|
| 414 |
+
if (abort) {
|
| 415 |
+
return;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
clearTimeout(resTimeout);
|
| 419 |
+
|
| 420 |
+
try {
|
| 421 |
+
resolve(Buffer.concat(accum, accumBytes));
|
| 422 |
+
} catch (err) {
|
| 423 |
+
// handle streams that have accumulated too much data (issue #414)
|
| 424 |
+
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err));
|
| 425 |
+
}
|
| 426 |
+
});
|
| 427 |
+
});
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
/**
|
| 431 |
+
* Detect buffer encoding and convert to target encoding
|
| 432 |
+
* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
|
| 433 |
+
*
|
| 434 |
+
* @param Buffer buffer Incoming buffer
|
| 435 |
+
* @param String encoding Target encoding
|
| 436 |
+
* @return String
|
| 437 |
+
*/
|
| 438 |
+
function convertBody(buffer, headers) {
|
| 439 |
+
if (typeof convert !== 'function') {
|
| 440 |
+
throw new Error('The package `encoding` must be installed to use the textConverted() function');
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
const ct = headers.get('content-type');
|
| 444 |
+
let charset = 'utf-8';
|
| 445 |
+
let res, str;
|
| 446 |
+
|
| 447 |
+
// header
|
| 448 |
+
if (ct) {
|
| 449 |
+
res = /charset=([^;]*)/i.exec(ct);
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
// no charset in content type, peek at response body for at most 1024 bytes
|
| 453 |
+
str = buffer.slice(0, 1024).toString();
|
| 454 |
+
|
| 455 |
+
// html5
|
| 456 |
+
if (!res && str) {
|
| 457 |
+
res = /<meta.+?charset=(['"])(.+?)\1/i.exec(str);
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
// html4
|
| 461 |
+
if (!res && str) {
|
| 462 |
+
res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
|
| 463 |
+
if (!res) {
|
| 464 |
+
res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
|
| 465 |
+
if (res) {
|
| 466 |
+
res.pop(); // drop last quote
|
| 467 |
+
}
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
if (res) {
|
| 471 |
+
res = /charset=(.*)/i.exec(res.pop());
|
| 472 |
+
}
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
// xml
|
| 476 |
+
if (!res && str) {
|
| 477 |
+
res = /<\?xml.+?encoding=(['"])(.+?)\1/i.exec(str);
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
// found charset
|
| 481 |
+
if (res) {
|
| 482 |
+
charset = res.pop();
|
| 483 |
+
|
| 484 |
+
// prevent decode issues when sites use incorrect encoding
|
| 485 |
+
// ref: https://hsivonen.fi/encoding-menu/
|
| 486 |
+
if (charset === 'gb2312' || charset === 'gbk') {
|
| 487 |
+
charset = 'gb18030';
|
| 488 |
+
}
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
// turn raw buffers into a single utf-8 buffer
|
| 492 |
+
return convert(buffer, 'UTF-8', charset).toString();
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
/**
|
| 496 |
+
* Detect a URLSearchParams object
|
| 497 |
+
* ref: https://github.com/bitinn/node-fetch/issues/296#issuecomment-307598143
|
| 498 |
+
*
|
| 499 |
+
* @param Object obj Object to detect by type or brand
|
| 500 |
+
* @return String
|
| 501 |
+
*/
|
| 502 |
+
function isURLSearchParams(obj) {
|
| 503 |
+
// Duck-typing as a necessary condition.
|
| 504 |
+
if (typeof obj !== 'object' || typeof obj.append !== 'function' || typeof obj.delete !== 'function' || typeof obj.get !== 'function' || typeof obj.getAll !== 'function' || typeof obj.has !== 'function' || typeof obj.set !== 'function') {
|
| 505 |
+
return false;
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
// Brand-checking and more duck-typing as optional condition.
|
| 509 |
+
return obj.constructor.name === 'URLSearchParams' || Object.prototype.toString.call(obj) === '[object URLSearchParams]' || typeof obj.sort === 'function';
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
/**
|
| 513 |
+
* Check if `obj` is a W3C `Blob` object (which `File` inherits from)
|
| 514 |
+
* @param {*} obj
|
| 515 |
+
* @return {boolean}
|
| 516 |
+
*/
|
| 517 |
+
function isBlob(obj) {
|
| 518 |
+
return typeof obj === 'object' && typeof obj.arrayBuffer === 'function' && typeof obj.type === 'string' && typeof obj.stream === 'function' && typeof obj.constructor === 'function' && typeof obj.constructor.name === 'string' && /^(Blob|File)$/.test(obj.constructor.name) && /^(Blob|File)$/.test(obj[Symbol.toStringTag]);
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
/**
|
| 522 |
+
* Clone body given Res/Req instance
|
| 523 |
+
*
|
| 524 |
+
* @param Mixed instance Response or Request instance
|
| 525 |
+
* @return Mixed
|
| 526 |
+
*/
|
| 527 |
+
function clone(instance) {
|
| 528 |
+
let p1, p2;
|
| 529 |
+
let body = instance.body;
|
| 530 |
+
|
| 531 |
+
// don't allow cloning a used body
|
| 532 |
+
if (instance.bodyUsed) {
|
| 533 |
+
throw new Error('cannot clone body after it is used');
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
// check that body is a stream and not form-data object
|
| 537 |
+
// note: we can't clone the form-data object without having it as a dependency
|
| 538 |
+
if (body instanceof Stream && typeof body.getBoundary !== 'function') {
|
| 539 |
+
// tee instance body
|
| 540 |
+
p1 = new PassThrough();
|
| 541 |
+
p2 = new PassThrough();
|
| 542 |
+
body.pipe(p1);
|
| 543 |
+
body.pipe(p2);
|
| 544 |
+
// set instance body to teed body and return the other teed body
|
| 545 |
+
instance[INTERNALS].body = p1;
|
| 546 |
+
body = p2;
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
return body;
|
| 550 |
+
}
|
| 551 |
+
|
| 552 |
+
/**
|
| 553 |
+
* Performs the operation "extract a `Content-Type` value from |object|" as
|
| 554 |
+
* specified in the specification:
|
| 555 |
+
* https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
| 556 |
+
*
|
| 557 |
+
* This function assumes that instance.body is present.
|
| 558 |
+
*
|
| 559 |
+
* @param Mixed instance Any options.body input
|
| 560 |
+
*/
|
| 561 |
+
function extractContentType(body) {
|
| 562 |
+
if (body === null) {
|
| 563 |
+
// body is null
|
| 564 |
+
return null;
|
| 565 |
+
} else if (typeof body === 'string') {
|
| 566 |
+
// body is string
|
| 567 |
+
return 'text/plain;charset=UTF-8';
|
| 568 |
+
} else if (isURLSearchParams(body)) {
|
| 569 |
+
// body is a URLSearchParams
|
| 570 |
+
return 'application/x-www-form-urlencoded;charset=UTF-8';
|
| 571 |
+
} else if (isBlob(body)) {
|
| 572 |
+
// body is blob
|
| 573 |
+
return body.type || null;
|
| 574 |
+
} else if (Buffer.isBuffer(body)) {
|
| 575 |
+
// body is buffer
|
| 576 |
+
return null;
|
| 577 |
+
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
|
| 578 |
+
// body is ArrayBuffer
|
| 579 |
+
return null;
|
| 580 |
+
} else if (ArrayBuffer.isView(body)) {
|
| 581 |
+
// body is ArrayBufferView
|
| 582 |
+
return null;
|
| 583 |
+
} else if (typeof body.getBoundary === 'function') {
|
| 584 |
+
// detect form data input from form-data module
|
| 585 |
+
return `multipart/form-data;boundary=${body.getBoundary()}`;
|
| 586 |
+
} else if (body instanceof Stream) {
|
| 587 |
+
// body is stream
|
| 588 |
+
// can't really do much about this
|
| 589 |
+
return null;
|
| 590 |
+
} else {
|
| 591 |
+
// Body constructor defaults other things to string
|
| 592 |
+
return 'text/plain;charset=UTF-8';
|
| 593 |
+
}
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
/**
|
| 597 |
+
* The Fetch Standard treats this as if "total bytes" is a property on the body.
|
| 598 |
+
* For us, we have to explicitly get it with a function.
|
| 599 |
+
*
|
| 600 |
+
* ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes
|
| 601 |
+
*
|
| 602 |
+
* @param Body instance Instance of Body
|
| 603 |
+
* @return Number? Number of bytes, or null if not possible
|
| 604 |
+
*/
|
| 605 |
+
function getTotalBytes(instance) {
|
| 606 |
+
const body = instance.body;
|
| 607 |
+
|
| 608 |
+
|
| 609 |
+
if (body === null) {
|
| 610 |
+
// body is null
|
| 611 |
+
return 0;
|
| 612 |
+
} else if (isBlob(body)) {
|
| 613 |
+
return body.size;
|
| 614 |
+
} else if (Buffer.isBuffer(body)) {
|
| 615 |
+
// body is buffer
|
| 616 |
+
return body.length;
|
| 617 |
+
} else if (body && typeof body.getLengthSync === 'function') {
|
| 618 |
+
// detect form data input from form-data module
|
| 619 |
+
if (body._lengthRetrievers && body._lengthRetrievers.length == 0 || // 1.x
|
| 620 |
+
body.hasKnownLength && body.hasKnownLength()) {
|
| 621 |
+
// 2.x
|
| 622 |
+
return body.getLengthSync();
|
| 623 |
+
}
|
| 624 |
+
return null;
|
| 625 |
+
} else {
|
| 626 |
+
// body is stream
|
| 627 |
+
return null;
|
| 628 |
+
}
|
| 629 |
+
}
|
| 630 |
+
|
| 631 |
+
/**
|
| 632 |
+
* Write a Body to a Node.js WritableStream (e.g. http.Request) object.
|
| 633 |
+
*
|
| 634 |
+
* @param Body instance Instance of Body
|
| 635 |
+
* @return Void
|
| 636 |
+
*/
|
| 637 |
+
function writeToStream(dest, instance) {
|
| 638 |
+
const body = instance.body;
|
| 639 |
+
|
| 640 |
+
|
| 641 |
+
if (body === null) {
|
| 642 |
+
// body is null
|
| 643 |
+
dest.end();
|
| 644 |
+
} else if (isBlob(body)) {
|
| 645 |
+
body.stream().pipe(dest);
|
| 646 |
+
} else if (Buffer.isBuffer(body)) {
|
| 647 |
+
// body is buffer
|
| 648 |
+
dest.write(body);
|
| 649 |
+
dest.end();
|
| 650 |
+
} else {
|
| 651 |
+
// body is stream
|
| 652 |
+
body.pipe(dest);
|
| 653 |
+
}
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
// expose Promise
|
| 657 |
+
Body.Promise = global.Promise;
|
| 658 |
+
|
| 659 |
+
/**
|
| 660 |
+
* headers.js
|
| 661 |
+
*
|
| 662 |
+
* Headers class offers convenient helpers
|
| 663 |
+
*/
|
| 664 |
+
|
| 665 |
+
const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
|
| 666 |
+
const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
|
| 667 |
+
|
| 668 |
+
function validateName(name) {
|
| 669 |
+
name = `${name}`;
|
| 670 |
+
if (invalidTokenRegex.test(name) || name === '') {
|
| 671 |
+
throw new TypeError(`${name} is not a legal HTTP header name`);
|
| 672 |
+
}
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
function validateValue(value) {
|
| 676 |
+
value = `${value}`;
|
| 677 |
+
if (invalidHeaderCharRegex.test(value)) {
|
| 678 |
+
throw new TypeError(`${value} is not a legal HTTP header value`);
|
| 679 |
+
}
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
/**
|
| 683 |
+
* Find the key in the map object given a header name.
|
| 684 |
+
*
|
| 685 |
+
* Returns undefined if not found.
|
| 686 |
+
*
|
| 687 |
+
* @param String name Header name
|
| 688 |
+
* @return String|Undefined
|
| 689 |
+
*/
|
| 690 |
+
function find(map, name) {
|
| 691 |
+
name = name.toLowerCase();
|
| 692 |
+
for (const key in map) {
|
| 693 |
+
if (key.toLowerCase() === name) {
|
| 694 |
+
return key;
|
| 695 |
+
}
|
| 696 |
+
}
|
| 697 |
+
return undefined;
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
const MAP = Symbol('map');
|
| 701 |
+
class Headers {
|
| 702 |
+
/**
|
| 703 |
+
* Headers class
|
| 704 |
+
*
|
| 705 |
+
* @param Object headers Response headers
|
| 706 |
+
* @return Void
|
| 707 |
+
*/
|
| 708 |
+
constructor() {
|
| 709 |
+
let init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
|
| 710 |
+
|
| 711 |
+
this[MAP] = Object.create(null);
|
| 712 |
+
|
| 713 |
+
if (init instanceof Headers) {
|
| 714 |
+
const rawHeaders = init.raw();
|
| 715 |
+
const headerNames = Object.keys(rawHeaders);
|
| 716 |
+
|
| 717 |
+
for (const headerName of headerNames) {
|
| 718 |
+
for (const value of rawHeaders[headerName]) {
|
| 719 |
+
this.append(headerName, value);
|
| 720 |
+
}
|
| 721 |
+
}
|
| 722 |
+
|
| 723 |
+
return;
|
| 724 |
+
}
|
| 725 |
+
|
| 726 |
+
// We don't worry about converting prop to ByteString here as append()
|
| 727 |
+
// will handle it.
|
| 728 |
+
if (init == null) ; else if (typeof init === 'object') {
|
| 729 |
+
const method = init[Symbol.iterator];
|
| 730 |
+
if (method != null) {
|
| 731 |
+
if (typeof method !== 'function') {
|
| 732 |
+
throw new TypeError('Header pairs must be iterable');
|
| 733 |
+
}
|
| 734 |
+
|
| 735 |
+
// sequence<sequence<ByteString>>
|
| 736 |
+
// Note: per spec we have to first exhaust the lists then process them
|
| 737 |
+
const pairs = [];
|
| 738 |
+
for (const pair of init) {
|
| 739 |
+
if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') {
|
| 740 |
+
throw new TypeError('Each header pair must be iterable');
|
| 741 |
+
}
|
| 742 |
+
pairs.push(Array.from(pair));
|
| 743 |
+
}
|
| 744 |
+
|
| 745 |
+
for (const pair of pairs) {
|
| 746 |
+
if (pair.length !== 2) {
|
| 747 |
+
throw new TypeError('Each header pair must be a name/value tuple');
|
| 748 |
+
}
|
| 749 |
+
this.append(pair[0], pair[1]);
|
| 750 |
+
}
|
| 751 |
+
} else {
|
| 752 |
+
// record<ByteString, ByteString>
|
| 753 |
+
for (const key of Object.keys(init)) {
|
| 754 |
+
const value = init[key];
|
| 755 |
+
this.append(key, value);
|
| 756 |
+
}
|
| 757 |
+
}
|
| 758 |
+
} else {
|
| 759 |
+
throw new TypeError('Provided initializer must be an object');
|
| 760 |
+
}
|
| 761 |
+
}
|
| 762 |
+
|
| 763 |
+
/**
|
| 764 |
+
* Return combined header value given name
|
| 765 |
+
*
|
| 766 |
+
* @param String name Header name
|
| 767 |
+
* @return Mixed
|
| 768 |
+
*/
|
| 769 |
+
get(name) {
|
| 770 |
+
name = `${name}`;
|
| 771 |
+
validateName(name);
|
| 772 |
+
const key = find(this[MAP], name);
|
| 773 |
+
if (key === undefined) {
|
| 774 |
+
return null;
|
| 775 |
+
}
|
| 776 |
+
|
| 777 |
+
return this[MAP][key].join(', ');
|
| 778 |
+
}
|
| 779 |
+
|
| 780 |
+
/**
|
| 781 |
+
* Iterate over all headers
|
| 782 |
+
*
|
| 783 |
+
* @param Function callback Executed for each item with parameters (value, name, thisArg)
|
| 784 |
+
* @param Boolean thisArg `this` context for callback function
|
| 785 |
+
* @return Void
|
| 786 |
+
*/
|
| 787 |
+
forEach(callback) {
|
| 788 |
+
let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
| 789 |
+
|
| 790 |
+
let pairs = getHeaders(this);
|
| 791 |
+
let i = 0;
|
| 792 |
+
while (i < pairs.length) {
|
| 793 |
+
var _pairs$i = pairs[i];
|
| 794 |
+
const name = _pairs$i[0],
|
| 795 |
+
value = _pairs$i[1];
|
| 796 |
+
|
| 797 |
+
callback.call(thisArg, value, name, this);
|
| 798 |
+
pairs = getHeaders(this);
|
| 799 |
+
i++;
|
| 800 |
+
}
|
| 801 |
+
}
|
| 802 |
+
|
| 803 |
+
/**
|
| 804 |
+
* Overwrite header values given name
|
| 805 |
+
*
|
| 806 |
+
* @param String name Header name
|
| 807 |
+
* @param String value Header value
|
| 808 |
+
* @return Void
|
| 809 |
+
*/
|
| 810 |
+
set(name, value) {
|
| 811 |
+
name = `${name}`;
|
| 812 |
+
value = `${value}`;
|
| 813 |
+
validateName(name);
|
| 814 |
+
validateValue(value);
|
| 815 |
+
const key = find(this[MAP], name);
|
| 816 |
+
this[MAP][key !== undefined ? key : name] = [value];
|
| 817 |
+
}
|
| 818 |
+
|
| 819 |
+
/**
|
| 820 |
+
* Append a value onto existing header
|
| 821 |
+
*
|
| 822 |
+
* @param String name Header name
|
| 823 |
+
* @param String value Header value
|
| 824 |
+
* @return Void
|
| 825 |
+
*/
|
| 826 |
+
append(name, value) {
|
| 827 |
+
name = `${name}`;
|
| 828 |
+
value = `${value}`;
|
| 829 |
+
validateName(name);
|
| 830 |
+
validateValue(value);
|
| 831 |
+
const key = find(this[MAP], name);
|
| 832 |
+
if (key !== undefined) {
|
| 833 |
+
this[MAP][key].push(value);
|
| 834 |
+
} else {
|
| 835 |
+
this[MAP][name] = [value];
|
| 836 |
+
}
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
+
/**
|
| 840 |
+
* Check for header name existence
|
| 841 |
+
*
|
| 842 |
+
* @param String name Header name
|
| 843 |
+
* @return Boolean
|
| 844 |
+
*/
|
| 845 |
+
has(name) {
|
| 846 |
+
name = `${name}`;
|
| 847 |
+
validateName(name);
|
| 848 |
+
return find(this[MAP], name) !== undefined;
|
| 849 |
+
}
|
| 850 |
+
|
| 851 |
+
/**
|
| 852 |
+
* Delete all header values given name
|
| 853 |
+
*
|
| 854 |
+
* @param String name Header name
|
| 855 |
+
* @return Void
|
| 856 |
+
*/
|
| 857 |
+
delete(name) {
|
| 858 |
+
name = `${name}`;
|
| 859 |
+
validateName(name);
|
| 860 |
+
const key = find(this[MAP], name);
|
| 861 |
+
if (key !== undefined) {
|
| 862 |
+
delete this[MAP][key];
|
| 863 |
+
}
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
/**
|
| 867 |
+
* Return raw headers (non-spec api)
|
| 868 |
+
*
|
| 869 |
+
* @return Object
|
| 870 |
+
*/
|
| 871 |
+
raw() {
|
| 872 |
+
return this[MAP];
|
| 873 |
+
}
|
| 874 |
+
|
| 875 |
+
/**
|
| 876 |
+
* Get an iterator on keys.
|
| 877 |
+
*
|
| 878 |
+
* @return Iterator
|
| 879 |
+
*/
|
| 880 |
+
keys() {
|
| 881 |
+
return createHeadersIterator(this, 'key');
|
| 882 |
+
}
|
| 883 |
+
|
| 884 |
+
/**
|
| 885 |
+
* Get an iterator on values.
|
| 886 |
+
*
|
| 887 |
+
* @return Iterator
|
| 888 |
+
*/
|
| 889 |
+
values() {
|
| 890 |
+
return createHeadersIterator(this, 'value');
|
| 891 |
+
}
|
| 892 |
+
|
| 893 |
+
/**
|
| 894 |
+
* Get an iterator on entries.
|
| 895 |
+
*
|
| 896 |
+
* This is the default iterator of the Headers object.
|
| 897 |
+
*
|
| 898 |
+
* @return Iterator
|
| 899 |
+
*/
|
| 900 |
+
[Symbol.iterator]() {
|
| 901 |
+
return createHeadersIterator(this, 'key+value');
|
| 902 |
+
}
|
| 903 |
+
}
|
| 904 |
+
Headers.prototype.entries = Headers.prototype[Symbol.iterator];
|
| 905 |
+
|
| 906 |
+
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
|
| 907 |
+
value: 'Headers',
|
| 908 |
+
writable: false,
|
| 909 |
+
enumerable: false,
|
| 910 |
+
configurable: true
|
| 911 |
+
});
|
| 912 |
+
|
| 913 |
+
Object.defineProperties(Headers.prototype, {
|
| 914 |
+
get: { enumerable: true },
|
| 915 |
+
forEach: { enumerable: true },
|
| 916 |
+
set: { enumerable: true },
|
| 917 |
+
append: { enumerable: true },
|
| 918 |
+
has: { enumerable: true },
|
| 919 |
+
delete: { enumerable: true },
|
| 920 |
+
keys: { enumerable: true },
|
| 921 |
+
values: { enumerable: true },
|
| 922 |
+
entries: { enumerable: true }
|
| 923 |
+
});
|
| 924 |
+
|
| 925 |
+
function getHeaders(headers) {
|
| 926 |
+
let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value';
|
| 927 |
+
|
| 928 |
+
const keys = Object.keys(headers[MAP]).sort();
|
| 929 |
+
return keys.map(kind === 'key' ? function (k) {
|
| 930 |
+
return k.toLowerCase();
|
| 931 |
+
} : kind === 'value' ? function (k) {
|
| 932 |
+
return headers[MAP][k].join(', ');
|
| 933 |
+
} : function (k) {
|
| 934 |
+
return [k.toLowerCase(), headers[MAP][k].join(', ')];
|
| 935 |
+
});
|
| 936 |
+
}
|
| 937 |
+
|
| 938 |
+
const INTERNAL = Symbol('internal');
|
| 939 |
+
|
| 940 |
+
function createHeadersIterator(target, kind) {
|
| 941 |
+
const iterator = Object.create(HeadersIteratorPrototype);
|
| 942 |
+
iterator[INTERNAL] = {
|
| 943 |
+
target,
|
| 944 |
+
kind,
|
| 945 |
+
index: 0
|
| 946 |
+
};
|
| 947 |
+
return iterator;
|
| 948 |
+
}
|
| 949 |
+
|
| 950 |
+
const HeadersIteratorPrototype = Object.setPrototypeOf({
|
| 951 |
+
next() {
|
| 952 |
+
// istanbul ignore if
|
| 953 |
+
if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) {
|
| 954 |
+
throw new TypeError('Value of `this` is not a HeadersIterator');
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
var _INTERNAL = this[INTERNAL];
|
| 958 |
+
const target = _INTERNAL.target,
|
| 959 |
+
kind = _INTERNAL.kind,
|
| 960 |
+
index = _INTERNAL.index;
|
| 961 |
+
|
| 962 |
+
const values = getHeaders(target, kind);
|
| 963 |
+
const len = values.length;
|
| 964 |
+
if (index >= len) {
|
| 965 |
+
return {
|
| 966 |
+
value: undefined,
|
| 967 |
+
done: true
|
| 968 |
+
};
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
this[INTERNAL].index = index + 1;
|
| 972 |
+
|
| 973 |
+
return {
|
| 974 |
+
value: values[index],
|
| 975 |
+
done: false
|
| 976 |
+
};
|
| 977 |
+
}
|
| 978 |
+
}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));
|
| 979 |
+
|
| 980 |
+
Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, {
|
| 981 |
+
value: 'HeadersIterator',
|
| 982 |
+
writable: false,
|
| 983 |
+
enumerable: false,
|
| 984 |
+
configurable: true
|
| 985 |
+
});
|
| 986 |
+
|
| 987 |
+
/**
|
| 988 |
+
* Export the Headers object in a form that Node.js can consume.
|
| 989 |
+
*
|
| 990 |
+
* @param Headers headers
|
| 991 |
+
* @return Object
|
| 992 |
+
*/
|
| 993 |
+
function exportNodeCompatibleHeaders(headers) {
|
| 994 |
+
const obj = Object.assign({ __proto__: null }, headers[MAP]);
|
| 995 |
+
|
| 996 |
+
// http.request() only supports string as Host header. This hack makes
|
| 997 |
+
// specifying custom Host header possible.
|
| 998 |
+
const hostHeaderKey = find(headers[MAP], 'Host');
|
| 999 |
+
if (hostHeaderKey !== undefined) {
|
| 1000 |
+
obj[hostHeaderKey] = obj[hostHeaderKey][0];
|
| 1001 |
+
}
|
| 1002 |
+
|
| 1003 |
+
return obj;
|
| 1004 |
+
}
|
| 1005 |
+
|
| 1006 |
+
/**
|
| 1007 |
+
* Create a Headers object from an object of headers, ignoring those that do
|
| 1008 |
+
* not conform to HTTP grammar productions.
|
| 1009 |
+
*
|
| 1010 |
+
* @param Object obj Object of headers
|
| 1011 |
+
* @return Headers
|
| 1012 |
+
*/
|
| 1013 |
+
function createHeadersLenient(obj) {
|
| 1014 |
+
const headers = new Headers();
|
| 1015 |
+
for (const name of Object.keys(obj)) {
|
| 1016 |
+
if (invalidTokenRegex.test(name)) {
|
| 1017 |
+
continue;
|
| 1018 |
+
}
|
| 1019 |
+
if (Array.isArray(obj[name])) {
|
| 1020 |
+
for (const val of obj[name]) {
|
| 1021 |
+
if (invalidHeaderCharRegex.test(val)) {
|
| 1022 |
+
continue;
|
| 1023 |
+
}
|
| 1024 |
+
if (headers[MAP][name] === undefined) {
|
| 1025 |
+
headers[MAP][name] = [val];
|
| 1026 |
+
} else {
|
| 1027 |
+
headers[MAP][name].push(val);
|
| 1028 |
+
}
|
| 1029 |
+
}
|
| 1030 |
+
} else if (!invalidHeaderCharRegex.test(obj[name])) {
|
| 1031 |
+
headers[MAP][name] = [obj[name]];
|
| 1032 |
+
}
|
| 1033 |
+
}
|
| 1034 |
+
return headers;
|
| 1035 |
+
}
|
| 1036 |
+
|
| 1037 |
+
const INTERNALS$1 = Symbol('Response internals');
|
| 1038 |
+
|
| 1039 |
+
// fix an issue where "STATUS_CODES" aren't a named export for node <10
|
| 1040 |
+
const STATUS_CODES = http.STATUS_CODES;
|
| 1041 |
+
|
| 1042 |
+
/**
|
| 1043 |
+
* Response class
|
| 1044 |
+
*
|
| 1045 |
+
* @param Stream body Readable stream
|
| 1046 |
+
* @param Object opts Response options
|
| 1047 |
+
* @return Void
|
| 1048 |
+
*/
|
| 1049 |
+
class Response {
|
| 1050 |
+
constructor() {
|
| 1051 |
+
let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
| 1052 |
+
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1053 |
+
|
| 1054 |
+
Body.call(this, body, opts);
|
| 1055 |
+
|
| 1056 |
+
const status = opts.status || 200;
|
| 1057 |
+
const headers = new Headers(opts.headers);
|
| 1058 |
+
|
| 1059 |
+
if (body != null && !headers.has('Content-Type')) {
|
| 1060 |
+
const contentType = extractContentType(body);
|
| 1061 |
+
if (contentType) {
|
| 1062 |
+
headers.append('Content-Type', contentType);
|
| 1063 |
+
}
|
| 1064 |
+
}
|
| 1065 |
+
|
| 1066 |
+
this[INTERNALS$1] = {
|
| 1067 |
+
url: opts.url,
|
| 1068 |
+
status,
|
| 1069 |
+
statusText: opts.statusText || STATUS_CODES[status],
|
| 1070 |
+
headers,
|
| 1071 |
+
counter: opts.counter
|
| 1072 |
+
};
|
| 1073 |
+
}
|
| 1074 |
+
|
| 1075 |
+
get url() {
|
| 1076 |
+
return this[INTERNALS$1].url || '';
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
get status() {
|
| 1080 |
+
return this[INTERNALS$1].status;
|
| 1081 |
+
}
|
| 1082 |
+
|
| 1083 |
+
/**
|
| 1084 |
+
* Convenience property representing if the request ended normally
|
| 1085 |
+
*/
|
| 1086 |
+
get ok() {
|
| 1087 |
+
return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300;
|
| 1088 |
+
}
|
| 1089 |
+
|
| 1090 |
+
get redirected() {
|
| 1091 |
+
return this[INTERNALS$1].counter > 0;
|
| 1092 |
+
}
|
| 1093 |
+
|
| 1094 |
+
get statusText() {
|
| 1095 |
+
return this[INTERNALS$1].statusText;
|
| 1096 |
+
}
|
| 1097 |
+
|
| 1098 |
+
get headers() {
|
| 1099 |
+
return this[INTERNALS$1].headers;
|
| 1100 |
+
}
|
| 1101 |
+
|
| 1102 |
+
/**
|
| 1103 |
+
* Clone this response
|
| 1104 |
+
*
|
| 1105 |
+
* @return Response
|
| 1106 |
+
*/
|
| 1107 |
+
clone() {
|
| 1108 |
+
return new Response(clone(this), {
|
| 1109 |
+
url: this.url,
|
| 1110 |
+
status: this.status,
|
| 1111 |
+
statusText: this.statusText,
|
| 1112 |
+
headers: this.headers,
|
| 1113 |
+
ok: this.ok,
|
| 1114 |
+
redirected: this.redirected
|
| 1115 |
+
});
|
| 1116 |
+
}
|
| 1117 |
+
}
|
| 1118 |
+
|
| 1119 |
+
Body.mixIn(Response.prototype);
|
| 1120 |
+
|
| 1121 |
+
Object.defineProperties(Response.prototype, {
|
| 1122 |
+
url: { enumerable: true },
|
| 1123 |
+
status: { enumerable: true },
|
| 1124 |
+
ok: { enumerable: true },
|
| 1125 |
+
redirected: { enumerable: true },
|
| 1126 |
+
statusText: { enumerable: true },
|
| 1127 |
+
headers: { enumerable: true },
|
| 1128 |
+
clone: { enumerable: true }
|
| 1129 |
+
});
|
| 1130 |
+
|
| 1131 |
+
Object.defineProperty(Response.prototype, Symbol.toStringTag, {
|
| 1132 |
+
value: 'Response',
|
| 1133 |
+
writable: false,
|
| 1134 |
+
enumerable: false,
|
| 1135 |
+
configurable: true
|
| 1136 |
+
});
|
| 1137 |
+
|
| 1138 |
+
const INTERNALS$2 = Symbol('Request internals');
|
| 1139 |
+
const URL = Url.URL || whatwgUrl.URL;
|
| 1140 |
+
|
| 1141 |
+
// fix an issue where "format", "parse" aren't a named export for node <10
|
| 1142 |
+
const parse_url = Url.parse;
|
| 1143 |
+
const format_url = Url.format;
|
| 1144 |
+
|
| 1145 |
+
/**
|
| 1146 |
+
* Wrapper around `new URL` to handle arbitrary URLs
|
| 1147 |
+
*
|
| 1148 |
+
* @param {string} urlStr
|
| 1149 |
+
* @return {void}
|
| 1150 |
+
*/
|
| 1151 |
+
function parseURL(urlStr) {
|
| 1152 |
+
/*
|
| 1153 |
+
Check whether the URL is absolute or not
|
| 1154 |
+
Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
|
| 1155 |
+
Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
|
| 1156 |
+
*/
|
| 1157 |
+
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
|
| 1158 |
+
urlStr = new URL(urlStr).toString();
|
| 1159 |
+
}
|
| 1160 |
+
|
| 1161 |
+
// Fallback to old implementation for arbitrary URLs
|
| 1162 |
+
return parse_url(urlStr);
|
| 1163 |
+
}
|
| 1164 |
+
|
| 1165 |
+
const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
|
| 1166 |
+
|
| 1167 |
+
/**
|
| 1168 |
+
* Check if a value is an instance of Request.
|
| 1169 |
+
*
|
| 1170 |
+
* @param Mixed input
|
| 1171 |
+
* @return Boolean
|
| 1172 |
+
*/
|
| 1173 |
+
function isRequest(input) {
|
| 1174 |
+
return typeof input === 'object' && typeof input[INTERNALS$2] === 'object';
|
| 1175 |
+
}
|
| 1176 |
+
|
| 1177 |
+
function isAbortSignal(signal) {
|
| 1178 |
+
const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
|
| 1179 |
+
return !!(proto && proto.constructor.name === 'AbortSignal');
|
| 1180 |
+
}
|
| 1181 |
+
|
| 1182 |
+
/**
|
| 1183 |
+
* Request class
|
| 1184 |
+
*
|
| 1185 |
+
* @param Mixed input Url or Request instance
|
| 1186 |
+
* @param Object init Custom options
|
| 1187 |
+
* @return Void
|
| 1188 |
+
*/
|
| 1189 |
+
class Request {
|
| 1190 |
+
constructor(input) {
|
| 1191 |
+
let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
| 1192 |
+
|
| 1193 |
+
let parsedURL;
|
| 1194 |
+
|
| 1195 |
+
// normalize input
|
| 1196 |
+
if (!isRequest(input)) {
|
| 1197 |
+
if (input && input.href) {
|
| 1198 |
+
// in order to support Node.js' Url objects; though WHATWG's URL objects
|
| 1199 |
+
// will fall into this branch also (since their `toString()` will return
|
| 1200 |
+
// `href` property anyway)
|
| 1201 |
+
parsedURL = parseURL(input.href);
|
| 1202 |
+
} else {
|
| 1203 |
+
// coerce input to a string before attempting to parse
|
| 1204 |
+
parsedURL = parseURL(`${input}`);
|
| 1205 |
+
}
|
| 1206 |
+
input = {};
|
| 1207 |
+
} else {
|
| 1208 |
+
parsedURL = parseURL(input.url);
|
| 1209 |
+
}
|
| 1210 |
+
|
| 1211 |
+
let method = init.method || input.method || 'GET';
|
| 1212 |
+
method = method.toUpperCase();
|
| 1213 |
+
|
| 1214 |
+
if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) {
|
| 1215 |
+
throw new TypeError('Request with GET/HEAD method cannot have body');
|
| 1216 |
+
}
|
| 1217 |
+
|
| 1218 |
+
let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
|
| 1219 |
+
|
| 1220 |
+
Body.call(this, inputBody, {
|
| 1221 |
+
timeout: init.timeout || input.timeout || 0,
|
| 1222 |
+
size: init.size || input.size || 0
|
| 1223 |
+
});
|
| 1224 |
+
|
| 1225 |
+
const headers = new Headers(init.headers || input.headers || {});
|
| 1226 |
+
|
| 1227 |
+
if (inputBody != null && !headers.has('Content-Type')) {
|
| 1228 |
+
const contentType = extractContentType(inputBody);
|
| 1229 |
+
if (contentType) {
|
| 1230 |
+
headers.append('Content-Type', contentType);
|
| 1231 |
+
}
|
| 1232 |
+
}
|
| 1233 |
+
|
| 1234 |
+
let signal = isRequest(input) ? input.signal : null;
|
| 1235 |
+
if ('signal' in init) signal = init.signal;
|
| 1236 |
+
|
| 1237 |
+
if (signal != null && !isAbortSignal(signal)) {
|
| 1238 |
+
throw new TypeError('Expected signal to be an instanceof AbortSignal');
|
| 1239 |
+
}
|
| 1240 |
+
|
| 1241 |
+
this[INTERNALS$2] = {
|
| 1242 |
+
method,
|
| 1243 |
+
redirect: init.redirect || input.redirect || 'follow',
|
| 1244 |
+
headers,
|
| 1245 |
+
parsedURL,
|
| 1246 |
+
signal
|
| 1247 |
+
};
|
| 1248 |
+
|
| 1249 |
+
// node-fetch-only options
|
| 1250 |
+
this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20;
|
| 1251 |
+
this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true;
|
| 1252 |
+
this.counter = init.counter || input.counter || 0;
|
| 1253 |
+
this.agent = init.agent || input.agent;
|
| 1254 |
+
}
|
| 1255 |
+
|
| 1256 |
+
get method() {
|
| 1257 |
+
return this[INTERNALS$2].method;
|
| 1258 |
+
}
|
| 1259 |
+
|
| 1260 |
+
get url() {
|
| 1261 |
+
return format_url(this[INTERNALS$2].parsedURL);
|
| 1262 |
+
}
|
| 1263 |
+
|
| 1264 |
+
get headers() {
|
| 1265 |
+
return this[INTERNALS$2].headers;
|
| 1266 |
+
}
|
| 1267 |
+
|
| 1268 |
+
get redirect() {
|
| 1269 |
+
return this[INTERNALS$2].redirect;
|
| 1270 |
+
}
|
| 1271 |
+
|
| 1272 |
+
get signal() {
|
| 1273 |
+
return this[INTERNALS$2].signal;
|
| 1274 |
+
}
|
| 1275 |
+
|
| 1276 |
+
/**
|
| 1277 |
+
* Clone this request
|
| 1278 |
+
*
|
| 1279 |
+
* @return Request
|
| 1280 |
+
*/
|
| 1281 |
+
clone() {
|
| 1282 |
+
return new Request(this);
|
| 1283 |
+
}
|
| 1284 |
+
}
|
| 1285 |
+
|
| 1286 |
+
Body.mixIn(Request.prototype);
|
| 1287 |
+
|
| 1288 |
+
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
|
| 1289 |
+
value: 'Request',
|
| 1290 |
+
writable: false,
|
| 1291 |
+
enumerable: false,
|
| 1292 |
+
configurable: true
|
| 1293 |
+
});
|
| 1294 |
+
|
| 1295 |
+
Object.defineProperties(Request.prototype, {
|
| 1296 |
+
method: { enumerable: true },
|
| 1297 |
+
url: { enumerable: true },
|
| 1298 |
+
headers: { enumerable: true },
|
| 1299 |
+
redirect: { enumerable: true },
|
| 1300 |
+
clone: { enumerable: true },
|
| 1301 |
+
signal: { enumerable: true }
|
| 1302 |
+
});
|
| 1303 |
+
|
| 1304 |
+
/**
|
| 1305 |
+
* Convert a Request to Node.js http request options.
|
| 1306 |
+
*
|
| 1307 |
+
* @param Request A Request instance
|
| 1308 |
+
* @return Object The options object to be passed to http.request
|
| 1309 |
+
*/
|
| 1310 |
+
function getNodeRequestOptions(request) {
|
| 1311 |
+
const parsedURL = request[INTERNALS$2].parsedURL;
|
| 1312 |
+
const headers = new Headers(request[INTERNALS$2].headers);
|
| 1313 |
+
|
| 1314 |
+
// fetch step 1.3
|
| 1315 |
+
if (!headers.has('Accept')) {
|
| 1316 |
+
headers.set('Accept', '*/*');
|
| 1317 |
+
}
|
| 1318 |
+
|
| 1319 |
+
// Basic fetch
|
| 1320 |
+
if (!parsedURL.protocol || !parsedURL.hostname) {
|
| 1321 |
+
throw new TypeError('Only absolute URLs are supported');
|
| 1322 |
+
}
|
| 1323 |
+
|
| 1324 |
+
if (!/^https?:$/.test(parsedURL.protocol)) {
|
| 1325 |
+
throw new TypeError('Only HTTP(S) protocols are supported');
|
| 1326 |
+
}
|
| 1327 |
+
|
| 1328 |
+
if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
|
| 1329 |
+
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
|
| 1330 |
+
}
|
| 1331 |
+
|
| 1332 |
+
// HTTP-network-or-cache fetch steps 2.4-2.7
|
| 1333 |
+
let contentLengthValue = null;
|
| 1334 |
+
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
|
| 1335 |
+
contentLengthValue = '0';
|
| 1336 |
+
}
|
| 1337 |
+
if (request.body != null) {
|
| 1338 |
+
const totalBytes = getTotalBytes(request);
|
| 1339 |
+
if (typeof totalBytes === 'number') {
|
| 1340 |
+
contentLengthValue = String(totalBytes);
|
| 1341 |
+
}
|
| 1342 |
+
}
|
| 1343 |
+
if (contentLengthValue) {
|
| 1344 |
+
headers.set('Content-Length', contentLengthValue);
|
| 1345 |
+
}
|
| 1346 |
+
|
| 1347 |
+
// HTTP-network-or-cache fetch step 2.11
|
| 1348 |
+
if (!headers.has('User-Agent')) {
|
| 1349 |
+
headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)');
|
| 1350 |
+
}
|
| 1351 |
+
|
| 1352 |
+
// HTTP-network-or-cache fetch step 2.15
|
| 1353 |
+
if (request.compress && !headers.has('Accept-Encoding')) {
|
| 1354 |
+
headers.set('Accept-Encoding', 'gzip,deflate');
|
| 1355 |
+
}
|
| 1356 |
+
|
| 1357 |
+
let agent = request.agent;
|
| 1358 |
+
if (typeof agent === 'function') {
|
| 1359 |
+
agent = agent(parsedURL);
|
| 1360 |
+
}
|
| 1361 |
+
|
| 1362 |
+
if (!headers.has('Connection') && !agent) {
|
| 1363 |
+
headers.set('Connection', 'close');
|
| 1364 |
+
}
|
| 1365 |
+
|
| 1366 |
+
// HTTP-network fetch step 4.2
|
| 1367 |
+
// chunked encoding is handled by Node.js
|
| 1368 |
+
|
| 1369 |
+
return Object.assign({}, parsedURL, {
|
| 1370 |
+
method: request.method,
|
| 1371 |
+
headers: exportNodeCompatibleHeaders(headers),
|
| 1372 |
+
agent
|
| 1373 |
+
});
|
| 1374 |
+
}
|
| 1375 |
+
|
| 1376 |
+
/**
|
| 1377 |
+
* abort-error.js
|
| 1378 |
+
*
|
| 1379 |
+
* AbortError interface for cancelled requests
|
| 1380 |
+
*/
|
| 1381 |
+
|
| 1382 |
+
/**
|
| 1383 |
+
* Create AbortError instance
|
| 1384 |
+
*
|
| 1385 |
+
* @param String message Error message for human
|
| 1386 |
+
* @return AbortError
|
| 1387 |
+
*/
|
| 1388 |
+
function AbortError(message) {
|
| 1389 |
+
Error.call(this, message);
|
| 1390 |
+
|
| 1391 |
+
this.type = 'aborted';
|
| 1392 |
+
this.message = message;
|
| 1393 |
+
|
| 1394 |
+
// hide custom error implementation details from end-users
|
| 1395 |
+
Error.captureStackTrace(this, this.constructor);
|
| 1396 |
+
}
|
| 1397 |
+
|
| 1398 |
+
AbortError.prototype = Object.create(Error.prototype);
|
| 1399 |
+
AbortError.prototype.constructor = AbortError;
|
| 1400 |
+
AbortError.prototype.name = 'AbortError';
|
| 1401 |
+
|
| 1402 |
+
const URL$1 = Url.URL || whatwgUrl.URL;
|
| 1403 |
+
|
| 1404 |
+
// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
|
| 1405 |
+
const PassThrough$1 = Stream.PassThrough;
|
| 1406 |
+
|
| 1407 |
+
const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) {
|
| 1408 |
+
const orig = new URL$1(original).hostname;
|
| 1409 |
+
const dest = new URL$1(destination).hostname;
|
| 1410 |
+
|
| 1411 |
+
return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest);
|
| 1412 |
+
};
|
| 1413 |
+
|
| 1414 |
+
/**
|
| 1415 |
+
* isSameProtocol reports whether the two provided URLs use the same protocol.
|
| 1416 |
+
*
|
| 1417 |
+
* Both domains must already be in canonical form.
|
| 1418 |
+
* @param {string|URL} original
|
| 1419 |
+
* @param {string|URL} destination
|
| 1420 |
+
*/
|
| 1421 |
+
const isSameProtocol = function isSameProtocol(destination, original) {
|
| 1422 |
+
const orig = new URL$1(original).protocol;
|
| 1423 |
+
const dest = new URL$1(destination).protocol;
|
| 1424 |
+
|
| 1425 |
+
return orig === dest;
|
| 1426 |
+
};
|
| 1427 |
+
|
| 1428 |
+
/**
|
| 1429 |
+
* Fetch function
|
| 1430 |
+
*
|
| 1431 |
+
* @param Mixed url Absolute url or Request instance
|
| 1432 |
+
* @param Object opts Fetch options
|
| 1433 |
+
* @return Promise
|
| 1434 |
+
*/
|
| 1435 |
+
function fetch(url, opts) {
|
| 1436 |
+
|
| 1437 |
+
// allow custom promise
|
| 1438 |
+
if (!fetch.Promise) {
|
| 1439 |
+
throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
|
| 1440 |
+
}
|
| 1441 |
+
|
| 1442 |
+
Body.Promise = fetch.Promise;
|
| 1443 |
+
|
| 1444 |
+
// wrap http.request into fetch
|
| 1445 |
+
return new fetch.Promise(function (resolve, reject) {
|
| 1446 |
+
// build request object
|
| 1447 |
+
const request = new Request(url, opts);
|
| 1448 |
+
const options = getNodeRequestOptions(request);
|
| 1449 |
+
|
| 1450 |
+
const send = (options.protocol === 'https:' ? https : http).request;
|
| 1451 |
+
const signal = request.signal;
|
| 1452 |
+
|
| 1453 |
+
let response = null;
|
| 1454 |
+
|
| 1455 |
+
const abort = function abort() {
|
| 1456 |
+
let error = new AbortError('The user aborted a request.');
|
| 1457 |
+
reject(error);
|
| 1458 |
+
if (request.body && request.body instanceof Stream.Readable) {
|
| 1459 |
+
destroyStream(request.body, error);
|
| 1460 |
+
}
|
| 1461 |
+
if (!response || !response.body) return;
|
| 1462 |
+
response.body.emit('error', error);
|
| 1463 |
+
};
|
| 1464 |
+
|
| 1465 |
+
if (signal && signal.aborted) {
|
| 1466 |
+
abort();
|
| 1467 |
+
return;
|
| 1468 |
+
}
|
| 1469 |
+
|
| 1470 |
+
const abortAndFinalize = function abortAndFinalize() {
|
| 1471 |
+
abort();
|
| 1472 |
+
finalize();
|
| 1473 |
+
};
|
| 1474 |
+
|
| 1475 |
+
// send request
|
| 1476 |
+
const req = send(options);
|
| 1477 |
+
let reqTimeout;
|
| 1478 |
+
|
| 1479 |
+
if (signal) {
|
| 1480 |
+
signal.addEventListener('abort', abortAndFinalize);
|
| 1481 |
+
}
|
| 1482 |
+
|
| 1483 |
+
function finalize() {
|
| 1484 |
+
req.abort();
|
| 1485 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1486 |
+
clearTimeout(reqTimeout);
|
| 1487 |
+
}
|
| 1488 |
+
|
| 1489 |
+
if (request.timeout) {
|
| 1490 |
+
req.once('socket', function (socket) {
|
| 1491 |
+
reqTimeout = setTimeout(function () {
|
| 1492 |
+
reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout'));
|
| 1493 |
+
finalize();
|
| 1494 |
+
}, request.timeout);
|
| 1495 |
+
});
|
| 1496 |
+
}
|
| 1497 |
+
|
| 1498 |
+
req.on('error', function (err) {
|
| 1499 |
+
reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
|
| 1500 |
+
|
| 1501 |
+
if (response && response.body) {
|
| 1502 |
+
destroyStream(response.body, err);
|
| 1503 |
+
}
|
| 1504 |
+
|
| 1505 |
+
finalize();
|
| 1506 |
+
});
|
| 1507 |
+
|
| 1508 |
+
fixResponseChunkedTransferBadEnding(req, function (err) {
|
| 1509 |
+
if (signal && signal.aborted) {
|
| 1510 |
+
return;
|
| 1511 |
+
}
|
| 1512 |
+
|
| 1513 |
+
if (response && response.body) {
|
| 1514 |
+
destroyStream(response.body, err);
|
| 1515 |
+
}
|
| 1516 |
+
});
|
| 1517 |
+
|
| 1518 |
+
/* c8 ignore next 18 */
|
| 1519 |
+
if (parseInt(process.version.substring(1)) < 14) {
|
| 1520 |
+
// Before Node.js 14, pipeline() does not fully support async iterators and does not always
|
| 1521 |
+
// properly handle when the socket close/end events are out of order.
|
| 1522 |
+
req.on('socket', function (s) {
|
| 1523 |
+
s.addListener('close', function (hadError) {
|
| 1524 |
+
// if a data listener is still present we didn't end cleanly
|
| 1525 |
+
const hasDataListener = s.listenerCount('data') > 0;
|
| 1526 |
+
|
| 1527 |
+
// if end happened before close but the socket didn't emit an error, do it now
|
| 1528 |
+
if (response && hasDataListener && !hadError && !(signal && signal.aborted)) {
|
| 1529 |
+
const err = new Error('Premature close');
|
| 1530 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1531 |
+
response.body.emit('error', err);
|
| 1532 |
+
}
|
| 1533 |
+
});
|
| 1534 |
+
});
|
| 1535 |
+
}
|
| 1536 |
+
|
| 1537 |
+
req.on('response', function (res) {
|
| 1538 |
+
clearTimeout(reqTimeout);
|
| 1539 |
+
|
| 1540 |
+
const headers = createHeadersLenient(res.headers);
|
| 1541 |
+
|
| 1542 |
+
// HTTP fetch step 5
|
| 1543 |
+
if (fetch.isRedirect(res.statusCode)) {
|
| 1544 |
+
// HTTP fetch step 5.2
|
| 1545 |
+
const location = headers.get('Location');
|
| 1546 |
+
|
| 1547 |
+
// HTTP fetch step 5.3
|
| 1548 |
+
let locationURL = null;
|
| 1549 |
+
try {
|
| 1550 |
+
locationURL = location === null ? null : new URL$1(location, request.url).toString();
|
| 1551 |
+
} catch (err) {
|
| 1552 |
+
// error here can only be invalid URL in Location: header
|
| 1553 |
+
// do not throw when options.redirect == manual
|
| 1554 |
+
// let the user extract the errorneous redirect URL
|
| 1555 |
+
if (request.redirect !== 'manual') {
|
| 1556 |
+
reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
|
| 1557 |
+
finalize();
|
| 1558 |
+
return;
|
| 1559 |
+
}
|
| 1560 |
+
}
|
| 1561 |
+
|
| 1562 |
+
// HTTP fetch step 5.5
|
| 1563 |
+
switch (request.redirect) {
|
| 1564 |
+
case 'error':
|
| 1565 |
+
reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
|
| 1566 |
+
finalize();
|
| 1567 |
+
return;
|
| 1568 |
+
case 'manual':
|
| 1569 |
+
// node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
|
| 1570 |
+
if (locationURL !== null) {
|
| 1571 |
+
// handle corrupted header
|
| 1572 |
+
try {
|
| 1573 |
+
headers.set('Location', locationURL);
|
| 1574 |
+
} catch (err) {
|
| 1575 |
+
// istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
|
| 1576 |
+
reject(err);
|
| 1577 |
+
}
|
| 1578 |
+
}
|
| 1579 |
+
break;
|
| 1580 |
+
case 'follow':
|
| 1581 |
+
// HTTP-redirect fetch step 2
|
| 1582 |
+
if (locationURL === null) {
|
| 1583 |
+
break;
|
| 1584 |
+
}
|
| 1585 |
+
|
| 1586 |
+
// HTTP-redirect fetch step 5
|
| 1587 |
+
if (request.counter >= request.follow) {
|
| 1588 |
+
reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect'));
|
| 1589 |
+
finalize();
|
| 1590 |
+
return;
|
| 1591 |
+
}
|
| 1592 |
+
|
| 1593 |
+
// HTTP-redirect fetch step 6 (counter increment)
|
| 1594 |
+
// Create a new Request object.
|
| 1595 |
+
const requestOpts = {
|
| 1596 |
+
headers: new Headers(request.headers),
|
| 1597 |
+
follow: request.follow,
|
| 1598 |
+
counter: request.counter + 1,
|
| 1599 |
+
agent: request.agent,
|
| 1600 |
+
compress: request.compress,
|
| 1601 |
+
method: request.method,
|
| 1602 |
+
body: request.body,
|
| 1603 |
+
signal: request.signal,
|
| 1604 |
+
timeout: request.timeout,
|
| 1605 |
+
size: request.size
|
| 1606 |
+
};
|
| 1607 |
+
|
| 1608 |
+
if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) {
|
| 1609 |
+
for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
|
| 1610 |
+
requestOpts.headers.delete(name);
|
| 1611 |
+
}
|
| 1612 |
+
}
|
| 1613 |
+
|
| 1614 |
+
// HTTP-redirect fetch step 9
|
| 1615 |
+
if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
|
| 1616 |
+
reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
|
| 1617 |
+
finalize();
|
| 1618 |
+
return;
|
| 1619 |
+
}
|
| 1620 |
+
|
| 1621 |
+
// HTTP-redirect fetch step 11
|
| 1622 |
+
if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') {
|
| 1623 |
+
requestOpts.method = 'GET';
|
| 1624 |
+
requestOpts.body = undefined;
|
| 1625 |
+
requestOpts.headers.delete('content-length');
|
| 1626 |
+
}
|
| 1627 |
+
|
| 1628 |
+
// HTTP-redirect fetch step 15
|
| 1629 |
+
resolve(fetch(new Request(locationURL, requestOpts)));
|
| 1630 |
+
finalize();
|
| 1631 |
+
return;
|
| 1632 |
+
}
|
| 1633 |
+
}
|
| 1634 |
+
|
| 1635 |
+
// prepare response
|
| 1636 |
+
res.once('end', function () {
|
| 1637 |
+
if (signal) signal.removeEventListener('abort', abortAndFinalize);
|
| 1638 |
+
});
|
| 1639 |
+
let body = res.pipe(new PassThrough$1());
|
| 1640 |
+
|
| 1641 |
+
const response_options = {
|
| 1642 |
+
url: request.url,
|
| 1643 |
+
status: res.statusCode,
|
| 1644 |
+
statusText: res.statusMessage,
|
| 1645 |
+
headers: headers,
|
| 1646 |
+
size: request.size,
|
| 1647 |
+
timeout: request.timeout,
|
| 1648 |
+
counter: request.counter
|
| 1649 |
+
};
|
| 1650 |
+
|
| 1651 |
+
// HTTP-network fetch step 12.1.1.3
|
| 1652 |
+
const codings = headers.get('Content-Encoding');
|
| 1653 |
+
|
| 1654 |
+
// HTTP-network fetch step 12.1.1.4: handle content codings
|
| 1655 |
+
|
| 1656 |
+
// in following scenarios we ignore compression support
|
| 1657 |
+
// 1. compression support is disabled
|
| 1658 |
+
// 2. HEAD request
|
| 1659 |
+
// 3. no Content-Encoding header
|
| 1660 |
+
// 4. no content response (204)
|
| 1661 |
+
// 5. content not modified response (304)
|
| 1662 |
+
if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
| 1663 |
+
response = new Response(body, response_options);
|
| 1664 |
+
resolve(response);
|
| 1665 |
+
return;
|
| 1666 |
+
}
|
| 1667 |
+
|
| 1668 |
+
// For Node v6+
|
| 1669 |
+
// Be less strict when decoding compressed responses, since sometimes
|
| 1670 |
+
// servers send slightly invalid responses that are still accepted
|
| 1671 |
+
// by common browsers.
|
| 1672 |
+
// Always using Z_SYNC_FLUSH is what cURL does.
|
| 1673 |
+
const zlibOptions = {
|
| 1674 |
+
flush: zlib.Z_SYNC_FLUSH,
|
| 1675 |
+
finishFlush: zlib.Z_SYNC_FLUSH
|
| 1676 |
+
};
|
| 1677 |
+
|
| 1678 |
+
// for gzip
|
| 1679 |
+
if (codings == 'gzip' || codings == 'x-gzip') {
|
| 1680 |
+
body = body.pipe(zlib.createGunzip(zlibOptions));
|
| 1681 |
+
response = new Response(body, response_options);
|
| 1682 |
+
resolve(response);
|
| 1683 |
+
return;
|
| 1684 |
+
}
|
| 1685 |
+
|
| 1686 |
+
// for deflate
|
| 1687 |
+
if (codings == 'deflate' || codings == 'x-deflate') {
|
| 1688 |
+
// handle the infamous raw deflate response from old servers
|
| 1689 |
+
// a hack for old IIS and Apache servers
|
| 1690 |
+
const raw = res.pipe(new PassThrough$1());
|
| 1691 |
+
raw.once('data', function (chunk) {
|
| 1692 |
+
// see http://stackoverflow.com/questions/37519828
|
| 1693 |
+
if ((chunk[0] & 0x0F) === 0x08) {
|
| 1694 |
+
body = body.pipe(zlib.createInflate());
|
| 1695 |
+
} else {
|
| 1696 |
+
body = body.pipe(zlib.createInflateRaw());
|
| 1697 |
+
}
|
| 1698 |
+
response = new Response(body, response_options);
|
| 1699 |
+
resolve(response);
|
| 1700 |
+
});
|
| 1701 |
+
raw.on('end', function () {
|
| 1702 |
+
// some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted.
|
| 1703 |
+
if (!response) {
|
| 1704 |
+
response = new Response(body, response_options);
|
| 1705 |
+
resolve(response);
|
| 1706 |
+
}
|
| 1707 |
+
});
|
| 1708 |
+
return;
|
| 1709 |
+
}
|
| 1710 |
+
|
| 1711 |
+
// for br
|
| 1712 |
+
if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
|
| 1713 |
+
body = body.pipe(zlib.createBrotliDecompress());
|
| 1714 |
+
response = new Response(body, response_options);
|
| 1715 |
+
resolve(response);
|
| 1716 |
+
return;
|
| 1717 |
+
}
|
| 1718 |
+
|
| 1719 |
+
// otherwise, use response as-is
|
| 1720 |
+
response = new Response(body, response_options);
|
| 1721 |
+
resolve(response);
|
| 1722 |
+
});
|
| 1723 |
+
|
| 1724 |
+
writeToStream(req, request);
|
| 1725 |
+
});
|
| 1726 |
+
}
|
| 1727 |
+
function fixResponseChunkedTransferBadEnding(request, errorCallback) {
|
| 1728 |
+
let socket;
|
| 1729 |
+
|
| 1730 |
+
request.on('socket', function (s) {
|
| 1731 |
+
socket = s;
|
| 1732 |
+
});
|
| 1733 |
+
|
| 1734 |
+
request.on('response', function (response) {
|
| 1735 |
+
const headers = response.headers;
|
| 1736 |
+
|
| 1737 |
+
if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) {
|
| 1738 |
+
response.once('close', function (hadError) {
|
| 1739 |
+
// if a data listener is still present we didn't end cleanly
|
| 1740 |
+
const hasDataListener = socket.listenerCount('data') > 0;
|
| 1741 |
+
|
| 1742 |
+
if (hasDataListener && !hadError) {
|
| 1743 |
+
const err = new Error('Premature close');
|
| 1744 |
+
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
| 1745 |
+
errorCallback(err);
|
| 1746 |
+
}
|
| 1747 |
+
});
|
| 1748 |
+
}
|
| 1749 |
+
});
|
| 1750 |
+
}
|
| 1751 |
+
|
| 1752 |
+
function destroyStream(stream, err) {
|
| 1753 |
+
if (stream.destroy) {
|
| 1754 |
+
stream.destroy(err);
|
| 1755 |
+
} else {
|
| 1756 |
+
// node < 8
|
| 1757 |
+
stream.emit('error', err);
|
| 1758 |
+
stream.end();
|
| 1759 |
+
}
|
| 1760 |
+
}
|
| 1761 |
+
|
| 1762 |
+
/**
|
| 1763 |
+
* Redirect code matching
|
| 1764 |
+
*
|
| 1765 |
+
* @param Number code Status code
|
| 1766 |
+
* @return Boolean
|
| 1767 |
+
*/
|
| 1768 |
+
fetch.isRedirect = function (code) {
|
| 1769 |
+
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
|
| 1770 |
+
};
|
| 1771 |
+
|
| 1772 |
+
// expose Promise
|
| 1773 |
+
fetch.Promise = global.Promise;
|
| 1774 |
+
|
| 1775 |
+
export default fetch;
|
| 1776 |
+
export { Headers, Request, Response, FetchError };
|
node_modules/node-fetch/package.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from": "node-fetch@^2.6.1",
|
| 3 |
+
"_id": "node-fetch@2.6.11",
|
| 4 |
+
"_inBundle": false,
|
| 5 |
+
"_integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
| 6 |
+
"_location": "/node-fetch",
|
| 7 |
+
"_phantomChildren": {},
|
| 8 |
+
"_requested": {
|
| 9 |
+
"type": "range",
|
| 10 |
+
"registry": true,
|
| 11 |
+
"raw": "node-fetch@^2.6.1",
|
| 12 |
+
"name": "node-fetch",
|
| 13 |
+
"escapedName": "node-fetch",
|
| 14 |
+
"rawSpec": "^2.6.1",
|
| 15 |
+
"saveSpec": null,
|
| 16 |
+
"fetchSpec": "^2.6.1"
|
| 17 |
+
},
|
| 18 |
+
"_requiredBy": [
|
| 19 |
+
"/dropbox"
|
| 20 |
+
],
|
| 21 |
+
"_resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
| 22 |
+
"_shasum": "cde7fc71deef3131ef80a738919f999e6edfff25",
|
| 23 |
+
"_spec": "node-fetch@^2.6.1",
|
| 24 |
+
"_where": "C:\\Users\\lenovo\\TSA\\node_modules\\dropbox",
|
| 25 |
+
"author": {
|
| 26 |
+
"name": "David Frank"
|
| 27 |
+
},
|
| 28 |
+
"browser": "./browser.js",
|
| 29 |
+
"bugs": {
|
| 30 |
+
"url": "https://github.com/bitinn/node-fetch/issues"
|
| 31 |
+
},
|
| 32 |
+
"bundleDependencies": false,
|
| 33 |
+
"dependencies": {
|
| 34 |
+
"whatwg-url": "^5.0.0"
|
| 35 |
+
},
|
| 36 |
+
"deprecated": false,
|
| 37 |
+
"description": "A light-weight module that brings window.fetch to node.js",
|
| 38 |
+
"devDependencies": {
|
| 39 |
+
"@ungap/url-search-params": "^0.1.2",
|
| 40 |
+
"abort-controller": "^1.1.0",
|
| 41 |
+
"abortcontroller-polyfill": "^1.3.0",
|
| 42 |
+
"babel-core": "^6.26.3",
|
| 43 |
+
"babel-plugin-istanbul": "^4.1.6",
|
| 44 |
+
"babel-plugin-transform-async-generator-functions": "^6.24.1",
|
| 45 |
+
"babel-polyfill": "^6.26.0",
|
| 46 |
+
"babel-preset-env": "1.4.0",
|
| 47 |
+
"babel-register": "^6.16.3",
|
| 48 |
+
"chai": "^3.5.0",
|
| 49 |
+
"chai-as-promised": "^7.1.1",
|
| 50 |
+
"chai-iterator": "^1.1.1",
|
| 51 |
+
"chai-string": "~1.3.0",
|
| 52 |
+
"codecov": "3.3.0",
|
| 53 |
+
"cross-env": "^5.2.0",
|
| 54 |
+
"form-data": "^2.3.3",
|
| 55 |
+
"is-builtin-module": "^1.0.0",
|
| 56 |
+
"mocha": "^5.0.0",
|
| 57 |
+
"nyc": "11.9.0",
|
| 58 |
+
"parted": "^0.1.1",
|
| 59 |
+
"promise": "^8.0.3",
|
| 60 |
+
"resumer": "0.0.0",
|
| 61 |
+
"rollup": "^0.63.4",
|
| 62 |
+
"rollup-plugin-babel": "^3.0.7",
|
| 63 |
+
"string-to-arraybuffer": "^1.0.2",
|
| 64 |
+
"teeny-request": "3.7.0"
|
| 65 |
+
},
|
| 66 |
+
"engines": {
|
| 67 |
+
"node": "4.x || >=6.0.0"
|
| 68 |
+
},
|
| 69 |
+
"files": [
|
| 70 |
+
"lib/index.js",
|
| 71 |
+
"lib/index.mjs",
|
| 72 |
+
"lib/index.es.js",
|
| 73 |
+
"browser.js"
|
| 74 |
+
],
|
| 75 |
+
"homepage": "https://github.com/bitinn/node-fetch",
|
| 76 |
+
"keywords": [
|
| 77 |
+
"fetch",
|
| 78 |
+
"http",
|
| 79 |
+
"promise"
|
| 80 |
+
],
|
| 81 |
+
"license": "MIT",
|
| 82 |
+
"main": "lib/index.js",
|
| 83 |
+
"module": "lib/index.mjs",
|
| 84 |
+
"name": "node-fetch",
|
| 85 |
+
"peerDependencies": {
|
| 86 |
+
"encoding": "^0.1.0"
|
| 87 |
+
},
|
| 88 |
+
"peerDependenciesMeta": {
|
| 89 |
+
"encoding": {
|
| 90 |
+
"optional": true
|
| 91 |
+
}
|
| 92 |
+
},
|
| 93 |
+
"release": {
|
| 94 |
+
"branches": [
|
| 95 |
+
"+([0-9]).x",
|
| 96 |
+
"main",
|
| 97 |
+
"next",
|
| 98 |
+
{
|
| 99 |
+
"name": "beta",
|
| 100 |
+
"prerelease": true
|
| 101 |
+
}
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
"repository": {
|
| 105 |
+
"type": "git",
|
| 106 |
+
"url": "git+https://github.com/bitinn/node-fetch.git"
|
| 107 |
+
},
|
| 108 |
+
"scripts": {
|
| 109 |
+
"build": "cross-env BABEL_ENV=rollup rollup -c",
|
| 110 |
+
"coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json",
|
| 111 |
+
"prepare": "npm run build",
|
| 112 |
+
"report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js",
|
| 113 |
+
"test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js"
|
| 114 |
+
},
|
| 115 |
+
"version": "2.6.11"
|
| 116 |
+
}
|
node_modules/tr46/.npmignore
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
scripts/
|
| 2 |
+
test/
|
| 3 |
+
|
| 4 |
+
!lib/mapping_table.json
|
node_modules/tr46/dropbox/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dropbox Code Of Conduct
|
| 2 |
+
|
| 3 |
+
*Dropbox believes that an inclusive development environment fosters greater technical achievement. To encourage a diverse group of contributors we've adopted this code of conduct.*
|
| 4 |
+
|
| 5 |
+
Please read the Official Dropbox [Code of Conduct](https://opensource.dropbox.com/coc/) before contributing.
|
node_modules/tr46/dropbox/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing to the Dropbox SDK for Javascript
|
| 2 |
+
We value and rely on the feedback from our community. This comes in the form of bug reports, feature requests, and general guidance. We welcome your issues and pull requests and try our hardest to be timely in both response and resolution. Please read through this document before submitting issues or pull requests to ensure we have the necessary information to help you resolve your issue.
|
| 3 |
+
|
| 4 |
+
## Filing Bug Reports
|
| 5 |
+
You can file a bug report on the [GitHub Issues][issues] page.
|
| 6 |
+
|
| 7 |
+
1. Search through existing issues to ensure that your issue has not been reported. If it is a common issue, there is likely already an issue.
|
| 8 |
+
|
| 9 |
+
2. Please ensure you are using the latest version of the SDK. While this may be a valid issue, we only will fix bugs affecting the latest version and your bug may have been fixed in a newer version.
|
| 10 |
+
|
| 11 |
+
3. Provide as much information as you can regarding the language version, SDK version, and any other relevant information about your environment so we can help resolve the issue as quickly as possible.
|
| 12 |
+
|
| 13 |
+
## Submitting Pull Requests
|
| 14 |
+
|
| 15 |
+
We are more than happy to recieve pull requests helping us improve the state of our SDK. You can open a new pull request on the [GitHub Pull Requests][pr] page.
|
| 16 |
+
|
| 17 |
+
1. Please ensure that you have read the [License][license], [Code of Conduct][coc] and have signed the [Contributing License Agreement (CLA)][cla].
|
| 18 |
+
|
| 19 |
+
2. Please add tests confirming the new functionality works. Pull requests will not be merged without passing continuous integration tests unless the pull requests aims to fix existing issues with these tests.
|
| 20 |
+
|
| 21 |
+
3. If the pull request is modifying typescript definitions, please remember to change the template found under `generator/typescript` and run the generation instead of manually changing types. If there is an issue with the generation, please file an issue.
|
| 22 |
+
|
| 23 |
+
## Updating Generated Code
|
| 24 |
+
|
| 25 |
+
Generated code can be updated by running the following commands:
|
| 26 |
+
|
| 27 |
+
```
|
| 28 |
+
$ git submodule init
|
| 29 |
+
$ git submodule update --remote --recursive
|
| 30 |
+
$ cd generator/stone
|
| 31 |
+
$ python setup.py install
|
| 32 |
+
$ cd ..
|
| 33 |
+
$ python generate_routes.py
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
This will generate typescript definitions and route code.
|
| 37 |
+
|
| 38 |
+
## Testing the Code
|
| 39 |
+
|
| 40 |
+
Tests live under the `test/` folder and are then broken down into the type of test it is. To run both the unit tests and the typescript tests, you can use:
|
| 41 |
+
|
| 42 |
+
```
|
| 43 |
+
$ npm test
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
If you would like to run the integration tests locally, you can run:
|
| 47 |
+
|
| 48 |
+
```
|
| 49 |
+
export DROPBOX_TOKEN={fill in user token}
|
| 50 |
+
export DROPBOX_TEAM_TOKEN={fill in team token}
|
| 51 |
+
export DROPBOX_USER_ID={fill in assume user id}
|
| 52 |
+
export DROPBOX_SHARED_LINK={fill in shared link}
|
| 53 |
+
$ npm run test:integration
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
Note: If you do not have all of these tokens available, we run integration tests as a part of pull request validation and you are able to rely on those if you are unable to obtain yourself.
|
| 57 |
+
|
| 58 |
+
[issues]: https://github.com/dropbox/dropbox-sdk-js/issues
|
| 59 |
+
[pr]: https://github.com/dropbox/dropbox-sdk-js/pulls
|
| 60 |
+
[coc]: https://github.com/dropbox/dropbox-sdk-js/blob/main/CODE_OF_CONDUCT.md
|
| 61 |
+
[license]: https://github.com/dropbox/dropbox-sdk-js/blob/main/LICENSE
|
| 62 |
+
[cla]: https://opensource.dropbox.com/cla/
|
node_modules/tr46/dropbox/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright (c) 2020 Dropbox Inc., http://www.dropbox.com/
|
| 2 |
+
|
| 3 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 4 |
+
a copy of this software and associated documentation files (the
|
| 5 |
+
"Software"), to deal in the Software without restriction, including
|
| 6 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
| 7 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
| 8 |
+
permit persons to whom the Software is furnished to do so, subject to
|
| 9 |
+
the following conditions:
|
| 10 |
+
|
| 11 |
+
The above copyright notice and this permission notice shall be
|
| 12 |
+
included in all copies or substantial portions of the Software.
|
| 13 |
+
|
| 14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 15 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 16 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 17 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
| 18 |
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
| 19 |
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 20 |
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
node_modules/tr46/dropbox/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[![Logo][logo]][repo]
|
| 2 |
+
|
| 3 |
+
[](https://www.npmjs.com/package/dropbox)
|
| 4 |
+
[](https://www.npmjs.com/package/dropbox)
|
| 5 |
+
[](https://codecov.io/gh/dropbox/dropbox-sdk-js)
|
| 6 |
+
|
| 7 |
+
The offical Dropbox SDK for Javascript.
|
| 8 |
+
|
| 9 |
+
Documentation can be found on [GitHub Pages][documentation]
|
| 10 |
+
|
| 11 |
+
## Installation
|
| 12 |
+
|
| 13 |
+
Create an app via the [Developer Console][devconsole]
|
| 14 |
+
|
| 15 |
+
Install via [npm](https://www.npmjs.com/)
|
| 16 |
+
|
| 17 |
+
```
|
| 18 |
+
$ npm install --save dropbox
|
| 19 |
+
```
|
| 20 |
+
|
| 21 |
+
Install from source:
|
| 22 |
+
|
| 23 |
+
```
|
| 24 |
+
$ git clone https://github.com/dropbox/dropbox-sdk-js.git
|
| 25 |
+
$ cd dropbox-sdk-js
|
| 26 |
+
$ npm install
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
If you are using the repository from the browser, you can use any CDNs that hosts the Dropbox package by including a script tag with the link to the package. However, we highly recommend you do not directly import the latest version and instead choose a specific version. When we update and release a breaking change, this could break production code which we hope to avoid. Note, we follow [semver](https://semver.org/) naming conventions which means that any major version update could contain a breaking change.
|
| 30 |
+
|
| 31 |
+
After installation, follow one of our [Examples][examples] or read the [Documentation][documentation].
|
| 32 |
+
|
| 33 |
+
You can also view our [OAuth guide][oauthguide].
|
| 34 |
+
|
| 35 |
+
## Examples
|
| 36 |
+
|
| 37 |
+
We provide [Examples][examples] to help get you started with a lot of the basic functionality in the SDK. We provide most examples in both Javascript and Typescript with some having a Node equivalent.
|
| 38 |
+
|
| 39 |
+
- **OAuth**
|
| 40 |
+
- Auth - [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/auth) ] - A simple auth example to get an access token and list the files in the root of your Dropbox account.
|
| 41 |
+
- Simple Backend [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/simple-backend) ] - A simple example of a node backend doing a multi-step auth flow for Short Lived Tokens.
|
| 42 |
+
- PKCE Backend [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/PKCE-backend) ] - A simple example of a node backend doing a multi-step auth flow using PKCE and Short Lived Tokens.
|
| 43 |
+
- PKCE Browser [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/pkce-browser) ] - A simple example of a frontend doing a multi-step auth flow using PKCE and Short Lived Tokens.
|
| 44 |
+
|
| 45 |
+
- **Other Examples**
|
| 46 |
+
- Basic - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/node), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/basic) ] - A simple example that takes in a token and fetches files from your Dropbox account.
|
| 47 |
+
- Download - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/node), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/download) ] - An example showing how to download a shared file.
|
| 48 |
+
- Team As User - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/node), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/team-as-user) ] - An example showing how to act as a user.
|
| 49 |
+
- Team - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/node), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/team) ] - An example showing how to use the team functionality and list team devices.
|
| 50 |
+
- Upload [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/node), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/upload) ] - An example showing how to upload a file to Dropbox.
|
| 51 |
+
|
| 52 |
+
## Getting Help
|
| 53 |
+
|
| 54 |
+
If you find a bug, please see [CONTRIBUTING.md][contributing] for information on how to report it.
|
| 55 |
+
|
| 56 |
+
If you need help that is not specific to this SDK, please reach out to [Dropbox Support][support].
|
| 57 |
+
|
| 58 |
+
## License
|
| 59 |
+
|
| 60 |
+
This SDK is distributed under the MIT license, please see [LICENSE][license] for more information.
|
| 61 |
+
|
| 62 |
+
[logo]: https://cfl.dropboxstatic.com/static/images/sdk/javascript_banner.png
|
| 63 |
+
[repo]: https://github.com/dropbox/dropbox-sdk-js
|
| 64 |
+
[documentation]: https://dropbox.github.io/dropbox-sdk-js/
|
| 65 |
+
[examples]: https://github.com/dropbox/dropbox-sdk-js/tree/main/examples
|
| 66 |
+
[license]: https://github.com/dropbox/dropbox-sdk-js/blob/main/LICENSE
|
| 67 |
+
[contributing]: https://github.com/dropbox/dropbox-sdk-js/blob/main/CONTRIBUTING.md
|
| 68 |
+
[devconsole]: https://dropbox.com/developers/apps
|
| 69 |
+
[oauthguide]: https://www.dropbox.com/lp/developers/reference/oauth-guide
|
| 70 |
+
[support]: https://www.dropbox.com/developers/contact
|
node_modules/tr46/dropbox/UPGRADING.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Upgrading the Dropbox SDK
|
| 2 |
+
|
| 3 |
+
This document is designed to show you how to upgrade to the latest version of the SDK accomodating any breaking changes introduced by major version updates. If you find any issues with either this guide on upgrading or the changes introduced in the new version, please see [CONTRIBUTING.md][contributing]
|
| 4 |
+
|
| 5 |
+
# Upgrading from v9.X.X to v10.0.0
|
| 6 |
+
|
| 7 |
+
## 1. Deprecating the `authenticateWithCordova` function
|
| 8 |
+
|
| 9 |
+
The `authenticateWithCordova` function used an in-app browser within the Cordova framework to authenticate users via OAuth. As a part of hardening security, we are following [Google’s recommendation](https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html) to remove support for authentication via a “web-view” or in-app browsers. Since the `authenticateWithCordova` function relies on running in an in-app browser, we have made the choice to deprecate this function.
|
| 10 |
+
|
| 11 |
+
Instead, apps will need to implement logic to handle this use case. The high level logic would be as follows:
|
| 12 |
+
|
| 13 |
+
1. getAuthenticationUrl with your app’s parameters. For Native Apps, we highly encourage using PKCE to increase your app’s security.
|
| 14 |
+
2. Open the authentication URL in the default system browser
|
| 15 |
+
3. Redirect back into your app upon completion of the OAuth flow.
|
| 16 |
+
|
| 17 |
+
We recommend using a custom URI for redirect to ensure you are redirecting directly back into your app. You can read up on this process more in detail on the [OAuth site](https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/).
|
| 18 |
+
|
| 19 |
+
# Upgrading from v8.X.X to v9.0.0
|
| 20 |
+
|
| 21 |
+
## 1. Unblocking browser PKCE flow
|
| 22 |
+
|
| 23 |
+
Previously, there was an issue in which Node and the Browser use different processes to generate the `codeVerifier` and `codeChallenge`. In order to remedy this, both `generatePKCECodes` and `getAuthenticationUrl` now return promises due to the how the browser digests hashes.
|
| 24 |
+
|
| 25 |
+
Previous Implementation(synchronous):
|
| 26 |
+
```
|
| 27 |
+
var authUrl = dbxAuth.getAuthenticationUrl(redirectUri, null, 'code', 'offline', null, 'none', false)
|
| 28 |
+
// logic for navigating to authUrl
|
| 29 |
+
```
|
| 30 |
+
New Implementation(async):
|
| 31 |
+
```
|
| 32 |
+
dbxAuth.getAuthenticationUrl(redirectUri, null, 'code', 'offline', null, 'none', false)
|
| 33 |
+
.then((authUrl) => {
|
| 34 |
+
// logic for navigating to authUrl
|
| 35 |
+
});
|
| 36 |
+
```
|
| 37 |
+
# Upgrading from v7.X.X to v8.0.0
|
| 38 |
+
|
| 39 |
+
## 1. Throwing Errors as `DropboxResponseError` rather than a literal object
|
| 40 |
+
|
| 41 |
+
We have created a new Error class called `DropboxResponseError` which contains the same members as the literal that was thrown, but in a cleaner format. It also allows you to leverage the fact this class now extends the builtin `Error` class.
|
| 42 |
+
|
| 43 |
+
# Upgrading from v6.X.X to v7.0.0
|
| 44 |
+
|
| 45 |
+
## 1. Fixing the Typescript argument parameter bug ([#41](https://github.com/dropbox/dropbox-sdk-js/issues/41))
|
| 46 |
+
|
| 47 |
+
We noticed a long lasting bug where the Typescript definitions of routes with no arg would require a `void` argument. This required users to make calls like this:
|
| 48 |
+
|
| 49 |
+
```
|
| 50 |
+
var result = dbx.usersGetCurrentAccount(null);
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
We have since fixed this to no longer require the null parameter.
|
| 54 |
+
|
| 55 |
+
# Upgrading from v5.X.X to v6.0.0
|
| 56 |
+
|
| 57 |
+
## 1. Unifying Dropbox and DropboxTeam
|
| 58 |
+
|
| 59 |
+
We made the decision to unify the Dropbox and DropboxTeam objects to further simplify the logic in the SDK. Migrating is very straightforward, a reference like this:
|
| 60 |
+
|
| 61 |
+
```
|
| 62 |
+
var dbx = new DropboxTeam({
|
| 63 |
+
accessToken: 'my_token'
|
| 64 |
+
});
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
Can be rewritten as:
|
| 68 |
+
|
| 69 |
+
```
|
| 70 |
+
var dbx = new Dropbox({
|
| 71 |
+
accessToken: 'my_token'
|
| 72 |
+
});
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
Additionally, when using features like assume user, select admin, or path root they are not set as a part of the constructor rather than creating a new client. Logic like this:
|
| 76 |
+
|
| 77 |
+
```
|
| 78 |
+
var dbx = new DropboxTeam({
|
| 79 |
+
accessToken: 'my_token'
|
| 80 |
+
});
|
| 81 |
+
var dbx_user = dbx.actAsUser(user_id);
|
| 82 |
+
dbx_user.usersGetCurrentAccount();
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
Can be rewritten as:
|
| 86 |
+
|
| 87 |
+
```
|
| 88 |
+
var dbx = new Dropbox({
|
| 89 |
+
accessToken: 'my_token',
|
| 90 |
+
selectUser: 'my_user_id'
|
| 91 |
+
});
|
| 92 |
+
dbx.usersGetcurrentAccount();
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
## 2. Moving authentication to DropboxAuth
|
| 96 |
+
|
| 97 |
+
Another change that was made was to move all auth related functionality into the DropboxAuth object. The main Dropbox object can be constructed the same way but this will internally create a DropboxAuth object. In order to access any auth functions from the main client you must change your code as such:
|
| 98 |
+
|
| 99 |
+
```
|
| 100 |
+
dbx.get_authentication_url(...);
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
Would become something like this:
|
| 104 |
+
|
| 105 |
+
```
|
| 106 |
+
dbx.auth.get_authentication_url(...);
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
However, we recommend creating a DropboxAuth object before creating a client and then constructing as such:
|
| 110 |
+
|
| 111 |
+
```
|
| 112 |
+
var dbxAuth = new DropboxAuth();
|
| 113 |
+
... // Do auth logic
|
| 114 |
+
var dbx = new Dropbox(dbxAuth);
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
That way if you need to create another instance of the client, you can easily plug in the same auth object.
|
| 118 |
+
|
| 119 |
+
## 3. Changing Typescript export format
|
| 120 |
+
|
| 121 |
+
We have updated the Typescript definitions to be a part of `Dropbox` namespace rather than the `DropboxTypes` namespace. This would look like:
|
| 122 |
+
|
| 123 |
+
```
|
| 124 |
+
const result: DropboxTypes.users.FullAccount dbx.usersGetCurrentAccount();
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
Would become:
|
| 128 |
+
|
| 129 |
+
```
|
| 130 |
+
const result: Dropbox.users.FullAccount dbx.usersGetCurrentAccount();
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
## 4. Updating the Response object
|
| 134 |
+
|
| 135 |
+
We have wrapped the raw responses into the `DropboxResponse` object in order to expose more information out to users. This change looks like:
|
| 136 |
+
|
| 137 |
+
```
|
| 138 |
+
var response = dbx.usersGetcurrentAccount();
|
| 139 |
+
console.log(response.fileBlob); //or fileBinary if using workers
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
Would become:
|
| 143 |
+
|
| 144 |
+
```
|
| 145 |
+
var response = dbx.usersGetcurrentAccount();
|
| 146 |
+
console.log(response.result.fileBlob); //or fileBinary if using workers
|
| 147 |
+
```
|
| 148 |
+
|
| 149 |
+
This also exposes the other components of the response like the status and headers which was not previously available.
|
| 150 |
+
|
| 151 |
+
```
|
| 152 |
+
var response = dbx.usersGetcurrentAccount();
|
| 153 |
+
console.log(response.status);
|
| 154 |
+
console.log(response.headers);
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
## 5. Default behavior for `fetch`.
|
| 158 |
+
|
| 159 |
+
Previously we have provided guidance to SDK users that they should not rely on the Dropbox SDK's global fetch and that it would be deprecated in future versions. In 6.0.0 onwards, we now include the `node-fetch` dependency as part of the NPM package. For browser environments, we fallback to `window.fetch` by default.
|
| 160 |
+
|
| 161 |
+
As a result, you should not pass in your own `fetch` to the Dropbox constructor unless you have a specific reason to do so (mocking, etc). Note that if you opt to pass in fetch to support your use case, you may need to bind your fetch to the appropriate context e.g. `fetch.bind(your_context)`.
|
| 162 |
+
|
| 163 |
+
[contributing]: https://github.com/dropbox/dropbox-sdk-js/blob/main/CONTRIBUTING.md
|
node_modules/tr46/dropbox/cjs/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
|
| 7 |
+
var _dropbox = require("./src/dropbox.js");
|
| 8 |
+
|
| 9 |
+
Object.defineProperty(exports, "Dropbox", {
|
| 10 |
+
enumerable: true,
|
| 11 |
+
get: function get() {
|
| 12 |
+
return _dropbox["default"];
|
| 13 |
+
}
|
| 14 |
+
});
|
| 15 |
+
|
| 16 |
+
var _auth = require("./src/auth.js");
|
| 17 |
+
|
| 18 |
+
Object.defineProperty(exports, "DropboxAuth", {
|
| 19 |
+
enumerable: true,
|
| 20 |
+
get: function get() {
|
| 21 |
+
return _auth["default"];
|
| 22 |
+
}
|
| 23 |
+
});
|
| 24 |
+
|
| 25 |
+
var _response = require("./src/response.js");
|
| 26 |
+
|
| 27 |
+
Object.defineProperty(exports, "DropboxResponse", {
|
| 28 |
+
enumerable: true,
|
| 29 |
+
get: function get() {
|
| 30 |
+
return _response.DropboxResponse;
|
| 31 |
+
}
|
| 32 |
+
});
|
| 33 |
+
|
| 34 |
+
var _error = require("./src/error.js");
|
| 35 |
+
|
| 36 |
+
Object.defineProperty(exports, "DropboxResponseError", {
|
| 37 |
+
enumerable: true,
|
| 38 |
+
get: function get() {
|
| 39 |
+
return _error.DropboxResponseError;
|
| 40 |
+
}
|
| 41 |
+
});
|
node_modules/tr46/dropbox/cjs/lib/routes.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
node_modules/tr46/dropbox/cjs/lib/types.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
node_modules/tr46/dropbox/cjs/src/auth.js
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
exports["default"] = undefined;
|
| 7 |
+
|
| 8 |
+
var _utils = require("./utils.js");
|
| 9 |
+
|
| 10 |
+
var _response = require("./response.js");
|
| 11 |
+
|
| 12 |
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
| 13 |
+
|
| 14 |
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
| 15 |
+
|
| 16 |
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
| 17 |
+
|
| 18 |
+
var fetch;
|
| 19 |
+
var crypto;
|
| 20 |
+
var Encoder; // Expiration is 300 seconds but needs to be in milliseconds for Date object
|
| 21 |
+
|
| 22 |
+
var TokenExpirationBuffer = 300 * 1000;
|
| 23 |
+
var PKCELength = 128;
|
| 24 |
+
var TokenAccessTypes = ['legacy', 'offline', 'online'];
|
| 25 |
+
var GrantTypes = ['code', 'token'];
|
| 26 |
+
var IncludeGrantedScopes = ['none', 'user', 'team'];
|
| 27 |
+
/**
|
| 28 |
+
* @class DropboxAuth
|
| 29 |
+
* @classdesc The DropboxAuth class that provides methods to manage, acquire, and refresh tokens.
|
| 30 |
+
* @arg {Object} options
|
| 31 |
+
* @arg {Function} [options.fetch] - fetch library for making requests.
|
| 32 |
+
* @arg {String} [options.accessToken] - An access token for making authenticated
|
| 33 |
+
* requests.
|
| 34 |
+
* @arg {Date} [options.AccessTokenExpiresAt] - Date of the current access token's
|
| 35 |
+
* expiration (if available)
|
| 36 |
+
* @arg {String} [options.refreshToken] - A refresh token for retrieving access tokens
|
| 37 |
+
* @arg {String} [options.clientId] - The client id for your app. Used to create
|
| 38 |
+
* authentication URL.
|
| 39 |
+
* @arg {String} [options.clientSecret] - The client secret for your app. Used to create
|
| 40 |
+
* authentication URL and refresh access tokens.
|
| 41 |
+
* @arg {String} [options.domain] - A custom domain to use when making api requests. This
|
| 42 |
+
* should only be used for testing as scaffolding to avoid making network requests.
|
| 43 |
+
* @arg {String} [options.domainDelimiter] - A custom delimiter to use when separating domain from
|
| 44 |
+
* subdomain. This should only be used for testing as scaffolding.
|
| 45 |
+
* @arg {Object} [options.customHeaders] - An object (in the form of header: value) designed to set
|
| 46 |
+
* custom headers to use during a request.
|
| 47 |
+
* @arg {Boolean} [options.dataOnBody] - Whether request data is sent on body or as URL params.
|
| 48 |
+
* Defaults to false.
|
| 49 |
+
*/
|
| 50 |
+
|
| 51 |
+
var DropboxAuth = /*#__PURE__*/function () {
|
| 52 |
+
function DropboxAuth(options) {
|
| 53 |
+
_classCallCheck(this, DropboxAuth);
|
| 54 |
+
|
| 55 |
+
options = options || {};
|
| 56 |
+
|
| 57 |
+
if ((0, _utils.isBrowserEnv)()) {
|
| 58 |
+
fetch = window.fetch.bind(window);
|
| 59 |
+
crypto = window.crypto || window.msCrypto; // for IE11
|
| 60 |
+
} else if ((0, _utils.isWorkerEnv)()) {
|
| 61 |
+
/* eslint-disable no-restricted-globals */
|
| 62 |
+
fetch = self.fetch.bind(self);
|
| 63 |
+
crypto = self.crypto;
|
| 64 |
+
/* eslint-enable no-restricted-globals */
|
| 65 |
+
} else {
|
| 66 |
+
fetch = require('node-fetch'); // eslint-disable-line global-require
|
| 67 |
+
|
| 68 |
+
crypto = require('crypto'); // eslint-disable-line global-require
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
if (typeof TextEncoder === 'undefined') {
|
| 72 |
+
Encoder = require('util').TextEncoder; // eslint-disable-line global-require
|
| 73 |
+
} else {
|
| 74 |
+
Encoder = TextEncoder;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
this.fetch = options.fetch || fetch;
|
| 78 |
+
this.accessToken = options.accessToken;
|
| 79 |
+
this.accessTokenExpiresAt = options.accessTokenExpiresAt;
|
| 80 |
+
this.refreshToken = options.refreshToken;
|
| 81 |
+
this.clientId = options.clientId;
|
| 82 |
+
this.clientSecret = options.clientSecret;
|
| 83 |
+
this.domain = options.domain;
|
| 84 |
+
this.domainDelimiter = options.domainDelimiter;
|
| 85 |
+
this.customHeaders = options.customHeaders;
|
| 86 |
+
this.dataOnBody = options.dataOnBody;
|
| 87 |
+
}
|
| 88 |
+
/**
|
| 89 |
+
* Set the access token used to authenticate requests to the API.
|
| 90 |
+
* @arg {String} accessToken - An access token
|
| 91 |
+
* @returns {undefined}
|
| 92 |
+
*/
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
_createClass(DropboxAuth, [{
|
| 96 |
+
key: "setAccessToken",
|
| 97 |
+
value: function setAccessToken(accessToken) {
|
| 98 |
+
this.accessToken = accessToken;
|
| 99 |
+
}
|
| 100 |
+
/**
|
| 101 |
+
* Get the access token
|
| 102 |
+
* @returns {String} Access token
|
| 103 |
+
*/
|
| 104 |
+
|
| 105 |
+
}, {
|
| 106 |
+
key: "getAccessToken",
|
| 107 |
+
value: function getAccessToken() {
|
| 108 |
+
return this.accessToken;
|
| 109 |
+
}
|
| 110 |
+
/**
|
| 111 |
+
* Set the client id, which is used to help gain an access token.
|
| 112 |
+
* @arg {String} clientId - Your apps client id
|
| 113 |
+
* @returns {undefined}
|
| 114 |
+
*/
|
| 115 |
+
|
| 116 |
+
}, {
|
| 117 |
+
key: "setClientId",
|
| 118 |
+
value: function setClientId(clientId) {
|
| 119 |
+
this.clientId = clientId;
|
| 120 |
+
}
|
| 121 |
+
/**
|
| 122 |
+
* Get the client id
|
| 123 |
+
* @returns {String} Client id
|
| 124 |
+
*/
|
| 125 |
+
|
| 126 |
+
}, {
|
| 127 |
+
key: "getClientId",
|
| 128 |
+
value: function getClientId() {
|
| 129 |
+
return this.clientId;
|
| 130 |
+
}
|
| 131 |
+
/**
|
| 132 |
+
* Set the client secret
|
| 133 |
+
* @arg {String} clientSecret - Your app's client secret
|
| 134 |
+
* @returns {undefined}
|
| 135 |
+
*/
|
| 136 |
+
|
| 137 |
+
}, {
|
| 138 |
+
key: "setClientSecret",
|
| 139 |
+
value: function setClientSecret(clientSecret) {
|
| 140 |
+
this.clientSecret = clientSecret;
|
| 141 |
+
}
|
| 142 |
+
/**
|
| 143 |
+
* Get the client secret
|
| 144 |
+
* @returns {String} Client secret
|
| 145 |
+
*/
|
| 146 |
+
|
| 147 |
+
}, {
|
| 148 |
+
key: "getClientSecret",
|
| 149 |
+
value: function getClientSecret() {
|
| 150 |
+
return this.clientSecret;
|
| 151 |
+
}
|
| 152 |
+
/**
|
| 153 |
+
* Gets the refresh token
|
| 154 |
+
* @returns {String} Refresh token
|
| 155 |
+
*/
|
| 156 |
+
|
| 157 |
+
}, {
|
| 158 |
+
key: "getRefreshToken",
|
| 159 |
+
value: function getRefreshToken() {
|
| 160 |
+
return this.refreshToken;
|
| 161 |
+
}
|
| 162 |
+
/**
|
| 163 |
+
* Sets the refresh token
|
| 164 |
+
* @param refreshToken - A refresh token
|
| 165 |
+
*/
|
| 166 |
+
|
| 167 |
+
}, {
|
| 168 |
+
key: "setRefreshToken",
|
| 169 |
+
value: function setRefreshToken(refreshToken) {
|
| 170 |
+
this.refreshToken = refreshToken;
|
| 171 |
+
}
|
| 172 |
+
/**
|
| 173 |
+
* Gets the access token's expiration date
|
| 174 |
+
* @returns {Date} date of token expiration
|
| 175 |
+
*/
|
| 176 |
+
|
| 177 |
+
}, {
|
| 178 |
+
key: "getAccessTokenExpiresAt",
|
| 179 |
+
value: function getAccessTokenExpiresAt() {
|
| 180 |
+
return this.accessTokenExpiresAt;
|
| 181 |
+
}
|
| 182 |
+
/**
|
| 183 |
+
* Sets the access token's expiration date
|
| 184 |
+
* @param accessTokenExpiresAt - new expiration date
|
| 185 |
+
*/
|
| 186 |
+
|
| 187 |
+
}, {
|
| 188 |
+
key: "setAccessTokenExpiresAt",
|
| 189 |
+
value: function setAccessTokenExpiresAt(accessTokenExpiresAt) {
|
| 190 |
+
this.accessTokenExpiresAt = accessTokenExpiresAt;
|
| 191 |
+
}
|
| 192 |
+
/**
|
| 193 |
+
* Sets the code verifier for PKCE flow
|
| 194 |
+
* @param {String} codeVerifier - new code verifier
|
| 195 |
+
*/
|
| 196 |
+
|
| 197 |
+
}, {
|
| 198 |
+
key: "setCodeVerifier",
|
| 199 |
+
value: function setCodeVerifier(codeVerifier) {
|
| 200 |
+
this.codeVerifier = codeVerifier;
|
| 201 |
+
}
|
| 202 |
+
/**
|
| 203 |
+
* Gets the code verifier for PKCE flow
|
| 204 |
+
* @returns {String} - code verifier for PKCE
|
| 205 |
+
*/
|
| 206 |
+
|
| 207 |
+
}, {
|
| 208 |
+
key: "getCodeVerifier",
|
| 209 |
+
value: function getCodeVerifier() {
|
| 210 |
+
return this.codeVerifier;
|
| 211 |
+
}
|
| 212 |
+
}, {
|
| 213 |
+
key: "generateCodeChallenge",
|
| 214 |
+
value: function generateCodeChallenge() {
|
| 215 |
+
var _this = this;
|
| 216 |
+
|
| 217 |
+
var encoder = new Encoder();
|
| 218 |
+
var codeData = encoder.encode(this.codeVerifier);
|
| 219 |
+
var codeChallenge;
|
| 220 |
+
|
| 221 |
+
if ((0, _utils.isBrowserEnv)() || (0, _utils.isWorkerEnv)()) {
|
| 222 |
+
return crypto.subtle.digest('SHA-256', codeData).then(function (digestedHash) {
|
| 223 |
+
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(digestedHash)));
|
| 224 |
+
codeChallenge = (0, _utils.createBrowserSafeString)(base64String).substr(0, 128);
|
| 225 |
+
_this.codeChallenge = codeChallenge;
|
| 226 |
+
});
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
var digestedHash = crypto.createHash('sha256').update(codeData).digest();
|
| 230 |
+
codeChallenge = (0, _utils.createBrowserSafeString)(digestedHash);
|
| 231 |
+
this.codeChallenge = codeChallenge;
|
| 232 |
+
return Promise.resolve();
|
| 233 |
+
}
|
| 234 |
+
}, {
|
| 235 |
+
key: "generatePKCECodes",
|
| 236 |
+
value: function generatePKCECodes() {
|
| 237 |
+
var codeVerifier;
|
| 238 |
+
|
| 239 |
+
if ((0, _utils.isBrowserEnv)() || (0, _utils.isWorkerEnv)()) {
|
| 240 |
+
var array = new Uint8Array(PKCELength);
|
| 241 |
+
var randomValueArray = crypto.getRandomValues(array);
|
| 242 |
+
var base64String = btoa(randomValueArray);
|
| 243 |
+
codeVerifier = (0, _utils.createBrowserSafeString)(base64String).substr(0, 128);
|
| 244 |
+
} else {
|
| 245 |
+
var randomBytes = crypto.randomBytes(PKCELength);
|
| 246 |
+
codeVerifier = (0, _utils.createBrowserSafeString)(randomBytes).substr(0, 128);
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
this.codeVerifier = codeVerifier;
|
| 250 |
+
return this.generateCodeChallenge();
|
| 251 |
+
}
|
| 252 |
+
/**
|
| 253 |
+
* Get a URL that can be used to authenticate users for the Dropbox API.
|
| 254 |
+
* @arg {String} redirectUri - A URL to redirect the user to after
|
| 255 |
+
* authenticating. This must be added to your app through the admin interface.
|
| 256 |
+
* @arg {String} [state] - State that will be returned in the redirect URL to help
|
| 257 |
+
* prevent cross site scripting attacks.
|
| 258 |
+
* @arg {String} [authType] - auth type, defaults to 'token', other option is 'code'
|
| 259 |
+
* @arg {String} [tokenAccessType] - type of token to request. From the following:
|
| 260 |
+
* null - creates a token with the app default (either legacy or online)
|
| 261 |
+
* legacy - creates one long-lived token with no expiration
|
| 262 |
+
* online - create one short-lived token with an expiration
|
| 263 |
+
* offline - create one short-lived token with an expiration with a refresh token
|
| 264 |
+
* @arg {Array<String>} [scope] - scopes to request for the grant
|
| 265 |
+
* @arg {String} [includeGrantedScopes] - whether or not to include previously granted scopes.
|
| 266 |
+
* From the following:
|
| 267 |
+
* user - include user scopes in the grant
|
| 268 |
+
* team - include team scopes in the grant
|
| 269 |
+
* Note: if this user has never linked the app, include_granted_scopes must be None
|
| 270 |
+
* @arg {boolean} [usePKCE] - Whether or not to use Sha256 based PKCE. PKCE should be only use
|
| 271 |
+
* on client apps which doesn't call your server. It is less secure than non-PKCE flow but
|
| 272 |
+
* can be used if you are unable to safely retrieve your app secret
|
| 273 |
+
* @returns {Promise<String>} - Url to send user to for Dropbox API authentication
|
| 274 |
+
* returned in a promise
|
| 275 |
+
*/
|
| 276 |
+
|
| 277 |
+
}, {
|
| 278 |
+
key: "getAuthenticationUrl",
|
| 279 |
+
value: function getAuthenticationUrl(redirectUri, state) {
|
| 280 |
+
var _this2 = this;
|
| 281 |
+
|
| 282 |
+
var authType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'token';
|
| 283 |
+
var tokenAccessType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
| 284 |
+
var scope = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
|
| 285 |
+
var includeGrantedScopes = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'none';
|
| 286 |
+
var usePKCE = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
| 287 |
+
var clientId = this.getClientId();
|
| 288 |
+
var baseUrl = (0, _utils.OAuth2AuthorizationUrl)(this.domain);
|
| 289 |
+
|
| 290 |
+
if (!clientId) {
|
| 291 |
+
throw new Error('A client id is required. You can set the client id using .setClientId().');
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
if (authType !== 'code' && !redirectUri) {
|
| 295 |
+
throw new Error('A redirect uri is required.');
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
if (!GrantTypes.includes(authType)) {
|
| 299 |
+
throw new Error('Authorization type must be code or token');
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
if (tokenAccessType && !TokenAccessTypes.includes(tokenAccessType)) {
|
| 303 |
+
throw new Error('Token Access Type must be legacy, offline, or online');
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
if (scope && !(scope instanceof Array)) {
|
| 307 |
+
throw new Error('Scope must be an array of strings');
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
if (!IncludeGrantedScopes.includes(includeGrantedScopes)) {
|
| 311 |
+
throw new Error('includeGrantedScopes must be none, user, or team');
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
var authUrl;
|
| 315 |
+
|
| 316 |
+
if (authType === 'code') {
|
| 317 |
+
authUrl = "".concat(baseUrl, "?response_type=code&client_id=").concat(clientId);
|
| 318 |
+
} else {
|
| 319 |
+
authUrl = "".concat(baseUrl, "?response_type=token&client_id=").concat(clientId);
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
if (redirectUri) {
|
| 323 |
+
authUrl += "&redirect_uri=".concat(redirectUri);
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
if (state) {
|
| 327 |
+
authUrl += "&state=".concat(state);
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
if (tokenAccessType) {
|
| 331 |
+
authUrl += "&token_access_type=".concat(tokenAccessType);
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
if (scope) {
|
| 335 |
+
authUrl += "&scope=".concat(scope.join(' '));
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
if (includeGrantedScopes !== 'none') {
|
| 339 |
+
authUrl += "&include_granted_scopes=".concat(includeGrantedScopes);
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
if (usePKCE) {
|
| 343 |
+
return this.generatePKCECodes().then(function () {
|
| 344 |
+
authUrl += '&code_challenge_method=S256';
|
| 345 |
+
authUrl += "&code_challenge=".concat(_this2.codeChallenge);
|
| 346 |
+
return authUrl;
|
| 347 |
+
});
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
return Promise.resolve(authUrl);
|
| 351 |
+
}
|
| 352 |
+
/**
|
| 353 |
+
* Get an OAuth2 access token from an OAuth2 Code.
|
| 354 |
+
* @arg {String} redirectUri - A URL to redirect the user to after
|
| 355 |
+
* authenticating. This must be added to your app through the admin interface.
|
| 356 |
+
* @arg {String} code - An OAuth2 code.
|
| 357 |
+
* @returns {Object} An object containing the token and related info (if applicable)
|
| 358 |
+
*/
|
| 359 |
+
|
| 360 |
+
}, {
|
| 361 |
+
key: "getAccessTokenFromCode",
|
| 362 |
+
value: function getAccessTokenFromCode(redirectUri, code) {
|
| 363 |
+
var clientId = this.getClientId();
|
| 364 |
+
var clientSecret = this.getClientSecret();
|
| 365 |
+
|
| 366 |
+
if (!clientId) {
|
| 367 |
+
throw new Error('A client id is required. You can set the client id using .setClientId().');
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
var path = (0, _utils.OAuth2TokenUrl)(this.domain, this.domainDelimiter);
|
| 371 |
+
path += '?grant_type=authorization_code';
|
| 372 |
+
path += "&code=".concat(code);
|
| 373 |
+
path += "&client_id=".concat(clientId);
|
| 374 |
+
|
| 375 |
+
if (clientSecret) {
|
| 376 |
+
path += "&client_secret=".concat(clientSecret);
|
| 377 |
+
} else {
|
| 378 |
+
if (!this.codeVerifier) {
|
| 379 |
+
throw new Error('You must use PKCE when generating the authorization URL to not include a client secret');
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
path += "&code_verifier=".concat(this.codeVerifier);
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
if (redirectUri) {
|
| 386 |
+
path += "&redirect_uri=".concat(redirectUri);
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
var fetchOptions = {
|
| 390 |
+
method: 'POST',
|
| 391 |
+
headers: {
|
| 392 |
+
'Content-Type': 'application/x-www-form-urlencoded'
|
| 393 |
+
}
|
| 394 |
+
};
|
| 395 |
+
return this.fetch(path, fetchOptions).then(function (res) {
|
| 396 |
+
return (0, _response.parseResponse)(res);
|
| 397 |
+
});
|
| 398 |
+
}
|
| 399 |
+
/**
|
| 400 |
+
* Checks if a token is needed, can be refreshed and if the token is expired.
|
| 401 |
+
* If so, attempts to refresh access token
|
| 402 |
+
* @returns {Promise<*>}
|
| 403 |
+
*/
|
| 404 |
+
|
| 405 |
+
}, {
|
| 406 |
+
key: "checkAndRefreshAccessToken",
|
| 407 |
+
value: function checkAndRefreshAccessToken() {
|
| 408 |
+
var canRefresh = this.getRefreshToken() && this.getClientId();
|
| 409 |
+
var needsRefresh = !this.getAccessTokenExpiresAt() || new Date(Date.now() + TokenExpirationBuffer) >= this.getAccessTokenExpiresAt();
|
| 410 |
+
var needsToken = !this.getAccessToken();
|
| 411 |
+
|
| 412 |
+
if ((needsRefresh || needsToken) && canRefresh) {
|
| 413 |
+
return this.refreshAccessToken();
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
return Promise.resolve();
|
| 417 |
+
}
|
| 418 |
+
/**
|
| 419 |
+
* Refreshes the access token using the refresh token, if available
|
| 420 |
+
* @arg {Array<String>} scope - a subset of scopes from the original
|
| 421 |
+
* refresh to acquire with an access token
|
| 422 |
+
* @returns {Promise<*>}
|
| 423 |
+
*/
|
| 424 |
+
|
| 425 |
+
}, {
|
| 426 |
+
key: "refreshAccessToken",
|
| 427 |
+
value: function refreshAccessToken() {
|
| 428 |
+
var _this3 = this;
|
| 429 |
+
|
| 430 |
+
var scope = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
| 431 |
+
var clientId = this.getClientId();
|
| 432 |
+
var clientSecret = this.getClientSecret();
|
| 433 |
+
|
| 434 |
+
if (!clientId) {
|
| 435 |
+
throw new Error('A client id is required. You can set the client id using .setClientId().');
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
if (scope && !(scope instanceof Array)) {
|
| 439 |
+
throw new Error('Scope must be an array of strings');
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
var refreshUrl = (0, _utils.OAuth2TokenUrl)(this.domain, this.domainDelimiter);
|
| 443 |
+
var fetchOptions = {
|
| 444 |
+
headers: {
|
| 445 |
+
'Content-Type': 'application/json'
|
| 446 |
+
},
|
| 447 |
+
method: 'POST'
|
| 448 |
+
};
|
| 449 |
+
|
| 450 |
+
if (this.dataOnBody) {
|
| 451 |
+
var body = {
|
| 452 |
+
grant_type: 'refresh_token',
|
| 453 |
+
client_id: clientId,
|
| 454 |
+
refresh_token: this.getRefreshToken()
|
| 455 |
+
};
|
| 456 |
+
|
| 457 |
+
if (clientSecret) {
|
| 458 |
+
body.client_secret = clientSecret;
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
if (scope) {
|
| 462 |
+
body.scope = scope.join(' ');
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
fetchOptions.body = body;
|
| 466 |
+
} else {
|
| 467 |
+
refreshUrl += "?grant_type=refresh_token&refresh_token=".concat(this.getRefreshToken());
|
| 468 |
+
refreshUrl += "&client_id=".concat(clientId);
|
| 469 |
+
|
| 470 |
+
if (clientSecret) {
|
| 471 |
+
refreshUrl += "&client_secret=".concat(clientSecret);
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
if (scope) {
|
| 475 |
+
refreshUrl += "&scope=".concat(scope.join(' '));
|
| 476 |
+
}
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
return this.fetch(refreshUrl, fetchOptions).then(function (res) {
|
| 480 |
+
return (0, _response.parseResponse)(res);
|
| 481 |
+
}).then(function (res) {
|
| 482 |
+
_this3.setAccessToken(res.result.access_token);
|
| 483 |
+
|
| 484 |
+
_this3.setAccessTokenExpiresAt((0, _utils.getTokenExpiresAtDate)(res.result.expires_in));
|
| 485 |
+
});
|
| 486 |
+
}
|
| 487 |
+
}]);
|
| 488 |
+
|
| 489 |
+
return DropboxAuth;
|
| 490 |
+
}();
|
| 491 |
+
|
| 492 |
+
exports["default"] = DropboxAuth;
|
node_modules/tr46/dropbox/cjs/src/constants.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
var RPC = exports.RPC = 'rpc';
|
| 7 |
+
var UPLOAD = exports.UPLOAD = 'upload';
|
| 8 |
+
var DOWNLOAD = exports.DOWNLOAD = 'download';
|
| 9 |
+
var APP_AUTH = exports.APP_AUTH = 'app';
|
| 10 |
+
var USER_AUTH = exports.USER_AUTH = 'user';
|
| 11 |
+
var TEAM_AUTH = exports.TEAM_AUTH = 'team';
|
| 12 |
+
var NO_AUTH = exports.NO_AUTH = 'noauth';
|
| 13 |
+
var COOKIE = exports.COOKIE = 'cookie';
|
| 14 |
+
var DEFAULT_API_DOMAIN = exports.DEFAULT_API_DOMAIN = 'dropboxapi.com';
|
| 15 |
+
var DEFAULT_DOMAIN = exports.DEFAULT_DOMAIN = 'dropbox.com';
|
| 16 |
+
var TEST_DOMAIN_MAPPINGS = exports.TEST_DOMAIN_MAPPINGS = {
|
| 17 |
+
api: 'api',
|
| 18 |
+
notify: 'bolt',
|
| 19 |
+
content: 'api-content'
|
| 20 |
+
};
|
node_modules/tr46/dropbox/cjs/src/dropbox.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
exports["default"] = undefined;
|
| 7 |
+
|
| 8 |
+
var _constants = require("./constants.js");
|
| 9 |
+
|
| 10 |
+
var _routes = require("../lib/routes.js");
|
| 11 |
+
|
| 12 |
+
var _auth = require("./auth.js");
|
| 13 |
+
|
| 14 |
+
var _utils = require("./utils.js");
|
| 15 |
+
|
| 16 |
+
var _response = require("./response.js");
|
| 17 |
+
|
| 18 |
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
| 19 |
+
|
| 20 |
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
| 21 |
+
|
| 22 |
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
| 23 |
+
|
| 24 |
+
var b64 = typeof btoa === 'undefined' ? function (str) {
|
| 25 |
+
return Buffer.from(str).toString('base64');
|
| 26 |
+
} : btoa;
|
| 27 |
+
/**
|
| 28 |
+
* @class Dropbox
|
| 29 |
+
* @classdesc The Dropbox SDK class that provides methods to read, write and
|
| 30 |
+
* create files or folders in a user or team's Dropbox.
|
| 31 |
+
* @arg {Object} options
|
| 32 |
+
* @arg {Function} [options.fetch] - fetch library for making requests.
|
| 33 |
+
* @arg {String} [options.selectUser] - Select user is only used for team functionality.
|
| 34 |
+
* It specifies which user the team access token should be acting as.
|
| 35 |
+
* @arg {String} [options.pathRoot] - root path to access other namespaces
|
| 36 |
+
* Use to access team folders for example
|
| 37 |
+
* @arg {String} [options.selectAdmin] - Select admin is only used by team functionality.
|
| 38 |
+
* It specifies which team admin the team access token should be acting as.
|
| 39 |
+
* @arg {DropboxAuth} [options.auth] - The DropboxAuth object used to authenticate requests.
|
| 40 |
+
* If this is set, the remaining parameters will be ignored.
|
| 41 |
+
* @arg {String} [options.accessToken] - An access token for making authenticated
|
| 42 |
+
* requests.
|
| 43 |
+
* @arg {Date} [options.accessTokenExpiresAt] - Date of the current access token's
|
| 44 |
+
* expiration (if available)
|
| 45 |
+
* @arg {String} [options.refreshToken] - A refresh token for retrieving access tokens
|
| 46 |
+
* @arg {String} [options.clientId] - The client id for your app. Used to create
|
| 47 |
+
* authentication URL.
|
| 48 |
+
* @arg {String} [options.clientSecret] - The client secret for your app. Used to create
|
| 49 |
+
* authentication URL and refresh access tokens.
|
| 50 |
+
* @arg {String} [options.domain] - A custom domain to use when making api requests. This
|
| 51 |
+
* should only be used for testing as scaffolding to avoid making network requests.
|
| 52 |
+
* @arg {String} [options.domainDelimiter] - A custom delimiter to use when separating domain from
|
| 53 |
+
* subdomain. This should only be used for testing as scaffolding.
|
| 54 |
+
* @arg {Object} [options.customHeaders] - An object (in the form of header: value) designed to set
|
| 55 |
+
* custom headers to use during a request.
|
| 56 |
+
*/
|
| 57 |
+
|
| 58 |
+
var Dropbox = /*#__PURE__*/function () {
|
| 59 |
+
function Dropbox(options) {
|
| 60 |
+
_classCallCheck(this, Dropbox);
|
| 61 |
+
|
| 62 |
+
options = options || {};
|
| 63 |
+
|
| 64 |
+
if (options.auth) {
|
| 65 |
+
this.auth = options.auth;
|
| 66 |
+
} else {
|
| 67 |
+
this.auth = new _auth["default"](options);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
this.fetch = options.fetch || this.auth.fetch;
|
| 71 |
+
this.selectUser = options.selectUser;
|
| 72 |
+
this.selectAdmin = options.selectAdmin;
|
| 73 |
+
this.pathRoot = options.pathRoot;
|
| 74 |
+
this.domain = options.domain || this.auth.domain;
|
| 75 |
+
this.domainDelimiter = options.domainDelimiter || this.auth.domainDelimiter;
|
| 76 |
+
this.customHeaders = options.customHeaders || this.auth.customHeaders;
|
| 77 |
+
Object.assign(this, _routes.routes);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
_createClass(Dropbox, [{
|
| 81 |
+
key: "request",
|
| 82 |
+
value: function request(path, args, auth, host, style) {
|
| 83 |
+
// scope is provided after "style", but unused in requests, so it's not in parameters
|
| 84 |
+
switch (style) {
|
| 85 |
+
case _constants.RPC:
|
| 86 |
+
return this.rpcRequest(path, args, auth, host);
|
| 87 |
+
|
| 88 |
+
case _constants.DOWNLOAD:
|
| 89 |
+
return this.downloadRequest(path, args, auth, host);
|
| 90 |
+
|
| 91 |
+
case _constants.UPLOAD:
|
| 92 |
+
return this.uploadRequest(path, args, auth, host);
|
| 93 |
+
|
| 94 |
+
default:
|
| 95 |
+
throw new Error("Invalid request style: ".concat(style));
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
}, {
|
| 99 |
+
key: "rpcRequest",
|
| 100 |
+
value: function rpcRequest(path, body, auth, host) {
|
| 101 |
+
var _this = this;
|
| 102 |
+
|
| 103 |
+
return this.auth.checkAndRefreshAccessToken().then(function () {
|
| 104 |
+
var fetchOptions = {
|
| 105 |
+
method: 'POST',
|
| 106 |
+
body: body ? JSON.stringify(body) : null,
|
| 107 |
+
headers: {}
|
| 108 |
+
};
|
| 109 |
+
|
| 110 |
+
if (body) {
|
| 111 |
+
fetchOptions.headers['Content-Type'] = 'application/json';
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
_this.setAuthHeaders(auth, fetchOptions);
|
| 115 |
+
|
| 116 |
+
_this.setCommonHeaders(fetchOptions);
|
| 117 |
+
|
| 118 |
+
return fetchOptions;
|
| 119 |
+
}).then(function (fetchOptions) {
|
| 120 |
+
return _this.fetch((0, _utils.baseApiUrl)(host, _this.domain, _this.domainDelimiter) + path, fetchOptions);
|
| 121 |
+
}).then(function (res) {
|
| 122 |
+
return (0, _response.parseResponse)(res);
|
| 123 |
+
});
|
| 124 |
+
}
|
| 125 |
+
}, {
|
| 126 |
+
key: "downloadRequest",
|
| 127 |
+
value: function downloadRequest(path, args, auth, host) {
|
| 128 |
+
var _this2 = this;
|
| 129 |
+
|
| 130 |
+
return this.auth.checkAndRefreshAccessToken().then(function () {
|
| 131 |
+
var fetchOptions = {
|
| 132 |
+
method: 'POST',
|
| 133 |
+
headers: {
|
| 134 |
+
'Dropbox-API-Arg': (0, _utils.httpHeaderSafeJson)(args)
|
| 135 |
+
}
|
| 136 |
+
};
|
| 137 |
+
|
| 138 |
+
_this2.setAuthHeaders(auth, fetchOptions);
|
| 139 |
+
|
| 140 |
+
_this2.setCommonHeaders(fetchOptions);
|
| 141 |
+
|
| 142 |
+
return fetchOptions;
|
| 143 |
+
}).then(function (fetchOptions) {
|
| 144 |
+
return _this2.fetch((0, _utils.baseApiUrl)(host, _this2.domain, _this2.domainDelimiter) + path, fetchOptions);
|
| 145 |
+
}).then(function (res) {
|
| 146 |
+
return (0, _response.parseDownloadResponse)(res);
|
| 147 |
+
});
|
| 148 |
+
}
|
| 149 |
+
}, {
|
| 150 |
+
key: "uploadRequest",
|
| 151 |
+
value: function uploadRequest(path, args, auth, host) {
|
| 152 |
+
var _this3 = this;
|
| 153 |
+
|
| 154 |
+
return this.auth.checkAndRefreshAccessToken().then(function () {
|
| 155 |
+
var contents = args.contents;
|
| 156 |
+
delete args.contents;
|
| 157 |
+
var fetchOptions = {
|
| 158 |
+
body: contents,
|
| 159 |
+
method: 'POST',
|
| 160 |
+
headers: {
|
| 161 |
+
'Content-Type': 'application/octet-stream',
|
| 162 |
+
'Dropbox-API-Arg': (0, _utils.httpHeaderSafeJson)(args)
|
| 163 |
+
}
|
| 164 |
+
};
|
| 165 |
+
|
| 166 |
+
_this3.setAuthHeaders(auth, fetchOptions);
|
| 167 |
+
|
| 168 |
+
_this3.setCommonHeaders(fetchOptions);
|
| 169 |
+
|
| 170 |
+
return fetchOptions;
|
| 171 |
+
}).then(function (fetchOptions) {
|
| 172 |
+
return _this3.fetch((0, _utils.baseApiUrl)(host, _this3.domain, _this3.domainDelimiter) + path, fetchOptions);
|
| 173 |
+
}).then(function (res) {
|
| 174 |
+
return (0, _response.parseResponse)(res);
|
| 175 |
+
});
|
| 176 |
+
}
|
| 177 |
+
}, {
|
| 178 |
+
key: "setAuthHeaders",
|
| 179 |
+
value: function setAuthHeaders(auth, fetchOptions) {
|
| 180 |
+
// checks for multiauth and assigns auth based on priority to create header in switch case
|
| 181 |
+
if (auth.split(',').length > 1) {
|
| 182 |
+
var authTypes = auth.replace(' ', '').split(',');
|
| 183 |
+
|
| 184 |
+
if (authTypes.includes(_constants.USER_AUTH) && this.auth.getAccessToken()) {
|
| 185 |
+
auth = _constants.USER_AUTH;
|
| 186 |
+
} else if (authTypes.includes(_constants.TEAM_AUTH) && this.auth.getAccessToken()) {
|
| 187 |
+
auth = _constants.TEAM_AUTH;
|
| 188 |
+
} else if (authTypes.includes(_constants.APP_AUTH)) {
|
| 189 |
+
auth = _constants.APP_AUTH;
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
switch (auth) {
|
| 194 |
+
case _constants.APP_AUTH:
|
| 195 |
+
if (this.auth.clientId && this.auth.clientSecret) {
|
| 196 |
+
var authHeader = b64("".concat(this.auth.clientId, ":").concat(this.auth.clientSecret));
|
| 197 |
+
fetchOptions.headers.Authorization = "Basic ".concat(authHeader);
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
break;
|
| 201 |
+
|
| 202 |
+
case _constants.TEAM_AUTH:
|
| 203 |
+
case _constants.USER_AUTH:
|
| 204 |
+
if (this.auth.getAccessToken()) {
|
| 205 |
+
fetchOptions.headers.Authorization = "Bearer ".concat(this.auth.getAccessToken());
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
break;
|
| 209 |
+
|
| 210 |
+
case _constants.NO_AUTH:
|
| 211 |
+
case _constants.COOKIE:
|
| 212 |
+
break;
|
| 213 |
+
|
| 214 |
+
default:
|
| 215 |
+
throw new Error("Unhandled auth type: ".concat(auth));
|
| 216 |
+
}
|
| 217 |
+
}
|
| 218 |
+
}, {
|
| 219 |
+
key: "setCommonHeaders",
|
| 220 |
+
value: function setCommonHeaders(options) {
|
| 221 |
+
var _this4 = this;
|
| 222 |
+
|
| 223 |
+
if (this.selectUser) {
|
| 224 |
+
options.headers['Dropbox-API-Select-User'] = this.selectUser;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
if (this.selectAdmin) {
|
| 228 |
+
options.headers['Dropbox-API-Select-Admin'] = this.selectAdmin;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
if (this.pathRoot) {
|
| 232 |
+
options.headers['Dropbox-API-Path-Root'] = this.pathRoot;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
if (this.customHeaders) {
|
| 236 |
+
var headerKeys = Object.keys(this.customHeaders);
|
| 237 |
+
headerKeys.forEach(function (header) {
|
| 238 |
+
options.headers[header] = _this4.customHeaders[header];
|
| 239 |
+
});
|
| 240 |
+
}
|
| 241 |
+
}
|
| 242 |
+
}]);
|
| 243 |
+
|
| 244 |
+
return Dropbox;
|
| 245 |
+
}();
|
| 246 |
+
|
| 247 |
+
exports["default"] = Dropbox;
|
node_modules/tr46/dropbox/cjs/src/error.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
| 4 |
+
|
| 5 |
+
Object.defineProperty(exports, "__esModule", {
|
| 6 |
+
value: true
|
| 7 |
+
});
|
| 8 |
+
|
| 9 |
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
| 10 |
+
|
| 11 |
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
| 12 |
+
|
| 13 |
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
| 14 |
+
|
| 15 |
+
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
| 16 |
+
|
| 17 |
+
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
| 18 |
+
|
| 19 |
+
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
|
| 20 |
+
|
| 21 |
+
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
|
| 22 |
+
|
| 23 |
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
| 24 |
+
|
| 25 |
+
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
|
| 26 |
+
|
| 27 |
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
| 28 |
+
|
| 29 |
+
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
| 30 |
+
|
| 31 |
+
/**
|
| 32 |
+
* The response class of HTTP errors from API calls using the Dropbox SDK.
|
| 33 |
+
* @class DropboxResponseError
|
| 34 |
+
* @classdesc The response class of HTTP errors from API calls using the Dropbox SDK.
|
| 35 |
+
* @arg {number} status - HTTP Status code of the call
|
| 36 |
+
* @arg {Object} headers - Headers returned from the call
|
| 37 |
+
* @arg {Object} error - Serialized Error of the call
|
| 38 |
+
*/
|
| 39 |
+
var DropboxResponseError = /*#__PURE__*/exports.DropboxResponseError = function (_Error) {
|
| 40 |
+
_inherits(DropboxResponseError, _Error);
|
| 41 |
+
|
| 42 |
+
var _super = _createSuper(DropboxResponseError);
|
| 43 |
+
|
| 44 |
+
function DropboxResponseError(status, headers, error) {
|
| 45 |
+
var _this;
|
| 46 |
+
|
| 47 |
+
_classCallCheck(this, DropboxResponseError);
|
| 48 |
+
|
| 49 |
+
_this = _super.call(this, "Response failed with a ".concat(status, " code"));
|
| 50 |
+
_this.name = 'DropboxResponseError';
|
| 51 |
+
_this.status = status;
|
| 52 |
+
_this.headers = headers;
|
| 53 |
+
_this.error = error;
|
| 54 |
+
return _this;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
return DropboxResponseError;
|
| 58 |
+
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
node_modules/tr46/dropbox/cjs/src/response.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
exports.DropboxResponse = undefined;
|
| 7 |
+
exports.parseResponse = parseResponse;
|
| 8 |
+
exports.parseDownloadResponse = parseDownloadResponse;
|
| 9 |
+
|
| 10 |
+
var _utils = require("./utils.js");
|
| 11 |
+
|
| 12 |
+
var _error = require("./error.js");
|
| 13 |
+
|
| 14 |
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
| 15 |
+
|
| 16 |
+
var DropboxResponse = exports.DropboxResponse = function DropboxResponse(status, headers, result) {
|
| 17 |
+
_classCallCheck(this, DropboxResponse);
|
| 18 |
+
|
| 19 |
+
this.status = status;
|
| 20 |
+
this.headers = headers;
|
| 21 |
+
this.result = result;
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
function throwAsError(res) {
|
| 25 |
+
return res.text().then(function (data) {
|
| 26 |
+
var errorObject;
|
| 27 |
+
|
| 28 |
+
try {
|
| 29 |
+
errorObject = JSON.parse(data);
|
| 30 |
+
} catch (error) {
|
| 31 |
+
errorObject = data;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
throw new _error.DropboxResponseError(res.status, res.headers, errorObject);
|
| 35 |
+
});
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
function parseResponse(res) {
|
| 39 |
+
if (!res.ok) {
|
| 40 |
+
return throwAsError(res);
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
return res.text().then(function (data) {
|
| 44 |
+
var responseObject;
|
| 45 |
+
|
| 46 |
+
try {
|
| 47 |
+
responseObject = JSON.parse(data);
|
| 48 |
+
} catch (error) {
|
| 49 |
+
responseObject = data;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
return new DropboxResponse(res.status, res.headers, responseObject);
|
| 53 |
+
});
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
function parseDownloadResponse(res) {
|
| 57 |
+
if (!res.ok) {
|
| 58 |
+
return throwAsError(res);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
return new Promise(function (resolve) {
|
| 62 |
+
if ((0, _utils.isWindowOrWorker)()) {
|
| 63 |
+
res.blob().then(function (data) {
|
| 64 |
+
return resolve(data);
|
| 65 |
+
});
|
| 66 |
+
} else {
|
| 67 |
+
res.buffer().then(function (data) {
|
| 68 |
+
return resolve(data);
|
| 69 |
+
});
|
| 70 |
+
}
|
| 71 |
+
}).then(function (data) {
|
| 72 |
+
var result = JSON.parse(res.headers.get('dropbox-api-result'));
|
| 73 |
+
|
| 74 |
+
if ((0, _utils.isWindowOrWorker)()) {
|
| 75 |
+
result.fileBlob = data;
|
| 76 |
+
} else {
|
| 77 |
+
result.fileBinary = data;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
return new DropboxResponse(res.status, res.headers, result);
|
| 81 |
+
});
|
| 82 |
+
}
|
node_modules/tr46/dropbox/cjs/src/utils.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use strict";
|
| 2 |
+
|
| 3 |
+
Object.defineProperty(exports, "__esModule", {
|
| 4 |
+
value: true
|
| 5 |
+
});
|
| 6 |
+
exports.OAuth2TokenUrl = exports.OAuth2AuthorizationUrl = exports.baseApiUrl = undefined;
|
| 7 |
+
exports.httpHeaderSafeJson = httpHeaderSafeJson;
|
| 8 |
+
exports.getTokenExpiresAtDate = getTokenExpiresAtDate;
|
| 9 |
+
exports.isWindowOrWorker = isWindowOrWorker;
|
| 10 |
+
exports.isBrowserEnv = isBrowserEnv;
|
| 11 |
+
exports.isWorkerEnv = isWorkerEnv;
|
| 12 |
+
exports.createBrowserSafeString = createBrowserSafeString;
|
| 13 |
+
|
| 14 |
+
var _constants = require("./constants");
|
| 15 |
+
|
| 16 |
+
function getSafeUnicode(c) {
|
| 17 |
+
var unicode = "000".concat(c.charCodeAt(0).toString(16)).slice(-4);
|
| 18 |
+
return "\\u".concat(unicode);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
var baseApiUrl = exports.baseApiUrl = function baseApiUrl(subdomain) {
|
| 22 |
+
var domain = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.DEFAULT_API_DOMAIN;
|
| 23 |
+
var domainDelimiter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.';
|
| 24 |
+
|
| 25 |
+
if (!domainDelimiter) {
|
| 26 |
+
return "https://".concat(domain, "/2/");
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
if (domain !== _constants.DEFAULT_API_DOMAIN && _constants.TEST_DOMAIN_MAPPINGS[subdomain] !== undefined) {
|
| 30 |
+
subdomain = _constants.TEST_DOMAIN_MAPPINGS[subdomain];
|
| 31 |
+
domainDelimiter = '-';
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
return "https://".concat(subdomain).concat(domainDelimiter).concat(domain, "/2/");
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
var OAuth2AuthorizationUrl = exports.OAuth2AuthorizationUrl = function OAuth2AuthorizationUrl() {
|
| 38 |
+
var domain = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.DEFAULT_DOMAIN;
|
| 39 |
+
|
| 40 |
+
if (domain !== _constants.DEFAULT_DOMAIN) {
|
| 41 |
+
domain = "meta-".concat(domain);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
return "https://".concat(domain, "/oauth2/authorize");
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
var OAuth2TokenUrl = exports.OAuth2TokenUrl = function OAuth2TokenUrl() {
|
| 48 |
+
var domain = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.DEFAULT_API_DOMAIN;
|
| 49 |
+
var domainDelimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.';
|
| 50 |
+
var subdomain = 'api';
|
| 51 |
+
|
| 52 |
+
if (domain !== _constants.DEFAULT_API_DOMAIN) {
|
| 53 |
+
subdomain = _constants.TEST_DOMAIN_MAPPINGS[subdomain];
|
| 54 |
+
domainDelimiter = '-';
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
return "https://".concat(subdomain).concat(domainDelimiter).concat(domain, "/oauth2/token");
|
| 58 |
+
}; // source https://www.dropboxforum.com/t5/API-support/HTTP-header-quot-Dropbox-API-Arg-quot-could-not-decode-input-as/m-p/173823/highlight/true#M6786
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
function httpHeaderSafeJson(args) {
|
| 62 |
+
return JSON.stringify(args).replace(/[\u007f-\uffff]/g, getSafeUnicode);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
function getTokenExpiresAtDate(expiresIn) {
|
| 66 |
+
return new Date(Date.now() + expiresIn * 1000);
|
| 67 |
+
}
|
| 68 |
+
/* global WorkerGlobalScope */
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
function isWindowOrWorker() {
|
| 72 |
+
return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope // eslint-disable-line no-restricted-globals
|
| 73 |
+
|| typeof module === 'undefined' || typeof window !== 'undefined';
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
function isBrowserEnv() {
|
| 77 |
+
return typeof window !== 'undefined';
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
function isWorkerEnv() {
|
| 81 |
+
return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; // eslint-disable-line no-restricted-globals
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
function createBrowserSafeString(toBeConverted) {
|
| 85 |
+
var convertedString = toBeConverted.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
| 86 |
+
return convertedString;
|
| 87 |
+
}
|
node_modules/tr46/dropbox/dist/Dropbox-sdk.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
node_modules/tr46/dropbox/dist/Dropbox-sdk.js.map
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
node_modules/tr46/dropbox/dist/Dropbox-sdk.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Dropbox={})}(this,(function(e){"use strict";function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){for(var r=0;t.length>r;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function i(e,t,i){return t&&r(e.prototype,t),i&&r(e,i),e}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function n(e,t){return(n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function a(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function o(e,t,r){return(o=a()?Reflect.construct:function(e,t,r){var i=[null];i.push.apply(i,t);var s=new(Function.bind.apply(e,i));return r&&n(s,r.prototype),s}).apply(null,arguments)}function u(e){var t="function"==typeof Map?new Map:void 0;return(u=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return o(e,arguments,s(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),n(r,e)})(e)}function c(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}var p="app",l="user",f="team",m="dropboxapi.com",h="dropbox.com",d={api:"api",notify:"bolt",content:"api-content"},_={};function g(e){var t="000".concat(e.charCodeAt(0).toString(16)).slice(-4);return"\\u".concat(t)}_.accountSetProfilePhoto=function(e){return this.request("account/set_profile_photo",e,"user","api","rpc","account_info.write")},_.authTokenFromOauth1=function(e){return this.request("auth/token/from_oauth1",e,"app","api","rpc",null)},_.authTokenRevoke=function(){return this.request("auth/token/revoke",null,"user","api","rpc",null)},_.checkApp=function(e){return this.request("check/app",e,"app","api","rpc",null)},_.checkUser=function(e){return this.request("check/user",e,"user","api","rpc","account_info.read")},_.contactsDeleteManualContacts=function(){return this.request("contacts/delete_manual_contacts",null,"user","api","rpc","contacts.write")},_.contactsDeleteManualContactsBatch=function(e){return this.request("contacts/delete_manual_contacts_batch",e,"user","api","rpc","contacts.write")},_.filePropertiesPropertiesAdd=function(e){return this.request("file_properties/properties/add",e,"user","api","rpc","files.metadata.write")},_.filePropertiesPropertiesOverwrite=function(e){return this.request("file_properties/properties/overwrite",e,"user","api","rpc","files.metadata.write")},_.filePropertiesPropertiesRemove=function(e){return this.request("file_properties/properties/remove",e,"user","api","rpc","files.metadata.write")},_.filePropertiesPropertiesSearch=function(e){return this.request("file_properties/properties/search",e,"user","api","rpc","files.metadata.read")},_.filePropertiesPropertiesSearchContinue=function(e){return this.request("file_properties/properties/search/continue",e,"user","api","rpc","files.metadata.read")},_.filePropertiesPropertiesUpdate=function(e){return this.request("file_properties/properties/update",e,"user","api","rpc","files.metadata.write")},_.filePropertiesTemplatesAddForTeam=function(e){return this.request("file_properties/templates/add_for_team",e,"team","api","rpc","files.team_metadata.write")},_.filePropertiesTemplatesAddForUser=function(e){return this.request("file_properties/templates/add_for_user",e,"user","api","rpc","files.metadata.write")},_.filePropertiesTemplatesGetForTeam=function(e){return this.request("file_properties/templates/get_for_team",e,"team","api","rpc","files.team_metadata.write")},_.filePropertiesTemplatesGetForUser=function(e){return this.request("file_properties/templates/get_for_user",e,"user","api","rpc","files.metadata.read")},_.filePropertiesTemplatesListForTeam=function(){return this.request("file_properties/templates/list_for_team",null,"team","api","rpc","files.team_metadata.write")},_.filePropertiesTemplatesListForUser=function(){return this.request("file_properties/templates/list_for_user",null,"user","api","rpc","files.metadata.read")},_.filePropertiesTemplatesRemoveForTeam=function(e){return this.request("file_properties/templates/remove_for_team",e,"team","api","rpc","files.team_metadata.write")},_.filePropertiesTemplatesRemoveForUser=function(e){return this.request("file_properties/templates/remove_for_user",e,"user","api","rpc","files.metadata.write")},_.filePropertiesTemplatesUpdateForTeam=function(e){return this.request("file_properties/templates/update_for_team",e,"team","api","rpc","files.team_metadata.write")},_.filePropertiesTemplatesUpdateForUser=function(e){return this.request("file_properties/templates/update_for_user",e,"user","api","rpc","files.metadata.write")},_.fileRequestsCount=function(){return this.request("file_requests/count",null,"user","api","rpc","file_requests.read")},_.fileRequestsCreate=function(e){return this.request("file_requests/create",e,"user","api","rpc","file_requests.write")},_.fileRequestsDelete=function(e){return this.request("file_requests/delete",e,"user","api","rpc","file_requests.write")},_.fileRequestsDeleteAllClosed=function(){return this.request("file_requests/delete_all_closed",null,"user","api","rpc","file_requests.write")},_.fileRequestsGet=function(e){return this.request("file_requests/get",e,"user","api","rpc","file_requests.read")},_.fileRequestsListV2=function(e){return this.request("file_requests/list_v2",e,"user","api","rpc","file_requests.read")},_.fileRequestsList=function(){return this.request("file_requests/list",null,"user","api","rpc","file_requests.read")},_.fileRequestsListContinue=function(e){return this.request("file_requests/list/continue",e,"user","api","rpc","file_requests.read")},_.fileRequestsUpdate=function(e){return this.request("file_requests/update",e,"user","api","rpc","file_requests.write")},_.filesAlphaGetMetadata=function(e){return this.request("files/alpha/get_metadata",e,"user","api","rpc","files.metadata.read")},_.filesAlphaUpload=function(e){return this.request("files/alpha/upload",e,"user","content","upload","files.content.write")},_.filesCopyV2=function(e){return this.request("files/copy_v2",e,"user","api","rpc","files.content.write")},_.filesCopy=function(e){return this.request("files/copy",e,"user","api","rpc","files.content.write")},_.filesCopyBatchV2=function(e){return this.request("files/copy_batch_v2",e,"user","api","rpc","files.content.write")},_.filesCopyBatch=function(e){return this.request("files/copy_batch",e,"user","api","rpc","files.content.write")},_.filesCopyBatchCheckV2=function(e){return this.request("files/copy_batch/check_v2",e,"user","api","rpc","files.content.write")},_.filesCopyBatchCheck=function(e){return this.request("files/copy_batch/check",e,"user","api","rpc","files.content.write")},_.filesCopyReferenceGet=function(e){return this.request("files/copy_reference/get",e,"user","api","rpc","files.content.write")},_.filesCopyReferenceSave=function(e){return this.request("files/copy_reference/save",e,"user","api","rpc","files.content.write")},_.filesCreateFolderV2=function(e){return this.request("files/create_folder_v2",e,"user","api","rpc","files.content.write")},_.filesCreateFolder=function(e){return this.request("files/create_folder",e,"user","api","rpc","files.content.write")},_.filesCreateFolderBatch=function(e){return this.request("files/create_folder_batch",e,"user","api","rpc","files.content.write")},_.filesCreateFolderBatchCheck=function(e){return this.request("files/create_folder_batch/check",e,"user","api","rpc","files.content.write")},_.filesDeleteV2=function(e){return this.request("files/delete_v2",e,"user","api","rpc","files.content.write")},_.filesDelete=function(e){return this.request("files/delete",e,"user","api","rpc","files.content.write")},_.filesDeleteBatch=function(e){return this.request("files/delete_batch",e,"user","api","rpc","files.content.write")},_.filesDeleteBatchCheck=function(e){return this.request("files/delete_batch/check",e,"user","api","rpc","files.content.write")},_.filesDownload=function(e){return this.request("files/download",e,"user","content","download","files.content.read")},_.filesDownloadZip=function(e){return this.request("files/download_zip",e,"user","content","download","files.content.read")},_.filesExport=function(e){return this.request("files/export",e,"user","content","download","files.content.read")},_.filesGetFileLockBatch=function(e){return this.request("files/get_file_lock_batch",e,"user","api","rpc","files.content.read")},_.filesGetMetadata=function(e){return this.request("files/get_metadata",e,"user","api","rpc","files.metadata.read")},_.filesGetPreview=function(e){return this.request("files/get_preview",e,"user","content","download","files.content.read")},_.filesGetTemporaryLink=function(e){return this.request("files/get_temporary_link",e,"user","api","rpc","files.content.read")},_.filesGetTemporaryUploadLink=function(e){return this.request("files/get_temporary_upload_link",e,"user","api","rpc","files.content.write")},_.filesGetThumbnail=function(e){return this.request("files/get_thumbnail",e,"user","content","download","files.content.read")},_.filesGetThumbnailV2=function(e){return this.request("files/get_thumbnail_v2",e,"app, user","content","download","files.content.read")},_.filesGetThumbnailBatch=function(e){return this.request("files/get_thumbnail_batch",e,"user","content","rpc","files.content.read")},_.filesListFolder=function(e){return this.request("files/list_folder",e,"app, user","api","rpc","files.metadata.read")},_.filesListFolderContinue=function(e){return this.request("files/list_folder/continue",e,"app, user","api","rpc","files.metadata.read")},_.filesListFolderGetLatestCursor=function(e){return this.request("files/list_folder/get_latest_cursor",e,"user","api","rpc","files.metadata.read")},_.filesListFolderLongpoll=function(e){return this.request("files/list_folder/longpoll",e,"noauth","notify","rpc","files.metadata.read")},_.filesListRevisions=function(e){return this.request("files/list_revisions",e,"user","api","rpc","files.metadata.read")},_.filesLockFileBatch=function(e){return this.request("files/lock_file_batch",e,"user","api","rpc","files.content.write")},_.filesMoveV2=function(e){return this.request("files/move_v2",e,"user","api","rpc","files.content.write")},_.filesMove=function(e){return this.request("files/move",e,"user","api","rpc","files.content.write")},_.filesMoveBatchV2=function(e){return this.request("files/move_batch_v2",e,"user","api","rpc","files.content.write")},_.filesMoveBatch=function(e){return this.request("files/move_batch",e,"user","api","rpc","files.content.write")},_.filesMoveBatchCheckV2=function(e){return this.request("files/move_batch/check_v2",e,"user","api","rpc","files.content.write")},_.filesMoveBatchCheck=function(e){return this.request("files/move_batch/check",e,"user","api","rpc","files.content.write")},_.filesPaperCreate=function(e){return this.request("files/paper/create",e,"user","api","upload","files.content.write")},_.filesPaperUpdate=function(e){return this.request("files/paper/update",e,"user","api","upload","files.content.write")},_.filesPermanentlyDelete=function(e){return this.request("files/permanently_delete",e,"user","api","rpc","files.permanent_delete")},_.filesPropertiesAdd=function(e){return this.request("files/properties/add",e,"user","api","rpc","files.metadata.write")},_.filesPropertiesOverwrite=function(e){return this.request("files/properties/overwrite",e,"user","api","rpc","files.metadata.write")},_.filesPropertiesRemove=function(e){return this.request("files/properties/remove",e,"user","api","rpc","files.metadata.write")},_.filesPropertiesTemplateGet=function(e){return this.request("files/properties/template/get",e,"user","api","rpc","files.metadata.read")},_.filesPropertiesTemplateList=function(){return this.request("files/properties/template/list",null,"user","api","rpc","files.metadata.read")},_.filesPropertiesUpdate=function(e){return this.request("files/properties/update",e,"user","api","rpc","files.metadata.write")},_.filesRestore=function(e){return this.request("files/restore",e,"user","api","rpc","files.content.write")},_.filesSaveUrl=function(e){return this.request("files/save_url",e,"user","api","rpc","files.content.write")},_.filesSaveUrlCheckJobStatus=function(e){return this.request("files/save_url/check_job_status",e,"user","api","rpc","files.content.write")},_.filesSearch=function(e){return this.request("files/search",e,"user","api","rpc","files.metadata.read")},_.filesSearchV2=function(e){return this.request("files/search_v2",e,"user","api","rpc","files.metadata.read")},_.filesSearchContinueV2=function(e){return this.request("files/search/continue_v2",e,"user","api","rpc","files.metadata.read")},_.filesTagsAdd=function(e){return this.request("files/tags/add",e,"user","api","rpc","files.metadata.write")},_.filesTagsGet=function(e){return this.request("files/tags/get",e,"user","api","rpc","files.metadata.read")},_.filesTagsRemove=function(e){return this.request("files/tags/remove",e,"user","api","rpc","files.metadata.write")},_.filesUnlockFileBatch=function(e){return this.request("files/unlock_file_batch",e,"user","api","rpc","files.content.write")},_.filesUpload=function(e){return this.request("files/upload",e,"user","content","upload","files.content.write")},_.filesUploadSessionAppendV2=function(e){return this.request("files/upload_session/append_v2",e,"user","content","upload","files.content.write")},_.filesUploadSessionAppend=function(e){return this.request("files/upload_session/append",e,"user","content","upload","files.content.write")},_.filesUploadSessionFinish=function(e){return this.request("files/upload_session/finish",e,"user","content","upload","files.content.write")},_.filesUploadSessionFinishBatch=function(e){return this.request("files/upload_session/finish_batch",e,"user","api","rpc","files.content.write")},_.filesUploadSessionFinishBatchV2=function(e){return this.request("files/upload_session/finish_batch_v2",e,"user","api","rpc","files.content.write")},_.filesUploadSessionFinishBatchCheck=function(e){return this.request("files/upload_session/finish_batch/check",e,"user","api","rpc","files.content.write")},_.filesUploadSessionStart=function(e){return this.request("files/upload_session/start",e,"user","content","upload","files.content.write")},_.filesUploadSessionStartBatch=function(e){return this.request("files/upload_session/start_batch",e,"user","api","rpc","files.content.write")},_.openidUserinfo=function(e){return this.request("openid/userinfo",e,"user","api","rpc","openid")},_.paperDocsArchive=function(e){return this.request("paper/docs/archive",e,"user","api","rpc","files.content.write")},_.paperDocsCreate=function(e){return this.request("paper/docs/create",e,"user","api","upload","files.content.write")},_.paperDocsDownload=function(e){return this.request("paper/docs/download",e,"user","api","download","files.content.read")},_.paperDocsFolderUsersList=function(e){return this.request("paper/docs/folder_users/list",e,"user","api","rpc","sharing.read")},_.paperDocsFolderUsersListContinue=function(e){return this.request("paper/docs/folder_users/list/continue",e,"user","api","rpc","sharing.read")},_.paperDocsGetFolderInfo=function(e){return this.request("paper/docs/get_folder_info",e,"user","api","rpc","sharing.read")},_.paperDocsList=function(e){return this.request("paper/docs/list",e,"user","api","rpc","files.metadata.read")},_.paperDocsListContinue=function(e){return this.request("paper/docs/list/continue",e,"user","api","rpc","files.metadata.read")},_.paperDocsPermanentlyDelete=function(e){return this.request("paper/docs/permanently_delete",e,"user","api","rpc","files.permanent_delete")},_.paperDocsSharingPolicyGet=function(e){return this.request("paper/docs/sharing_policy/get",e,"user","api","rpc","sharing.read")},_.paperDocsSharingPolicySet=function(e){return this.request("paper/docs/sharing_policy/set",e,"user","api","rpc","sharing.write")},_.paperDocsUpdate=function(e){return this.request("paper/docs/update",e,"user","api","upload","files.content.write")},_.paperDocsUsersAdd=function(e){return this.request("paper/docs/users/add",e,"user","api","rpc","sharing.write")},_.paperDocsUsersList=function(e){return this.request("paper/docs/users/list",e,"user","api","rpc","sharing.read")},_.paperDocsUsersListContinue=function(e){return this.request("paper/docs/users/list/continue",e,"user","api","rpc","sharing.read")},_.paperDocsUsersRemove=function(e){return this.request("paper/docs/users/remove",e,"user","api","rpc","sharing.write")},_.paperFoldersCreate=function(e){return this.request("paper/folders/create",e,"user","api","rpc","files.content.write")},_.sharingAddFileMember=function(e){return this.request("sharing/add_file_member",e,"user","api","rpc","sharing.write")},_.sharingAddFolderMember=function(e){return this.request("sharing/add_folder_member",e,"user","api","rpc","sharing.write")},_.sharingCheckJobStatus=function(e){return this.request("sharing/check_job_status",e,"user","api","rpc","sharing.write")},_.sharingCheckRemoveMemberJobStatus=function(e){return this.request("sharing/check_remove_member_job_status",e,"user","api","rpc","sharing.write")},_.sharingCheckShareJobStatus=function(e){return this.request("sharing/check_share_job_status",e,"user","api","rpc","sharing.write")},_.sharingCreateSharedLink=function(e){return this.request("sharing/create_shared_link",e,"user","api","rpc","sharing.write")},_.sharingCreateSharedLinkWithSettings=function(e){return this.request("sharing/create_shared_link_with_settings",e,"user","api","rpc","sharing.write")},_.sharingGetFileMetadata=function(e){return this.request("sharing/get_file_metadata",e,"user","api","rpc","sharing.read")},_.sharingGetFileMetadataBatch=function(e){return this.request("sharing/get_file_metadata/batch",e,"user","api","rpc","sharing.read")},_.sharingGetFolderMetadata=function(e){return this.request("sharing/get_folder_metadata",e,"user","api","rpc","sharing.read")},_.sharingGetSharedLinkFile=function(e){return this.request("sharing/get_shared_link_file",e,"user","content","download","sharing.read")},_.sharingGetSharedLinkMetadata=function(e){return this.request("sharing/get_shared_link_metadata",e,"app, user","api","rpc","sharing.read")},_.sharingGetSharedLinks=function(e){return this.request("sharing/get_shared_links",e,"user","api","rpc","sharing.read")},_.sharingListFileMembers=function(e){return this.request("sharing/list_file_members",e,"user","api","rpc","sharing.read")},_.sharingListFileMembersBatch=function(e){return this.request("sharing/list_file_members/batch",e,"user","api","rpc","sharing.read")},_.sharingListFileMembersContinue=function(e){return this.request("sharing/list_file_members/continue",e,"user","api","rpc","sharing.read")},_.sharingListFolderMembers=function(e){return this.request("sharing/list_folder_members",e,"user","api","rpc","sharing.read")},_.sharingListFolderMembersContinue=function(e){return this.request("sharing/list_folder_members/continue",e,"user","api","rpc","sharing.read")},_.sharingListFolders=function(e){return this.request("sharing/list_folders",e,"user","api","rpc","sharing.read")},_.sharingListFoldersContinue=function(e){return this.request("sharing/list_folders/continue",e,"user","api","rpc","sharing.read")},_.sharingListMountableFolders=function(e){return this.request("sharing/list_mountable_folders",e,"user","api","rpc","sharing.read")},_.sharingListMountableFoldersContinue=function(e){return this.request("sharing/list_mountable_folders/continue",e,"user","api","rpc","sharing.read")},_.sharingListReceivedFiles=function(e){return this.request("sharing/list_received_files",e,"user","api","rpc","sharing.read")},_.sharingListReceivedFilesContinue=function(e){return this.request("sharing/list_received_files/continue",e,"user","api","rpc","sharing.read")},_.sharingListSharedLinks=function(e){return this.request("sharing/list_shared_links",e,"user","api","rpc","sharing.read")},_.sharingModifySharedLinkSettings=function(e){return this.request("sharing/modify_shared_link_settings",e,"user","api","rpc","sharing.write")},_.sharingMountFolder=function(e){return this.request("sharing/mount_folder",e,"user","api","rpc","sharing.write")},_.sharingRelinquishFileMembership=function(e){return this.request("sharing/relinquish_file_membership",e,"user","api","rpc","sharing.write")},_.sharingRelinquishFolderMembership=function(e){return this.request("sharing/relinquish_folder_membership",e,"user","api","rpc","sharing.write")},_.sharingRemoveFileMember=function(e){return this.request("sharing/remove_file_member",e,"user","api","rpc","sharing.write")},_.sharingRemoveFileMember2=function(e){return this.request("sharing/remove_file_member_2",e,"user","api","rpc","sharing.write")},_.sharingRemoveFolderMember=function(e){return this.request("sharing/remove_folder_member",e,"user","api","rpc","sharing.write")},_.sharingRevokeSharedLink=function(e){return this.request("sharing/revoke_shared_link",e,"user","api","rpc","sharing.write")},_.sharingSetAccessInheritance=function(e){return this.request("sharing/set_access_inheritance",e,"user","api","rpc","sharing.write")},_.sharingShareFolder=function(e){return this.request("sharing/share_folder",e,"user","api","rpc","sharing.write")},_.sharingTransferFolder=function(e){return this.request("sharing/transfer_folder",e,"user","api","rpc","sharing.write")},_.sharingUnmountFolder=function(e){return this.request("sharing/unmount_folder",e,"user","api","rpc","sharing.write")},_.sharingUnshareFile=function(e){return this.request("sharing/unshare_file",e,"user","api","rpc","sharing.write")},_.sharingUnshareFolder=function(e){return this.request("sharing/unshare_folder",e,"user","api","rpc","sharing.write")},_.sharingUpdateFileMember=function(e){return this.request("sharing/update_file_member",e,"user","api","rpc","sharing.write")},_.sharingUpdateFolderMember=function(e){return this.request("sharing/update_folder_member",e,"user","api","rpc","sharing.write")},_.sharingUpdateFolderPolicy=function(e){return this.request("sharing/update_folder_policy",e,"user","api","rpc","sharing.write")},_.teamDevicesListMemberDevices=function(e){return this.request("team/devices/list_member_devices",e,"team","api","rpc","sessions.list")},_.teamDevicesListMembersDevices=function(e){return this.request("team/devices/list_members_devices",e,"team","api","rpc","sessions.list")},_.teamDevicesListTeamDevices=function(e){return this.request("team/devices/list_team_devices",e,"team","api","rpc","sessions.list")},_.teamDevicesRevokeDeviceSession=function(e){return this.request("team/devices/revoke_device_session",e,"team","api","rpc","sessions.modify")},_.teamDevicesRevokeDeviceSessionBatch=function(e){return this.request("team/devices/revoke_device_session_batch",e,"team","api","rpc","sessions.modify")},_.teamFeaturesGetValues=function(e){return this.request("team/features/get_values",e,"team","api","rpc","team_info.read")},_.teamGetInfo=function(){return this.request("team/get_info",null,"team","api","rpc","team_info.read")},_.teamGroupsCreate=function(e){return this.request("team/groups/create",e,"team","api","rpc","groups.write")},_.teamGroupsDelete=function(e){return this.request("team/groups/delete",e,"team","api","rpc","groups.write")},_.teamGroupsGetInfo=function(e){return this.request("team/groups/get_info",e,"team","api","rpc","groups.read")},_.teamGroupsJobStatusGet=function(e){return this.request("team/groups/job_status/get",e,"team","api","rpc","groups.write")},_.teamGroupsList=function(e){return this.request("team/groups/list",e,"team","api","rpc","groups.read")},_.teamGroupsListContinue=function(e){return this.request("team/groups/list/continue",e,"team","api","rpc","groups.read")},_.teamGroupsMembersAdd=function(e){return this.request("team/groups/members/add",e,"team","api","rpc","groups.write")},_.teamGroupsMembersList=function(e){return this.request("team/groups/members/list",e,"team","api","rpc","groups.read")},_.teamGroupsMembersListContinue=function(e){return this.request("team/groups/members/list/continue",e,"team","api","rpc","groups.read")},_.teamGroupsMembersRemove=function(e){return this.request("team/groups/members/remove",e,"team","api","rpc","groups.write")},_.teamGroupsMembersSetAccessType=function(e){return this.request("team/groups/members/set_access_type",e,"team","api","rpc","groups.write")},_.teamGroupsUpdate=function(e){return this.request("team/groups/update",e,"team","api","rpc","groups.write")},_.teamLegalHoldsCreatePolicy=function(e){return this.request("team/legal_holds/create_policy",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsGetPolicy=function(e){return this.request("team/legal_holds/get_policy",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsListHeldRevisions=function(e){return this.request("team/legal_holds/list_held_revisions",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsListHeldRevisionsContinue=function(e){return this.request("team/legal_holds/list_held_revisions_continue",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsListPolicies=function(e){return this.request("team/legal_holds/list_policies",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsReleasePolicy=function(e){return this.request("team/legal_holds/release_policy",e,"team","api","rpc","team_data.governance.write")},_.teamLegalHoldsUpdatePolicy=function(e){return this.request("team/legal_holds/update_policy",e,"team","api","rpc","team_data.governance.write")},_.teamLinkedAppsListMemberLinkedApps=function(e){return this.request("team/linked_apps/list_member_linked_apps",e,"team","api","rpc","sessions.list")},_.teamLinkedAppsListMembersLinkedApps=function(e){return this.request("team/linked_apps/list_members_linked_apps",e,"team","api","rpc","sessions.list")},_.teamLinkedAppsListTeamLinkedApps=function(e){return this.request("team/linked_apps/list_team_linked_apps",e,"team","api","rpc","sessions.list")},_.teamLinkedAppsRevokeLinkedApp=function(e){return this.request("team/linked_apps/revoke_linked_app",e,"team","api","rpc","sessions.modify")},_.teamLinkedAppsRevokeLinkedAppBatch=function(e){return this.request("team/linked_apps/revoke_linked_app_batch",e,"team","api","rpc","sessions.modify")},_.teamMemberSpaceLimitsExcludedUsersAdd=function(e){return this.request("team/member_space_limits/excluded_users/add",e,"team","api","rpc","members.write")},_.teamMemberSpaceLimitsExcludedUsersList=function(e){return this.request("team/member_space_limits/excluded_users/list",e,"team","api","rpc","members.read")},_.teamMemberSpaceLimitsExcludedUsersListContinue=function(e){return this.request("team/member_space_limits/excluded_users/list/continue",e,"team","api","rpc","members.read")},_.teamMemberSpaceLimitsExcludedUsersRemove=function(e){return this.request("team/member_space_limits/excluded_users/remove",e,"team","api","rpc","members.write")},_.teamMemberSpaceLimitsGetCustomQuota=function(e){return this.request("team/member_space_limits/get_custom_quota",e,"team","api","rpc","members.read")},_.teamMemberSpaceLimitsRemoveCustomQuota=function(e){return this.request("team/member_space_limits/remove_custom_quota",e,"team","api","rpc","members.write")},_.teamMemberSpaceLimitsSetCustomQuota=function(e){return this.request("team/member_space_limits/set_custom_quota",e,"team","api","rpc","members.read")},_.teamMembersAddV2=function(e){return this.request("team/members/add_v2",e,"team","api","rpc","members.write")},_.teamMembersAdd=function(e){return this.request("team/members/add",e,"team","api","rpc","members.write")},_.teamMembersAddJobStatusGetV2=function(e){return this.request("team/members/add/job_status/get_v2",e,"team","api","rpc","members.write")},_.teamMembersAddJobStatusGet=function(e){return this.request("team/members/add/job_status/get",e,"team","api","rpc","members.write")},_.teamMembersDeleteProfilePhotoV2=function(e){return this.request("team/members/delete_profile_photo_v2",e,"team","api","rpc","members.write")},_.teamMembersDeleteProfilePhoto=function(e){return this.request("team/members/delete_profile_photo",e,"team","api","rpc","members.write")},_.teamMembersGetAvailableTeamMemberRoles=function(){return this.request("team/members/get_available_team_member_roles",null,"team","api","rpc","members.read")},_.teamMembersGetInfoV2=function(e){return this.request("team/members/get_info_v2",e,"team","api","rpc","members.read")},_.teamMembersGetInfo=function(e){return this.request("team/members/get_info",e,"team","api","rpc","members.read")},_.teamMembersListV2=function(e){return this.request("team/members/list_v2",e,"team","api","rpc","members.read")},_.teamMembersList=function(e){return this.request("team/members/list",e,"team","api","rpc","members.read")},_.teamMembersListContinueV2=function(e){return this.request("team/members/list/continue_v2",e,"team","api","rpc","members.read")},_.teamMembersListContinue=function(e){return this.request("team/members/list/continue",e,"team","api","rpc","members.read")},_.teamMembersMoveFormerMemberFiles=function(e){return this.request("team/members/move_former_member_files",e,"team","api","rpc","members.write")},_.teamMembersMoveFormerMemberFilesJobStatusCheck=function(e){return this.request("team/members/move_former_member_files/job_status/check",e,"team","api","rpc","members.write")},_.teamMembersRecover=function(e){return this.request("team/members/recover",e,"team","api","rpc","members.delete")},_.teamMembersRemove=function(e){return this.request("team/members/remove",e,"team","api","rpc","members.delete")},_.teamMembersRemoveJobStatusGet=function(e){return this.request("team/members/remove/job_status/get",e,"team","api","rpc","members.delete")},_.teamMembersSecondaryEmailsAdd=function(e){return this.request("team/members/secondary_emails/add",e,"team","api","rpc","members.write")},_.teamMembersSecondaryEmailsDelete=function(e){return this.request("team/members/secondary_emails/delete",e,"team","api","rpc","members.write")},_.teamMembersSecondaryEmailsResendVerificationEmails=function(e){return this.request("team/members/secondary_emails/resend_verification_emails",e,"team","api","rpc","members.write")},_.teamMembersSendWelcomeEmail=function(e){return this.request("team/members/send_welcome_email",e,"team","api","rpc","members.write")},_.teamMembersSetAdminPermissionsV2=function(e){return this.request("team/members/set_admin_permissions_v2",e,"team","api","rpc","members.write")},_.teamMembersSetAdminPermissions=function(e){return this.request("team/members/set_admin_permissions",e,"team","api","rpc","members.write")},_.teamMembersSetProfileV2=function(e){return this.request("team/members/set_profile_v2",e,"team","api","rpc","members.write")},_.teamMembersSetProfile=function(e){return this.request("team/members/set_profile",e,"team","api","rpc","members.write")},_.teamMembersSetProfilePhotoV2=function(e){return this.request("team/members/set_profile_photo_v2",e,"team","api","rpc","members.write")},_.teamMembersSetProfilePhoto=function(e){return this.request("team/members/set_profile_photo",e,"team","api","rpc","members.write")},_.teamMembersSuspend=function(e){return this.request("team/members/suspend",e,"team","api","rpc","members.write")},_.teamMembersUnsuspend=function(e){return this.request("team/members/unsuspend",e,"team","api","rpc","members.write")},_.teamNamespacesList=function(e){return this.request("team/namespaces/list",e,"team","api","rpc","team_data.member")},_.teamNamespacesListContinue=function(e){return this.request("team/namespaces/list/continue",e,"team","api","rpc","team_data.member")},_.teamPropertiesTemplateAdd=function(e){return this.request("team/properties/template/add",e,"team","api","rpc","files.team_metadata.write")},_.teamPropertiesTemplateGet=function(e){return this.request("team/properties/template/get",e,"team","api","rpc","files.team_metadata.write")},_.teamPropertiesTemplateList=function(){return this.request("team/properties/template/list",null,"team","api","rpc","files.team_metadata.write")},_.teamPropertiesTemplateUpdate=function(e){return this.request("team/properties/template/update",e,"team","api","rpc","files.team_metadata.write")},_.teamReportsGetActivity=function(e){return this.request("team/reports/get_activity",e,"team","api","rpc","team_info.read")},_.teamReportsGetDevices=function(e){return this.request("team/reports/get_devices",e,"team","api","rpc","team_info.read")},_.teamReportsGetMembership=function(e){return this.request("team/reports/get_membership",e,"team","api","rpc","team_info.read")},_.teamReportsGetStorage=function(e){return this.request("team/reports/get_storage",e,"team","api","rpc","team_info.read")},_.teamSharingAllowlistAdd=function(e){return this.request("team/sharing_allowlist/add",e,"team","api","rpc","team_info.write")},_.teamSharingAllowlistList=function(e){return this.request("team/sharing_allowlist/list",e,"team","api","rpc","team_info.read")},_.teamSharingAllowlistListContinue=function(e){return this.request("team/sharing_allowlist/list/continue",e,"team","api","rpc","team_info.read")},_.teamSharingAllowlistRemove=function(e){return this.request("team/sharing_allowlist/remove",e,"team","api","rpc","team_info.write")},_.teamTeamFolderActivate=function(e){return this.request("team/team_folder/activate",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderArchive=function(e){return this.request("team/team_folder/archive",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderArchiveCheck=function(e){return this.request("team/team_folder/archive/check",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderCreate=function(e){return this.request("team/team_folder/create",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderGetInfo=function(e){return this.request("team/team_folder/get_info",e,"team","api","rpc","team_data.content.read")},_.teamTeamFolderList=function(e){return this.request("team/team_folder/list",e,"team","api","rpc","team_data.content.read")},_.teamTeamFolderListContinue=function(e){return this.request("team/team_folder/list/continue",e,"team","api","rpc","team_data.content.read")},_.teamTeamFolderPermanentlyDelete=function(e){return this.request("team/team_folder/permanently_delete",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderRename=function(e){return this.request("team/team_folder/rename",e,"team","api","rpc","team_data.content.write")},_.teamTeamFolderUpdateSyncSettings=function(e){return this.request("team/team_folder/update_sync_settings",e,"team","api","rpc","team_data.content.write")},_.teamTokenGetAuthenticatedAdmin=function(){return this.request("team/token/get_authenticated_admin",null,"team","api","rpc","team_info.read")},_.teamLogGetEvents=function(e){return this.request("team_log/get_events",e,"team","api","rpc","events.read")},_.teamLogGetEventsContinue=function(e){return this.request("team_log/get_events/continue",e,"team","api","rpc","events.read")},_.usersFeaturesGetValues=function(e){return this.request("users/features/get_values",e,"user","api","rpc","account_info.read")},_.usersGetAccount=function(e){return this.request("users/get_account",e,"user","api","rpc","sharing.read")},_.usersGetAccountBatch=function(e){return this.request("users/get_account_batch",e,"user","api","rpc","sharing.read")},_.usersGetCurrentAccount=function(){return this.request("users/get_current_account",null,"user","api","rpc","account_info.read")},_.usersGetSpaceUsage=function(){return this.request("users/get_space_usage",null,"user","api","rpc","account_info.read")};var q=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:m,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".";return r?(t!==m&&void 0!==d[e]&&(e=d[e],r="-"),"https://".concat(e).concat(r).concat(t,"/2/")):"https://".concat(t,"/2/")},b=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:h;return e!==h&&(e="meta-".concat(e)),"https://".concat(e,"/oauth2/authorize")},v=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:m,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:".",r="api";return e!==m&&(r=d[r],t="-"),"https://".concat(r).concat(t).concat(e,"/oauth2/token")};function w(e){return JSON.stringify(e).replace(/[\u007f-\uffff]/g,g)}function k(e){return new Date(Date.now()+1e3*e)}function y(){return"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope||"undefined"==typeof module||"undefined"!=typeof window}function A(){return"undefined"!=typeof window}function S(){return"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope}function C(e){return e.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}var T,L,M,P=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&n(e,t)}(u,e);var r,i,o=(r=u,i=a(),function(){var e,t=s(r);if(i){var n=s(this).constructor;e=Reflect.construct(t,arguments,n)}else e=t.apply(this,arguments);return c(this,e)});function u(e,r,i){var s;return t(this,u),(s=o.call(this,"Response failed with a ".concat(e," code"))).name="DropboxResponseError",s.status=e,s.headers=r,s.error=i,s}return u}(u(Error)),R=function e(r,i,s){t(this,e),this.status=r,this.headers=i,this.result=s};function F(e){return e.text().then((function(t){var r;try{r=JSON.parse(t)}catch(e){r=t}throw new P(e.status,e.headers,r)}))}function D(e){return e.ok?e.text().then((function(t){var r;try{r=JSON.parse(t)}catch(e){r=t}return new R(e.status,e.headers,r)})):F(e)}var G=["legacy","offline","online"],U=["code","token"],x=["none","user","team"],E=function(){function e(r){t(this,e),r=r||{},A()?(T=window.fetch.bind(window),L=window.crypto||window.msCrypto):S()?(T=self.fetch.bind(self),L=self.crypto):(T=require("node-fetch"),L=require("crypto")),M="undefined"==typeof TextEncoder?require("util").TextEncoder:TextEncoder,this.fetch=r.fetch||T,this.accessToken=r.accessToken,this.accessTokenExpiresAt=r.accessTokenExpiresAt,this.refreshToken=r.refreshToken,this.clientId=r.clientId,this.clientSecret=r.clientSecret,this.domain=r.domain,this.domainDelimiter=r.domainDelimiter,this.customHeaders=r.customHeaders,this.dataOnBody=r.dataOnBody}return i(e,[{key:"setAccessToken",value:function(e){this.accessToken=e}},{key:"getAccessToken",value:function(){return this.accessToken}},{key:"setClientId",value:function(e){this.clientId=e}},{key:"getClientId",value:function(){return this.clientId}},{key:"setClientSecret",value:function(e){this.clientSecret=e}},{key:"getClientSecret",value:function(){return this.clientSecret}},{key:"getRefreshToken",value:function(){return this.refreshToken}},{key:"setRefreshToken",value:function(e){this.refreshToken=e}},{key:"getAccessTokenExpiresAt",value:function(){return this.accessTokenExpiresAt}},{key:"setAccessTokenExpiresAt",value:function(e){this.accessTokenExpiresAt=e}},{key:"setCodeVerifier",value:function(e){this.codeVerifier=e}},{key:"getCodeVerifier",value:function(){return this.codeVerifier}},{key:"generateCodeChallenge",value:function(){var e,t=this,r=(new M).encode(this.codeVerifier);if(A()||S())return L.subtle.digest("SHA-256",r).then((function(r){var i=btoa(String.fromCharCode.apply(null,new Uint8Array(r)));e=C(i).substr(0,128),t.codeChallenge=e}));var i=L.createHash("sha256").update(r).digest();return e=C(i),this.codeChallenge=e,Promise.resolve()}},{key:"generatePKCECodes",value:function(){var e;if(A()||S()){var t=new Uint8Array(128),r=L.getRandomValues(t);e=C(btoa(r)).substr(0,128)}else{e=C(L.randomBytes(128)).substr(0,128)}return this.codeVerifier=e,this.generateCodeChallenge()}},{key:"getAuthenticationUrl",value:function(e,t){var r,i=this,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"token",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"none",u=arguments.length>6&&void 0!==arguments[6]&&arguments[6],c=this.getClientId(),p=b(this.domain);if(!c)throw Error("A client id is required. You can set the client id using .setClientId().");if("code"!==s&&!e)throw Error("A redirect uri is required.");if(!U.includes(s))throw Error("Authorization type must be code or token");if(n&&!G.includes(n))throw Error("Token Access Type must be legacy, offline, or online");if(a&&!(a instanceof Array))throw Error("Scope must be an array of strings");if(!x.includes(o))throw Error("includeGrantedScopes must be none, user, or team");return r="code"===s?"".concat(p,"?response_type=code&client_id=").concat(c):"".concat(p,"?response_type=token&client_id=").concat(c),e&&(r+="&redirect_uri=".concat(e)),t&&(r+="&state=".concat(t)),n&&(r+="&token_access_type=".concat(n)),a&&(r+="&scope=".concat(a.join(" "))),"none"!==o&&(r+="&include_granted_scopes=".concat(o)),u?this.generatePKCECodes().then((function(){return r+="&code_challenge_method=S256",r+="&code_challenge=".concat(i.codeChallenge)})):Promise.resolve(r)}},{key:"getAccessTokenFromCode",value:function(e,t){var r=this.getClientId(),i=this.getClientSecret();if(!r)throw Error("A client id is required. You can set the client id using .setClientId().");var s=v(this.domain,this.domainDelimiter);if(s+="?grant_type=authorization_code",s+="&code=".concat(t),s+="&client_id=".concat(r),i)s+="&client_secret=".concat(i);else{if(!this.codeVerifier)throw Error("You must use PKCE when generating the authorization URL to not include a client secret");s+="&code_verifier=".concat(this.codeVerifier)}e&&(s+="&redirect_uri=".concat(e));return this.fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then((function(e){return D(e)}))}},{key:"checkAndRefreshAccessToken",value:function(){var e=this.getRefreshToken()&&this.getClientId(),t=!this.getAccessTokenExpiresAt()||new Date(Date.now()+3e5)>=this.getAccessTokenExpiresAt(),r=!this.getAccessToken();return(t||r)&&e?this.refreshAccessToken():Promise.resolve()}},{key:"refreshAccessToken",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,r=this.getClientId(),i=this.getClientSecret();if(!r)throw Error("A client id is required. You can set the client id using .setClientId().");if(t&&!(t instanceof Array))throw Error("Scope must be an array of strings");var s=v(this.domain,this.domainDelimiter),n={headers:{"Content-Type":"application/json"},method:"POST"};if(this.dataOnBody){var a={grant_type:"refresh_token",client_id:r,refresh_token:this.getRefreshToken()};i&&(a.client_secret=i),t&&(a.scope=t.join(" ")),n.body=a}else s+="?grant_type=refresh_token&refresh_token=".concat(this.getRefreshToken()),s+="&client_id=".concat(r),i&&(s+="&client_secret=".concat(i)),t&&(s+="&scope=".concat(t.join(" ")));return this.fetch(s,n).then((function(e){return D(e)})).then((function(t){e.setAccessToken(t.result.access_token),e.setAccessTokenExpiresAt(k(t.result.expires_in))}))}}]),e}(),B="undefined"==typeof btoa?function(e){return Buffer.from(e).toString("base64")}:btoa;e.Dropbox=function(){function e(r){t(this,e),this.auth=(r=r||{}).auth?r.auth:new E(r),this.fetch=r.fetch||this.auth.fetch,this.selectUser=r.selectUser,this.selectAdmin=r.selectAdmin,this.pathRoot=r.pathRoot,this.domain=r.domain||this.auth.domain,this.domainDelimiter=r.domainDelimiter||this.auth.domainDelimiter,this.customHeaders=r.customHeaders||this.auth.customHeaders,Object.assign(this,_)}return i(e,[{key:"request",value:function(e,t,r,i,s){switch(s){case"rpc":return this.rpcRequest(e,t,r,i);case"download":return this.downloadRequest(e,t,r,i);case"upload":return this.uploadRequest(e,t,r,i);default:throw Error("Invalid request style: ".concat(s))}}},{key:"rpcRequest",value:function(e,t,r,i){var s=this;return this.auth.checkAndRefreshAccessToken().then((function(){var e={method:"POST",body:t?JSON.stringify(t):null,headers:{}};return t&&(e.headers["Content-Type"]="application/json"),s.setAuthHeaders(r,e),s.setCommonHeaders(e),e})).then((function(t){return s.fetch(q(i,s.domain,s.domainDelimiter)+e,t)})).then((function(e){return D(e)}))}},{key:"downloadRequest",value:function(e,t,r,i){var s=this;return this.auth.checkAndRefreshAccessToken().then((function(){var e={method:"POST",headers:{"Dropbox-API-Arg":w(t)}};return s.setAuthHeaders(r,e),s.setCommonHeaders(e),e})).then((function(t){return s.fetch(q(i,s.domain,s.domainDelimiter)+e,t)})).then((function(e){return function(e){return e.ok?new Promise((function(t){y()?e.blob().then((function(e){return t(e)})):e.buffer().then((function(e){return t(e)}))})).then((function(t){var r=JSON.parse(e.headers.get("dropbox-api-result"));return y()?r.fileBlob=t:r.fileBinary=t,new R(e.status,e.headers,r)})):F(e)}(e)}))}},{key:"uploadRequest",value:function(e,t,r,i){var s=this;return this.auth.checkAndRefreshAccessToken().then((function(){var e=t.contents;delete t.contents;var i={body:e,method:"POST",headers:{"Content-Type":"application/octet-stream","Dropbox-API-Arg":w(t)}};return s.setAuthHeaders(r,i),s.setCommonHeaders(i),i})).then((function(t){return s.fetch(q(i,s.domain,s.domainDelimiter)+e,t)})).then((function(e){return D(e)}))}},{key:"setAuthHeaders",value:function(e,t){if(e.split(",").length>1){var r=e.replace(" ","").split(",");r.includes(l)&&this.auth.getAccessToken()?e=l:r.includes(f)&&this.auth.getAccessToken()?e=f:r.includes(p)&&(e=p)}switch(e){case p:if(this.auth.clientId&&this.auth.clientSecret){var i=B("".concat(this.auth.clientId,":").concat(this.auth.clientSecret));t.headers.Authorization="Basic ".concat(i)}break;case f:case l:this.auth.getAccessToken()&&(t.headers.Authorization="Bearer ".concat(this.auth.getAccessToken()));break;case"noauth":case"cookie":break;default:throw Error("Unhandled auth type: ".concat(e))}}},{key:"setCommonHeaders",value:function(e){var t=this;(this.selectUser&&(e.headers["Dropbox-API-Select-User"]=this.selectUser),this.selectAdmin&&(e.headers["Dropbox-API-Select-Admin"]=this.selectAdmin),this.pathRoot&&(e.headers["Dropbox-API-Path-Root"]=this.pathRoot),this.customHeaders)&&Object.keys(this.customHeaders).forEach((function(r){e.headers[r]=t.customHeaders[r]}))}}]),e}(),e.DropboxAuth=E,e.DropboxResponse=R,e.DropboxResponseError=P,Object.defineProperty(e,"__esModule",{value:!0})}));
|