admin管理员组文章数量:1127036
I can hit this endpoint, via Postman and it returns
JSON
Additionally I am using create-react-app and would like to avoid setting up any server config.
In my client code I am trying to use fetch
to do the same thing, but I get the error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
So I am trying to pass in an object, to my Fetch which will disable CORS, like so:
fetch('', { mode: 'no-cors'})
.then(blob => blob.json())
.then(data => {
console.table(data);
return data;
})
.catch(e => {
console.log(e);
return e;
});
Interestingly enough the error I get is actually a syntax error with this function. I am not sure my actual fetch
is broken, because when I remove the { mode: 'no-cors' } object, and supply it with a different URL it works just fine.
I have also tried to pass in the object { mode: 'opaque'}
, but this returns the original error from above.
I belive all I need to do is disable CORS.. What am I missing?
I can hit this endpoint, http://catfacts-api.appspot.com/api/facts?number=99
via Postman and it returns JSON
Additionally I am using create-react-app and would like to avoid setting up any server config.
In my client code I am trying to use fetch
to do the same thing, but I get the error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
So I am trying to pass in an object, to my Fetch which will disable CORS, like so:
fetch('http://catfacts-api.appspot.com/api/facts?number=99', { mode: 'no-cors'})
.then(blob => blob.json())
.then(data => {
console.table(data);
return data;
})
.catch(e => {
console.log(e);
return e;
});
Interestingly enough the error I get is actually a syntax error with this function. I am not sure my actual fetch
is broken, because when I remove the { mode: 'no-cors' } object, and supply it with a different URL it works just fine.
I have also tried to pass in the object { mode: 'opaque'}
, but this returns the original error from above.
I belive all I need to do is disable CORS.. What am I missing?
Share Improve this question edited Jun 22, 2019 at 8:59 sideshowbarker♦ 87.9k29 gold badges214 silver badges211 bronze badges asked Apr 6, 2017 at 17:36 dwwwdwww 5,5983 gold badges14 silver badges12 bronze badges 1- 1 Does this answer your question? Handle response - SyntaxError: Unexpected end of input when using mode: 'no-cors' – Cees Timmerman Commented Nov 20, 2020 at 9:15
14 Answers
Reset to default 820mode: 'no-cors'
won’t magically make things work. In fact it makes things worse, because one effect it has is to tell browsers, “Block my frontend JavaScript code from seeing contents of the response body and headers under all circumstances.” Of course you never want that.
What happens with cross-origin requests from frontend JavaScript is that browsers by default block frontend code from accessing resources cross-origin. If Access-Control-Allow-Origin
is in a response, then browsers relax that blocking and allow your code to access the response.
But if a site sends no Access-Control-Allow-Origin
in its responses, your frontend code can’t directly access responses from that site. In particular, you can’t fix it by specifying mode: 'no-cors'
(in fact that’ll ensure your frontend code can’t access the response contents).
However, one thing that will work: if you send your request through a CORS proxy.
You can also easily deploy your own proxy to Heroku in just 2-3 minutes, with 5 commands:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
After running those commands, you’ll end up with your own CORS Anywhere server running at, for example, https://cryptic-headland-94862.herokuapp.com/
.
Prefix your request URL with your proxy URL; for example:
https://cryptic-headland-94862.herokuapp.com/https://example.com
Adding the proxy URL as a prefix causes the request to get made through your proxy, which:
- Forwards the request to
https://example.com
. - Receives the response from
https://example.com
. - Adds the
Access-Control-Allow-Origin
header to the response. - Passes that response, with that added header, back to the requesting frontend code.
The browser then allows the frontend code to access the response, because that response with the Access-Control-Allow-Origin
response header is what the browser sees.
This works even if the request is one that triggers browsers to do a CORS preflight OPTIONS
request, because in that case, the proxy also sends back the Access-Control-Allow-Headers
and Access-Control-Allow-Methods
headers needed to make the preflight successful.
I can hit this endpoint,
http://catfacts-api.appspot.com/api/facts?number=99
via Postman
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS explains why it is that even though you can access the response with Postman, browsers won’t let you access the response cross-origin from frontend JavaScript code running in a web app unless the response includes an Access-Control-Allow-Origin
response header.
http://catfacts-api.appspot.com/api/facts?number=99 has no Access-Control-Allow-Origin
response header, so there’s no way your frontend code can access the response cross-origin.
Your browser can get the response fine and you can see it in Postman and even in browser devtools—but that doesn’t mean browsers expose it to your code. They won’t, because it has no Access-Control-Allow-Origin
response header. So you must instead use a proxy to get it.
The proxy makes the request to that site, gets the response, adds the Access-Control-Allow-Origin
response header and any other CORS headers needed, then passes that back to your requesting code. And that response with the Access-Control-Allow-Origin
header added is what the browser sees, so the browser lets your frontend code actually access the response.
So I am trying to pass in an object, to my Fetch which will disable CORS
You don’t want to do that. To be clear, when you say you want to “disable CORS” it seems you actually mean you want to disable the same-origin policy. CORS itself is actually a way to do that — CORS is a way to loosen the same-origin policy, not a way to restrict it.
But anyway, it’s true you can—in your local environment—do suff like give a browser runtime flags to disable security and run insecurely, or you can install a browser extension locally to get around the same-origin policy, but all that does is change the situation just for you locally.
No matter what you change locally, anybody else trying to use your app is still going to run into the same-origin policy, and there’s no way you can disable that for other users of your app.
You most likely never want to use mode: 'no-cors'
in practice except in a few limited cases, and even then only if you know exactly what you’re doing and what the effects are. That’s because what setting mode: 'no-cors'
actually says to the browser is, “Block my frontend JavaScript code from looking into the contents of the response body and headers under all circumstances.” In most cases that’s obviously really not what you want.
As far as the cases when you would want to consider using mode: 'no-cors'
, see the answer at What limitations apply to opaque responses? for the details. The gist of it is:
In the limited case when you’re using JavaScript to put content from another origin into a
<script>
,<link rel=stylesheet>
,<img>
,<video>
,<audio>
,<object>
,<embed>
, or<iframe>
element (which works because embedding of resources cross-origin is allowed for those)—but for some reason you don’t want to/can’t do that just by having the markup of the document use the resource URL as thehref
orsrc
attribute for the element.When the only thing you want to do with a resource is to cache it. As alluded to in What limitations apply to opaque responses?, in practice the scenario that’s for is when you’re using Service Workers, in which case the API that’s relevant is the Cache Storage API.
But even in those limited cases, there are some important gotchas to be aware of; see the answer at What limitations apply to opaque responses? for the details.
I have also tried to pass in the object
{ mode: 'opaque'}
There is no 'opaque'
request mode — opaque
is instead just a property of the response, and browsers set that opaque property on responses from requests sent with no-cors
mode.
But incidentally the word opaque is a pretty explicit signal about the nature of the response you end up with: “opaque” means you can’t see into any of its details; it blocks you from seeing.
If you are trying to address this issue temporarily on your localhost, you can use this Chrome extension :
Allow CORS Access-Control-Allow-Origin
If you are using Express as back-end you just have to install cors
and import and use it in
app.use(cors());.
If it is not resolved then try switching ports. It will surely resolve after switching ports
So if you're like me and developing a website on localhost where you're trying to fetch data from Laravel API and use it in your Vue front-end, and you see this problem, here is how I solved it:
- In your Laravel project, run command
php artisan make:middleware Cors
. This will createapp/Http/Middleware/Cors.php
for you. Add the following code inside the
handles
function inCors.php
:return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
In
app/Http/kernel.php
, add the following entry in$routeMiddleware
array:‘cors’ => \App\Http\Middleware\Cors::class
(There would be other entries in the array like
auth
,guest
etc. Also make sure you're doing this inapp/Http/kernel.php
because there is anotherkernel.php
too in Laravel)Add this middleware on route registration for all the routes where you want to allow access, like this:
Route::group(['middleware' => 'cors'], function () { Route::get('getData', 'v1\MyController@getData'); Route::get('getData2', 'v1\MyController@getData2'); });
- In Vue front-end, make sure you call this API in
mounted()
function and not indata()
. Also make sure you usehttp://
orhttps://
with the URL in yourfetch()
call.
Full credits to Pete Houston's blog article.
You can also set up a reverse proxy which adds the CORS headers using a self-hosted CORS Anywhere or Just CORS if you want a managed solution.
https://justcors.com/<id>/<your-requested-resource>
http://cors-anywhere.com/<your-requested-resource>
Very easy solution (2 min to config) is to use local-ssl-proxy package from npm
The usage is straight pretty forward:
1. Install the package:
npm install -g local-ssl-proxy
2. While running your local-server
mask it with the local-ssl-proxy --source 9001 --target 9000
P.S: Replace --target 9000
with the -- "number of your port"
and --source 9001
with --source "number of your port +1"
Solution for me was to just do it server side
I used the C# WebClient
library to get the data (in my case it was image data) and send it back to the client. There's probably something very similar in your chosen server-side language.
//Server side, api controller
[Route("api/ItemImage/GetItemImageFromURL")]
public IActionResult GetItemImageFromURL([FromQuery] string url)
{
ItemImage image = new ItemImage();
using(WebClient client = new WebClient()){
image.Bytes = client.DownloadData(url);
return Ok(image);
}
}
You can tweak it to whatever your own use case is. The main point is client.DownloadData()
worked without any CORS errors. Typically CORS issues are only between websites, hence it being okay to make 'cross-site' requests from your server.
Then the React fetch call is as simple as:
//React component
fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {
method: 'GET',
})
.then(resp => resp.json() as Promise<ItemImage>)
.then(imgResponse => {
// Do more stuff....
)}
I had a similar problem with my browser debugger saying my response.body was null but fiddler and the developer tools show it as populated that turned out to be basically the same scenario as this. I was using a local Angular application hitting a Web Api service running on IISExpress. I fixed it by following the steps outlined here to find the correct applicationhost.config file to add a Access-Control-Allow-Origin header like so:
<customHeaders>
<clear />
<add name="X-Powered-By" value="ASP.NET" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
If all the above solutions don't work, probably it's because of the file permissions as sometimes even if you have fixed the non-cors problem using Heroku or another way, it throws 403 forbidden error. Set the directory/file permissions like this:
Permissions and ownership errors A 403 Forbidden error can also be caused by incorrect ownership or permissions on your web content files and folders.
Permissions Rule of thumb for correct permissions:
Folders: 755
Static Content: 644
Dynamic Content: 700
I have to add some notes for anyone making CORS requests.
- Make sure both websites use HTTPS. CORS only works over HTTPS if you want to set
withCredentials: true
and send over the cookie. - Configure CORS on the server side(eg, Nginx config).
Here is an example of Nginx config.
server {
# CORS block BEGIN
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Headers' 'x-requested-with, Content-Type, origin, authorization, accept, client-security-token';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,PATCH,DELETE';
add_header 'Access-Control-Allow-Credentials' 'true';
# CORS block END
}
$http_origin
should only be used on the dev server. Replace it with your domain on the production server. For the rest, please continue your search.
References:
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
in my case removing of previously added
headers: { 'Content-Type': 'application/json' }
solved similar issue and works for me with no any mode cors/no-cors
.
of course my backend has proper Access-Control-Allow-Origin: *
header added to the response.
fetch(url, {mode: 'cors'})
works for me.
Basically,
fetch(url, {requestParameterDataObject})
The fetch JS documentation will have more info about the specific field names within the request parameters object. Here, we are using the request's mode field & setting it to 'cors'.
My final code:
useEffect(() => {
// Loading while etching API data
setIsLoading(true);
fetch(url, {mode: 'cors'})
.then((response) => response.json())
.then((data) => {
setData(data);
// Turn off loading flag once data comes back
setIsLoading(false);
});
}, [url]);
The most upvoted answer is the right approach of sending the request through CORS proxy. However, since Heroku no longer offers a free tier, the deployment part is a little bit outdated.
For a 2024 solution, you can host a CORS proxy yourself with Cloudflare Worker free tier using this repository: https://github.com/Zibri/cloudflare-cors-anywhere
However, be aware that there are daily requests limits when using Cloudflare Worker, so depending on your use case it might not be suitable for production use.
If you are looking for a production ready CORS proxy, you can check out Corsfix, it has unlimited monthly requests and supports request header overrides.
Here is an example of how to send request through the CORS proxy
fetch("https://proxy.corsfix.com/?<TARGET_URL>");
(I am affiliated with Corsfix)
If you’re using React, I recommend creating a new project with the following command:
npm create vite@latest project_name -- --template react
To address the CORS issue, update the vite.config.js file as follows:
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': {
target: "http://localhost:3000"
}
}
}
})
本文标签: javascriptTrying to use fetch and pass in mode nocorsStack Overflow
版权声明:本文标题:javascript - Trying to use fetch and pass in mode: no-cors - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736687978a1947765.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论