Requête HTTP GET dans Node.js Express

192

Comment puis-je faire une requête HTTP depuis Node.js ou Express.js? J'ai besoin de me connecter à un autre service. J'espère que l'appel est asynchrone et que le rappel contient la réponse du serveur distant.

Parcs Travis
la source

Réponses:

220

Voici un extrait de code d'un échantillon du mien. Il est asynchrone et renvoie un objet JSON. Il peut faire n'importe quelle forme de demande GET.

Notez qu'il existe des moyens plus optimaux (juste un échantillon) - par exemple, au lieu de concaténer les morceaux que vous avez mis dans un tableau et de le joindre, etc.

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

Il est appelé en créant un objet d'options comme:

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

Et en fournissant une fonction de rappel.

Par exemple, dans un service, j'ai besoin du module REST ci-dessus, puis procédez comme suit:

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

METTRE À JOUR

Si vous recherchez async/ await(linéaire, pas de rappel), des promesses, la prise en charge du temps de compilation et intellisense, nous avons créé un client HTTP et REST léger qui correspond à cette facture:

Client de repos typé Microsoft

bryanmac
la source
@bryanmac pouvez-vous s'il vous plaît envoyer / ajouter l'échantillon complet?
StErMi
@bryanmac avec votre permission Je voudrais utiliser ce plugin de code grunt que je suis en train de construire. Je ne sais pas quand, mais il serait rendu open source une fois terminé.
JeffH
3
essayez le module de demande .. c'est beaucoup plus simple sitepoint.com/making-http-requests-in-node-js
saurshaz
6
oui - le module de requête est simple mais il s'agit d'un niveau inférieur indiquant ce que font les bibliothèques comme le module de requête. Si vous avez besoin d'un contrôle de niveau inférieur ou de requêtes http (montrant la progression des gros téléchargements, etc.), cela montre comment cela se fait.
bryanmac
1
@KrIsHnA - le nœud a un objet de chaîne de requête: nodejs.org/api/querystring.html et un objet url nodejs.org/docs/latest/api/url.html
bryanmac
100

Essayez d'utiliser la http.get(options, callback)fonction simple dans 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);
});

Il existe également une http.request(options, callback)fonction générale qui vous permet de spécifier la méthode de demande et d'autres détails de la demande.

maerics
la source
Où est le contenu de la réponse du serveur demandée par le PO?
Dan Dascalescu
Merci pour la mise à jour. On dirait qu'il y a un besoin d'un gestionnaire de «fin» pour concaténer les morceaux alors. Ce qui équivaut essentiellement à la réponse de @ bryanmac?
Dan Dascalescu
@DanDascalescu: oui, si vous voulez traiter le corps dans son ensemble (ce qui est probable), vous voudrez probablement le mettre en mémoire tampon et le traiter en «fin». Je mettrai également à jour ma réponse par souci d'exhaustivité.
maerics
désolé, je ne peux pas comprendre avec quels paramètres le rappel est appelé ... comment puis-je obtenir le corps et où se trouve la référence pour les paramètres et les propriétés de ces paramètres.
Muhammad Umer
@maerics Comment puis-je utiliser cette GETrequête si j'ai cette URL? graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token}?
frank17
70

Request et Superagent sont de très bonnes bibliothèques à utiliser.

note: la demande est obsolète , utilisez à vos risques et périls!

Utilisation 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
la source
7
Doit-il être res.statusCode === 200 en seconde si? )
Gleb Dolzikov
1
quelle est la variable d'options? juste passer un indéfini?
j'en
32

Vous pouvez également utiliser Requestify , un client HTTP vraiment cool et très simple que j'ai écrit pour nodeJS +, il prend en charge la mise en cache.

Procédez simplement comme suit pour la demande de méthode 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();
  }
);
ranm8
la source
1
«Essayez cet autre outil» n'est pas une réponse acceptable si le jeu d'outils existant est suffisant.
Grunion Shaftoe
9

Cette version est basée sur la fonction initialement proposée par bryanmac qui utilise des promesses, une meilleure gestion des erreurs, et est réécrite dans 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();
    });
};

En conséquence, vous n'avez pas à passer une fonction de rappel, mais getJSON () renvoie une promesse. Dans l'exemple suivant, la fonction est utilisée à l'intérieur d'un gestionnaire d'itinéraire 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);
    });
});

En cas d'erreur, il délègue l'erreur au middleware de gestion des erreurs du serveur.

maqduni
la source
1
Oui, cet exemple montre comment le faire dans une getdéfinition d'itinéraire Express , ce qui manque à de nombreux articles ici.
Micros
7

Unirest est la meilleure bibliothèque que j'ai rencontrée pour faire des requêtes HTTP à partir de Node. Il vise à être un framework multiplateforme, donc apprendre comment cela fonctionne sur Node vous sera utile si vous devez également utiliser un client HTTP sur Ruby, PHP, Java, Python, Objective C, .Net ou Windows 8. Pour autant que je sache, les bibliothèques unirest sont principalement soutenues par des clients HTTP existants (par exemple sur Java, le client HTTP Apache, sur Node, la bibliothèque Request de Mikeal ) - Unirest met simplement une API plus agréable au sommet.

Voici quelques exemples de code pour 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)
    }
  })

Vous pouvez accéder directement à la documentation Node ici

Brian Beckett
la source
3

Découvrez shred . C'est un client HTTP de nœud créé et maintenu par spire.io qui gère les redirections, les sessions et les réponses JSON. C'est idéal pour interagir avec les API de repos. Consultez cet article de blog pour plus de détails.

Jonathan McIntire
la source
3

Consultez httpreq : c'est une bibliothèque de nœuds que j'ai créée parce que j'étais frustré qu'il n'y ait pas de module http GET ou POST simple ;-)

Sam
la source
0

Si vous avez juste besoin de faire des requêtes get simples et que vous n'avez pas besoin de support pour d'autres méthodes HTTP, jetez un œil à: 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
});
benjiman
la source
0

Utilisez reqclient : non conçu à des fins de script comme requestou de nombreuses autres bibliothèques. Reqclient permet dans le constructeur de spécifier de nombreuses configurations utiles lorsque vous devez réutiliser la même configuration encore et encore: URL de base, en-têtes, options d'authentification, options de journalisation, mise en cache, etc. Analyse JSON, etc.

La meilleure façon d'utiliser la bibliothèque est de créer un module pour exporter l'objet pointant vers l'API et les configurations nécessaires pour se connecter:

Module 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

Et dans les contrôleurs où vous devez consommer l'API, utilisez comme ceci:

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

reqclientprend en charge de nombreuses fonctionnalités, mais certaines d'entre elles ne sont pas prises en charge par d'autres bibliothèques: intégration OAuth2 et intégration de l'enregistreur avec la syntaxe cURL , et renvoie toujours des objets Promise natifs.

Mariano Ruiz
la source
0

Si jamais vous avez besoin d'envoyer une GETdemande à un IPainsi qu'à un Domain(d'autres réponses n'ont pas mentionné que vous pouvez spécifier une portvariable), vous pouvez utiliser cette fonction:

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

Ne manquez pas d'exiger des modules en haut de votre fichier:

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

N'oubliez pas que vous pouvez utiliser le httpsmodule pour communiquer sur un réseau sécurisé. donc ces deux lignes changeraient:

https = require("https");
...
https.get(url.format(requestUrl), (resp) => { ......
AmiNadimi
la source
-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
la source
(En l'occurrence, cela ne résoudra pas le problème. Ce code écoutera une requête mais la question est de savoir comment envoyer une requête )
Quentin
1
il est corrigé, vous pouvez l'essayer. @Quentin
izhar ahmad