nodejs - o primeiro argumento deve ser uma string ou Buffer - ao usar response.write com http.request

92

Estou simplesmente tentando criar um servidor de nó que produza o status HTTP de um determinado URL.

Quando tento liberar a resposta com res.write, recebo o erro: throw new TypeError ('o primeiro argumento deve ser uma string ou buffer');

Mas se eu substituí-los por console.log, está tudo bem (mas preciso gravá-los no navegador, não no console).

O código é

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

Eu acredito que devo adicionar um retorno de chamada em algum lugar, mas muito confuso e qualquer ajuda é apreciada.

umutm
fonte

Respostas:

31

A solicitação usa um método de retorno de chamada, é assíncrono! Portanto, estou assumindo que, no momento em que o retorno de chamada for executado, res.end()talvez seja chamado. Tente fechar a solicitação no retorno de chamada.

Gaurav Agarwal
fonte
1
Fiz isso e também adicionou .toString. Muito obrigado.
umutm
Parece que esqueci. Acabei de fazer isso. THX.
umutm
1
@umutm Existem respostas mais bem escritas e elaboradas, você provavelmente deveria aceitar uma delas; tornando-o visível para qualquer pessoa que vier a esta questão.
Gaurav Agarwal
52

response.statusCodeé um número, por exemplo response.statusCode === 200, não '200'. Como diz a mensagem de erro, writeespera um objeto stringou Buffer, portanto, você deve convertê-lo.

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

Você também está correto sobre o seu comentário de retorno de chamada. res.end();deve estar dentro do retorno de chamada, logo abaixo de suas writechamadas.

loganfsmyth
fonte
Sim, isso funcionou. Como um novato nodejs, não sabia disso e muito obrigado.
umutm
48

Recebo esta mensagem de erro e menciona options.body

Eu tinha isso originalmente

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

Eu mudei para este:

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

e parece funcionar agora sem a mensagem de erro ... parece um bug.

Acho que esta é a maneira mais oficial de fazer isso:

 request.post({
        url: apiServerBaseUrl + '/v1/verify',
        json: true,
        body: {
            email: req.user.email
        }
    });
Alexander Mills
fonte
4
Seu problema é diferente, espera-se que o corpo seja uma string ou Buffer por padrão. Você também pode alterá-lo (para ser serializável em json) adicionando json: true às opções. Ex .: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Nuno Tomas
2
Você pode usar isso para evitar stringify javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino
13

Bem, obviamente você está tentando enviar algo que não é uma string ou buffer. :) Funciona com console, porque o console aceita qualquer coisa. Exemplo simples:

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

Uma maneira de converter qualquer coisa em string é fazer isso:

res.write( "" + obj );

sempre que você está tentando enviar algo. A outra maneira é chamar o .toString()método:

res.write( obj.toString( ) );

Observe que ainda pode não ser o que você está procurando. Você deve sempre passar strings / buffers .writesem tais truques.

Como observação: presumo que requestseja uma operação assíncrona. Se for esse o caso, então res.end();será chamado antes de qualquer escrita, ou seja, qualquer escrita irá falhar de qualquer maneira (porque a conexão será encerrada nesse ponto). Mova essa linha para o manipulador:

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( );
});
esquisito
fonte
Muito obrigado pela resposta e pelas informações detalhadas. E, sim, movi o res.end para o manipulador. Aceitei @loganfsmyth como era antes. Obrigado novamente.
umutm
1

se você quiser gravar um objeto JSON na resposta, altere o tipo de conteúdo do cabeçalho para 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
fonte
1

E há outra possibilidade (não neste caso) ao trabalhar com ajax (XMLhttpRequest), ao enviar informações de volta para o cliente final, você deve usar res.send (responsetext) em vez de res.end (responsetext)

Prajith P
fonte
1

Embora a questão seja resolvida, compartilhando conhecimentos para esclarecimento do correto significado do erro.

O erro diz que o parâmetro necessário para a função de quebra em questão não está no formato exigido, ou seja, string ou Buffer

A solução é mudar o parâmetro para string

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

ou buffer

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

O primeiro argumento deve ser do tipo string ou Buffer. Objeto de tipo recebido

 at write_

Eu estava recebendo o erro acima ao passar os dados do corpo para o módulo de solicitação.

Passei outro parâmetro que é JSON: true e 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
fonte