nodejs - первый аргумент должен быть строкой или буфером - при использовании response.write с http.request

94

Я просто пытаюсь создать сервер узла, который выводит HTTP-статус данного URL-адреса.

Когда я пытаюсь сбросить ответ с помощью res.write, я получаю сообщение об ошибке: throw new TypeError («первый аргумент должен быть строкой или буфером»);

Но если я заменю их на console.log, все будет хорошо (но мне нужно записать их в браузер, а не в консоль).

Код

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

Я считаю, что я должен добавить обратный вызов где-нибудь, но довольно запутан, и любая помощь приветствуется.

умутм
источник

Ответы:

32

Запрос принимает метод обратного вызова, его асинхронный! Итак, я предполагаю, что к моменту выполнения обратного вызова res.end()может быть вызван. Попробуйте закрыть запрос в обратном вызове.

Гаурав Агарвал
источник
1
Сделал это, а также добавил .toString. Большое спасибо.
umutm
Похоже, я забыл. Только что сделал это. Спасибо.
umutm
1
@umutm Есть более хорошо написанные и подробные ответы, вам, вероятно, следует принять один из них; сделать его видимым для всех, кто задаст этот вопрос.
Gaurav Agarwal
52

response.statusCodeчисло, например response.statusCode === 200, нет '200'. Как говорится в сообщении об ошибке, writeожидает объект stringили Buffer, поэтому вы должны его преобразовать.

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

Однако вы также правы в своем комментарии к обратному вызову. res.end();должен быть внутри обратного вызова, чуть ниже ваших writeвызовов.

логанфсмиф
источник
Да, это помогло. Как новичок в nodejs, я этого не знал и большое спасибо.
umutm
48

Я получаю это сообщение об ошибке, в котором упоминается options.body

У меня было это изначально

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

Я изменил его на это:

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

и, похоже, теперь он работает без сообщения об ошибке ... хотя кажется, что это ошибка.

Я думаю, что это более официальный способ сделать это:

 request.post({
        url: apiServerBaseUrl + '/v1/verify',
        json: true,
        body: {
            email: req.user.email
        }
    });
Александр Миллс
источник
4
Ваша проблема в другом, по умолчанию ожидается, что тело будет строкой или буфером. Вы также можете изменить его (чтобы он был сериализуемым по json), добавив json: true в параметры. Например: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Нуно Томас
2
Вы можете использовать это , чтобы избежать stringify javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino
13

Что ж, очевидно, вы пытаетесь отправить что-то, что не является строкой или буфером. :) С консолью работает, потому что консоль принимает все что угодно. Простой пример:

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

Один из способов преобразовать что-либо в строку - это сделать:

res.write( "" + obj );

всякий раз, когда вы пытаетесь что-то отправить. Другой способ - вызвать .toString()метод:

res.write( obj.toString( ) );

Обратите внимание, что это может быть не то, что вы ищете. Вы всегда должны передавать строки / буферы .writeбез таких уловок.

В качестве примечания: я предполагаю, что requestэто асинхронная операция. Если это так, then res.end();будет вызываться перед любой записью, т. Е. Любая запись все равно завершится неудачно (потому что в этот момент соединение будет закрыто). Переместите эту строку в обработчик:

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( );
});
причудливый
источник
Большое спасибо за ответ и подробную информацию. И, да, я переместил ответ в обработчик. Я принял @loganfsmyth, как это было раньше. Еще раз спасибо.
umutm
1

если вы хотите записать объект JSON в ответ, измените тип содержимого заголовка на 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();
Мохсин Музавар
источник
1

И есть еще одна возможность (не в этом случае) при работе с ajax (XMLhttpRequest), при отправке информации обратно на клиентскую часть вы должны использовать res.send (responsetext) вместо res.end (responsetext)

Праджит П.
источник
1

Хотя вопрос решен, делимся знаниями для выяснения правильного смысла ошибки.

Ошибка говорит о том, что параметр, необходимый для соответствующей функции прерывания, не находится в требуемом формате, то есть в строке или буфере.

Решение - изменить параметр на строку

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

или буфер

breakingFunction(BSON.serialize(offendingParameter), ... other params...);
Замир Ансари
источник
0

Первый аргумент должен быть строкового типа или буфера. Полученный объект типа

 at write_

Когда я передавал данные тела модулю запроса, я получал указанную выше ошибку.

Я передал еще один параметр - JSON: true и его рабочий.

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});})
А. ПРАБИН САРАБ
источник