pasar JSON a HTTP POST Request

92

Estoy intentando realizar una solicitud HTTP POST a la API de Google QPX Express [1] utilizando nodejs y la solicitud [2].

Mi código se ve como sigue:

    // create http request client to consume the QPX API
    var request = require("request")

    // JSON to be passed to the QPX Express API
    var requestData = {
        "request": {
            "slice": [
                {
                    "origin": "ZRH",
                    "destination": "DUS",
                    "date": "2014-12-02"
                }
            ],
            "passengers": {
                "adultCount": 1,
                "infantInLapCount": 0,
                "infantInSeatCount": 0,
                "childCount": 0,
                "seniorCount": 0
            },
            "solutions": 2,
            "refundable": false
        }
    }

    // QPX REST API URL (I censored my api key)
    url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=myApiKey"

    // fire request
    request({
        url: url,
        json: true,
        multipart: {
            chunked: false,
            data: [
                {
                    'content-type': 'application/json',
                    body: requestData
                }
            ]
        }
    }, function (error, response, body) {
        if (!error && response.statusCode === 200) {
            console.log(body)
        }
        else {

            console.log("error: " + error)
            console.log("response.statusCode: " + response.statusCode)
            console.log("response.statusText: " + response.statusText)
        }
    })

Lo que estoy tratando de hacer es pasar el JSON usando el argumento multiparte [3]. Pero en lugar de la respuesta JSON adecuada, recibí un error (400 indefinido).

Cuando hago una solicitud usando el mismo JSON y API Key usando CURL en su lugar, funciona bien. Entonces, no hay nada de malo con mi clave API o JSON.

¿Qué pasa con mi código?

EDITAR :

ejemplo de CURL de trabajo:

i) Guardé el JSON que pasaría a mi solicitud en un archivo llamado "request.json":

{
  "request": {
    "slice": [
      {
        "origin": "ZRH",
        "destination": "DUS",
        "date": "2014-12-02"
      }
    ],
    "passengers": {
      "adultCount": 1,
      "infantInLapCount": 0,
      "infantInSeatCount": 0,
      "childCount": 0,
      "seniorCount": 0
    },
    "solutions": 20,
    "refundable": false
  }
}

ii) luego, en la terminal cambié al directorio en el que se ubicó y ejecutó el archivo request.json recién creado (myApiKey significa mi clave API real obviamente):

curl -d @request.json --header "Content-Type: application/json" https://www.googleapis.com/qpxExpress/v1/trips/search?key=myApiKey

[1] https://developers.google.com/qpx-express/ [2] un cliente de solicitud http diseñado para nodejs: https://www.npmjs.org/package/request [3] aquí hay un ejemplo que encontré https://www.npmjs.org/package/request#multipart-related [4] La API de QPX Express devuelve un error de análisis 400

Ronin
fuente
Intente eliminar 'json: true' de su solicitud
Baart
no hace la diferencia. pero hasta donde yo sé, esto solo especifica que la respuesta es un json, ¿verdad?
Ronin
¿Puede mostrar la línea de comando cURL que funciona?
mscdex
Por curiosidad, ¿por qué utiliza varias partes?
Cloudfeet
@mscdex, por favor vea mi publicación original actualizada
Ronin

Respuestas:

168

Creo que lo siguiente debería funcionar:

// fire request
request({
    url: url,
    method: "POST",
    json: requestData
}, ...

En este caso, el Content-type: application/jsonencabezado se agrega automáticamente.

Tobi
fuente
1
Por alguna razón, el punto final al que estaba accediendo no pudo leer los parámetros usando el primer método (como si no se hubieran enviado), pero pudo hacerlo con el segundo método.
The Unknown Dev
Asimismo, a lo que dijo Jamil. Conseguí SyntaxError: Unexpected token &quot;<br> &nbsp; &nbsp;at parse (/home/malcolm/complice/node_modules/body-parser/lib/types/json.js:83:15)con el primer método.
MalcolmOcean
@MalcolmOcean Eso es porque una etiqueta de <br> no es un contenido JSON válido
Tobi
Recibí este error: [ERR_STREAM_WRITE_AFTER_END]: write after end¿cómo puedo solucionarlo?
Mehdi Dehghani
18

Trabajé en esto durante demasiado tiempo. La respuesta que me ayudó fue: enviar Content-Type: application / json post con node.js

Que usa el siguiente formato:

request({
    url: url,
    method: "POST",
    headers: {
        "content-type": "application/json",
        },
    json: requestData
//  body: JSON.stringify(requestData)
    }, function (error, resp, body) { ...
DanBaker
fuente
10

No desea varias partes, sino una solicitud POST "simple" (con Content-Type: application/json) en su lugar. Aquí tienes todo lo que necesitas:

var request = require('request');

var requestData = {
  request: {
    slice: [
      {
        origin: "ZRH",
        destination: "DUS",
        date: "2014-12-02"
      }
    ],
    passengers: {
      adultCount: 1,
      infantInLapCount: 0,
      infantInSeatCount: 0,
      childCount: 0,
      seniorCount: 0
    },
    solutions: 2,
    refundable: false
  }
};

request('https://www.googleapis.com/qpxExpress/v1/trips/search?key=myApiKey',
        { json: true, body: requestData },
        function(err, res, body) {
  // `body` is a js object if request was successful
});
mscdex
fuente
Intenté esto, pero obtuve otro error: "400. Eso es un error. Su cliente ha emitido una solicitud incorrecta o ilegal. Eso es todo lo que sabemos". para obtener la respuesta completa, visite jsfiddle.net/f71opd7p por favor
Ronin
4
@Tobi de acuerdo con la documentación de la solicitud y el código , json: truetanto JSON.stringify() body como JSON.parse() la respuesta.
mscdex
Esta es la respuesta. Además, también puede canalizar la respuestarequest('xxx',{ json: true, body: req.body }).pipe(res).on('error', catchErr);
sidonaldson
Esto funcionó para mí cuando la respuesta aceptada no lo era.
greg_diesel
Recibí este error: [ERR_STREAM_WRITE_AFTER_END]: write after end¿cómo puedo solucionarlo?
Mehdi Dehghani
9

Ahora, con la nueva versión de JavaScript (ECMAScript 6 http://es6-features.org/#ClassDefinition ) hay una mejor manera de enviar solicitudes utilizando nodejs y la solicitud de Promise ( http://www.wintellect.com/devcenter/nstieglitz/5 -grandes-funciones-en-es6-harmonia )

Usando la biblioteca: https://github.com/request/request-promise

npm install --save request
npm install --save request-promise

cliente:

//Sequential execution for node.js using ES6 ECMAScript
var rp = require('request-promise');

rp({
    method: 'POST',
    uri: 'http://localhost:3000/',
    body: {
        val1 : 1,
        val2 : 2
    },
    json: true // Automatically stringifies the body to JSON
}).then(function (parsedBody) {
        console.log(parsedBody);
        // POST succeeded...
    })
    .catch(function (err) {
        console.log(parsedBody);
        // POST failed...
    });

servidor:

var express = require('express')
    , bodyParser = require('body-parser');

var app = express();

app.use(bodyParser.json());

app.post('/', function(request, response){
    console.log(request.body);      // your JSON

    var jsonRequest = request.body;
    var jsonResponse = {};

    jsonResponse.result = jsonRequest.val1 + jsonRequest.val2;

    response.send(jsonResponse);
});


app.listen(3000);
Evalds Urtans
fuente
3

Ejemplo.

var request = require('request');

var url = "http://localhost:3000";

var requestData = {
    ...
} 

var data = {
    url: url,
    json: true,
    body: JSON.stringify(requestData)
}

request.post(data, function(error, httpResponse, body){
    console.log(body);
});

Como json: trueopción de inserción , establece el cuerpo en la representación JSON del valor y agrega el "Content-type": "application/json"encabezado. Además, analiza el cuerpo de la respuesta como JSON. ENLACE

Youngmin Kim
fuente
2

Según doc: https://github.com/request/request

El ejemplo es:

  multipart: {
      chunked: false,
      data: [
        {
          'content-type': 'application/json', 
          body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
        },
      ]
    }

Creo que envías un objeto donde se espera una cadena, reemplaza

body: requestData

por

body: JSON.stringify(requestData)
Baart
fuente
2
       var request = require('request');
        request({
            url: "http://localhost:8001/xyz",
            json: true,
            headers: {
                "content-type": "application/json",
            },
            body: JSON.stringify(requestData)
        }, function(error, response, body) {
            console.log(response);
        });
Ashish Gupta
fuente
0

siento

var x = request.post({
       uri: config.uri,
       json: reqData
    });

Definir así será la forma efectiva de escribir su código. Y la aplicación / json debería agregarse automáticamente. No es necesario declararlo específicamente.

Siddhartha Thota
fuente
0

puede pasar el objeto json como el cuerpo (tercer argumento) de la solicitud de recuperación.

ankur tiwari
fuente
1
Esto no proporciona una respuesta a la pregunta. Una vez que tenga suficiente reputación , podrá comentar en cualquier publicación ; en su lugar, proporcione respuestas de acuerdo con la guía
Anna