nodejs - el primer argumento debe ser una cadena o búfer - cuando se usa response.write con http.request

92

Simplemente estoy tratando de crear un servidor de nodo que genere el estado HTTP de una URL determinada.

Cuando intento limpiar la respuesta con res.write, aparece el error: throw new TypeError ('el primer argumento debe ser una cadena o Buffer');

Pero si los reemplazo con console.log, todo está bien (pero necesito escribirlos en el navegador, no en la consola).

El codigo es

var server = http.createServer(function (req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});

    request({
        uri: 'http://www.google.com',
        method: 'GET',
        maxRedirects:3
    }, function(error, response, body) {
        if (!error) {
            res.write(response.statusCode);
        } else {
            //response.end(error);
            res.write(error);
        }
    });     

    res.end();
});
server.listen(9999);

Creo que debería agregar una devolución de llamada en algún lugar pero bastante confuso y se agradece cualquier ayuda.

umutm
fuente

Respuestas:

31

La solicitud toma un método de devolución de llamada, ¡es asincrónico! Así que supongo que para cuando se ejecuta la devolución de llamada, es res.end()posible que se llame. Intente cerrar la solicitud dentro de la devolución de llamada.

Gaurav Agarwal
fuente
1
Hice eso y también agregó .toString. Muchas gracias.
umutm
Parece que lo olvidé. Simplemente lo hizo. Gracias.
umutm
1
@umutm Hay respuestas más bien escritas y elaboradas, probablemente debería aceptar una de ellas; haciéndolo visible para cualquiera que se acerque a esta pregunta.
Gaurav Agarwal
52

response.statusCodees un número, por ejemplo response.statusCode === 200, no '200'. Como dice el mensaje de error, writeespera un objeto stringo Buffer, por lo que debe convertirlo.

res.write(response.statusCode.toString());

Sin embargo, también tiene razón sobre su comentario de devolución de llamada. res.end();debe estar dentro de la devolución de llamada, justo debajo de sus writellamadas.

loganfsmyth
fuente
Sí, eso funcionó. Como novato de nodejs, no sabía eso y muchas gracias.
umutm
48

Recibo este mensaje de error y menciona options.body

Tenía esto originalmente

request.post({
    url: apiServerBaseUrl + '/v1/verify',
    body: {
        email: req.user.email
    }
});

Lo cambié a esto:

request.post({
    url: apiServerBaseUrl + '/v1/verify',
    body: JSON.stringify({
        email: req.user.email
    })
});

y parece funcionar ahora sin el mensaje de error ... aunque parece un error.

Creo que esta es la forma más oficial de hacerlo:

 request.post({
        url: apiServerBaseUrl + '/v1/verify',
        json: true,
        body: {
            email: req.user.email
        }
    });
Alexander Mills
fuente
4
Su problema es diferente, se espera que el cuerpo sea de forma predeterminada una cadena o un búfer. También puede cambiarlo (para que sea serializable en json) agregando json: true a las opciones. Por ejemplo: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Nuno Tomas
2
Podría usar esto para evitar la deformación javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino
13

Bueno, obviamente está intentando enviar algo que no es una cadena o un búfer. :) Funciona con consola, porque la consola acepta cualquier cosa. Ejemplo simple:

var obj = { test : "test" };
console.log( obj ); // works
res.write( obj ); // fails

Una forma de convertir cualquier cosa en cadena es hacer eso:

res.write( "" + obj );

cada vez que intentas enviar algo. La otra forma es llamar al .toString()método:

res.write( obj.toString( ) );

Tenga en cuenta que es posible que aún no sea lo que está buscando. Siempre debe pasar cadenas / búferes .writesin tales trucos.

Como nota al margen: supongo que requestes una operación asincrónica. Si ese es el caso, entonces res.end();se llamará antes de cualquier escritura, es decir, cualquier escritura fallará de todos modos (porque la conexión se cerrará en ese punto). Mueva esa línea al controlador:

request({
    uri: 'http://www.google.com',
    method: 'GET',
    maxRedirects:3
}, function(error, response, body) {
    if (!error) {
        res.write(response.statusCode);
    } else {
        //response.end(error);
        res.write(error);
    }
    res.end( );
});
monstruoso
fuente
Muchas gracias por la respuesta y la información detallada. Y sí, he movido el final de la resolución al controlador. He aceptado @loganfsmyth como era antes. Gracias de nuevo.
umutm
1

si desea escribir un objeto JSON en la respuesta, cambie el tipo de contenido del encabezado a application / json

response.writeHead(200, {"Content-Type": "application/json"});
var d = new Date(parseURL.query.iso);
var postData = {
    "hour" : d.getHours(),
    "minute" : d.getMinutes(),
    "second" : d.getSeconds()
}
response.write(postData)
response.end();
Mohsin Muzawar
fuente
1

Y existe otra posibilidad (no en este caso) cuando se trabaja con ajax (XMLhttpRequest), mientras se envía información al cliente, debe usar res.send (responsetext) en lugar de res.end (responsetext)

Prajith P
fuente
1

Aunque la pregunta está resuelta, compartiendo conocimientos para aclarar el correcto significado del error.

El error dice que el parámetro necesario para la función de ruptura en cuestión no está en el formato requerido, es decir, cadena o búfer

La solución es cambiar el parámetro a cadena

breakingFunction(JSON.stringify(offendingParameter), ... other params...);

o tampón

breakingFunction(BSON.serialize(offendingParameter), ... other params...);
Zameer Ansari
fuente
0

El primer argumento debe ser de tipo cadena o Buffer. Objeto de tipo recibido

 at write_

Recibía el error anterior mientras pasaba los datos del cuerpo al módulo de solicitud.

He pasado otro parámetro que es JSON: true y está funcionando.

var option={
url:"https://myfirstwebsite/v1/appdata",
json:true,
body:{name:'xyz',age:30},
headers://my credential
}
rp(option)
.then((res)=>{
res.send({response:res});})
.catch((error)=>{
res.send({response:error});})
A. PRABIN SARAB
fuente