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

92

J'essaie simplement de créer un serveur de nœud qui génère le statut HTTP d'une URL donnée.

Quand j'essaye de vider la réponse avec res.write, j'obtiens l'erreur: throw new TypeError ('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 dans le navigateur et non dans 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.

umutm
la source

Réponses:

31

La requête prend une méthode de rappel, c'est asynchrone! Donc, je suppose qu'au moment où le rappel est exécuté, il res.end()pourrait être appelé. Essayez de fermer la demande dans le rappel.

Gaurav Agarwal
la source
1
Fait cela et a également ajouté .toString. Merci beaucoup.
umutm
On dirait que j'ai oublié de le faire. Je viens de le faire. THX.
umutm
1
@umutm Il y a des réponses plus bien écrites et élaborées, vous devriez probablement en accepter une; le rendant visible à quiconque vient à cette question.
Gaurav Agarwal
52

response.statusCodeest un nombre, par exemple response.statusCode === 200non '200'. Comme le message d'erreur l'indique, writeattend un objet stringou Buffer, vous devez donc le convertir.

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

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

loganfsmyth
la source
Oui, cela a fait l'affaire. En tant que débutant de nodejs, je ne le savais pas et merci beaucoup.
umutm
48

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

J'avais ça à 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 ... cela semble être un bug.

Je pense que c'est la façon la plus officielle de le faire:

 request.post({
        url: apiServerBaseUrl + '/v1/verify',
        json: true,
        body: {
            email: req.user.email
        }
    });
Alexander Mills
la source
4
Votre problème est différent, le corps est censé être par défaut une chaîne ou un tampon. Vous pouvez également le modifier (pour qu'il soit sérialisable json) en ajoutant json: true aux options. Par exemple: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Nuno Tomas
2
Vous pouvez utiliser ceci pour éviter de stringify javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino
13

Eh bien, de toute évidence, vous essayez d'envoyer quelque chose qui n'est pas une chaîne ou un tampon. :) Cela fonctionne avec la console, car la console accepte tout. Exemple simple:

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

Une façon de convertir quoi que ce soit en chaîne est de le faire:

res.write( "" + obj );

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

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 à .writesans ces astuces.

En remarque: je suppose que requestc'est une opération asynchrone. Si c'est le cas, alors res.end();sera appelé avant toute écriture, c'est-à-dire que toute écriture échouera de toute façon (car la connexion sera fermée à ce stade). 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( );
});
bizarre
la source
Merci beaucoup pour la réponse et les informations détaillées. Et, oui, j'ai déplacé le res.end dans le gestionnaire. J'ai accepté @loganfsmyth tel qu'il était auparavant. Merci encore.
umutm
1

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();
Mohsin Muzawar
la source
1

Et il y a une autre possibilité (pas dans ce cas) lorsque vous travaillez avec ajax (XMLhttpRequest), tout en renvoyant les informations au client, vous devez utiliser res.send (responsetext) au lieu de res.end (responsetext)

Prajith P
la source
1

Bien que la question soit résolue, partager les connaissances pour clarifier la signification correcte de l'erreur.

L'erreur indique que le paramètre nécessaire à la fonction de coupure concernée n'est pas dans le format requis, c'est-à-dire chaîne ou tampon

La solution est de changer le paramètre en string

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

ou tampon

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

Le premier argument doit être de type string ou Buffer. Objet de type reçu

 at write_

J'obtenais comme l'erreur ci-dessus en passant des données corporelles au module de requête.

J'ai passé un autre paramètre qui est JSON: true et son fonctionnement.

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
la source