Żądanie HTTP GET w Node.js Express

192

Jak mogę złożyć żądanie HTTP z Node.js lub Express.js? Muszę połączyć się z inną usługą. Mam nadzieję, że połączenie jest asynchroniczne i że wywołanie zwrotne zawiera odpowiedź zdalnego serwera.

Travis Parks
źródło

Odpowiedzi:

220

Oto fragment kodu z mojej próbki. Jest asynchroniczny i zwraca obiekt JSON. Może wykonać dowolną formę żądania GET.

Zauważ, że istnieją bardziej optymalne sposoby (tylko próbka) - na przykład, zamiast łączyć fragmenty, które wkładasz do tablicy i dołączasz do niej itp. Mam nadzieję, że zaczniesz we właściwym kierunku:

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

Jest to wywoływane przez utworzenie obiektu opcji, takiego jak:

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

I zapewniając funkcję oddzwaniania.

Na przykład w usłudze wymagam powyższego modułu REST, a następnie wykonaj następujące czynności:

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

AKTUALIZACJA

Jeśli szukasz async/ await(liniowy, bez oddzwaniania), obietnic, wsparcia czasu kompilacji i intellisense, stworzyliśmy lekkiego klienta HTTP i REST, który pasuje do tego rachunku:

Klient napisany przez Microsoft

bryanmac
źródło
@bryanmac, czy możesz wysłać / dodać kompletną próbkę?
StErMi
@ bryanmac za twoją zgodą Chciałbym użyć tej wtyczki do krojenia kodu, którą właśnie buduję. Nie jestem pewien, kiedy, ale kiedy zostanie ukończony, zostanie otwarty.
JeffH
3
wypróbuj moduł żądania .. jest o wiele prostsze sitepoint.com/making-http-requests-in-node-js
saurshaz
6
tak - moduł żądania jest prosty, ale jest to niższy poziom pokazujący, co robią biblioteki takie jak moduł żądania. Jeśli potrzebujesz kontroli niższego poziomu lub żądań HTTP (pokazujących postępy przy dużych pobraniach itp.), Pokazuje to, jak to się robi.
bryanmac
1
@KrIsHnA - węzeł ma obiekt zapytania : nodejs.org/api/querystring.html i obiekt url nodejs.org/docs/latest/api/url.html
bryanmac
100

Spróbuj użyć prostej http.get(options, callback)funkcji w 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);
});

Istnieje również ogólna http.request(options, callback)funkcja, która pozwala określić metodę żądania i inne szczegóły żądania.

maerika
źródło
Gdzie jest treść odpowiedzi serwera, o którą poprosił PO?
Dan Dascalescu,
Dziękuję za aktualizację. Wygląda na to, że wtedy potrzebny jest moduł obsługi „końca” do łączenia fragmentów. Co w zasadzie odpowiada odpowiedzi @ bryanmac?
Dan Dascalescu,
@DanDascalescu: ya, jeśli chcesz przetwarzać ciało jako całość (co jest prawdopodobne), prawdopodobnie chcesz je buforować i przetwarzać na „końcu”. Zaktualizuję również moją odpowiedź pod kątem kompletności.
maerics
przepraszam, nie mogę ustalić, z jakimi parametrami jest wywoływane wywołanie zwrotne ... jak mogę uzyskać treść i gdzie jest odwołanie do parametrów i właściwości tych parametrów.
Muhammad Umer
@maerics Jak mogę użyć tego GETżądania, jeśli mam ten adres URL? graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token}?
frank17
70

Request i Superagent to całkiem niezłe biblioteki do użycia.

Uwaga: prośba jest wycofana , użyj na własne ryzyko!

Używanie 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
źródło
7
Czy powinien to być res.statusCode === 200 sekund, jeśli? )
Gleb Dolzikov
1
jaka jest zmienna opcji? przekazać tylko niezdefiniowany? wątpię
lxknvlk
32

Możesz także użyć Requestify , naprawdę fajnego i bardzo prostego klienta HTTP, który napisałem dla nodeJS +, który obsługuje buforowanie.

Po prostu wykonaj następujące czynności dla żądania metody 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
źródło
1
„Wypróbuj to inne narzędzie” nie jest akceptowalną odpowiedzią, jeśli istniejący zestaw narzędzi jest wystarczający.
Grunion Shaftoe,
9

Ta wersja jest oparta na pierwotnie zaproponowanej przez bryanmac funkcji, która wykorzystuje obietnice, lepszą obsługę błędów i została przepisana w 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();
    });
};

W rezultacie nie musisz przekazywać funkcji wywołania zwrotnego, zamiast tego getJSON () zwraca obietnicę. W poniższym przykładzie funkcja jest używana w module obsługi trasy 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);
    });
});

W przypadku błędu deleguje błąd do oprogramowania pośredniego obsługującego błędy serwera.

maqduni
źródło
1
Tak, ten przykład pokazuje, jak to zrobić w getdefinicji trasy ekspresowej , której brakuje tutaj wielu postów.
Micros
7

Unirest to najlepsza biblioteka, z jaką się spotkałem, aby wysyłać żądania HTTP z węzła. Jego celem jest bycie platformą wieloplatformową, więc nauczenie się, jak działa na Node, będzie ci dobrze służyć, jeśli będziesz musiał używać klienta HTTP w Ruby, PHP, Java, Python, Objective C, .Net lub Windows 8. O ile mogę stwierdzić, biblioteki unirest są w większości wspierane przez istniejących klientów HTTP (np. W Javie, kliencie HTTP Apache, w węźle, bibliotece żądania Mikeala ) - Unirest po prostu umieszcza ładniejszy API na wierzchu.

Oto kilka przykładów kodu dla 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)
    }
  })

Możesz przejść bezpośrednio do dokumentów węzła tutaj

Brian Beckett
źródło
3

Sprawdź niszczenie . Jest to węzłowy klient HTTP utworzony i obsługiwany przez spire.io, który obsługuje przekierowania, sesje i odpowiedzi JSON. Jest świetny do interakcji z pozostałymi interfejsami API. Zobacz ten post na blogu, aby uzyskać więcej informacji.

Jonathan McIntire
źródło
3

Sprawdź httpreq : to biblioteka węzłów, którą utworzyłem, ponieważ byłem sfrustrowany, że nie było tam prostego modułu HTTP GET ani POST ;-)

Sam
źródło
0

Jeśli potrzebujesz tylko prostych żądań pobierania i nie potrzebujesz obsługi innych metod HTTP, spójrz na: 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
źródło
0

Użyj reqclient : nieprzeznaczony do celów skryptowych, takich jak requestwiele innych bibliotek. Reqclient pozwala konstruktorowi na określenie wielu konfiguracji przydatnych, gdy trzeba wielokrotnie używać tej samej konfiguracji: podstawowy adres URL, nagłówki, opcje uwierzytelniania, opcje rejestrowania, buforowanie itp. Posiada również przydatne funkcje, takie jak analizowanie zapytań i adresów URL, automatyczne kodowanie zapytań i Parsowanie JSON itp.

Najlepszym sposobem korzystania z biblioteki jest utworzenie modułu do wyeksportowania obiektu wskazującego na interfejs API oraz niezbędnych konfiguracji do połączenia z:

Moduł 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

A w kontrolerach, w których musisz korzystać z interfejsu API, użyj następującego:

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

reqclientobsługuje wiele funkcji, ale ma takie, które nie są obsługiwane przez inne biblioteki: integracja OAuth2 i integracja rejestratora ze składnią cURL i zawsze zwraca natywne obiekty Promise.

Mariano Ruiz
źródło
0

Jeśli kiedykolwiek będziesz musiał wysłać GETzapytanie do ( IPa także w Domaininnych odpowiedziach nie wspomniano, że możesz podać portzmienną), możesz skorzystać z tej funkcji:

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

Nie przegap wymaganych modułów na górze pliku:

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

Pamiętaj również, że możesz używać httpsmodułu do komunikacji przez zabezpieczoną sieć. więc te dwie linie zmieniłyby się:

https = require("https");
...
https.get(url.format(requestUrl), (resp) => { ......
AmiNadimi
źródło
-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
źródło
(Tak się składa, że ​​nie rozwiąże problemu. Ten kod będzie nasłuchiwał żądania, ale pytanie dotyczy sposobu wysłania żądania )
Quentin
1
jest naprawiony, możesz go wypróbować. @Quentin
izhar ahmad