HTTP-GET-Anforderung in Node.js Express

191

Wie kann ich eine HTTP-Anfrage in Node.js oder Express.js stellen? Ich muss mich mit einem anderen Dienst verbinden. Ich hoffe, dass der Anruf asynchron ist und dass der Rückruf die Antwort des Remote-Servers enthält.

Travis Parks
quelle

Antworten:

219

Hier ist ein Ausschnitt eines Codes aus einem Beispiel von mir. Es ist asynchron und gibt ein JSON-Objekt zurück. Es kann jede Form von GET-Anfrage ausführen.

Beachten Sie, dass es optimalere Möglichkeiten gibt (nur ein Beispiel) - zum Beispiel, anstatt die Chunks, die Sie in ein Array eingefügt und verknüpft haben, zu verketten usw. Hoffentlich können Sie damit in die richtige Richtung starten:

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

/**
 * getJSON:  RESTful GET request returning JSON object(s)
 * @param options: http options object
 * @param callback: callback to pass the results JSON object(s) back
 */

module.exports.getJSON = (options, onResult) => {
  console.log('rest::getJSON');
  const port = options.port == 443 ? https : http;

  let output = '';

  const req = port.request(options, (res) => {
    console.log(`${options.host} : ${res.statusCode}`);
    res.setEncoding('utf8');

    res.on('data', (chunk) => {
      output += chunk;
    });

    res.on('end', () => {
      let obj = JSON.parse(output);

      onResult(res.statusCode, obj);
    });
  });

  req.on('error', (err) => {
    // res.send('error: ' + err.message);
  });

  req.end();
};

Es wird aufgerufen, indem ein Optionsobjekt wie folgt erstellt wird:

const options = {
  host: 'somesite.com',
  port: 443,
  path: '/some/path',
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  }
};

Und Bereitstellung einer Rückruffunktion.

Zum Beispiel benötige ich in einem Service das obige REST-Modul und mache dann Folgendes:

rest.getJSON(options, (statusCode, result) => {
  // I could work with the resulting HTML/JSON here. I could also just return it
  console.log(`onResult: (${statusCode})\n\n${JSON.stringify(result)}`);

  res.statusCode = statusCode;

  res.send(result);
});

AKTUALISIEREN

Wenn Sie nach async/ await(linear, kein Rückruf), Versprechungen, Unterstützung bei der Kompilierungszeit und Intellisense suchen, haben wir einen leichtgewichtigen HTTP- und REST-Client erstellt, der genau zu dieser Rechnung passt:

Microsoft tippte-Rest-Client

Bryanmac
quelle
@bryanmac können Sie bitte das komplette Muster senden / hinzufügen?
StErMi
@bryanmac mit Ihrer Erlaubnis Ich möchte dieses Code-Grunz-Plugin verwenden, das ich gerade baue. Ich bin mir nicht sicher, wann, aber es wird nach Fertigstellung als Open-Source-Lösung angeboten.
JeffH
3
versuchen Sie Anforderungsmodul .. es ist viel einfacher sitepoint.com/making-http-requests-in-node-js
saurshaz
6
Ja - das Anforderungsmodul ist einfach, aber dies ist eine niedrigere Ebene, die zeigt, was Bibliotheken wie das Anforderungsmodul tun. Wenn Sie eine Steuerung auf niedrigerer Ebene oder HTTP-Anforderungen benötigen (Anzeige des Fortschritts bei großen Downloads usw.), wird hier die Vorgehensweise angezeigt.
Bryanmac
1
@KrIsHnA - Knoten hat ein Querystring-Objekt: nodejs.org/api/querystring.html und URL-Objekt nodejs.org/docs/latest/api/url.html
Bryanmac
100

Versuchen Sie es mit der einfachen http.get(options, callback)Funktion in node.js:

var http = require('http');
var options = {
  host: 'www.google.com',
  path: '/index.html'
};

var req = http.get(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));

  // Buffer the body entirely for processing as a whole.
  var bodyChunks = [];
  res.on('data', function(chunk) {
    // You can process streamed parts here...
    bodyChunks.push(chunk);
  }).on('end', function() {
    var body = Buffer.concat(bodyChunks);
    console.log('BODY: ' + body);
    // ...and/or process the entire body here.
  })
});

req.on('error', function(e) {
  console.log('ERROR: ' + e.message);
});

Es gibt auch eine allgemeine http.request(options, callback)Funktion , mit der Sie die Anforderungsmethode und andere Anforderungsdetails angeben können.

Maerics
quelle
Wo ist der Inhalt der Antwort des Servers, nach der das OP gefragt hat?
Dan Dascalescu
Danke für das Update. Es sieht so aus, als ob ein 'End'-Handler erforderlich ist, um die Chunks zu verketten. Was entspricht im Grunde der Antwort von @ bryanmac?
Dan Dascalescu
@DanDascalescu: Ja, wenn Sie den Körper als Ganzes verarbeiten möchten (was wahrscheinlich ist), möchten Sie ihn wahrscheinlich puffern und am Ende verarbeiten. Der Vollständigkeit halber werde ich auch meine Antwort aktualisieren.
Maerics
Entschuldigung, ich kann nicht herausfinden, mit welchen Parametern Rückruf aufgerufen wird ... wie kann ich body bekommen und wo ist die Referenz für Parameter und Eigenschaften dieser Parameter.
Muhammad Umer
@maerics Wie kann ich diese GETAnfrage verwenden, wenn ich diese URL habe? graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token}?
Frank17
70

Request und Superagent sind ziemlich gute Bibliotheken.

Hinweis: Anfrage ist veraltet , Verwendung auf eigenes Risiko!

Verwenden von request:

var request=require('request');

request.get('https://someplace',options,function(err,res,body){
  if(err) //TODO: handle err
  if(res.statusCode === 200 ) //etc
  //TODO Do something with response
});
staackuser2
quelle
7
Sollte es res.statusCode === 200 in Sekunden sein, wenn? )
Gleb Dolzikov
1
Was ist die Optionsvariable? einfach undefiniert übergeben? Ich bezweifle es
lxknvlk
32

Sie können auch Requestify verwenden , einen wirklich coolen und sehr einfachen HTTP-Client, den ich für nodeJS + geschrieben habe und der das Caching unterstützt.

Führen Sie für die Anforderung der GET-Methode einfach Folgendes aus:

var requestify = require('requestify');

requestify.get('http://example.com/api/resource')
  .then(function(response) {
      // Get the response body (JSON parsed or jQuery object for XMLs)
      response.getBody();
  }
);
ranm8
quelle
1
"Dieses andere Tool ausprobieren" ist keine akzeptable Antwort, wenn das vorhandene Toolset ausreicht.
Grunion Shaftoe
9

Diese Version basiert auf der ursprünglich von bryanmac vorgeschlagenen Funktion, die Versprechen und eine bessere Fehlerbehandlung verwendet und in ES6 neu geschrieben wurde.

let http = require("http"),
    https = require("https");

/**
 * getJSON:  REST get request returning JSON object(s)
 * @param options: http options object
 */
exports.getJSON = function(options)
{
    console.log('rest::getJSON');
    let reqHandler = +options.port === 443 ? https : http;

    return new Promise((resolve, reject) => {
        let req = reqHandler.request(options, (res) =>
        {
            let output = '';
            console.log('rest::', options.host + ':' + res.statusCode);
            res.setEncoding('utf8');

            res.on('data', function (chunk) {
                output += chunk;
            });

            res.on('end', () => {
                try {
                    let obj = JSON.parse(output);
                    // console.log('rest::', obj);
                    resolve({
                        statusCode: res.statusCode,
                        data: obj
                    });
                }
                catch(err) {
                    console.error('rest::end', err);
                    reject(err);
                }
            });
        });

        req.on('error', (err) => {
            console.error('rest::request', err);
            reject(err);
        });

        req.end();
    });
};

Daher müssen Sie keine Rückruffunktion übergeben, sondern getJSON () gibt ein Versprechen zurück. Im folgenden Beispiel wird die Funktion in einem ExpressJS-Routenhandler verwendet

router.get('/:id', (req, res, next) => {
    rest.getJSON({
        host: host,
        path: `/posts/${req.params.id}`,
        method: 'GET'
    }).then(({status, data}) => {
        res.json(data);
    }, (error) => {
        next(error);
    });
});

Bei einem Fehler wird der Fehler an die Middleware zur Behandlung von Serverfehlern delegiert.

maqduni
quelle
1
Ja, dieses Beispiel zeigt, wie es in einer Express- getRoutendefinition gemacht wird, die vielen Posts hier fehlt.
Micros
7

Unirest ist die beste Bibliothek, auf die ich gestoßen bin, um HTTP-Anfragen von Node zu stellen. Es soll ein Multiplattform-Framework sein. Wenn Sie also einen HTTP-Client unter Ruby, PHP, Java, Python, Objective C, .Net oder Windows 8 verwenden müssen, ist es hilfreich, zu lernen, wie es auf Node funktioniert. Soweit ich das beurteilen kann, werden die unirest-Bibliotheken hauptsächlich von vorhandenen HTTP-Clients unterstützt (z. B. auf Java, dem Apache-HTTP-Client, auf Node, Mikeals Request-Bibliothek ) - Unirest setzt lediglich eine schönere API ein.

Hier sind einige Codebeispiele für Node.js:

var unirest = require('unirest')

// GET a resource
unirest.get('http://httpbin.org/get')
  .query({'foo': 'bar'})
  .query({'stack': 'overflow'})
  .end(function(res) {
    if (res.error) {
      console.log('GET error', res.error)
    } else {
      console.log('GET response', res.body)
    }
  })

// POST a form with an attached file
unirest.post('http://httpbin.org/post')
  .field('foo', 'bar')
  .field('stack', 'overflow')
  .attach('myfile', 'examples.js')
  .end(function(res) {
    if (res.error) {
      console.log('POST error', res.error)
    } else {
      console.log('POST response', res.body)
    }
  })

Sie können den Knoten docs gerade springen hier

Brian Beckett
quelle
3

Schauen Sie sich Shred an . Es handelt sich um einen von spire.io erstellten und verwalteten Knoten-HTTP-Client , der Weiterleitungen, Sitzungen und JSON-Antworten verarbeitet. Es ist großartig für die Interaktion mit Rest-APIs. Weitere Informationen finden Sie in diesem Blogbeitrag .

Jonathan McIntire
quelle
3

Check out httpreq : Es ist eine Knotenbibliothek, die ich erstellt habe, weil ich frustriert war, dass es kein einfaches http GET- oder POST-Modul gibt ;-)

Sam
quelle
0

Wenn Sie nur einfache Get-Anfragen stellen müssen und keine Unterstützung für andere HTTP-Methoden benötigen, schauen Sie sich Folgendes an: simple-get :

var get = require('simple-get');

get('http://example.com', function (err, res) {
  if (err) throw err;
  console.log(res.statusCode); // 200
  res.pipe(process.stdout); // `res` is a stream
});
Benjamin
quelle
0

Verwenden Sie reqclient : Nicht für Skriptzwecke wie requestoder viele andere Bibliotheken konzipiert. Mit Reqclient können im Konstruktor viele Konfigurationen angegeben werden, die nützlich sind, wenn Sie dieselbe Konfiguration immer wieder verwenden müssen: Basis-URL, Header, Authentifizierungsoptionen, Protokollierungsoptionen, Caching usw. Enthält nützliche Funktionen wie Abfrage- und URL-Analyse, automatische Abfragecodierung und JSON-Analyse usw.

Die Bibliothek kann am besten mit einem Modul erstellt werden, um das auf die API verweisende Objekt und die erforderlichen Konfigurationen für die Verbindung zu exportieren:

Modul client.js:

let RequestClient = require("reqclient").RequestClient

let client = new RequestClient({
  baseUrl: "https://myapp.com/api/v1",
  cache: true,
  auth: {user: "admin", pass: "secret"}
})

module.exports = client

Und in den Controllern, in denen Sie die API verwenden müssen, verwenden Sie Folgendes:

let client = require('client')
//let router = ...

router.get('/dashboard', (req, res) => {
  // Simple GET with Promise handling to https://myapp.com/api/v1/reports/clients
  client.get("reports/clients")
    .then(response => {
       console.log("Report for client", response.userId)  // REST responses are parsed as JSON objects
       res.render('clients/dashboard', {title: 'Customer Report', report: response})
    })
    .catch(err => {
      console.error("Ups!", err)
      res.status(400).render('error', {error: err})
    })
})

router.get('/orders', (req, res, next) => {
  // GET with query (https://myapp.com/api/v1/orders?state=open&limit=10)
  client.get({"uri": "orders", "query": {"state": "open", "limit": 10}})
    .then(orders => {
      res.render('clients/orders', {title: 'Customer Orders', orders: orders})
    })
    .catch(err => someErrorHandler(req, res, next))
})

router.delete('/orders', (req, res, next) => {
  // DELETE with params (https://myapp.com/api/v1/orders/1234/A987)
  client.delete({
    "uri": "orders/{client}/{id}",
    "params": {"client": "A987", "id": 1234}
  })
  .then(resp => res.status(204))
  .catch(err => someErrorHandler(req, res, next))
})

reqclientunterstützt viele Funktionen, hat jedoch einige, die von anderen Bibliotheken nicht unterstützt werden: OAuth2-Integration und Logger-Integration mit cURL-Syntax und gibt immer native Promise-Objekte zurück.

Mariano Ruiz
quelle
0

Wenn Sie jemals eine GETAnfrage an eine IPoder eine senden müssen Domain(andere Antworten haben nicht erwähnt, dass Sie eine portVariable angeben können), können Sie diese Funktion verwenden:

function getCode(host, port, path, queryString) {
    console.log("(" + host + ":" + port + path + ")" + "Running httpHelper.getCode()")

    // Construct url and query string
    const requestUrl = url.parse(url.format({
        protocol: 'http',
        hostname: host,
        pathname: path,
        port: port,
        query: queryString
    }));

    console.log("(" + host + path + ")" + "Sending GET request")
    // Send request
    console.log(url.format(requestUrl))
    http.get(url.format(requestUrl), (resp) => {
        let data = '';

        // A chunk of data has been received.
        resp.on('data', (chunk) => {
            console.log("GET chunk: " + chunk);
            data += chunk;
        });

        // The whole response has been received. Print out the result.
        resp.on('end', () => {
            console.log("GET end of response: " + data);
        });

    }).on("error", (err) => {
        console.log("GET Error: " + err);
    });
}

Verpassen Sie nicht, Module oben in Ihrer Datei zu benötigen:

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

Denken Sie auch daran, dass Sie das httpsModul für die Kommunikation über ein gesichertes Netzwerk verwenden können. Also würden sich diese beiden Zeilen ändern:

https = require("https");
...
https.get(url.format(requestUrl), (resp) => { ......
AmiNadimi
quelle
-1
## you can use request module and promise in express to make any request ##
const promise                       = require('promise');
const requestModule                 = require('request');

const curlRequest =(requestOption) =>{
    return new Promise((resolve, reject)=> {
        requestModule(requestOption, (error, response, body) => {
            try {
                if (error) {
                    throw error;
                }
                if (body) {

                    try {
                        body = (body) ? JSON.parse(body) : body;
                        resolve(body);
                    }catch(error){
                        resolve(body);
                    }

                } else {

                    throw new Error('something wrong');
                }
            } catch (error) {

                reject(error);
            }
        })
    })
};

const option = {
    url : uri,
    method : "GET",
    headers : {

    }
};


curlRequest(option).then((data)=>{
}).catch((err)=>{
})
Izhar Ahmad
quelle
(Wie es passiert, wird es das Problem nicht lösen. Dieser Code wartet auf eine Anfrage, aber die Frage fragt, wie eine Anfrage
Quentin
1
es ist behoben, Sie können es ausprobieren. @ Quentin
izhar ahmad