Axios set Content-Length manually, nodeJS - node.js

Is there a way to send a post request in nodeJS and specify th content-length.
I tried (using axios):
let data = `Some text data...........`;
let form = await Axios.post(
"url.......",
data,
{
headers: {
Authentication: "token.....",
"Content-Type": "multipart/form-data; boundary=c9236fb18bed42c49590f58f8cc327e3",
//set content-length manually
"Content-Length": "268"
}
}
).catch(e => e);
It doesn't work, the length is set automatically to a value other then the one I pass.
I am using axios but open to using any other way to post from nodeJS.

I can't add a comment because of low reputation, but part of Sandeep Patel's answer regarding Axios is outdated. You can set Content-Length manually. Axios will not override Content-Length if content-length header is present:
// Add Content-Length header if data exists
if (!headerNames['content-length']) {
headers['Content-Length'] = data.length;
}
Source: https://github.com/axios/axios/blob/main/lib/adapters/http.js#L209-L213
So in your case it would be:
let data = `Some text data...`;
let form = await Axios.post(
"url...",
data,
{
headers: {
Authentication: "token....",
"Content-Type": "contentType...",
//set content-length manually
"Content-Length": "268",
"content-length": "268"
}
}
).catch(e => e);

In Axios, If data is present it will set length calculated from data, so even if you pass header content-length, it will be overridden by code:
Check this out for more details:
https://github.com/axios/axios/blob/master/lib/adapters/http.js
Using http or https module you can do:
const https = require('https')
const data = JSON.stringify({
key:values
})
const options = {
hostname: 'example.com',
port: 443,
path: '/testpath',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()

Related

Error when sending https request to ROBLOX API

I'm writing a simple API request to Roblox so I can retrieve the X-CSRF-TOKEN to do POST requests. The issue I'm facing is "Error: socket hang up".
I tried to just run the link in my browser and it displays a JSON table, but when I do the request through node.js it errors out.
const https = require("https")
const options = {
hostname: "groups.roblox.com",
path: "/v1/groups/5307563",
method: "GET",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cookie': '.ROBLOSECURITY=' + cookie
}
}
const request = https.request(options, res => {
res.on('data', data => {
console.log("data received")
})
});
request.on('error', error => {
console.log(error)
})
You need to end the request with request.end().
const https = require("https")
const options = {
hostname: "groups.roblox.com",
path: "/v1/groups/5307563",
method: "GET",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cookie': '.ROBLOSECURITY=' + cookie
}
}
const request = https.request(options, res => {
res.on('data', data => {
console.log("data received")
})
});
request.on('error', error => {
console.log(error)
})
request.end()

The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method

I am trying to get a signed url and then upload a file, but it returns an error that I have not been able to solve, I have already seen other questions but nothing yet, I'm trying with a png file and I specified it in the cont.
const fileD = storage.bucket(bucket).file(file)
const config = {
action: 'write',
expires: '03-17-2025',
ContentType: 'image/png'
}
fileD.getSignedUrl(config, async function Sing(err, url) {
if (!err) {
const options1 = {
method: 'PUT',
url,
headers: {
'cache-control': 'no-cache',
'Content-Type': 'image/png'
},
data: './uploads/test.png'
}
axios(options1)
.then((response) => res.json(response))
.catch((error) => res.json(error.response.data))
}
})
You get errors on Postman because you're sending the request with GET. Change the request method to PUT.
On your code, the root cause of the problem is simply because of a typo. If you check the docs the correct property for your config should be contentType, not ContentType.
Because of the typo, Content-Type is not properly signed in the URL so adding this header on your request will result in a mismatch error.
Here's a fixed version of your code:
const fileD = storage.bucket(bucket).file(file)
const config = {
action: 'write',
expires: '03-17-2025',
contentType: 'image/png'
}
fileD.getSignedUrl(config, async function Sing(err, url) {
if (!err) {
const data = fs.readFileSync('./uploads/test.png')
const options1 = {
headers: {
'Content-Type': 'image/png'
}
}
axios.put(url, data, options1)
.then((response) => console.log(response.status))
.catch((error) => console.error(error.response.data))
}else{
console.error(err)
}
})
For additional reference, see Content-Type in https://cloud.google.com/storage/docs/access-control/signed-urls-v2#string-components

nodejs request post large json fail

I am trying to post large json to a http server(a grafana server actually):
here is my code:
const http = require('http')
const request = require('request')
const fs = require('fs')
const opts = {
hostname: 'myip',
port: 3000,
path: '/api/dashboards/uid/KPEiIQVWk',
method: 'GET',
timeout: 5000,
headers : {
'Authorization' : 'Bearer ********************************************',
'Accept' : 'application/json',
'Content-Type' : 'application/json'
}
}
const req = http.request(opts, res => {
console.log(`Fetch: statusCode: ${res.statusCode}`)
var origin = ''
res.on('data', d => {
origin += d
})
res.on('end', function(){
dash = JSON.parse(origin)
dash.dashboard.panels.forEach(p => {
if(p.id == 26){
fs.readFile(__dirname + '/grafana/pm/branch-graph.html','utf-8', function(err, newPanel){
if(err){
console.log(err)
}
p.content = newPanel
const fresh = JSON.stringify(dash)
const updateOptions = {
uri: 'http://myip:3000/api/dashboards/db',
method: 'post',
headers : {
'Authorization' : 'Bearer *************************',
'Accept' : 'application/json',
'Content-Type' : 'application/json',
'Content-length' : fresh.length
},
json: fresh
}
fs.writeFile('tmp.json', fresh, function(err){
if(err){
console.error(err)
}
})
request(updateOptions, function(error, response, body){
console.log(`update: statusCode=${response.statusCode}`)
console.log(`update: ${body}`)
})
})
}
})
})
})
req.on('error', error => {
console.error(error)
})
req.on('timeout', () => {
req.abort()
})
req.end()
as you can see, I first fetch a grafana dashboard's source, then make some udpate, then post it back to grafana server. but always get 400 error. The strange thing is that if I dump the json to a file and use curl to post, it will work.
curl -vH "Authorization: Bearer $TOKEN" -H "Expect:" -d #tmp.json -H "Content-Type:application/json" http://myip:3000/api/dashboards/db
the whole json is about 40000+ bytes. any hint on this? I am not very famillar with nodejs. I am just trying to write some CI scripts.
First, I don't think it's necessary to use both the http and request modules. http is a module built into nodejs, and request is an npm package.
I recommend you use the npm request package because it's easier. You can read its documentation here: https://www.npmjs.com/package/request#http-authentication
Second, the options you're passing to the request module is not formatted correctly, I think this is why it is not working. With your current code, I would console.log('POST error', error); to print out the error. The correct options for the request module is proposed below.
const options = {
url: 'https://myip:3000/api/dashboards/db',
body: fresh, // the json from the fs.read callback
auth: {
'bearer': 'bearerToken'
},
json: true // from docs: If json is true, then body must be a JSON-serializable object.
}
request.post(
options,
(err, httpResponse, body) => {
console.log(err, body);
});

Sending form in post request using https library

I have to call an api, for which we are using request library.
const options = {
uri: 'https://abcd.com',
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer xxxxxxxxx'
},
form: {
'a':1,
'b':2
}
}
request(options, (e, res, data) => {});
How would I rewrite the same using node's https library.
I tried using https library's https.request() with 'POST' type and .write with form object. Didn't work.
Also changed Content-Type to application/x-www-form-urlencoded, didn't work either
This example is from the documentation using the request package ,the form takes a object consisting of key value pair from that of the form
request.post('http://service.com/upload', {form:{key:'value'}})
// or
request.post('http://service.com/upload').form({key:'value'})
// or
request.post({url:'http://service.com/upload', form: {key:'value'}},
function(err,httpResponse,body){ /* ... */ })
enter link description here
You can read the API docs at: https://nodejs.org/api/https.html
Below code should work fine:
const https = require('https')
const data = JSON.stringify({
'a':1,
'b':2
})
const options = {
hostname: 'example.com',
port: 443,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Length': data.length
'Authorization': 'Bearer xxxxxxxxx'
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()

HTTP call to send data to server using Axios/Axios-retry

I have a JSON object that I wish to send to a server using the server's API key. I wish to have a retry count of 3 so that I can retry sending data if previous calls fail.
I am not sure whether to use 'axios-retry' or 'retry-axios'.
How do I configure the Content-Type in the header, and where do I add the API key and the data to be sent. My present code looks like this:
const axiosRetry = require('axios-retry');
axiosRetry(axios, { retries: 3 });
var data = { /*----My JSON Object----*/ };
axios.post('my url', data, {
headers: {
'Authorization': 'API_Key',
'Content-Type': 'application/json'
}
})
.then(function(response){
console.log(response);
})
.catch(function(error){
console.log(error);
});
Use axios instead, it is a Promise based HTTP client for the browser and node.js
var axios = require('axios')
axios.post(url,data, {
headers: {
'authorization': your_token,
'Accept' : 'application/json',
'Content-Type': 'application/json'
}
}).then(response => {
// return response;
}).catch((error) => {
//return error;
});

Resources