tomas / needle

Nimble, streamable HTTP client for Node.js. With proxy, iconv, cookie, deflate & multipart support.

Home Page:https://www.npmjs.com/package/needle

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Proposal: Supporting User-Defined "Follow If" Conditions

jonathansampson opened this issue · comments

I needed a bit more control over the follow-if logic today, so I created a small patch to enable the declaration of numerous user-defined conditions:

const options = {
    follow_max: 5,
    follow_if_all: [
        // Only follow if the new endpoint is HTTP or HTTPS
        ( redirect, original ) => /^https?:/.test( redirect )
    ]
};

I'm okay with a redirect from HTTP to HTTPS, or the other way around, but I encountered a URL today that aimed to redirect from HTTPS to MAILTO. This would throw from within http.request, causing all sorts of problems for me.

I'd love to hear everybody's thoughts about this proposal.

Here is the diff that solved my problem:

diff --git a/node_modules/needle/lib/needle.js b/node_modules/needle/lib/needle.js
index a8a1627..509bb37 100644
--- a/node_modules/needle/lib/needle.js
+++ b/node_modules/needle/lib/needle.js
@@ -105,7 +105,10 @@ var defaults = {
   follow_keep_method      : false,
   follow_if_same_host     : false,
   follow_if_same_protocol : false,
-  follow_if_same_location : false
+  follow_if_same_location : false,
+
+  // custom
+  follow_if_all: []
 }
 
 var aliased = {
@@ -258,7 +261,7 @@ Needle.prototype.setup = function(uri, options) {
 
   function check_value(expected, key) {
     var value = get_option(key),
-        type  = typeof value;
+        type  = Array.isArray( value ) ? 'array' : typeof value;
 
     if (type != 'undefined' && type != expected)
       throw new TypeError(type + ' received for ' + key + ', but expected a ' + expected);
@@ -290,6 +293,10 @@ Needle.prototype.setup = function(uri, options) {
     config[key] = check_value('number', key);
   })
 
+  keys_by_type(Array).forEach(function(key) {
+    config[key] = check_value('array', key);
+  })
+
   // populate http_opts with given TLS options
   tls_options.split(' ').forEach(function(key) {
     if (typeof options[key] != 'undefined') {
@@ -511,6 +518,10 @@ Needle.prototype.should_follow = function(location, config, original) {
   if (config.follow_if_same_protocol && !matches('protocol'))
     return false; // procotol does not match, so not following
 
+  if ( config.follow_if_all && !config.follow_if_all.every( o => o( location ) ) ) {
+    return false; // One of the user-provided conditions were not met
+  }
+
   return true;
 }
 

This issue body was partially generated by patch-package.