Code dump:
$.ajax({
type: 'GET',
dataType: 'json',
url: api,
xhrFields: {
withCredentials: true
},
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', "Basic [my auth token]");
},
success: function(jd) {
console.log(jd.stringify());
}
});
The problem is that Chrome and Firefox send an OPTIONS preflight when I include a beforeSend, however that OPTIONS request is refused by the API because it doesn't know how to handle an OPTIONS request and treats it like a GET, sees no Authorization header and refuses the request.
The only way I can get this to work is to coerce the browser either to not send an OPTIONS request or include my header with it. I am unable to modify the API that I am using.
I would appreciate it if anyone could advise me.
The reason why browser sends preflight request is that you are using custom headers. Please. read about how to avoid preflight request (content type should be text or html and no custom headers)
If you could not chagne server side the last chance to make it work is to create your custom proxy (for example you can create node server and that node app would take your requests and forward them to those Api Then you will have you own server even in the some domain and this proxy server will send CORS requests to another server domain.
Related
AJAX call:
$.ajax({
url: "http://myserver2:296/api/Demo/HelloWorld",
type: "GET",
dataType: 'JSONP',
jsonp: "callback",
headers: { 'API_KEY': 'mykey09090' },
success: function (result) {
console.log(result);
},
error: ajaxFailed
});
function ajaxFailed(xmlRequest) {
alert(xmlRequest.status + ' \n\r ' +
xmlRequest.statusText + '\n\r' +
xmlRequest.responseText);
}
I get the following error: Failed to load resource: the server responded with a status of 403 (Forbidden). However when I use Postman, I just have to add the headers with the http://myserver2:296/api/Demo/HelloWorld url it returns the string.
Can I please get some assistance to resolve the issue.
My goal, is to allow the origin server along with the API key correctly provided to get the data back from the Web Api.
Adding the API_KEY header to the request triggers your browser to first send a CORS preflight OPTIONS request. Any headers you add to a request other than headers defined as CORS-safelisted request-headers will trigger your browser to send a CORS preflight OPTIONS request.
I can’t tell for sure but it seems like the 403 you’re seeing is from your server responding to that OPTIONS request, and saying it doesn’t expect to get OPTIONS requests and doesn’t allow them.
The reason you don’t get this from Postman is that unlike browser engines, Postman does not implement CORS, so it does not send the OPTIONS request. (Postman does not operate under the same-origin Web-security model that browsers enforce for Web applications.)
So to make your client app work as expected for scripted cross-origin access to that server, you must configure the server to respond in the right way to that CORS preflight OPTIONS request.
I am trying to subscribe an email to a list on mailchimp, I followed the documentation first, made a request using "Postman" added what was needed and everything works just fine, so I tried to do it on my website and it didn't work
I tried to made a simple request with the same values I set on postman, but everytime I try to send the request the response says
XMLHttpRequest cannot load
https://us12.api.mailchimp.com/3.0/lists/xxxxxx/members. Response
to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://mywebsite.com' is therefore not allowed
access. The response had HTTP status code 501.
I tried to find a way to overcome this but it has been impossible
I searched on stackoverflow everybody says to use jsonp or add something to the ajax call or use a mailchimp ajax plugin nothing has worked
I tried diferent stackoverflow posts like this one
Mailchimp subscribe using jQuery AJAX?
but almost all of them say the same
I tried cache: false dataType:jsonp crossDomain: true xhrFields: {withCredentials: true}
Here it is my code, I am using Jquery
$.ajax({
type: "POST",
url: "https://usxx.api.mailchimp.com/3.0/lists/xxxxxxxx/members",
data: { "email_address":email#adress.com, "status":"subscribed"},
headers: {
"Authorization": "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==",
"Content-Type": "application/json"
},
success: function(data){
alert('Thanks for subscribing');
},
error: function(data){
alert('there was an error, try again later');
}
});
I also Thought on creating my own api and then make the call to mailchimp api but I might ran into the same problem
Do you have any suggestions?
Thanks in advance
As charliefl noted, this is a CORS issue. MailChimp doesn't support CORS, mostly because it would require you passing your API credentials to the user of the webpage, allowing them to takeover your entire account.
Your two options for MailChimp are to proxy your requests through a server or, for signing people up to your list, you can build a custom signup form that uses a much more restricted API. The caveat of this second method is that it forces all of your subscribes through MailChimp's double opt-in process.
We are using JIRA 6.4.5 in our company but I am struggeling fetching data from its API REST interface. I have been trying now for the last couple of days, getting stuck on a cross-domain problem or that I don't know the user credentials so I cannot do any server-side either.
Ideally I am having a jQuery page where the user will use his own credentials/session for querying the JIRA data. The JIRA REST API is located at srv1.mydomain.xyz and I am using srv2.mydomain.xyz as my webserver with my code.
I have read the JIRA REST API Reference.
I have tried various Javascript/jQuery stuff - in the below example I am trying to submit 1h 30minutes to a specific issue:
$.ajax({
url: "https://srv1.mydomain.xyz/rest/api/latest/issue/proj-3/worklog",
dataType: "json",
method: "post",
data: { time: "1h 30m",
comment: "Test" }
}).done(function(data) {
alert("Success");
}).fail(function(jqXHR, textStatus) {
alert("Failed");
});
I get this error:
XMLHttpRequest cannot load
https://srv1.mydomain.xyz/rest/api/latest/issue/proj-3/worklog?time=1h+30m&comment=Test.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://srv2.mydomain.xyz' is therefore not
allowed access. The response had HTTP status code 401.
I then looked more in to this and saw that Atlassian has something called Atlassian Connect so I tried with this:
AJS.$.ajax({
url: "https://srv1.mydomain.xyz/rest/api/latest/issue/proj-3/worklog",
type: "post",
dataType: "json",
contentType: "application/json",
xhrFields: { withCredentials: true },
async: false,
method: "post",
data: { time: "1h 30m",
comment: "Test" }
}).done(function(data) {
alert("Success");
}).fail(function() {
alert("Failed");
});
But I get a similar error:
XMLHttpRequest cannot load
https://srv1.mydomain.xyz/rest/api/latest/issue/proj-3/worklog.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://srv2.mydomain.xyz' is therefore not
allowed access.
I have also looked in to if I could do this server-side from my PHP enabled server in the same domain as the JIRA server but as I don't get the base64 encoded credentials when doing a phpinfo() then I don't think I can use this approach either (and I don't want to prompt the user for credentials).
I am painfully aware that my problem is related to cross-domain protection but I cannot find any examples on how to fix it? It would be great if the JIRA server could set a Access-Control-Allow-Origin for certain hosts but I assume this is not a configuration option (I am not in control of the JIRA server).
This is definitely a cross-domain case. And believe me, it exists for your own protection ; )
The method I use is to send the jQuery request to a server-based processing page, which then authenticates and interracts with the Jira server. In your case, since srv1 and srv2 are under the same domain, srv2 (webserver) can talk to srv1 (Jira) using internal IPs (https://10.50.25.87:8080/rest/api/latest/issue/proj-3/worklog, for example) so the cross-domain issue doesn't apply.
It appears that jQuery doesn't send along the Authorization header when sending an OPTIONS request before a POST request (or possibly other types). The server I'm trying to reach is returning a 401 status for the OPTIONS request - how can I force jQuery to include the Authorization header, even in this initial request?
$.ajax({
type: "POST",
url: url,
data: postData,
beforeSend: function ajaxBeforeSend(jqXHR) {
jqXHR.withCredentials = true;
jqXHR.setRequestHeader("Authorization", "Basic " + btoa(encodeURIComponent(escape($username.val())) + ":" + encodeURIComponent(escape($password.val()))));
},
success: runReportUrlCallback,
error: runReportErrorCallback
});
I also tried adding username and password to the ajax options, to no avail.
It seems that the 3rd party server has been configured incorrectly without the OPTIONS request in mind.
W3 states that preflight OPTIONS request must:
Exclude user credentials.
User credentials are defined:
The term user credentials for the purposes of this specification means cookies, HTTP authentication, and client-side SSL certificates
See https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
If the server is in your control then you simply put the OPTIONS request handler in front of your auth check.
If the server is NOT in your control, which seems to be the case here, then you moan at the server administrator explaining they've done it wrong and hope they change it.
I'm developing a javascript app to control some smart TVs but angular pre lights OPTIONS requests before try the POST request (SOAP) I'm trying to send. The devices return a response with a proper Access-Control-Allow-Origin: * but angular refuses to send the POST request.
Of course, I can't change the configurations of the device's server to send another header angular "needs" and I need to send a Cookie and Content-Type.
How can I work around this?
UPDATE with a screenshot of request (bottom) and response (top) headers.
UPDATE with related angular code:
App is configured with:
app.config(['$httpProvider',function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
}])
The request is:
var body = '<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:X_SendIRCC xmlns:u="urn:schemas-sony-com:service:IRCC:1"><IRCCCode>{command}</IRCCCode></u:X_SendIRCC></s:Body></s:Envelope>';
var headers = {
"Content-Type": "text/xml; charset=UTF-8",
"SOAPACTION": "urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"
};
return $http({
method:"POST",
url: "http://{ip}/sony/IRCC".replace("{ip}", config.ip),
data: body.replace("{command}", signal),
headers: headers
});
I believe your problem is withCredentials. When you use withCredentials, the server must indicate that allows credentials. In a simple GET request that doesn't require preflighting, the browser is supposed to keep any such response from your app; in a preflighted request, it should not send the actual request.
Here is the best description at mozilla https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
It says:
but the browser will reject any response that does not have the Access-Control-Allow-Credentials: true header,
and not make the response available to the invoking web content
If you look at the preflight response, you see the headers:
Access-Control-Allow-Headers: "content-type,soapaction"
Access-Control-Allow-Origin: "*"
But the required Access-Control-Allow-Credentials header is not there.
The Options are only fetched if your browser does not know them,
so if you could beforehand load something from the server (regular not via soap) like including an invisible image, your browser should already know the options and not re request them.