Richiesta GET HTTP in Node.js Express


192

Come posso effettuare una richiesta HTTP da Node.js o Express.js? Devo connettermi a un altro servizio. Spero che la chiamata sia asincrona e che il callback contenga la risposta del server remoto.

Risposte:


220

Ecco uno snippet di codice da un mio esempio. È asincrono e restituisce un oggetto JSON. Può fare qualsiasi forma di richiesta GET.

Si noti che ci sono modi più ottimali (solo un esempio) - ad esempio, invece di concatenare i blocchi che si inseriscono in un array e si uniscono ad esso, ecc. Speriamo che inizi nella giusta direzione:

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();
};

Viene chiamato creando un oggetto opzioni come:

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

E fornendo una funzione di richiamata.

Ad esempio, in un servizio, ho bisogno del modulo REST sopra e quindi faccio questo:

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);
});

AGGIORNARE

Se stai cercando async/ await(lineare, nessun callback), promesse, supporto per il tempo di compilazione e intellisense, abbiamo creato un client HTTP e REST leggero che si adatta a quel conto:

Client di riposo tipizzato Microsoft


@bryanmac puoi per favore inviare / aggiungere il campione completo?
StErMi,

@bryanmac con il tuo permesso Vorrei usare questo plugin di codice grugnito che sto costruendo. Non so quando ma sarebbe reso open source una volta completato.
JeffH,

3
prova il modulo di richiesta .. è molto più semplice sitepoint.com/making-http-requests-in-node-js
saurshaz

6
sì - il modulo di richiesta è semplice ma questo è un livello inferiore che mostra cosa stanno facendo le librerie come il modulo di richiesta. Se hai bisogno di controllo di livello inferiore o richieste http (che mostrano progressi su download di grandi dimensioni, ecc ...), questo mostra come è fatto.
bryanmac,

1
@KrIsHnA - il nodo ha un oggetto querystring: nodejs.org/api/querystring.html e l'oggetto url nodejs.org/docs/latest/api/url.html
bryanmac

100

Prova a utilizzare la semplice http.get(options, callback)funzione 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);
});

Esiste anche una http.request(options, callback)funzione generale che consente di specificare il metodo di richiesta e altri dettagli della richiesta.


Dov'è il contenuto della risposta del server richiesta dall'OP?
Dan Dascalescu,

Grazie per l'aggiornamento. Sembra quindi che sia necessario un gestore "end" per concatenare i blocchi. Che sostanzialmente equivale alla risposta di @ bryanmac?
Dan Dascalescu,

@DanDascalescu: ya, se si desidera elaborare il corpo nel suo insieme (il che è probabile), probabilmente si desidera bufferizzarlo ed elaborarlo su "end". Aggiornerò anche la mia risposta per completezza.
Maerics,

scusate, non riesco a capire con quali parametri viene richiamata la richiamata ... come posso ottenere body e dove è il riferimento per i parametri e le proprietà di quei parametri.
Muhammad Umer,

@maerics Come posso usare questa GETrichiesta se ho questo URL? graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token}?
frank17

70

Request e Superagent sono librerie abbastanza buone da usare.

nota: la richiesta è obsoleta , utilizzare a proprio rischio!

Utilizzando 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
});

7
Dovrebbe essere res.statusCode === 200 in secondo se? )
Gleb Dolzikov,

1
qual è la variabile opzioni? appena passato uno indefinito? ne dubito
lxknvlk,

32

Puoi anche usare Requestify , un client HTTP davvero interessante e molto semplice che ho scritto per nodeJS + che supporta la memorizzazione nella cache.

Effettuate le seguenti operazioni per la richiesta del metodo GET:

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();
  }
);

1
"Prova questo altro strumento" non è una risposta accettabile se il set di strumenti esistente è sufficiente.
Grunion Shaftoe,

9

Questa versione si basa sulla funzione inizialmente proposta dalla funzione bryanmac che utilizza promesse, migliore gestione degli errori e viene riscritta in ES6.

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();
    });
};

Di conseguenza non è necessario passare una funzione di callback, ma getJSON () restituisce una promessa. Nel seguente esempio la funzione viene utilizzata all'interno di un gestore di route ExpressJS

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);
    });
});

In caso di errore, delega l'errore al middleware di gestione degli errori del server.


1
Sì, questo esempio mostra come farlo all'interno di una getdefinizione di percorso Express , che manca a molti post qui.
Micros,

7

Unirest è la migliore libreria che abbia mai incontrato per fare richieste HTTP da Node. L'obiettivo è quello di essere un framework multipiattaforma, quindi imparare come funziona su Node ti servirà bene se devi usare un client HTTP su Ruby, PHP, Java, Python, Objective C, .Net o Windows 8. Per quanto ne so, le librerie unirest sono per lo più supportate da client HTTP esistenti (ad es. Su Java, il client HTTP Apache, su Node, richiesta libary di Mikeal ) - Unirest mette semplicemente in cima un'API più bella.

Ecco un paio di esempi di codice per 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)
    }
  })

Puoi passare direttamente ai documenti del nodo qui



3

Dai un'occhiata a httpreq : è una libreria di nodi che ho creato perché ero frustrato che non esistesse un semplice modulo GET o POST http ;-)


0

Se hai solo bisogno di rendere semplici richieste get e non hai bisogno di supporto per altri metodi HTTP, dai un'occhiata a: 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
});

0

Usa reqclient : non progettato per scopi di scripting come requesto molte altre librerie. Reqclient consente nel costruttore di specificare molte configurazioni utili quando è necessario riutilizzare più volte la stessa configurazione: URL di base, intestazioni, opzioni di autenticazione, opzioni di registrazione, memorizzazione nella cache, ecc. Dispone inoltre di utili funzioni come analisi di query e URL, codifica automatica delle query e Analisi JSON, ecc.

Il modo migliore per utilizzare la libreria è creare un modulo per esportare l'oggetto che punta all'API e le configurazioni necessarie per connettersi con:

Modulo 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

E nei controller in cui è necessario consumare l'API utilizzare in questo modo:

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))
})

reqclientsupporta molte funzionalità, ma ne ha alcune che non sono supportate da altre librerie: integrazione OAuth2 e integrazione logger con sintassi cURL e restituisce sempre oggetti Promise nativi.


0

Se hai bisogno di inviare GETrichiesta a un IPcosì come un Domain(Altre risposte non ha menzionato è possibile specificare una portvariabile), è possibile fare uso di questa funzione:

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);
    });
}

Non perdere i moduli richiesti nella parte superiore del tuo file:

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

Ricorda inoltre che puoi utilizzare il httpsmodulo per comunicare su una rete protetta. quindi queste due righe cambieranno:

https = require("https");
...
https.get(url.format(requestUrl), (resp) => { ......

-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)=>{
})

(In questo caso, non risolverà il problema. Questo codice ascolterà una richiesta ma la domanda è come inviare una richiesta )
Quentin

1
è stato risolto, puoi provarlo. @Quentin
izhar ahmad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.