web-dev-qa-db-fra.com

nodejs - le premier argument doit être une chaîne ou un tampon - lors de l'utilisation de response.write avec http.request

J'essaie simplement de créer un serveur de noeud qui affiche le statut HTTP d'une URL donnée.

Lorsque j'essaie de vider la réponse avec res.write, le message d'erreur suivant s'affiche: throw new TypeError ('le premier argument doit être une chaîne ou un tampon');

Mais si je les remplace par console.log, tout va bien (mais je dois les écrire sur le navigateur, pas sur la console).

Le code est

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

Je crois que je devrais ajouter un rappel quelque part mais assez confus et toute aide est appréciée.

78
umutm

Request prend une méthode de rappel, c'est async! Je suppose donc que, au moment de l'exécution du rappel, la res.end() pourrait être appelée. Essayez de fermer la demande dans le rappel?!

26
Gaurav Agarwal

response.statusCode est un nombre, par exemple. response.statusCode === 200, pas '200'. Comme le message d'erreur le dit, write attend un objet string ou Buffer. Vous devez donc le convertir.

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

Vous avez également raison de votre commentaire de rappel. res.end(); devrait être à l'intérieur du rappel, juste en dessous de vos appels write.

50
loganfsmyth

Je reçois ce message d'erreur et il mentionne options.body

J'avais à l'origine

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

Je l'ai changé en ceci:

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

et cela semble fonctionner maintenant sans le message d'erreur ... semble être un bug cependant.

Je pense que c'est la manière la plus officielle de le faire:

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

Évidemment, vous essayez d’envoyer quelque chose qui n’est pas une chaîne ni un tampon. :) Cela fonctionne avec console, car la console accepte n'importe quoi. Exemple simple:

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

Une façon de convertir n'importe quoi en chaîne est de le faire:

res.write( "" + obj );

chaque fois que vous essayez d'envoyer quelque chose. L’autre méthode consiste à appeler la méthode .toString():

res.write( obj.toString( ) );

Notez que ce n'est peut-être toujours pas ce que vous recherchez. Vous devriez toujours passer des chaînes/tampons à .write sans ces astuces.

Remarque: je suppose que request est une opération asynchrone. Si tel est le cas, alors res.end(); sera appelée avant toute écriture, c’est-à-dire que toute écriture échouera de toute façon (car la connexion sera fermée à ce moment-là). Déplacez cette ligne dans le gestionnaire:

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

Et il existe une autre possibilité (pas dans ce cas) lorsque vous utilisez ajax (XMLhttpRequest), lors de l'envoi d'informations au client, vous devez utiliser res.send (responsetext) au lieu de res.end (responsetext)

1
Prajith P

Bien que la question soit résolue, le partage des connaissances permet de clarifier le sens correct de l'erreur.

L'erreur indique que le paramètre nécessaire à la fonction de coupure concernée n'est pas au format requis, c'est-à-dire string ou Buffer.

La solution est de changer le paramètre en chaîne

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

ou tampon

breakingFunction(BSON.serialize(offendingParameter), ... other params...);
1
student

si vous voulez écrire un objet JSON dans la réponse, changez le type de contenu de l'en-tête en 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
Mohsin Muzawar