I have read about CORS many times in the past, and understand what it is. I am currently trying to make a POST request to an endpoint that I have been provided, but I keep getting a CORS error.
I have been ensured that the POST request can be made by the owner of the endpoint, so I want to confirm I am not doing anything wrong by checking on this forum.
this is the latest code that I am using:
$.post({
url: "http://working-api-apparently.com",
data: {
"name": "Paul",
"about": "I want to fix this",
"urls":"['paul.com', 'paul2.com']"
},
contentType:"application/json"
});
I have also tried using a callback with jsonp, but this doesnt work as the endpoint doesnt allow GET requests.
The instructions I have been provided are:
POST to http://working-api-apparently.com
With Content-Type set to "application/json", and a JSON document as body with the following keys:
"name": Your real name as a String
"about": about as string
"urls": Array of Strings
I have tried writing the request in both plain javascript and also using jquery. Can anyone help and let me know what I am doing wrong before I respond by saying it is not working due to a fault on their end.
Also, I am making this request from my local machine, but also tried from a http: address
You are claiming to be sending JSON, but you aren't actually passing JSON.
To do that, you need to encode the data:
data: JSON.stringify({
"name": "Paul",
"about": "I want to fix this",
"urls":"['paul.com', 'paul2.com']"
}),
Fixing that is unlikely to resolve cross origin issues though. It is possible that the instructions are you are following are for a generic REST client and that the server doesn't provide the CORS headers that are required for you to do cross origin requests from JS in a web page. (These are required because you aren't making the request, you are asking the user's browser to make it with the user's identity).
Related
I am trying to get the csv data from a url from the nrel developer website. Unfortunately I can't work with json data because it will send it to the email, while the csv file is immediate. I could achieve this using vba using the following:
With req
.Open "GET", parsedUrl, False
.SetRequestHeader "Content-Type", "text/csv;"
.Send
End With
result = Split(req.responseText, Chr(10))
'do work with result
However, working with javascript and the excel addins documentation I am not able to store the csv data on a variable.
I tried the following code
const res = await fetch(tmyUrl, {
method: "GET",
headers: {
"Content-Type": "text/csv;",
},
});
if (!res.ok) throw new Error("There was a problem trying to get the the weather data.");
But this gives me the following error:
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I also tried adding the following:
mode: "no-cors"
But the res.ok is false and the body seems to be empty.
It takes a little time to process this request, so I know it is doing something in the background.
I also could trigger the download using downloadjs but I don't need to download, I just need to temporary store the data in a variable.
Any help or advice please.
I also tried adding [mode: "no-cors"] but... the body seems to be empty.
This is precisely because you're calling the endpoint with mode: no-cors. This behavior is well-documented, and discussed at length in this SO thread. From the linked MDN page (emphasis mine):
no-cors — Prevents the method from being anything other than HEAD, GET or POST, and the headers from being anything other than simple headers. If any ServiceWorkers intercept these requests, they may not add or override any headers except for those that are simple headers. In addition, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues arising from leaking data across domains.
The reason you're seeing CORS errors in the first place is that the server that's responding to your request has deliberately been configured this way to prevent these types of requests on its resources. You can bypass this by making the request to your own server (which allows CORS), which can then proxy the ultimate request to the service and return the response to your client. There used to be several prominent drop-in services that provided this functionality, but most have gone by the wayside due to service abuse (CORS Anywhere and Whatever Origin, to name two).
There still exists one service that appears to still proxy these types of requests - All Origins. Drop in your URL according to their documentation to effectively bypass this restriction:
const res = await fetch(`https://allorigins.win/get?url=${encodeURIComponent(tmyUrl)}`, {
method: "GET",
headers: {
"Content-Type": "text/csv;",
},
});
Be forewarned, you really, really need to trust this service to use this in any project. By routing your requests through their service, you are implicitly allowing them to snoop on your traffic uninhibited and potentially return malicious content to your clients. It's a much better idea to do this on your own server that you control.
A while ago I created a chrome extension called MalOnTheGo. It has been working well however chrome is now dropping support for the way I access resources from an API. The Chromestatus for the drop can be found here. They are dropping support for a format of urls called Embedded Credentials. I have looked for alternatives however I haven't been able to find anything.
In the API documentation they specify formatting the link in the same way I do using jQuery with the username and password parameters like this :
"Usage Examples:
CURL:
curl -u user:passwordhttps://myanimelist.net/api/account/verify_credentials.xml
This is one of the code snippets that chrome is alerting me will not work at some point in June.
function verifyCredentials(username, password, error, success) {
$.ajax({
"url": "https://myanimelist.net/api/account/verify_credentials.xml",
"error": error,
"username": encodeURIComponent(username),
"password": encodeURIComponent(password),
"success": success
});
}
The API's documentation states that this is the way to access that resource.
Is there anything I can change on my end or is this the only way I can use it and the API developers need to update their implementation?
Any alternatives to what I currently have would help
Thanks
You may find CORS to be helpful for making a cross-domain request to verify credentials. There is a lot of helpful info in this tutorial:
https://www.html5rocks.com/en/tutorials/cors/
You can still use ajax to make your request, you will just need to add some more headers for authentication. There is a section specifically for Chrome extensions as well:
https://www.html5rocks.com/en/tutorials/cors/#toc-cross-domain-from-chrome-extensions
I have already published a app script, and I test the query string in the browser, and it works well. I would like to send a xmlhttprequest to the script, but it shows =>
XMLHttpRequest cannot load https://script.google.com/macros /s/XXXXXXXXXX/exec. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://docs.google.com' is therefore not allowed access.
This is the app script code:
function doGet(e){
Logger.log(e.parameter.id);
//other function
return ContentService.createTextOutput("Hello World");
}
Here is the client code:
$.ajax({
url:'https://script.google.com/macros/s/XXXXXXXX/exec',
method:'POST',
data:{
id: "123123"
},
success:function(){
console.log("success");
}
});
There are a few possibilites, and I have ran into this error before myself. As I have insufficient reputation to comment and ask for clarification, I will write the most probable cause.
This problem has 2 parts - You can't post (unstringified) objects, and errors on google apps script do not have CORS headers
solution: stringify and parse the object
Without converting the object to a string, your browser will just send [Object object] and not the information.
This will cause an error on your script, and error messages by Google Script are HTML webpages that don't have CORS headers, which triggers the CORS error that does not really tell you the true problem
To be able to successfully POST the parameters, you have to convert the object to a string (e.g. by using JSON.stringify()), get the value through e.postData.contents on your google apps script, parse it, before you can use it as if it were an object.
I personally found when I read that I can't send raw objects in javascript - pass object via post
You mentioned that the code worked when you tested it using the query string in your browser, however, it is different as that will be a GET request and will trigger doGet instead of doPost
this is the most probable explanation and hope it helps!
Do test your code with default values before deploying it as once you deploy your code it can get very troublesome. You can use https://hurl.it to see what actually comes out without cors errors in the way.
I attempt to send a GET request in a jQuery AJAX request.
$.ajax({
type: 'GET',
url: /* <the link as string> */,
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); },
});
However, whatever I've tried, I got XMLHttpRequest cannot load <page>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7776' is therefore not allowed access.
I tried everything, from adding header : {} definitions to the AJAX request to setting dataType to JSONP, or even text/plain, using simple AJAX instead of jQuery, even downloading a plugin that enables CORS - but nothing could help.
And the same happens if I attempt to reach any other sites.
Any ideas for a proper and simple solution? Is there any at all?
This is by design. You can't make an arbitrary HTTP request to another server using XMLHttpRequest unless that server allows it by putting out an Access-Control-Allow-Origin header for the requesting host.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You could retrieve it in a script tag (there isn't the same restriction on scripts and images and stylesheets), but unless the content returned is a script, it won't do you much good.
Here's a tutorial on CORS:
http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm
This is all done to protect the end user. Assuming that an image is actually an image, a stylesheet is just a stylesheet and a script is just a script, requesting those resources from another server can't really do any harm.
But in general, cross-origin requests can do really bad things. Say that you, Zoltan, are using coolsharks.com. Say also that you are logged into mybank.com and there is a cookie for mybank.com in your browser. Now, suppose that coolsharks.com sends an AJAX request to mybank.com, asking to transfer all your money into another account. Because you have a mybank.com cookie stored, they successfully complete the request. And all of this happens without your knowledge, because no page reload occurred. This is the danger of allowing general cross-site AJAX requests.
If you want to perform cross-site requests, you have two options:
Get the server you are making the request to to either
a. Admit you by putting out a Access-Control-Allow-Origin header that includes you (or *)
b. Provide you with a JSONP API.
or
Write your own browser that doesn't follow the standards and has no restrictions.
In (1), you must have the cooperation of the server you are making requests to, and in (2), you must have control over the end user's browser. If you can't fulfill (1) or (2), you're pretty much out of luck.
However, there is a third option (pointed out by charlietfl). You can make the request from a server that you do control and then pass the result back to your page. E.g.
<script>
$.ajax({
type: 'GET',
url: '/proxyAjax.php?url=http%3A%2F%2Fstackoverflow.com%2F10m',
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); }
});
</script>
And then on your server, at its most simple:
<?php
// proxyAjax.php
// ... validation of params
// and checking of url against whitelist would happen here ...
// assume that $url now contains "http://stackoverflow.com/10m"
echo file_get_contents($url);
Of course, this method may run into other issues:
Does the site you are a proxy for require the correct referrer or a certain IP address?
Do cookies need to be passed through to the target server?
Does your whitelist sufficiently protect you from making arbitrary requests?
Which headers (e.g. modify time, etc) will you be passing back to the browser as your server received them and which ones will you omit or change?
Will your server be implicated as having made a request that was unlawful (since you are acting as a proxy)?
I'm sure there are others. But if none of those issues prevent it, this third method could work quite well.
you can ask the developers of that domain if they would set the appropriate header for you, this restriction is only for javascript, basically you can request the ressource from your server with php or whatever and the javascript requests the data from your domain then
Old question, but I'm not seeing this solution, which worked for me, anywhere. So hoping this can be helpful for someone.
First, remember that it makes no sense to try modifying the headers of the request to get around a cross-origin resource request. If that were all it took, it would be easy for malicious users to then circumvent this security measure.
Cross-origin requests in this context are only possible if the partner site's server allows it through their response headers.
I got this to work in Django without any CORS middleware by setting the following headers on the response:
response["Access-Control-Allow-Origin"] = "requesting_site.com"
response["Access-Control-Allow-Methods"] = "GET"
response["Access-Control-Allow-Headers"] = "requesting_site.com"
Most answers on here seem to mention the first one, but not the second two. I've just confirmed they are all required. You'll want to modify as needed for your framework or request method (GET, POST, OPTION).
p.s. You can try "*" instead of "requesting_site.com" for initial development just to get it working, but it would be a security hole to allow every site access. Once working, you can restrict it for your requesting site only to make sure you don't have any formatting typos.
I trying to make an ajax request to another domain, it already works, but now I have another problem...
This is my code:
function getChannelMessages(channel) {
jQuery.support.cors = true;
$.ajax(channel, {
cache : true,
type : "get",
data : _channels[channel].request,
global : false,
dataType : "jsonp text xml",
jsonp : false,
success : function jsonpCallback (response) {
console.log(response);
updateChannelRequest(channel);
//getChannelMessages(channel);
}
});
}
As I said, it already works, but the problem is the server returns an XML (Is not my server, is another server from another company - a web service - so I can not change what it returns) and as jsonp expects an json it fails with the error:
SyntaxError: syntax error
<?xml version="1.0"?><ReceiveMessageResponse xmlns="http://q ... />
According to jQuery documentation, adding jsonp text xml should make the magic, converting the response to simple text and then parsing it as XML, but it does not works.
I was already able to make it using YQL, but it has a limit of 10,000 requests per hour, and the system I'm developing will have up to 10 million request per hour. For that same reason, I can not "proxy" in my own server those requests...
FYI: I'm trying to get the newest messages from SQS, so if there is anyway to tell it to return the data as json, it will be easier and better, but I have not find anything either in the documentation...
The plain answer to my question is this: There are only two ways of do this:
Use a proxy. I won't put here all the how-to's to make it, but you can find a lot of information in the web searching for "cors" "cross domains ajax requests" and "yql" (this last is a proxy by Yahoo)
Use CORS. This is Cross-Origin Resource Sharing. That is: activate the server from which you want to get information to sent information to any other domain and to answer to requests from any other domain. To do this you must be the one who manage the server/service.
Those two are the only ways of getting information XML (or any other format) from another domain. To make json cross domain requests:
Use jsonp (Json Padded). I won't explain this (and actually is just extra information since it won't work if the answer from the server is XML - my main problem), cause there is a lot of information on the web.
Unfortunately I was not able to accomplished my goal, cause SQS is not configured to any of this methods... Still, I've got plenty insight of how Cross-Domains Requests works. And I hope this help anyone...