Axios POST to URL without urlencoding reserved character - node.js

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?

Related

NodeJS request get return me html code instead of json

I'm trying to get get a json from a get request it's work in python but in NodeJs that display me the html code source of the page
this is my code :
app.get("/well", function(request, response) {
const req = require('request');
const options = {
url: 'https://swarmmanager.francecentral.cloudapp.azure.com:3000',
method: 'GET',
headers: {
'Accept': 'application/json',
},
agentOptions: {
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
}
};
req(options, function(err, res, body) {
console.log(body);
});
});
and this is another version but same problem:
app.get("/well", function(request, response) {
g_CnieOidcAddr = 'https://swarmmanager.francecentral.cloudapp.azure.com:3000';
const options = {
hostname: 'swarmmanager.francecentral.cloudapp.azure.com',
port: 3000,
method: 'GET',
headers: {
'Accept': 'application/json',
},
ca: fs.readFileSync("public/IdaktoPKIRootCA.crt")
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
});
i try to do it in python and it's work find that return me a json:
headers = {'Accept': 'application/json'}
r = requests.get(g_CnieOidcAddr + '/.well-known/openid-configuration', params={}, headers = headers, verify='./IdaktoPKIRootCA.crt')
print (r.text)
if anyone has an idea i'm a taker ^^ thanks for reading.
ok that work find i just forgot something at the end of the url so if you come to this page the 2 codes work find to to a request

Node.js post request not executing callback

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

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

How to authenticate using appid and appsecret in nodejs using https request

Here is the sample code for my application. Why It's not working ?
Error:
"{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}"
var post_data = JSON.stringify({
'appid' : results.appid,
'appsecret': results.appsecret,
});
var url = serviceUrl+"/oauth-service/oauth/token?grant_type=client_credentials";
var post_options = {
host: url,
headers: {
'Content-Type': 'application/json'
},
data:post_data
};
const req = https.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data',function(chunk){
console.log(chunk);
});
});
req.write(post_data);
req.end();
From the HTTPS request side, you don't need to have data in post_options (the data is sent using write).
More importantly, you need to set the Content-Length header to Buffer.byteLength(post_data).
Also, the host (or hostname) field should contain just the hostname (e.g. www.facebook.com - no https:// is needed) and the rest of the URL (e.g. /oauth_service/...) should be put in the path field.
Here's an example adapted from the node.js docs. They only provide examples for http but it's mostly the same as for https:
const postData = JSON.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = https.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.write(postData);
req.end();
Note that without specifying which service you're working with, it's impossible to say whether you're implementing the protocol correctly (e.g. whether the URL is correct, whether your request body is correct, etc.). So if you fix the Content-Length and things still don't work, please provide more information.

Resources