nodejs request post large json fail - node.js

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

Related

Why i am getting unable to open document error or blank pdf in opening a pdf on client side?

I am hitting a get api in react similar to http://www.orimi.com/pdf-test.pdf which needs some secret information which is available only at middleware written in node. I want to open the pdf on client side(browser). So I am hitting the proxy get api which will hit the middleware and middleware will hit the backend server, but I am getting unable to open document and blank pdf. Can anyone tell me what is wrong with this code?
fetch(pdfApiMiddlewareUrl, {
method: "GET",
headers: {
"Content-Type": "application/pdf",
'Content-Disposition': 'inline; filename=your_file_name'
},
responseType : 'blob'
})
.then(res => res.blob())
.then(response => {
var blobUrl = URL.createObjectURL(response);
window.open(blobUrl);
})
.catch(error => {
console.log("HEREEEEEEEE");
console.log(error);
});
MIDDLEWARE CODE:
var urlEndPointsToHit = decodeURIComponent(req.query.urlToHit);
var url = urlEndPointsToHit+'?secret='+secretInfo;
var options;
options = {
url: url,
method: 'GET',
headers: {
'Content-type': 'application/pdf'
},
};
if(options) {
options.qs = req.query || {};
}
request(options, function(err, resp, body) {
req.locals = body;
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Cache-Control', 'no-cache');
next();
});

Always get 502 error when calling AWS lambda endpoint from Node Js using `requestjs`

trying to post data in our AWS serverless api using Nodejs Request package but always get 502 error and can post data from the front end app (React or Jquery).
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
request(
{ method: 'POST'
, uri: 'url here...'
, headers: {
'User-Agent': 'request'
} , multipart:
[ { 'content-type': 'application/json'
, body: JSON.stringify(dataToPost)
}
]
}
, function (error, response, body) {
if(response.statusCode == 201){
console.log('document saved')
} else {
console.log('error: '+ response.statusCode)
console.log(body)
}
}
)```
If you are able to post data using react and Jquery then probably you are not making a post request correctly.Try this code for post request :
const request = require('request');
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
const options = {
url: 'url goes here',
json: true,
body: dataToPost
};
request.post(options, (err, res, body) => {
if (err) {
return console.log(err);
}
console.log(`Status: ${res.statusCode}`);
console.log(body);
});
Alternatively you can also use axios which makes code more readable and have inbuilt promise support:
const axios = require('axios');
var dataToPost = {
name: 'ABC',
address: 'XYZ'
}
const url = 'put url here'
axios.post(url, data)
.then((res) => {
console.log(`Status: ${res.status}`);
console.log('Body: ', res.data);
}).catch((err) => {
console.error(err);
});
Also check what does AWS Lmbada logs says.

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

make a post request with in node.js application

I've a node.js service with /api/authenticate endpoint. I can call this service successfully from POSTMAN with 'username' and 'password' as input (body parameters). How do I call the same services from another node.js server?
With postman I get,
body: {name: 'xxxxxx', password: 'xxxxxx' }
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
Following is another nodejs application ... which makes a successful request call but doesn't have any body parameters (username and password) when it reaches to the authentication server api.
var my_http = require('http');
app.get('/makeacall', function(req, res) {
var output = '';
var options = {
body: { name: 'xxxxxx', password: 'xxxxxx' },
method: 'POST',
host: 'xx.xx.xx.xx',
port: 'xxxx',
path: '/api/authenticate',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
console.log('before request');
var req = my_http.request(options, function(response) {
console.log('response is: ' + response);
console.log('Response status code: ' + response.statusCode);
response.on('data', function(chunk) {
console.log('Data ..');
output += chunk;
});
response.on('end', function(chunk) {
console.log('Whole Data ..' + output);
});
});
req.on('error', function(err) {
console.log('Error: ' + err);
});
req.end();
console.log('444');
res.send({ message: 'View record message'});
});
From this nodejs application I get empty body on the server.
body: {}
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
What am I missing? Any help is appreciated.
Using stock http library of NodeJS doesn't allow you to use that syntax.
Take a look at RequestJS as a much simpler solution. It will make your life a lot easier and allow you to use the syntax you want.
This is the solution to do it with stock Node.
https://nodejs.org/api/http.html#http_http_request_options_callback
Relevant Parts:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
And then, at the end:
// write data to request body
req.write(postData);
req.end();
But use a library unless you absolutely can't.
Are you trying to get the posted data from a form/etc?
Try using express.
npm install express -save
You can get posted data from a url with the ff:
app.post('*', function(request, response){
var post = {};
if(Object.keys(request.body).length){
for(var key in request.body){
post[key] = request.body[key];
console.log(key+'=>'+post[key];
}
}
});

Testing express app with mocha

I have the following request that I need to test:
curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"content":{"value":"18.5", "date": "20120413"}}' 'http://SERVER:PORT/marks'
I'm using expressjs and mocha. I did not find the way to add some header and specify some json parameters in a mocha's request:
it('Checks creation of a new mark', function(done){
request.post('http://SERVER:PORT/marks', function(err, response, body){
// Some headers and parameters should be set in the request
response.statusCode.should.equal(201);
done();
});
});
The test below (GET request) works well though:
it('Checks existence of marks for user dummyuser', function(done){
request.get('http://SERVER:PORT/user/dummyuser/marks', function(err, response, body){
response.statusCode.should.equal(200);
done();
});
});
UPDATE
The following works like a charm: (I though request what some kind of variable created by mocha).
request(
{ method: 'POST'
, uri: 'http://SERVER:PORT/marks'
, headers: { 'content-type': 'application/json' , 'accept': 'application/json' }
, json: { "content":{"value":"18,5", "date": "2012-04-13"} }
}
, function(err, response, body){
response.statusCode.should.equal(201);
done();
});
Take a look at the documentation. There is a great explaination of how to do a post with custom headers. One way of doing it which works for me could be the following.
var options = {
host: 'localhost',
port: 80,
path: '/echo/200',
method: 'POST',
headers: {
"X-Terminal-Id" : terminalId
}
};
var data = ""
var req = https.request(options, function(res) {
res.on('data', function(d) {
data += d;
});
res.on('end', function(err){
//Check that data is as expected
done(null, data)
})
});
req.end();
req.on('error', function(err) {}
done(err)
});

Resources