Node.js equivalent of this curl request - javascript

I'm trying to use the HTML validator API. The curl examples work fine for me and I can run them find in Node as a child process. Here is the code for that:
var command = ('curl -H "Content-Type:text/html; charset=utf-8" --data-binary #' + file +
' https://validator.w3.org/nu/?out=json');
exec(command, function(err1, out, err2) {
console.log(out);
console.log('done');
});
However, when I tried to use a standard HTTP request, I couldn't get it working. I tried it with the Unirest library for Node. Here is the code I used:
var source = '<html><head><title>a</title></head><body>a</body></html>';
var url = 'http://validator.w3.org/nu/?out=json';
var Request = unirest.post(url);
Request.headers({'Content-Type': 'text/html', 'charset': 'utf-8'});
Request.send(source);
Request.end(res => console.log(res));
The response body is undefined and the response raw_body is empty. I don't know what I'm doing wrong and would appreciate any help.

Seems validator.w3.org won't respond to requests without a user-agent header. Add this header:
Request.headers({'Content-Type': 'text/html; charset=utf-8', 'user-agent': 'Node.js'});
Or use whatever useragent you want.

With super agent:
const request = require('superagent');
const body = '<html><head><title>a</title></head><body>a</body></html>';
request.post('https://validator.w3.org/nu/?out=json')
.set('Content-Type', 'text/html; charset=utf-8')
.send(body)
.end((err, res) => {
console.log('got body: ' + JSON.stringify(res.body));
});

Related

How do I send a filestream to localhost node-fetch?

On server side, I have this:
app.post('/testReadStream', function(req, res) {
var readStream = req.body;
readStream.pipe(process.stdout);
})
}).listen(443, () => console.log(`Listening on 443`));
I am making the following request from somewhere else:
let readStream = fs.createReadStream(path);
const fileSizeInBytes = fs.statSync(path).size;
fetch('https://localhost:443/testReadStream', {
method: 'POST',
headers: {
"Content-length": fileSizeInBytes
},
body: readStream
}).catch((err) => {
console.log(err);
})
I get the following error.
'request to https://localhost:443/testReadStream failed, reason: write EPROTO 4365467072:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:332:\n',
From this link https://github.com/openssl/openssl/issues/10938 it seems I did something wrong with filestreams. I copied it from here How to send a file in request node-fetch or Node?
What did i do wrong?
Looks like an SSL problem.
Can you try a simple string body
body: "text"
The SSL problem came from me putting "https" + localhost instead of "http://localhost". .-.
After that, all I had to change was req.body to req.

Node.js send post with array parameter

Hello and happy new year!
I'm trying to send a post petition in Node.js. The version I need to replicate in javascript looks like this:
$.post('website.com/api/buy.php', {
action: order,
'items[]': cart_i,
time: localtime,
utb: x //I don't know why that parameter is sent. It's always 0 ._.
} ... //rest of the code of that website
I'm trying to do this in Node.js to replicate that:
var postData = querystring.stringify({
action: 'order',
"items[]": item.i,
time: local_time,
utb: 0
});
var https = require('https');
var options = { method: 'POST', host: 'website.com', port: 443, path: '/api/buy.php', headers: { 'Cache-Control': 'no-cache', 'Cookie': cookies, 'Accept': '/', 'Connection': 'keep-alive' } };
var req = https.request(options, function (res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
content = content+ chunk;
});
res.on('end', function () {
console.log(content)
});
}
);
req.write(postData);
req.end();
But I always get an error telling me that I didnt send anything. I think the problem could be in items[] because I see it sends "items%5B%5D", but I dont know if I'm doing something wrong. I think is is not about cookies, because if I'm not logged I get other error.
I'm doing the request well? Or I'm missing something that is not about the request? Is there other way to send "post" data easier?
Any help would be appreciated :)

The right way to construct HTTP request to API in Nodejs and Express

I'm totally new to HTTP and trying to make HTTP request. Here is the API:
I construct the request like this:
let reqString = 'GET https://login.yandex.ru/info?format=json&with_openid_identity=1 HTTP/1.1\r\n' +
'Authorization: OAuth ' + this.token;
And here is the error:
Error: Invalid URI "GET%20https://login.yandex.ru/info?format=json&with_openid_identity=1%20HTTP/1.1%0D%0AAuthorization:%20OAuth%20AQAAAAAc3LKEAAQQaS1B6d6nz0B8mq_kOr-AD6M"
I'm totally new to HTTP and backend at all, please, explain what I'm doing wrong and show me the right way
Thanks in advance
The solution for my case was to create the object and make HTTP request like this:
const request = require('request');
let reqobj = {
uri: 'https://login.yandex.ru/info?format=json&with_openid_identity=1 HTTP/1.1',
headers: {
'Authorization': 'OAuth ' + this.token
}
};
request(reqobj, (error, response, body) => {...}
Thanks for help in comments

Bearer Token in Node.js command line client http.request - Unauthorized

I'm developing a Node.js command line client which calls a REST API.
I have no issues calling non-authenticated gets and posts, but after I authenticate and receive my Bearer token, I'm not able to get an authorized response.
With what little samples are out there, I've simplified my call for test purposes with the following:
var options =
{
host: "localhost",
port: "62405",
path: "/api/Job",
method: 'GET',
headers:
{
Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJVbml0VGVzdGVyQG12cHNpLmNvbSIsInJvbGUiOiJ1c2VyIiwiSkFNU1RlbmVudElkIjoiNDIiLCJXaW5kb3dzSWRlbnRpdHkiOiJVbml0VGVzdGVyQG12cHNpLmNvbSIsImlzcyI6Ik1WUFNJIiwiYXVkIjoiSkFNU0FEQ2xpZW50SWQiLCJleHAiOjE0MzEzOTY4NzEsIm5iZiI6MTQzMTM1MzY3MX0.iYYX3TjcJONKhbNDqxG2hNGFwxGV0zG2m3rJ1wqmzIw"
}
};
var callback = function (res) {
console.log(res.statusCode);
console.log(res.headers);
var str = "";
res.on("data", function(chunk) {
str += chunk;
});
res.on("end", function() {
console.log(str);
});
};
var request = require('http').request(options, callback);
request.end();
Instead of receiving the reply, I'm getting a 401 with a response message of "Authorization has been denied for this request."
Again, this is a simplified version of my extensible code... but any suggestions would be greatly appreciated.
Clarification, when I use Postman and manually put in the token into the Authentication header, I receive an authorized (and the expected) response.

How to post to a request using node.js

I am trying to post some json to a URL. I saw various other questions about this on stackoverflow but none of them seemed to be clear or work. This is how far I got, I modified the example on the api docs:
var http = require('http');
var google = http.createClient(80, 'server');
var request = google.request('POST', '/get_stuff',
{'host': 'sever', 'content-type': 'application/json'});
request.write(JSON.stringify(some_json),encoding='utf8'); //possibly need to escape as well?
request.end();
request.on('response', function (response) {
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
When I post this to the server I get an error telling me that it's not of the json format or that it's not utf8, which they should be. I tried to pull the request url but it is null. I am just starting with nodejs so please be nice.
The issue is that you are setting Content-Type in the wrong place. It is part of the request headers, which have their own key in the options object, the first parameter of the request() method. Here's an implementation using ClientRequest() for a one-time transaction (you can keep createClient() if you need to make multiple connections to the same server):
var http = require('http')
var body = JSON.stringify({
foo: "bar"
})
var request = new http.ClientRequest({
hostname: "SERVER_NAME",
port: 80,
path: "/get_stuff",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(body)
}
})
request.end(body)
The rest of the code in the question is correct (request.on() and below).
Jammus got this right. If the Content-Length header is not set, then the body will contain some kind of length at the start and a 0 at the end.
So when I was sending from Node:
{"email":"joe#bloggs.com","passwd":"123456"}
my rails server was receiving:
"2b {"email":"joe#bloggs.com","passwd":"123456"} 0 "
Rails didn't understand the 2b, so it wouldn't interpret the results.
So, for passing params via JSON, set the Content-Type to application/json, and always give the Content-Length.
To send JSON as POST to an external API with NodeJS... (and "http" module)
var http = require('http');
var post_req = null,
post_data = '{"login":"toto","password":"okay","duration":"9999"}';
var post_options = {
hostname: '192.168.1.1',
port : '8080',
path : '/web/authenticate',
method : 'POST',
headers : {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Content-Length': post_data.length
}
};
post_req = http.request(post_options, function (res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ', chunk);
});
});
post_req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
post_req.write(post_data);
post_req.end();
There is a very good library that support sending POST request in Nodejs:
Link: https://github.com/mikeal/request
Sample code:
var request = require('request');
//test data
var USER_DATA = {
"email": "email#mail.com",
"password": "a075d17f3d453073853f813838c15b8023b8c487038436354fe599c3942e1f95"
}
var options = {
method: 'POST',
url: 'URL:PORT/PATH',
headers: {
'Content-Type': 'application/json'
},
json: USER_DATA
};
function callback(error, response, body) {
if (!error) {
var info = JSON.parse(JSON.stringify(body));
console.log(info);
}
else {
console.log('Error happened: '+ error);
}
}
//send request
request(options, callback);
Try including the content length.
var body = JSON.stringify(some_json);
var request = google.request('POST', '/get_stuff', {
host: 'server',
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'application/json'
});
request.write(body);
request.end();
This might not solve your problem, but javascript doesn't support named arguments, so where you say:
request.write(JSON.stringify(some_json),encoding='utf8');
You should be saying:
request.write(JSON.stringify(some_json),'utf8');
The encoding= is assigning to a global variable, so it's valid syntax but probably not doing what you intend.
Probably non-existent at the time this question was asked, you could use nowadays a higher level library for handling http requests, such as https://github.com/mikeal/request. Node's built-in http module is too low level for beginners to start with.
Mikeal's request module has built-in support for directly handling JSON (see the documentation, especially https://github.com/mikeal/request#requestoptions-callback).
var request = google.request(
'POST',
'/get_stuff',
{
'host': 'sever',
**'headers'**:
{
'content-type': 'application/json'
}
}
);

Categories