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 2022/12/16 13:45:44 UTC

[couchdb-nano] 03/13: removed unwanted request/axios code

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

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

commit 5cbf072ce37248d7b17dadfc0777375a1be5f1b7
Author: Glynn Bird <gl...@apache.org>
AuthorDate: Tue Dec 13 09:03:03 2022 +0000

    removed unwanted request/axios code
---
 lib/nano.js            | 224 ++++++++++++++++++-------------------------------
 test/nano.auth.test.js |   1 -
 2 files changed, 81 insertions(+), 144 deletions(-)

diff --git a/lib/nano.js b/lib/nano.js
index 7fc46c6..aa7845f 100644
--- a/lib/nano.js
+++ b/lib/nano.js
@@ -147,15 +147,6 @@ module.exports = exports = function dbScope (cfg) {
       statusCode
     }, response.headers)
     if (!response.status) {
-      // if (axios.isCancel(response)) {
-      //   if (resolve) {
-      //     resolve('canceled')
-      //   }
-      //   if (callback) {
-      //     callback(null, 'canceled', responseHeaders)
-      //   }
-      //   return
-      // }
       response.statusText = response.cause.toString()
       log({ err: 'socket', body, headers: responseHeaders })
       if (reject) {
@@ -173,12 +164,6 @@ module.exports = exports = function dbScope (cfg) {
     delete responseHeaders.server
     delete responseHeaders['content-length']
 
-    /* if (opts.dontParse) {
-      parsed = body
-    } else {
-      try { parsed = JSON.parse(body) } catch (err) { parsed = body }
-    } */
-
     if (statusCode >= 200 && statusCode < 400) {
       log({ err: null, body, headers: responseHeaders })
       const ct = response.headers.get('content-type')
@@ -253,13 +238,8 @@ module.exports = exports = function dbScope (cfg) {
 
   const streamResponseHandler = function (response, req, stream) {
     const statusCode = response.status || (response.response && response.response.status) || 500
-    if (response.isAxiosError && response.response) {
-      response = response.response
-    }
     const message = response.statusText
-
     scrubRequest(req)
-
     const responseHeaders = Object.assign({
       uri: req.url,
       statusCode
@@ -287,120 +267,111 @@ module.exports = exports = function dbScope (cfg) {
       callback = opts
       opts = { path: '' }
     }
-
     if (typeof opts === 'string') {
       opts = { path: opts }
     }
-
     if (!opts) {
       opts = { path: '' }
       callback = null
     }
 
-    const qs = Object.assign({}, opts.qs)
+    // the building blocks of the request
+    let body, uri
 
+    // construct headers object to be passed in the request
     const headers = {
       // 'content-type': 'application/json',
       accept: 'application/json',
       'user-agent': `${pkg.name}/${pkg.version} (Node.js ${process.version})`,
       'Accept-Encoding': 'deflate, gzip'
     }
-
-    const req = Object.assign({
-      method: (opts.method || 'GET'),
-      headers,
-      uri: cfg.plainURL
-    }, {
-      headers: Object.assign(headers, cfg.headers ? cfg.headers : {})
-    })
+    Object.assign(headers, cfg.headers ? cfg.headers : {})
     if (!headers['content-type']) {
       headers['content-type'] = 'application/json'
     }
 
-    // https://github.com/mikeal/request#requestjar
-    // const isJar = opts.jar || cfg.jar || (cfg.requestDefaults && cfg.requestDefaults.jar)
+    // prevent bugs where people set encoding when piping
+    if (opts.encoding !== undefined) {
+      // req.encoding = opts.encoding
+      delete headers['content-type']
+      delete headers.accept
+    }
 
-    if (opts.signal) {
-      req.signal = opts.signal
+    if (opts.contentType) {
+      headers['content-type'] = opts.contentType
+      delete headers.accept
     }
 
-    // if (isJar) {
-    //   req.jar = cookieJar
-    //   req.withCredentials = true
-    // }
+    if (opts.accept) {
+      headers.accept = opts.accept
+    }
 
-    // http://wiki.apache.org/couchdb/HTTP_database_API#Naming_and_Addressing
-    if (opts.db) {
-      req.uri = urlResolveFix(req.uri, encodeURIComponent(opts.db))
+    // http://guide.couchdb.org/draft/security.html#cookies
+    if (cfg.cookie) {
+      headers['X-CouchDB-WWW-Authenticate'] = 'Cookie'
+      headers.cookie = cfg.cookie
     }
 
+    // form submission
+    if (opts.form) {
+      headers['content-type'] =
+        'application/x-www-form-urlencoded; charset=utf-8'
+      body = new URLSearchParams(opts.form)
+    }
+
+    // multipart requests
     if (opts.multipart) {
       // generate the multipart/related body, header and boundary to
       // upload multiple binary attachments in one request
       const mp = new MultiPartFactory(opts.multipart)
-      opts.contentType = mp.header
-      req.body = mp.data
+      headers['content-type'] = mp.header
+      body = mp.data
     }
 
-    req.headers = Object.assign(req.headers, opts.headers, cfg.defaultHeaders)
+    // construct the URL
+    const method = opts.method ? opts.method.toLowerCase() : 'get'
+    uri = cfg.plainURL
+    if (opts.db) {
+      uri = urlResolveFix(uri, encodeURIComponent(opts.db))
+    }
 
+    // http://wiki.apache.org/couchdb/HTTP_database_API#Naming_and_Addressing
     if (opts.path) {
-      if (!req.uri.endsWith('/')) {
-        req.uri += '/'
+      if (!uri.endsWith('/')) {
+        uri += '/'
       }
-      req.uri += opts.path
+      uri += opts.path
     } else if (opts.doc) {
       if (!/^_design|_local/.test(opts.doc)) {
         // http://wiki.apache.org/couchdb/HTTP_Document_API#Naming.2FAddressing
-        req.uri += '/' + encodeURIComponent(opts.doc)
+        uri += '/' + encodeURIComponent(opts.doc)
       } else {
         // http://wiki.apache.org/couchdb/HTTP_Document_API#Document_IDs
-        req.uri += '/' + opts.doc
+        uri += '/' + opts.doc
       }
 
       // http://wiki.apache.org/couchdb/HTTP_Document_API#Attachments
       if (opts.att) {
-        req.uri += '/' + opts.att
+        uri += '/' + opts.att
       }
     }
 
-    // prevent bugs where people set encoding when piping
-    if (opts.encoding !== undefined) {
-      req.encoding = opts.encoding
-      delete req.headers['content-type']
-      delete req.headers.accept
-    }
-
-    if (opts.contentType) {
-      req.headers['content-type'] = opts.contentType
-      delete req.headers.accept
-    }
-
-    if (opts.accept) {
-      req.headers.accept = opts.accept
-    }
-
-    // http://guide.couchdb.org/draft/security.html#cookies
-    if (cfg.cookie) {
-      req.headers['X-CouchDB-WWW-Authenticate'] = 'Cookie'
-      req.headers.cookie = cfg.cookie
-    }
-
     // http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
-    if (typeof opts.qs === 'object' && !isEmpty(opts.qs)) {
+    const qs = Object.assign({}, opts.qs)
+    if (typeof qs === 'object' && !isEmpty(qs)) {
       ['startkey', 'endkey', 'key', 'keys', 'start_key', 'end_key'].forEach(function (key) {
-        if (key in opts.qs) {
-          qs[key] = JSON.stringify(opts.qs[key])
+        if (key in qs) {
+          qs[key] = JSON.stringify(qs[key])
         }
       })
-      req.qs = qs
     }
 
+    // HTTP request body
     if (opts.body) {
       if (Buffer.isBuffer(opts.body) || opts.dontStringify) {
-        req.body = opts.body
+        body = opts.body
       } else {
-        req.body = JSON.stringify(opts.body, function (key, value) {
+        body = JSON.stringify(opts.body, function (key, value) {
           // don't encode functions
           if (typeof (value) === 'function') {
             return value.toString()
@@ -411,61 +382,28 @@ module.exports = exports = function dbScope (cfg) {
       }
     }
 
-    if (opts.form) {
-      req.headers['content-type'] =
-        'application/x-www-form-urlencoded; charset=utf-8'
-      req.body = new URLSearchParams(opts.form)
-    }
-
-    // ask request to render query string arrays as repeated values e.g.
-    // ?drilldown=["author","Dickens"]&drilldown=["publisher","Penguin"]
-    req.qsStringifyOptions = { arrayFormat: 'repeat' }
-
-    // cfg.cookies = cookieJar.getCookiesSync(cfg.url)
-
-    // 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
-    req.serializedParams = new URLSearchParams(req.params)
-    req.data = req.body
-    delete req.body
-    req.maxRedirects = 0
-    if (opts.stream) {
-      req.responseType = 'stream'
-    } else if (opts.dontParse) {
-      req.responseType = 'arraybuffer'
-    }
-
     // scrub and log
     const scrubbedReq = {
-      method: req.method,
-      headers: JSON.parse(JSON.stringify(req.headers)),
-      url: req.url
+      method,
+      headers: JSON.parse(JSON.stringify(headers)),
+      url: uri
     }
     scrubRequest(scrubbedReq, true)
     log(scrubbedReq)
 
-    // add http agents
-    // req.httpAgent = cfg.requestDefaults.agent || defaultHttpAgent
-    // req.httpsAgent = cfg.requestDefaults.agent || defaultHttpsAgent
-    // req.httpAgent.jar = req.httpAgent.jar ? req.httpAgent.jar : cookieJar
-    // req.httpsAgent.jar = req.httpsAgent.jar ? req.httpsAgent.jar : cookieJar
-
     // insert basic auth headers, if present
-    Object.assign(req.headers, cfg.headers)
+    Object.assign(headers, cfg.headers)
 
+    // build the options we send to undici.fetch
     const fetchOptions = {
-      method: req.method,
-      headers: req.headers,
+      url: uri,
+      method,
+      headers,
       credentials: 'include',
-      body: req.method !== 'get' && req.data ? req.data : undefined,
+      body: method !== 'get' && body ? body : undefined,
       redirect: 'error',
       keepalive: true,
-      signal: req.signal
+      signal: opts.signal
     }
 
     // add custom agent if present
@@ -474,9 +412,10 @@ module.exports = exports = function dbScope (cfg) {
     }
 
     // add querystring params
-    const queryString = req.serializedParams.toString()
+    const searchParams = new URLSearchParams(qs)
+    const queryString = searchParams.toString()
     if (queryString.length > 0) {
-      req.url += '?' + queryString
+      fetchOptions.url += '?' + queryString
     }
 
     // if the body is readable stream
@@ -486,7 +425,7 @@ module.exports = exports = function dbScope (cfg) {
     }
 
     // add any cookies for this domain
-    const cookie = cookieJar.getCookieStringSync(req.url)
+    const cookie = cookieJar.getCookieStringSync(uri)
     if (cookie) {
       fetchOptions.headers.cookie = cookie
     }
@@ -495,32 +434,31 @@ module.exports = exports = function dbScope (cfg) {
     if (opts.stream) {
       // return the Request object for streaming
       const outStream = new stream.PassThrough()
-      fetch(req.url, fetchOptions)
-        .then(async (response) => {
-          const readableWebStream = response.body
-          const readableNodeStream = Readable.fromWeb(readableWebStream)
-          if (response.status > 300) {
-            streamResponseHandler(response, req, outStream)
-          } else {
-            readableNodeStream.pipe(outStream)
-          }
-        }).catch(e => {
-          streamResponseHandler(e, req, outStream)
-        })
+      undici.fetch(fetchOptions.url, fetchOptions).then((response) => {
+        const readableWebStream = response.body
+        const readableNodeStream = Readable.fromWeb(readableWebStream)
+        if (response.status > 300) {
+          streamResponseHandler(response, fetchOptions, outStream)
+        } else {
+          readableNodeStream.pipe(outStream)
+        }
+      }).catch((e) => {
+        streamResponseHandler(e, fetchOptions, outStream)
+      })
       return outStream
     } else {
       if (typeof callback === 'function') {
-        fetch(req.url, fetchOptions).then((response) => {
-          responseHandler(response, req, opts, null, null, callback)
+        undici.fetch(fetchOptions.url, fetchOptions).then((response) => {
+          responseHandler(response, fetchOptions, opts, null, null, callback)
         }).catch((e) => {
-          responseHandler(e, req, opts, null, null, callback)
+          responseHandler(e, fetchOptions, opts, null, null, callback)
         })
       } else {
         return new Promise((resolve, reject) => {
-          fetch(req.url, fetchOptions).then((response) => {
-            responseHandler(response, req, opts, resolve, reject)
+          undici.fetch(fetchOptions.url, fetchOptions).then((response) => {
+            responseHandler(response, fetchOptions, opts, resolve, reject)
           }).catch((e) => {
-            responseHandler(e, req, opts, resolve, reject)
+            responseHandler(e, fetchOptions, opts, resolve, reject)
           })
         })
       }
diff --git a/test/nano.auth.test.js b/test/nano.auth.test.js
index 8a24acb..28971b1 100644
--- a/test/nano.auth.test.js
+++ b/test/nano.auth.test.js
@@ -110,4 +110,3 @@ test('should be able to handle cookie refresh - POST /_session - nano.auth', asy
   assert.deepEqual(p3, ['a'])
   mockAgent.assertNoPendingInterceptors()
 })
-