NodeJS XML HTTP POST request headers object not accepting - javascript

I am trying to get a Ping message back from an API of a channel manager for hotels. (XML Open Travel Alliance)
I made the HTTP XML POST request first with SoapUI-5.3.0 tool including the following parameter:
otaRQ: <OTA_PingRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="3.30" TimeStamp="2011-07-24T10:07:24" Target="Production"> <EchoData><![CDATA[Hello World!!]]> </EchoData> </OTA_PingRQ>
and received the following XML response:
<OTA_PingRS PrimaryLangID="en" Target="Production" TimeStamp="2017-03-21T09:43:55" Version="3.00" xmlns="http://www.opentravel.org/OTA/2003/05">
<Success/>
<EchoData>Hello World!!</EchoData>
</OTA_PingRS>
I included the same parameter in the http POST request in NodeJS in the options variable in the headers object. (see code below)
Still I recieve the following response: 200 "'otaRQ' is missing in post-form data!"
So my question is, how do I get the same response like with SoapUI-5.3.0?
Thanks a lot for the efforts!
var http = require('http');
var body = '<OTA_PingRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="3.30" TimeStamp="2011-07-24T10:07:24" Target="Production"> <EchoData><![CDATA[Hello World!!]]></EchoData> </OTA_PingRQ>'
var postRequest = {
hostname: "cultswitch.cultuzz.de",
path: "/cultswitch/processOTA",
method: "POST",
port: 8080,
headers: {
'otaRQ': '<OTA_PingRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="3.30" TimeStamp="2011-07-24T10:07:24" Target="Production"> <EchoData><![CDATA[Hello World!!]]> </EchoData> </OTA_PingRQ>',
'Cookie': "cookie",
'Content-Type': 'text/xml',
'Content-Length': Buffer.byteLength(body)
}
};
var buffer = "";
var req = http.request( postRequest, function( res ) {
console.log( res.statusCode );
var buffer = "";
res.on( "data", function( data ) { buffer = buffer + data; } );
res.on( "end", function( data ) { console.log( buffer ); } );
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write( body );
req.end();
Excerpt from channel manager provider:
The data exchange will be carried out using the standard HTTP protocol. The
request message should be sent as POST-DATA within a parameter called 'otaRQ'
and the reply message will be written directly into the HTTP-Response by the
CultSwitch. CultSwitch accepts request in "text/xml" format only. CultSwitch also
supports gzip compression for every request and response. The requesting system
should set proper request headers. "PrimaryLangID" is mandatory to post any
request to CultSwitch.

I see that it requires your parameter be called otaRQ. You have not done that. Try this:
var body = 'otaRQ=<OTA_PingRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="3.30" TimeStamp="2011-07-24T10:07:24" Target="Production"> <EchoData><![CDATA[Hello World!!]]></EchoData> </OTA_PingRQ>'

Since your error message says that you are missing post-form data, try setting your content-type header to "application/x-www-form-urlencoded".
So, 'Content-type': 'application/x-www-form-urlencoded',

Related

Error 400 Cognito /oauth2/token endpoint from client-side javascript

I am using AWS Cognito-hosted UI for my signup and login. There is no app client secret defined.
I am trying to make an API call from the browser javascript code to the /oauth2/token endpoint in order to exchange autohorization_token with an ID token.
The problem is, when I make the call through Postman, Insomnia it works fine. However, when I make the same call through javascript from the browser it fails with the 400 response type and I can't get much about the reason.
This is the Insomnia call which is a success;
However, when I make the same call via javascript it fails.
I have used both fetch and XMLHttpRequest and the same result.
const XHR = new XMLHttpRequest();
let urlEncodedData = "",
urlEncodedDataPairs = [],
name;
urlEncodedDataPairs.push( encodeURIComponent( 'grant_type' ) + '=' + encodeURIComponent( 'authorization_code' ) );
urlEncodedDataPairs.push( encodeURIComponent( 'code' ) + '=' + encodeURIComponent( code ) );
urlEncodedDataPairs.push( encodeURIComponent( 'client_id' ) + '=' + encodeURIComponent( 'xxxxx' ) );
urlEncodedDataPairs.push( encodeURIComponent( 'redirect_url' ) + '=' + encodeURIComponent( 'https://www.xxx.me/xxx' ) );
XHR.addEventListener( 'load', function(event) {
alert( 'Yeah! Data sent and response loaded.' );
} );
// Define what happens in case of error
XHR.addEventListener( 'error', function(event) {
alert( 'Oops! Something went wrong.' );
});
// Set up our request
XHR.open( 'POST', 'https://xxx.auth.us-west-2.amazoncognito.com/oauth2/token' );
// Add the required HTTP header for form data POST requests
XHR.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
// Finally, send our data.
XHR.send( urlEncodedData );
This is the response I am getting:
I have tried the same request with fetch and the result is the same.
let tokenRequest = new Request(tokenURL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Origin' : 'https://www.xxx.me'
},
body: new URLSearchParams({
'grant_type': 'authorization_code',
'code': code,
'client_id': 'xxx',
'redirect_url': 'https://www.xxx.me/xxx'
}).toString()
});
let response = await fetch(tokenRequest);
let data = await response.json();
One thing I have realized when I check the browser developer tool for other POST calls made to auth endpoints with content type=application/x-www-form-urlencoded, it shows query params added to URL like shown below, however, for my call, params are not encoded as part of URL. I am not sure if the problem might be related to this.
Any idea how I can make this call with client-side javascript?
Looks like the browser is using redirect_url which is wrong, and Postman is using redirect_uri which is correct. Also you should use PKCE to make the message more secure - see steps 4 and 8 of my blog post to understand how this looks.
Note also that in OAuth it is common to not return error details, or return to the app, if an unrecognised Client ID or Redirect URI are supplied. If these are both correct you should instead receive the standard OAuth error and error_description fields in a response payload.

Error sending AJAX POST request from local .html file to localhost:8080. CORS: "It does not have HTTP ok status."

I am getting an error when attempting to send a POST via AJAX from my own .html and .js files to localhost:8080. Upon submitting the request, the full error reads: "Access to XMLHttpRequest at 'http://localhost:8080/contact/new-message' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
CORS is already enabled on my browser, so access is automatically "Access-Control-Allow-Origin : *", so this is a different from that error.
Is there a way to include an "ok" status in the header? Or is the problem arising from elsewhere? Any help is greatly appreciated. Here are some code snippets:
My JavaScript, which runs as part of a form-submission:
function submitMessageAJAXCall(inputName, inputEmail, inputMessage, inputRegion) {
$.ajax({
type: 'POST',
url: 'http://localhost:8080/contact/new-message',
data: JSON.stringify({
rbName: inputName,
rbEmail: inputEmail,
rbMessageText: inputMessage,
rbRegionId: inputRegion
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
success: function() {
alert('Success!');
displayThankYouMessage();
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Unfortunately that message did not go through.');
}
});
}
The Java code which recieves it:
#PostMapping("/new-message")
private ResponseEntity<HttpStatus> addNewMessage(#RequestBody RBNewMessage rbNewMessage) {
//validate message in service layer
boolean isRequestValid = contactService.validateNewMessageRB(rbNewMessage);
//is message is good, save it; else, return an error
if (isRequestValid == true) {
//create a new message
ContactMessage message = new ContactMessage();
//set message fields
message.setMyName(rbNewMessage.getRbName());
message.setMyEmail(rbNewMessage.getRbEmail());
message.setMessageText(rbNewMessage.getRbMessageText());
LocalDateTime timeOfMessage = LocalDateTime.now();
LocalDateTime timeWithoutNano = timeOfMessage.withNano(0);
message.setTimeStamp(timeWithoutNano);
int regionId = rbNewMessage.getRbRegionId();
Region region = regionService.getRegionById(regionId);
message.setRegion(region);
ContactStatus cs = contactStatService.getStatusById(1);
message.setContactStatus(cs);
//save message
contactService.save(message);
//return success
return new ResponseEntity<>(HttpStatus.OK);
} else {
//return error
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
And this is an example of a Postman request that is successful:
{
"rbName": "John Johnson",
"rbEmail" : "JohnJohnson#Email.com",
"rbMessageText" : "Hello there, this is my message.",
"rbRegionId" : 5
}
Add #CrossOrigin annotation (import org.springframework.web.bind.annotation.CrossOrigin) to the top of the controller class that is handling the request.

Nodejs request post with body include api key

I have been trying about a week but I couldn't make a post request to get a result.
I tried a bunch of middlewares (exp: 'request', 'axios', 'reqclient','superagent etc..) but I couldn't make it.
Please provide me a simple post request with sending API key and body.
I also read all the documentation.
Please check below to see what I want :
*Authentication API key required.
*O-Auth Scopes trades
*Input One of: user_id + token or user_url is required.
here is my one of try :
const request = require('request-promise')
const options = {
method: 'POST',
uri: 'api-site.com/Offer/v1/',
headers: {
'User-Agent': 'Request-Promise',
'Authorization': 'Basic 123123asdasd123123'
},
body: {
user_url: "site.com/user/user1234123",
otherparams: "parameter"
},
json: true
};
request(options)
.then(function (response) {
Console.log(response);
})
.catch(function (err) {
console.log('Error ', err.message);
});
I am getting this output :
Error : 401 - {"status":401,"time":1540458426,"message":"API Key Required"}
I tried some other request post middle-wares and played with content-type (application/json. dataForm, x-www-form-urlencoded) or
changed the location of my API key from header to body or
tried my API key inside of auth{authorization: "API Key"}
tried much more.
the result didn't change. I got the same output or errors.
EDIT :
this is the link that I am trying to do but got stack :
check here
Solved !
Everything works great. Problem was I needed to send my API Key base64 string.
Buffer.from("your_api_key_value" + ":", "ascii").toString("base64")

HTTPS request not posting body of REST request

I'm trying to POST to an API endpoint on my server. I know my endpoint works because if I use Advanced REST Client, I can hit it and get a JSON response as expected. The problem seems to be that no data is being sent in the body of my request despite calling request.write(postData) which contains a key, value pair. Without this data being sent in the body, my server returns a 401 error as expected without this information. Printing out the content of the POST server-side is empty but I'm clueless as to why it's empty.
var postData = querystring.stringify({
"access_token" : accessToken,
"id": applianceId
});
var serverError = function (e) {
log("Error", e.message);
context.fail(generateControlError(requestName, "DEPENDENT_SERVICE_UNAVAILABLE", "Unable to connect to server"));
};
var callback = function(response) {
var str = "";
response.on("data", function(chunk) {
str += chunk.toString("utf-8");
});
response.on("end", function() {
result = generateResult(CONTROL, requestName.replace("Request", "Confirmation"), messageId);
context.succeed(result);
});
response.on("error", serverError);
};
var options = {
hostname: REMOTE_CLOUD_HOSTNAME,
port: 443,
path: REMOTE_CLOUD_BASE_PATH + "/" + endpoint,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
var request = https.request(options, callback);
request.on("error", serverError);
//This doesn't seem to write anything since if I print out the POST
//data server-side it's empty; however, if I print out the value of
//postData here, it looks as expected: 'access_token=xxxxx'
request.write(postData);
request.end();
I have testing you code again httpbin.org/post and it seems that it is working.
I believe that the issue related to, that your should POST application/json and not "application/x-www-form-urlencoded
Please try to change the header
headers: {
"Content-Type": "application/json"
}
Then, try to change the postData to JSON string:
var postData=JSON.stringify({access_token:"xxxxx"})
To be sure that problem you success to send and the problem is not local (maybe there is an issue in your server), change the target to mirror URL:
var options = {
hostname: "httpbin.org",
path:'/post',
port: 443,
method: "POST",
headers: {
"Content-Type": "application/json"
}
};
If there is no problem in your NodeJS version, the is the response you should get: (It is mean that the server got the posted data)
{
"args": {},
"data": "{\"access_token\":\"xxxxx\"}",
"files": {},
"form": {},
"headers": {
"Content-Length": "24",
"Content-Type": "application/json",
"Host": "httpbin.org"
},
"json": {
"access_token": "xxxxx"
},
"origin": "5.29.63.30",
"url": "https://httpbin.org/post"
}
BTW: I really recommend you to move to a library to manage the request for you:
https://github.com/request/request - Very popular
https://github.com/request/request-promise - For popular who like to use the Promise syntax (The next thing in JavaScript)
https://github.com/visionmedia/superagent - For people who like to write same code in Browser & Server

"JSON_PARSING_ERROR: Unexpected character (d) at position 0." when sending GCM request from GAS

This seems very similar to a number of other questions and it seems obvious that the error indicates there's something wrong with my JSON payload. But I'm at a loss as to why.
I'm running a Google Apps Script to test sending a message to Google Firebase Cloud Messaging.
My code:
function SendGCMessage() {
var url = "https://gcm-http.googleapis.com/gcm/send";
var apiKey = "AbCdEfG";
var to = "ZyXwVuT:ToKeNtOkEnToKeNtOkEnToKeNtOkEn"
var payload = {
"data": {
"message" : "This is the message"
},
"to":to
};
var sendCount = 1;
var headers = {
"Content-Type": "application/json",
"Authorization": "key=" + apiKey
};
var params = {
headers: headers,
method: "post",
payload: payload
};
var response = UrlFetchApp.fetch(url, params);
return {message: "send completed: " + response.getContentText()};
}
When I run this in debug mode, the object payload looks fine - like a normal Javascript object. params as well. UrlFetchApp takes a Javascript object, not a String in JSON notation. However I did try "JSON.stringify(params)" and I got an error. What did I do wrong?
Note: params looks like this when I pause it in the debugger:
{"headers":{"Content-Type":"application/json","Authorization":"key=AbCdEfG"},"method":"post","payload":{"data":{"message":"This
is the message"},"to":"ZyXwVuT:ToKeNtOkEnToKeNtOkEnToKeNtOkEn"}}
I discovered the problem, thanks to https://stackoverflow.com/a/10894233/3576831
the 'payload' parameter must be a string as specified here:
https://developers.google.com/apps-script/class_urlfetchapp?hl=fr-FR#fetch.
Adjusting this section of the script works:
var params = {
headers: headers,
method: "post",
payload: JSON.stringify(payload)
};

Categories