आप Node.js में एक HTTP पुनर्निर्देशन का पालन कैसे करते हैं?


86

मैं नोड में एक पेज खोलना चाहता हूं और अपने आवेदन में सामग्री को संसाधित करना चाहता हूं। कुछ इस तरह से काम करने लगता है:

var opts = {host: host, path:pathname, port: 80};
http.get(opts, function(res) {
  var page = '';
  res.on('data', function (chunk) {
    page += chunk;
  });
  res.on('end', function() {
     // process page
  });

हालाँकि, यह काम नहीं करता है, यदि पृष्ठ 301/302 पुनर्निर्देशित करता है। मैं एक पुन: प्रयोज्य तरीके से कैसे करूँगा कि मामले में कई पुनर्निर्देश हैं? क्या नोड अनुप्रयोग से http प्रतिक्रियाओं को संसाधित करने के लिए http के शीर्ष पर एक रैपर मॉड्यूल है?

जवाबों:


46

क्या नोड अनुप्रयोग से http प्रतिक्रियाओं को संसाधित करने के लिए http के शीर्ष पर एक रैपर मॉड्यूल है?

request

अनुरोध में पुनर्निर्देशन तर्क


20
क्यों जीवित b'jesus अंतर्निहित http मॉड्यूल का यह हिस्सा नहीं है ?!
अयादन

1
यह है। यह http.requestएपीआई बहुत आसान है कहा जाता है।
रेयनोस

3
क्या प्रत्येक पुनर्निर्देशन के लिए किसी तरह कॉलबैक करना संभव है? मैं हर एक URL को स्टोर करना चाहता हूँ जो अनुरोध के माध्यम से जाता है। डॉक्स में नहीं मिल सका।
इग्नास

13
@ रेयानोस, अंतर्निहित httpमॉड्यूल का अनुरोध () विधि पुनर्निर्देश का पालन नहीं करता है, इसलिए यह अंतर्निहित httpमॉड्यूल का हिस्सा नहीं है ।
गिलाद मेयानी

4
requestपदावनत कर दिया गया है।
इवान रुबिन्सन

111

यदि आप सभी को पुनर्निर्देशित करना चाहते हैं, लेकिन फिर भी अंतर्निहित HTTP और HTTPS मॉड्यूल का उपयोग करना चाहते हैं, तो मेरा सुझाव है कि आप https://github.com/follow-redirects/follow-redirects का उपयोग करें

yarn add follow-redirects
npm install follow-redirects

आपको बस इतना करना चाहिए:

var http = require('http');

साथ में

var http = require('follow-redirects').http;

... और आपके सभी अनुरोध स्वचालित रूप से पुनर्निर्देशित होंगे।

टाइपस्क्रिप्ट के साथ आप प्रकार भी स्थापित कर सकते हैं

npm install @types/follow-redirects

और फिर उपयोग करें

import { http, https } from 'follow-redirects';

प्रकटीकरण: मैंने यह मॉड्यूल लिखा है।



1
यह स्वीकार किए गए उत्तर की तुलना में बेहतर है, requestजिसमें ऐसे सरल कार्य के लिए आपके मॉड्यूल में 20+ नई निर्भरताएं शामिल हैं। Npm मॉड्यूल को हल्का रखने के लिए धन्यवाद, ओलिवर! :)
संतन

काम नहीं करता है जब मैं इसे s3 पर सुरक्षित रूप से होस्ट किए गए ऑडियो के साथ उपयोग करता हूं।
thedreamsaver

टाइपस्क्रिप्ट का उपयोग करके इसे अपने npm इंस्टॉल में जोड़ें: npm इंस्टॉल @ प्रकार / फ़ॉलो-रीडायरेक्ट करें ताकि आप 'फॉलो-रीडायरेक्ट' से {https} आयात का उपयोग कर सकें; यह एक शानदार, सरल, ओह इतना कुशल मॉड्यूल है। मर्सी ओलिवियर!
लुई-एरिक सिमरड

26

अपडेट करें:

अब आप परम var request = require('request');का उपयोग करके सभी पुनर्निर्देशों का पालन कर सकते हैं followAllRedirects

request({
  followAllRedirects: true,
  url: url
}, function (error, response, body) {
  if (!error) {
    console.log(response);
  }
});

क्या यह पूरा कोड है? अपने वर है http, लेकिन फिर आप एक समारोह कहा जाता है का उपयोग करेंrequest
jcollum

7
आपको बस ('अनुरोध') की आवश्यकता नहीं हो सकती है, यह एक बाहरी मॉड्यूल है और इसे पहले डाउनलोड और इंस्टॉल करने की आवश्यकता है - npmjs.com/package/request ( npm इंस्टॉल अनुरोध)
gilad mayani

requestपदावनत किया गया है
रॉस मैकआर्थर

18

इसके आधार पर एक और अनुरोध करें response.headers.location:

      const request = function(url) {
        lib.get(url, (response) => {
          var body = [];
          if (response.statusCode == 302) {
            body = [];
            request(response.headers.location);
          } else {
            response.on("data", /*...*/);
            response.on("end", /*...*/);
          };
        } ).on("error", /*...*/);
      };
      request(url);

यह उत्तर है यदि आप http लिब में निर्मित का उपयोग करना चाहते हैं, तो अनुसरण करेंresponse.headers.location
Vidar

6

यहां वह फ़ंक्शन है जिसका उपयोग मैं उस url को लाने के लिए करता हूं, जिसे रीडायरेक्ट किया गया है:

const http = require('http');
const url = require('url');

function get({path, host}, callback) {
    http.get({
        path,
        host
    }, function(response) {
        if (response.headers.location) {    
            var loc = response.headers.location;
            if (loc.match(/^http/)) {
                loc = new Url(loc);
                host = loc.host;
                path = loc.path;
            } else {
                path = loc;
            }
            get({host, path}, callback);
        } else {
            callback(response);
        }
    });
}

यह http.get जैसा ही काम करता है, लेकिन पुनर्निर्देशित करता है।


2

PUT या POST Request के मामले में। यदि आप स्टेटसकोड 405 प्राप्त करते हैं या विधि अनुमति नहीं है। " अनुरोध " लाइब्रेरी के साथ इस कार्यान्वयन का प्रयास करें , और उल्लेखित गुण जोड़ें।
followAllRedirects: true,
followOriginalHttpMethod: true

       const options = {
           headers: {
               Authorization: TOKEN,
               'Content-Type': 'application/json',
               'Accept': 'application/json'
           },
           url: `https://${url}`,
           json: true,
           body: payload,
           followAllRedirects: true,
           followOriginalHttpMethod: true
       }

       console.log('DEBUG: API call', JSON.stringify(options));
       request(options, function (error, response, body) {
       if (!error) {
        console.log(response);
        }
     });
}

1

यहाँ JSON को सादे नोड के साथ डाउनलोड करने के लिए मेरा दृष्टिकोण है, किसी भी पैकेज की आवश्यकता नहीं है।

import https from "https";

function get(url, resolve, reject) {
  https.get(url, (res) => {
    if(res.statusCode === 301 || res.statusCode === 302) {
      return get(res.headers.location, resolve, reject)
    }

    let body = [];

    res.on("data", (chunk) => {
      body.push(chunk);
    });

    res.on("end", () => {
      try {
        // remove JSON.parse(...) for plain data
        resolve(JSON.parse(Buffer.concat(body).toString()));
      } catch (err) {
        reject(err);
      }
    });
  });
}

async function getData(url) {
  return new Promise((resolve, reject) => get(url, resolve, reject));
}

// call
getData("some-url-with-redirect").then((r) => console.log(r));


0

यदि आपके पास httpsसर्वर है, तो https://प्रोटोकॉल का उपयोग करने के लिए अपना यूआरएल बदलें ।

मैं इस एक के साथ इसी तरह के मुद्दे पर मिला। मेरे यूआरएल में http://प्रोटोकॉल है और मैं एक POSTअनुरोध करना चाहता हूं , लेकिन सर्वर इसे पुनर्निर्देशित करना चाहता है https। ऐसा क्या होता है, नोड हो जाता है HTTP व्यवहार व्यवहार पुनर्निर्देशित अनुरोध (अगला) में भेजता हैGET विधि जो कि मामला नहीं है।

मैंने जो किया वह अपने यूआरएल को https://प्रोटोकॉल में बदलने के लिए है और यह काम करता है।


यह पुनर्निर्देशन का एक बहुत ही विशिष्ट उदाहरण है, और छोटे लिंक या बिट.ली लिंक के लिए कुछ भी नहीं करेगा।
डेन डस्केलस्क्यू

-1

संभवतः यहाँ एक नेक्रोमैंटिंग पोस्ट का थोड़ा सा हिस्सा है, लेकिन ...

यहां एक फ़ंक्शन है जो 10 रीडायरेक्ट तक चलता है, और अनंत रीडायरेक्ट लूप का पता लगाता है। यह भी JSON में परिणाम देता है

नोट - एक कॉलबैक सहायक का उपयोग करता है (इस पोस्ट के अंत में दिखाया गया है)

(TLDR; पूर्ण संदर्भ में काम कर रहे डेमो यहाँ या रीमिक्स-संस्करण यहाँ )

function getJSON(url,cb){

    var callback=errBack(cb);
    //var callback=errBack(cb,undefined,false);//replace previous line with this to turn off logging

    if (typeof url!=='string') {
        return callback.error("getJSON:expecting url as string");
    }

    if (typeof cb!=='function') {
        return callback.error("getJSON:expecting cb as function");
    }

    var redirs = [url],
    fetch = function(u){
        callback.info("hitting:"+u);
        https.get(u, function(res){
            var body = [];
            callback.info({statusCode:res.statusCode});
            if ([301,302].indexOf(res.statusCode)>=0) {
                if (redirs.length>10) {
                    return callback.error("excessive 301/302 redirects detected");
                } else {
                    if (redirs.indexOf(res.headers.location)<0) {
                        redirs.push(res.headers.location);
                        return fetch(res.headers.location);
                    } else {
                        return callback.error("301/302 redirect loop detected");
                    }
                }
            } else {
              res.on('data', function(chunk){
                  body.push(chunk);
                  callback.info({onData:{chunkSize:chunk.length,chunks:body.length}});
              });
              res.on('end', function(){
                  try {
                      // convert to a single buffer
                      var json = Buffer.concat(body);
                      console.info({onEnd:{chunks:body.length,bodyLength:body.length}});

                      // parse the buffer as json
                      return callback.result(JSON.parse(json),json);
                  } catch (err) {

                      console.error("exception in getJSON.fetch:",err.message||err);

                      if (json.length>32) {
                        console.error("json==>|"+json.toString('utf-8').substr(0,32)+"|<=== ... (+"+(json.length-32)+" more bytes of json)");
                      } else {
                          console.error("json==>|"+json.toString('utf-8')+"|<=== json");
                      }

                      return callback.error(err,undefined,json);
                  }
              });
            }
        });
    };
    fetch(url);   
}

नोट - कॉलबैक सहायक का उपयोग करता है (नीचे दिखाया गया है)

आप इसे नोड कंसोल में पेस्ट कर सकते हैं और इसे वैसे ही चलाना चाहिए।

(या संदर्भ में पूर्ण कामकाजी डेमो के लिए यहां देखें )

var 

fs      = require('fs'),
https   = require('https');

function errBack (cb,THIS,logger) {

   var 
   self,
   EB=function(fn,r,e){
       if (logger===false) {
           fn.log=fn.info=fn.warn=fn.errlog=function(){};       
       } else {
           fn.log        = logger?logger.log   : console.log.bind(console);
           fn.info       = logger?logger.info  : console.info.bind(console);
           fn.warn       = logger?logger.warn  : console.warn.bind(console);
           fn.errlog     = logger?logger.error : console.error.bind(console);
       }
       fn.result=r;
       fn.error=e;
       return (self=fn);
   };


   if (typeof cb==='function') {
       return EB(

            logger===false // optimization when not logging - don't log errors
            ?   function(err){
                   if (err) {
                      cb (err);
                     return true;
                   }
                   return false;
               }

            :  function(err){
                   if (err) {
                      self.errlog(err);
                      cb (err);
                     return true;
                   }
                   return false;
               },

           function () {
               return cb.apply (THIS,Array.prototype.concat.apply([undefined],arguments));
           },
           function (err) {
               return cb.apply (THIS,Array.prototype.concat.apply([typeof err==='string'?new Error(err):err],arguments));
           }
       );
   } else {

       return EB(

           function(err){
               if (err) {
                   if (typeof err ==='object' && err instanceof Error) {
                       throw err;
                   } else {
                       throw new Error(err);
                   }
                   return true;//redundant due to throw, but anyway.
               }
               return false;
           },

           logger===false
              ? self.log //optimization :resolves to noop when logger==false
              : function () {
                   self.info("ignoring returned arguments:",Array.prototype.concat.apply([],arguments));
           },

           function (err) {
               throw typeof err==='string'?new Error(err):err;
           }
       );
   }
}

function getJSON(url,cb){

    var callback=errBack(cb);

    if (typeof url!=='string') {
        return callback.error("getJSON:expecting url as string");
    }

    if (typeof cb!=='function') {
        return callback.error("getJSON:expecting cb as function");
    }

    var redirs = [url],
    fetch = function(u){
        callback.info("hitting:"+u);
        https.get(u, function(res){
            var body = [];
            callback.info({statusCode:res.statusCode});
            if ([301,302].indexOf(res.statusCode)>=0) {
                if (redirs.length>10) {
                    return callback.error("excessive 302 redirects detected");
                } else {
                    if (redirs.indexOf(res.headers.location)<0) {
                        redirs.push(res.headers.location);
                        return fetch(res.headers.location);
                    } else {
                        return callback.error("302 redirect loop detected");
                    }
                }
            } else {
              res.on('data', function(chunk){
                  body.push(chunk);
                  console.info({onData:{chunkSize:chunk.length,chunks:body.length}});
              });
              res.on('end', function(){
                  try {
                      // convert to a single buffer
                      var json = Buffer.concat(body);
                      callback.info({onEnd:{chunks:body.length,bodyLength:body.length}});

                      // parse the buffer as json
                      return callback.result(JSON.parse(json),json);
                  } catch (err) {
                      // read with "bypass refetch" option
                      console.error("exception in getJSON.fetch:",err.message||err);

                      if (json.length>32) {
                        console.error("json==>|"+json.toString('utf-8').substr(0,32)+"|<=== ... (+"+(json.length-32)+" more bytes of json)");
                      } else {
                          console.error("json==>|"+json.toString('utf-8')+"|<=== json");
                      }

                      return callback.error(err,undefined,json);
                  }
              });
            }
        });
    };
    fetch(url);   
}

var TLDs,TLDs_fallback = "com.org.tech.net.biz.info.code.ac.ad.ae.af.ag.ai.al.am.ao.aq.ar.as.at.au.aw.ax.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cw.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gb.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.rs.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.st.su.sv.sx.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tr.tt.tv.tw.tz.ua.ug.uk.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.za.zm.zw".split(".");
var TLD_url = "https://gitcdn.xyz/repo/umpirsky/tld-list/master/data/en/tld.json";
var TLD_cache = "./tld.json";
var TLD_refresh_msec = 15 * 24 * 60 * 60 * 1000;
var TLD_last_msec;
var TLD_default_filter=function(dom){return dom.substr(0,3)!="xn-"};


function getTLDs(cb,filter_func){

    if (typeof cb!=='function') return TLDs;

    var 
    read,fetch,
    CB_WRAP=function(tlds){
        return cb(
            filter_func===false
            ? cb(tlds)
            : tlds.filter(
                typeof filter_func==='function'
                 ? filter_func
                 : TLD_default_filter)
            );
    },
    check_mtime = function(mtime) {
       if (Date.now()-mtime > TLD_refresh_msec) {
           return fetch();
       } 
       if (TLDs) return CB_WRAP (TLDs);
       return read();
    };

    fetch = function(){

        getJSON(TLD_url,function(err,data){
            if (err) {
                console.log("exception in getTLDs.fetch:",err.message||err);
                return read(true);      
            } else {
                TLDs=Object.keys(data);

                fs.writeFile(TLD_cache,JSON.stringify(TLDs),function(err){
                    if (err) {
                        // ignore save error, we have the data
                        CB_WRAP(TLDs);
                    } else {
                        // get mmtime for the file we just made
                        fs.stat(TLD_cache,function(err,stats){
                            if (!err && stats) {
                               TLD_last_msec = stats.mtimeMs; 
                            }
                            CB_WRAP(TLDs);    
                        });
                    }
                });
            }
        });
    };

    read=function(bypassFetch) {
        fs.readFile(TLD_cache,'utf-8',function(err,json){

            try {
                if (err) {

                    if (bypassFetch) {
                        // after a http errror, we fallback to hardcoded basic list of tlds
                        // if the disk file is not readable
                        console.log("exception in getTLDs.read.bypassFetch:",err.messsage||err);    

                        throw err;
                    }
                    // if the disk read failed, get the data from the CDN server instead
                    return fetch();
                }

                TLDs=JSON.parse(json);
                if (bypassFetch) {
                    // we need to update stats here as fetch called us directly
                    // instead of being called by check_mtime
                    return fs.stat(TLD_cache,function(err,stats){
                        if (err) return fetch();
                        TLD_last_msec =stats.mtimeMs;
                        return CB_WRAP(TLDs);
                    });
                }

            } catch (e){
                // after JSON error, if we aren't in an http fail situation, refetch from cdn server
                if (!bypassFetch) {
                    return fetch();
                }

                // after a http,disk,or json parse error, we fallback to hardcoded basic list of tlds

                console.log("exception in getTLDs.read:",err.messsage||err);    
                TLDs=TLDs_fallback;
            }

            return CB_WRAP(TLDs);
        });
    };

    if (TLD_last_msec) {
        return check_mtime(TLD_last_msec);
    } else {
        fs.stat(TLD_cache,function(err,stats){
            if (err) return fetch();
            TLD_last_msec =stats.mtimeMs;
            return check_mtime(TLD_last_msec);
        });
    }
}

getTLDs(console.log.bind(console));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.