I am trying to call a Firebase Cloud function written in python from my website. The function works perfectly when I call it from command line using curl, however, when I try to do the same from JavaScript I am getting the following issue. Essentially the JSON params are not being received.
How I am calling in JavaScript
var xmlhttp = new XMLHttpRequest();
var theUrl = "https://us-central1-scan2checkout.cloudfunctions.net/registerUser";
xmlhttp.open("POST", theUrl,true);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send('{"auth":"ac_Fn0GuKLhuh8yltMVlmFeBkQpdpaTrqug"}');
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
console.log(xmlhttp.responseText);
}
}
Cloud Function
def registerUser(request):
print(request) # Printing '<Request 'http://us-central1-scan2checkout.cloudfunctions.net/' [OPTIONS]>'
print(request.json) # Printing 'NONE' :(
auth = request.json['auth'] # Issue is here
# ... SOME STUFF ...
return {...},201
How it works when I use command line
time curl -v -X POST -d '{"auth":"ac_Fn0GuKLhuh8yltMVlmFeBkQpdpaTrqug"}' -H "Content-type: application/json" https://us-central1-scan2checkout.cloudfunctions.net/registerUser
If you run this now you'll probably get something like "Authorization code expired" which is correct.
To handle this request, you will need to set the appropriate Access-Control-Allow-* headers in your Cloud Function to match the requests you want to accept. Please see an example of a CORS function written in Python.
You will notice that CORS consists of two requests: a preflight OPTIONS request, and a main request that follows it.
The preflight request contains the following headers:
Access-Control-Request-Method - indicates which method will be sent in the main request.
Access-Control-Request-Headers - indicates additional headers along with the origin of the main request.
Let me know if it helps.
Related
I am new to using API's that have authentications, on the pivotal website they have commands using curl commands that look like this
export TOKEN='your Pivotal Tracker API token'
curl -X GET -H "X-TrackerToken: $TOKEN" "https://www.pivotaltracker.com/services/v5/projects/99"
I was wondering how I can convert this to JavaScript by making a request, the problem is I don't know where to put the token when making the request to an API.
So far in JavaScript I have this
function reqListener () {
console.log(this.responseText);
}
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "https://www.pivotaltracker.com/services/v5/projects/99?fields=version");
oReq.setRequestHeader(header, 'Pivotal token');
oReq.send();
Also i dont know what to in place of header.
When you set up your http request put the access token in the headers using the key "X-TrackerToken". I have been using the following headers when making a request:
{
"Content-Type": "application/json",
"X-TrackerToken": apiToken
}
I have been using postman to test an API which, I am successfully able to call.
When I try to execute this call through javascript I get an authentication error.
The URL and authorization match that of the postman call and when I call using these details with curl I am able to retrieve the correct data.
<script type="text/javascript">
var data = new FormData();
data.append("attributeId", "");
data.append("validFrom", "");
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "http:/restpAPI/test");
xhr.setRequestHeader("authorization", "Basic asdsadsadjlafdkfjkldfj==");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("postman-token", "dsadasd-asdsad-asd-asd-aasd");
xhr.send(data);
</script>
When I run a local web page with this script I get a 401 saying Unauthorized.
What is the difference between the JavaScript code and postman or cURL and is there a way of authenticating from JavaScript?
Update
I have discovered that setting the RequestHeader with the authorization key turns the request from a get to an options. This is causing the error.
Although HTTP Headers are supposed to be case insensitive, have you tried setting the headers' names with title case (Authorization)?
I am trying to make request with XMLHttpRequest from file://example.html to http://localhost/index.php. I read a lot about CORS(in this case origin is null, this is OK.) and i have no idea what i am doing wrong.
My request finishes well but the $_POST is empty! Except if i set "Content-type: application/x-www-form-urlencoded". But "text/plain" or "application/json" gives no result in $_POST... Why?
xhr.open("POST", "http://localhost/index.php", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = handler;
xhr.send({'a':'12'});
You are probably doing one of these two things wrong:
If the content-type is not application/x-www-form-urlencoded, CORS must send a preflight request. That means that the browser will send before doing the POST request an OPTIONS request, which is used to determine if the POST request is allowed. Take a look here how this works.
Secondly, if you use xhr.setRequestHeader("Content-Type", "application/json"), the $_POST parameters will not be filled with parameters, this is only the case for application/x-www-form-urlencoded. To get the JSON you send, you will have to do:
<?php
$input = json_decode(file_get_contents("php://input"), true);
echo $input['a']; //echoes: 12
For more info, see this question.
Furthermore, if you go into the debugging facilities of any decent browser, it will create an error message if the CORS request is not allowed, please be sure to check if the CORS request was actually made by the browser.
I hope this helps you.
complementing #user23127 response
server side should have something like this to respond to the OPTIONS preflight request:
if (request.method === 'OPTIONS') {
htmlRes = HttpResponse()
htmlRes['Access-Control-Allow-Origin']='*' // or your not origin domain
htmlRes['Access-Control-Allow-Methods']='*' // or POST, GET, PUT, DELETE
htmlRes['Access-Control-Allow-Headers']='*' // Content-Type, X-REQUEST
}
// the rest of the code as if it was not a CORS request
Hi I'm working on connecting to an API that is using Layer 7 as an IP authorizer and eGalaxy as a credentials authorizer, when the curl request is sent a line of xml is sent back to me. I'm currently working on localhost, I've implemented the Access-Control-Allow-Origin chrome extension.
My curl request looks as such:
curl https://client-url/eGalaxy.aspx -H 'Content-Type:text/html' --data '<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header><SourceID>0</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password*</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>' --insecure
When I tried to create an ajax request I receive an "Invalid HTTP status code 500" error and "OPTIONS url" which drops down to show:
n.ajaxTransport.k.cors.a.crossDomain.send # jquery-2.1.3.js:4
n.extend.ajax # jquery-2.1.3.js:4
(anonymous function) # VM947:2
InjectedScript._evaluateOn # VM899:895
InjectedScript._evaluateAndWrap # VM899:828
InjectedScript.evaluate # VM899:694
My ajax code is as follows:
$.ajax({
url:'https://client-url/eGalaxy.aspx',
data:'<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header>
<SourceID>0</SourceID><MessageID>131</MessageID>
<MessageType>Authenticate</MessageType></Header><Body>
<Authenticate><Username>*username*</Username>
<Password>*password*</Password>
<PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body>
</Envelope>',
type:'POST',
contentType:'text/xml',
dataType:'xml',
success: function(data){
},
error: function(){
}
});
Any help with translating into a proper AJAX request would be appreciated!
EDIT: If this makes a difference these are the headers that are returned with the client's xml when the curl is complete(client information deleted)
This application will be made into a widget as well, so it will not be running off of a hosting site.
UPDATE 1: I'm using #KevinB's suggestion that the CORS headers were still not properly added.
Here is my updated JS code, copied from this link:
var url = 'https://client-url/eGalaxy.aspx';
var data = '<?xml version="1.0" encoding="UTF-8"?><Envelope><Header><SourceID>1</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>';
var xhr = createCORSRequest('POST', url);
xhr.send(data);
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
When run with the CORS Chrome extension off I receive an Access-Control-Allow-Origin =! 'null' error. Knowing that CORS needs Access-Control-Allow-Origin header to =! 'null' will this cause problems in the future with making this into a widget that will be put into a Content Manager system?
With it on the origin is set to 'www.evil.com', with the only error in the code being that it says the xhr.send() is an anonymous method. Using breakpoints I can see the xhr in xhr.send() is set to an empty request:
> XMLHttpRequest {response: "", responseText: ""}
Inside the createCORSRequest this line is undefined. I've tested using 'GET' and 'POST' as the method.
xhr.open(method, url, true)
EDIT 2:
Using #Fabiano's approach I've changed the web.config for two versions of what I suspect is my server(?). I'm attaching screenshots of what I've gone through
No luck, so far. Decided to use xhr.AppendHeader:
I decided to use xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
The Network tab Headers for eGalaxy.aspx
There is an error in your XML. You put version:"1.0", and this makes the XML invalid.
Change to version="1.0" and try to make your request. It should work.
This may be the cause for the "Bad request" error.
You can validate your XML here: enter link description here
EDIT: After some research, the problem may be with the headers sent by your server. Your server (or page, .aspx in this case) seems to skip the header you need, the "Access-Control-Allow-Origin: *".
Look at this link: http://enable-cors.org/server.html
This site shows you how to implement it for your server. Since the page you are requesting is called eGalaxy.aspx, then you have 2 ways to implement the headers:
1- Put the line Response.AppendHeader("Access-Control-Allow-Origin", "*"); if the page is a simple ASP.NET application. If it uses Web API 2, you need to implement a different way as it is shown here: http://enable-cors.org/server_aspnet.html
2- Edit the web.config file on the root of your server and add these lines inside the tag:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
For a ASP.NET application, these are the ways you have. The link I mentioned has solutions for other applications, take a look and choose the right one. :)
Note that the value * tells you that your server will accept any cross-origin request. This may lead to a security issue, so the best you can do is to put your domain address instead of *.
I hope it helps!
I use JS automation framework for testing iOS application. In the middle of a test I need to create POST request to server to some money to user and then verify that changes are reflected in UI.
Request looks like: wwww.testserver.com/userAddMoney?user_id=1&amount=999
but to authorize on server I need to pass special parameters to Header of request:
Headers: X-Testing-Auth-Secret: kI7wGju76kjhJHGklk76
Thanks in advance!
So basically you want to set the header of a POST request. You can do it only if its an ajax request (You can't set headers for a normal html form submission request). Here is a way to set headers for an ajax request:
var request = new XMLHttpRequest();
request.onreadystatechange= function () {
if (request.readyState==4) {
//handle response
}
}
request.open("POST", "url", true);
request.setRequestHeader("header", "blah blah");
request.setRequestHeader("Accept","text/plain");
request.send("post data");