Node.js post request not executing callback - node.js

So ive got this function:
async function getRandomNumber(){
const https = require('https');
const url = 'https://api.random.org/json-rpc/2/invoke';
const params:object = {
"jsonrpc": "2.0",
"method": "generateIntegers",
"params": {
"apiKey": process.env.randomApiKey,
"n": 1,
"min": 1,
"max": 10,
},
"id": 42
}
const options = {
hostname: 'https://api.random.org',
port: 443,
path: '/json-rpc/2/invoke',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(JSON.stringify(params))
}
};
const req = https.request(options, (res:any) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk:any) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e:any) => {
console.error(`problem with request: ${e.message}`);
});
// Write data to request body
req.write(JSON.stringify(params));
req.end();
}
which is being called like this:
await getRandomNumber();
But the call back does not log anything, so it seem that the post request is not beeing executed? How can I make this work?
Is it better to use the request module?

The problem is that you are trying to await a callback style function which doesn't return a promise. You need to return a promise to await it.
Regarding request module, i wouldn't suggest using it as it is not maintained. You can read more here
https://github.com/request/request/issues/3142
This also talks about alternative libraries
https://github.com/request/request/issues/3143
One of the library is got which can simplify the work which are doing. the code will look like
const getResponse = await got("http://someurlhere");
console.log(getResponse.body);

Related

Send request with equivalent to Python's bytes() in Node.js

I'm looking to send a request in Node.js which requires sending the data in byte format.
In python, I've implemented it as follow:
r = requests.post(url="https://example.com",headers=headers, data=bytes(exampleArray))
The type of exampleArray is uint8 array
Is it possible to do this same post in Node.js, potentially with axios or another module?
Axios accepts a variety of formats as payload. This is an example with an Uint8Array array:
const axios = require('axios');
const data = new TextEncoder().encode(
JSON.stringify({
foo: 'bar',
})
);
axios
.post('http://localhost:3001', data)
.then((res) => {
console.log(`Status: ${res.status}`);
console.log('Body: ', res.data);
})
.catch((err) => {
console.error(err);
});
The same applies to the http(s) module
const http = require('http');
const data = new TextEncoder().encode(
JSON.stringify({
foo: 'bar',
})
);
const options = {
hostname: 'localhost',
port: 3001,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
},
};
const req = http.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();

Axios POST to URL without urlencoding reserved character

I'm using Axios to POST to an external service where the URL requires including multiple apostrophes. The receiving service does not decode the URL of the received request, forcing us to figure out a way to POST to an unencoded URL.
I've not been able to discern any accessible way in which we could accomplish this.
const response = await axios.post("https://foo.bar/Company('ACME')", body, {
headers: {
Authorization: this.authHeader,
'Content-Type': 'application/json'
}
})
The crux of the issue is having the URL include Company('ACME') without the apostrophes being URL-encoded to %27.
I've figured this to be possible with the native HTTPS module, but I'd like to see if this couldn't be accomplished with Axios (or a similar library).
const https = require('https');
const data = JSON.stringify({
company: 'Acme Corporation'
});
const options = {
"hostname": "foo.bar",
"path": "/Company('ACME')",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Content-Length": data.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();
Is there any way to accomplish this with Axios or a similiar library?

error using nodejs to do http post request

I have followed some instructions to do http request in nodejs and I am doing it in TypeScript in the following way:
code that calls the function to do http post call:
const getCaseInfoRequest: GetCaseInfoRequest = {
emailAddress: 'some-email-address#amazon.com'
};
makeCardinalCall('/SalesforceCaseService/1.0/GetCaseInfoFromEmail', getCaseInfoRequest, process.env.STAGE)
.then((data) => {
...
}).catch(...);
the function that does http post call:
export function makeCardinalCall(path: string, requestBody: GetCaseInfoRequest, stage?: string) {
return new Promise((resolve, reject) => {
const data = JSON.stringify(requestBody);
const options: http.RequestOptions = {
host: 'my-service.google.com',
port: 443,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
}
};
const req = http.request(options, (res: http.IncomingMessage) => {
res.setEncoding("utf8");
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
resolve(data);
})
});
req.on('error', (e: any) => {
reject(e);
});
req.end(data);
});
}
but i always got the following error:
{"bytesParsed":0,"code":"HPE_INVALID_CONSTANT","reason":"Expected HTTP/","rawPacket":{"type":"Buffer","data":[21,0,0,0,2,1,0]}}
any hint / help would be greatly appreciated!
You're attempting to use the raw http module with an HTTPS endpoint (as evident from the port 443). The HTTP parser fails to parse the TLS bytes coming over the wire.
For your own sanity's sake, use a wrapper module for requests -- such as node-fetch...

How to add JSON data in a http post request in AWS lambda?

const http = require('http');
exports.handler = function(event, context) {
var url = event && event.url;
http.post(url, function(res) {
context.succeed();
}).on('error', function(e) {
context.done(null, 'FAILURE');
});
};
I am using this in my AWS lambda code to send http request.
I have a JSON file that has to be sent as a part of this post request.
How to add JSON ? Where do I specify ?
If you are asking from where to pickup that json file form, then s3 would be the correct place to put that file and read form the lambda and do a post.
const obj= {'msg': [
{
"firstName": "test",
"lastName": "user1"
},
{
"firstName": "test",
"lastName": "user2"
}
]};
request.post({
url: 'your website.com',
body: obj,
json: true
}, function(error, response, body){
console.log(body);
});
With just http
const postData = querystring.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// Write data to request body
req.write(postData);
req.end();

Using CSRF Token from GET and Uses that in POST | 403 Forbidden | AWS Lambda

I am creating node.js function through aws lambda which makes a GET request to Hybris Market Place and gets a CSRF Token. Then I am using that token to make another POST request to post some data to Hybris Market place but I am getting an error of 403 Forbidden. Same thing works in Postman which I believe due to POSTMAN keeps GET session alive and hence CSRF token is still valid. How May I achieve that in AWS Lambda function. Below is my code. I am using promise to make two requests.
const https = require('https');
exports.handler = async (event, context, callback) => {
const tokenOptions = {
"host": "*******.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/***********/",
"port": null,
"headers":{
"authorization": "Basic ************=",
"cache-control": "no-cache",
"x-csrf-token": "fetch"
},
"method": "GET"
};
var getToken = (tokenOptions) => {
return new Promise((resolve,reject)=>{
const req = https.request(tokenOptions, (res) => {
var xToken = res.headers["x-csrf-token"];
var sCookies = res.headers["set-cookie"];
var response = [xToken,sCookies]
res.on('data', () => {
console.log('Successfully processed HTTPS response');
resolve(response);
});
res.on('end', () => {
});
});
req.on('error', function(){
reject('Request to get token failed.');
});
req.end();
});
};
var postContent = (response) => {
return new Promise((resolve,reject)=>{
var options = {
"method": "POST",
"host": "*********-***.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/*********/*******",
"port":null,
"headers":
{ "authorization": "Basic *******==",
"x-csrf-token": response[0],
"accept": "application/json",
"content-type": "application/json",
"cache-control": "no-cache",
},
"cookie":response[1],
"body":
{
/* Data I want to POST */
},
"json": true
};
const req = https.request(options, (res,data) => {
console.log(res.statusCode);
res.on('data', () => {
resolve('Successfully submitted.');
});
res.on('end', () => {
});
});
req.on('error', function(err,res){
reject('Request to get Post failed.');
});
req.end();
});
};
getToken(tokenOptions).then((response) =>{
console.log('Result: ' +response[0]);
return postContent(response);
}).then((successMsg) =>{
callback(null,successMsg);
}).catch((errMsg)=>{
callback();
});
};

Resources