You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by gl...@apache.org on 2020/02/27 16:09:55 UTC

[couchdb-nano] 01/12: stash changes

This is an automated email from the ASF dual-hosted git repository.

glynnbird pushed a commit to branch axios
in repository https://gitbox.apache.org/repos/asf/couchdb-nano.git

commit 07b4e63ead16aea281b3381bf8a08e650deffbb8
Author: Glynn Bird <gl...@gmail.com>
AuthorDate: Thu Feb 13 10:18:27 2020 +0000

    stash changes
---
 lib/nano.js       | 184 ++++++++++++++++++++++++++++++++----------------------
 package-lock.json |  82 ++++++++++++------------
 package.json      |   6 +-
 3 files changed, 152 insertions(+), 120 deletions(-)

diff --git a/lib/nano.js b/lib/nano.js
index b4cc0d0..c77f040 100644
--- a/lib/nano.js
+++ b/lib/nano.js
@@ -12,12 +12,13 @@
 
 const URL = require('url').URL
 const assert = require('assert')
-const querystring = require('querystring')
-const request = require('request')
+const querystring = require('qs')
+const axios = require('axios').default
 const errs = require('errs')
 const follow = require('cloudant-follow')
 const logger = require('./logger')
 const INVALID_PARAMETERS_ERROR = new Error('Invalid parameters')
+const stream = require('stream')
 
 function isEmpty (val) {
   return val == null || !(Object.keys(val) || val).length
@@ -51,8 +52,6 @@ module.exports = exports = function dbScope (cfg) {
   serverScope.config = cfg
   cfg.requestDefaults = cfg.requestDefaults || {}
 
-  const httpAgent = (typeof cfg.request === 'function') ? cfg.request
-    : request.defaults(cfg.requestDefaults)
   const followAgent = (typeof cfg.follow === 'function') ? cfg.follow : follow
   const log = typeof cfg.log === 'function' ? cfg.log : logger(cfg)
   const parseUrl = 'parseUrl' in cfg ? cfg.parseUrl : true
@@ -79,85 +78,89 @@ module.exports = exports = function dbScope (cfg) {
     }
     return str
   }
-  const responseHandler = function (req, opts, resolve, reject, callback) {
-    return function (err, response = { statusCode: 500 }, body = '') {
-      let parsed
-      const responseHeaders = Object.assign({
-        uri: req.uri,
-        statusCode: response.statusCode
-      }, response.headers)
-      if (err) {
-        log({ err: 'socket', body: body, headers: responseHeaders })
-        const returnError = errs.merge(err, {
+  const responseHandler = function (response, req, opts, resolve, reject, callback) {
+    if (response.isAxiosError && response.response) {
+      response = response.response
+    }
+    let body = response.data
+    response.statusCode = response.status
+
+    // let parsed
+    const responseHeaders = Object.assign({
+      uri: req.url,
+      statusCode: response.statusCode
+    }, response.headers)
+    if (!response.status) {
+      log({ err: 'socket', body: body, headers: responseHeaders })
+      if (reject) {
+        reject(new Error('error happened in your connection'))
+      }
+      if (callback) {
+        const returnError = {
           message: 'error happened in your connection',
           scope: 'socket',
           errid: 'request'
-        })
-        if (reject) {
-          reject(returnError)
-        }
-        if (callback) {
-          callback(returnError)
         }
-        return
+        callback(returnError)
       }
+      return
+    }
 
-      delete responseHeaders.server
-      delete responseHeaders['content-length']
+    delete responseHeaders.server
+    delete responseHeaders['content-length']
 
-      if (opts.dontParse) {
-        parsed = body
-      } else {
-        try { parsed = JSON.parse(body) } catch (err) { parsed = body }
-      }
+    /* if (opts.dontParse) {
+      parsed = body
+    } else {
+      try { parsed = JSON.parse(body) } catch (err) { parsed = body }
+    } */
 
-      if (responseHeaders.statusCode >= 200 && responseHeaders.statusCode < 400) {
-        log({ err: null, body: parsed, headers: responseHeaders })
-        if (resolve) {
-          resolve(parsed)
-        }
-        if (callback) {
-          callback(null, parsed, responseHeaders)
-        }
-        return
+    if (responseHeaders.statusCode >= 200 && responseHeaders.statusCode < 400) {
+      log({ err: null, body: body, headers: responseHeaders })
+      if (resolve) {
+        resolve(body)
       }
+      if (callback) {
+        callback(null, body, responseHeaders)
+      }
+      return
+    }
 
-      log({ err: 'couch', body: parsed, headers: responseHeaders })
+    log({ err: 'couch', body: body, headers: responseHeaders })
 
-      // cloudant stacktrace
-      if (typeof parsed === 'string') {
-        parsed = { message: parsed }
-      }
+    // cloudant stacktrace
+    if (typeof body === 'string') {
+      body = { message: body }
+    }
 
-      if (!parsed.message && (parsed.reason || parsed.error)) {
-        parsed.message = (parsed.reason || parsed.error)
-      }
+    if (!body.message && (body.reason || body.error)) {
+      body.message = (body.reason || body.error)
+    }
 
-      // fix cloudant issues where they give an erlang stacktrace as js
-      delete parsed.stack
+    // fix cloudant issues where they give an erlang stacktrace as js
+    delete body.stack
 
-      // scrub credentials
-      req.uri = scrub(req.uri)
-      responseHeaders.uri = scrub(responseHeaders.uri)
-      if (req.headers.cookie) {
-        req.headers.cookie = 'XXXXXXX'
-      }
+    // scrub credentials
+    req.url = scrub(req.url)
+    responseHeaders.url = scrub(responseHeaders.url)
+    if (req.headers.cookie) {
+      req.headers.cookie = 'XXXXXXX'
+    }
 
-      const errors = errs.merge({
-        message: 'couch returned ' + responseHeaders.statusCode,
-        scope: 'couch',
-        statusCode: responseHeaders.statusCode,
-        request: req,
-        headers: responseHeaders,
-        errid: 'non_200'
-      }, errs.create(parsed))
+    const errors = errs.merge({
+      message: 'couch returned ' + req.statusCode,
+      scope: 'couch',
+      statusCode: req.statusCode,
+      request: req,
+      headers: responseHeaders,
+      errid: 'non_200'
+    }, errs.create(body))
 
-      if (reject) {
-        reject(errors)
-      }
-      if (callback) {
-        callback(errors)
-      }
+    if (reject) {
+      reject(errors)
+    }
+    if (callback) {
+      callback(errors)
     }
   }
 
@@ -183,11 +186,11 @@ module.exports = exports = function dbScope (cfg) {
       accept: 'application/json'
     }
 
-    const req = {
+    const req = Object.assign({
       method: (opts.method || 'GET'),
       headers: headers,
       uri: cfg.url
-    }
+    }, cfg.requestDefaults)
 
     // https://github.com/mikeal/request#requestjar
     const isJar = opts.jar || cfg.jar
@@ -283,17 +286,46 @@ module.exports = exports = function dbScope (cfg) {
 
     log(req)
 
+    // This where the HTTP request is made.
+    // Nano used to use the now-deprecated "request" library but now we're going to
+    // use axios, so let's modify the "req" object to suit axios
+    req.url = req.uri
+    delete req.uri
+    req.method = req.method.toLowerCase()
+    req.params = req.qs
+    delete req.qs
+    req.paramsSerializer = (params) => {
+      return querystring.stringify(params, { arrayFormat: 'brackets' })
+    }
+    req.data = req.body
+    delete req.body
+    req.maxRedirects = 0
+    if (opts.stream) {
+      req.responseType = 'stream'
+    } else if (opts.dontParse) {
+      req.responseType = 'arraybuffer'
+    }
+
+    // actually do the HTTP request
     if (opts.stream) {
       // return the Request object for streaming
-      return httpAgent(req)
+      const outStream = new stream.PassThrough()
+      axios(req).then((response) => { response.data.pipe(outStream) })
+      return outStream
     } else {
       if (typeof callback === 'function') {
-        // return nothing - feedback via the callback function
-        httpAgent(req, responseHandler(req, opts, null, null, callback))
+        axios(req).then((response) => {
+          responseHandler(response, req, opts, null, null, callback)
+        }).catch((e) => {
+          responseHandler(e, req, opts, null, null, callback)
+        })
       } else {
-        // return a Promise
-        return new Promise(function (resolve, reject) {
-          httpAgent(req, responseHandler(req, opts, resolve, reject))
+        return new Promise((resolve, reject) => {
+          axios(req).then((response) => {
+            responseHandler(response, req, opts, resolve, reject)
+          }).catch((e) => {
+            responseHandler(e, req, opts, resolve, reject)
+          })
         })
       }
     }
@@ -422,7 +454,7 @@ module.exports = exports = function dbScope (cfg) {
   function followDb (dbName, qs0, callback0) {
     const { opts, callback } = getCallback(qs0, callback0)
     opts.db = urlResolveFix(cfg.url, encodeURIComponent(dbName))
-    opts.httpAgent = httpAgent
+    // opts.httpAgent = httpAgent
     if (typeof callback === 'function') {
       return followAgent(opts, callback)
     } else {
diff --git a/package-lock.json b/package-lock.json
index 18f6963..39a6004 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -937,11 +937,6 @@
         "@babel/types": "^7.3.0"
       }
     },
-    "@types/caseless": {
-      "version": "0.12.2",
-      "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
-      "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
-    },
     "@types/color-name": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -973,45 +968,12 @@
         "@types/istanbul-lib-report": "*"
       }
     },
-    "@types/node": {
-      "version": "13.7.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.0.tgz",
-      "integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ=="
-    },
-    "@types/request": {
-      "version": "2.48.4",
-      "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.4.tgz",
-      "integrity": "sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw==",
-      "requires": {
-        "@types/caseless": "*",
-        "@types/node": "*",
-        "@types/tough-cookie": "*",
-        "form-data": "^2.5.0"
-      },
-      "dependencies": {
-        "form-data": {
-          "version": "2.5.1",
-          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
-          "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
-          "requires": {
-            "asynckit": "^0.4.0",
-            "combined-stream": "^1.0.6",
-            "mime-types": "^2.1.12"
-          }
-        }
-      }
-    },
     "@types/stack-utils": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
       "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
       "dev": true
     },
-    "@types/tough-cookie": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.6.tgz",
-      "integrity": "sha512-wHNBMnkoEBiRAd3s8KTKwIuO9biFtTf0LehITzBhSco+HQI0xkXZbLOD55SW3Aqw3oUkHstkm5SPv58yaAdFPQ=="
-    },
     "@types/yargs": {
       "version": "15.0.3",
       "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.3.tgz",
@@ -1208,6 +1170,14 @@
       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
       "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
     },
+    "axios": {
+      "version": "0.19.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
+      "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
+      "requires": {
+        "follow-redirects": "1.5.10"
+      }
+    },
     "babel-jest": {
       "version": "25.1.0",
       "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.1.0.tgz",
@@ -2682,6 +2652,29 @@
       "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
       "dev": true
     },
+    "follow-redirects": {
+      "version": "1.5.10",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+      "requires": {
+        "debug": "=3.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+        }
+      }
+    },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -5832,9 +5825,9 @@
       "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
     },
     "qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz",
+      "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA=="
     },
     "react-is": {
       "version": "16.12.0",
@@ -5931,6 +5924,13 @@
         "tough-cookie": "~2.4.3",
         "tunnel-agent": "^0.6.0",
         "uuid": "^3.3.2"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+        }
       }
     },
     "request-promise-core": {
diff --git a/package.json b/package.json
index 7cf621d..2ec5360 100644
--- a/package.json
+++ b/package.json
@@ -17,11 +17,11 @@
     "database"
   ],
   "dependencies": {
-    "@types/request": "^2.48.4",
+    "axios": "^0.19.2",
     "cloudant-follow": "^0.18.2",
     "debug": "^4.1.1",
     "errs": "^0.3.2",
-    "request": "^2.88.0"
+    "qs": "^6.9.1"
   },
   "devDependencies": {
     "async": "^2.6.2",
@@ -32,7 +32,7 @@
   "scripts": {
     "standard": "standard --fix",
     "test": "standard && npm run jest",
-    "jest": "jest test/* --coverage"
+    "jest": "jest test/* --coverage --env=node"
   },
   "main": "./lib/nano.js",
   "types": "./lib/nano.d.ts",