Fetch API - CORS issues with http and https - javascript

I got some trouble with Fetch API. When I launch this code :
fetch('https://g.tenor.com/v1/search?q=love%20is%20war&key=3TXJWOV3UY1V&limit=8')
.then(response => response.json(),{headers:headers})
.then(data => {
console.log(data) // Prints result from `response.json()` in getRequest
})
From http://quenouillere.fr/, it works without any issues. But when I want to use it from https://quenouillere.fr/ , it won't works with a CORS Issue. It detect that the origin isn't the same (because it's http who launch the request, and https who receive it)
I search on Internet, but nobody seems to have this issue.
CORS issue on https
Thank u for ur answers in advance :)

I tried your request from the console tab of stackoverflow and everything was working fine because we send this header (in the request, this header is added automatically by your browser so you have nothing to do for it) :
Origin: https://stackoverflow.com
And we receive this header from the response :
Access-Control-Allow-Origin: https://stackoverflow.com
I try the same request (your code basically) in the console tab of another website (here it was slack) and the header send is the request is (as expected) :
Origin: https://app.slack.com
But I received this in the response :
Access-Control-Allow-Origin: https://stackoverflow.com
I checked (with network tab, Postman and Fiddler) and the second request has no mention of stackoverflow...
I don't know exactly why but it seems the server associate the origin with something from the sender (maybe the IP?) so you're stuck with the same origin for the moment...
So basically https://quenouillere.fr/ would have worked if it was your first try...
Best you can do is contact them directly.

Related

Window exe API cors issue when calling from any webapp. C++

We've created one EXE file using the CPP language and create one API like http://localhost:5800/get-id/. when I open in browser return me the perfect output.
When I used fetch in HTML > script page, then getting No "Access-Control-Allow-Origin" header is present on the requested resource.
Code1:
fetch("http://localhost:5800/get-id/", {method: 'GET').then(function(response) {
console.log(response.text());
}).catch(function(error) {
console.log('Request failed', error)
});
After research, I've added the mode: no-cors error lost but getting an empty response.
Code2:
fetch("http://localhost:5800/get-id/", {method: 'GET', mode: 'no-cors'}).then(function(response) {
console.log(response.text());
}).catch(function(error) {
console.log('Request failed', error)
});
If I use code2 in any inspect console then getting an empty body but when I open http://localhost:5800/get-id/ in the browser and try to hit code2 in the console then getting the perfect parameter.
It means, localhost domain it's working fine but when it's fetched from any domain through my error.
What is the proper solution for it? In C/CPP language how can we allow cors?
Strange:
when I hit from console, it's show me empty
For same request I checked network tab, show 200 OK with proper response / preview data
CORS is a complex topic, I usually use CORS middleware to handle it in Node.JS in Express server (maybe the code will be useful to solve this).
It's goal is to allow API on domain api-domain to list web applications that can use it, for example your application is on webapp-domain domain.
When application calls fetch('http://api-domain/get-id/') to another domain it is referred to as cross-origin call.
All browser do CORS preflight call like this to check for allowance:
OPTIONS /get-id/
Access-Control-Request-Method: GET
Access-Control-Request-Headers: origin, x-requested-with
Origin: http://webapp-domain
(please note it's an OPTION request to the API, not GET)
And response should list webapp-domain as allowed (and specify which HTTP methods are allowed)
HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: http://webapp-domain
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400
After the successful preflight call like this the browser will continue with fetch, for example, it will send GET request to http://api-domain/get-id/
P.S.
One of the ways to skip CORS is to set HTTP proxy in webapp-domain which will call api-domain on server-side and is not limited by CORS. See this answer for details.

CORS policy: No 'Access-Control-Allow-Origin' / 500 (Internal Server Error) Problem

Basically, I'm trying to get a username by id from Sequelize. The problem is that I am either stuck with a CORS problem or 500 Internal Server error depending on the response(status)
cors and 500
controller code
async getUserFromUserId (req, res) {
try {
// const user = await User.findByPk(req.body.id)
const id = req.body.id
const user = await User.findByPk(id)
res.send(user.username)
} catch (err) {
// or res.status(some random number).send() for CORS problem to appear
res.status(500).send({
error: 'an error has occured trying to fetch the users id'
})
}
},
client code
this.notifiedUser = (await UserService.getUserFromUserId({id: UserId})).data
I get a Status: 200 OK from postman though.
Postman Solution
Edit:
I have seen how the other Solution for the cors thingy, but the solutions does not specify as to why I get "undefined" results after resolving the cors problem.
So, CORS is actually really obnoxious in this regard, but there's a fairly straightforward way to fix this. It's a super useful security feature, though it is frustrating at best sometimes.
Your browser does what is called a Preflight Request, which is of the http verb OPTIONS. Your browser calls whatever route you want, but instead of what you asked it to do, it calls using OPTIONS first. Your server should accept all routes that the client can ask for with the OPTIONS method, and your server should respond with the following headers to be an externally available, cross-origin API.
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, ...
(note, you should not put the ... in, but you can put any HTTP verb in this list)
If you require your own headers (for auth purposes), you want to add this header for Client -> Server.
Access-Control-Allow-Headers: YourHeader, YourHeader2, YourHeader3
You want to add this one for Server -> Client
Access-Control-Expose-Headers: YourHeader,YourHeader3
Note that the OPTIONS call is an entirely separate call that you should handle as well as the GET method.
You've now told the browser what it is allowed to ask for, and what it can expect to get back from your API. If you don't respond to the OPTIONS request, the browser terminates the request, resulting in a CORS error.
I'm going to take a gander at a guess and assume you're likely using Express, which this answer describes how to set the headers on.
What do the headers mean, in English?
Access-Control-Allow-Origin
From where are clients allowed to access this resource (endpoint)? This can match partial domains with wildcards, or just a * to allow anywhere.
Access-Control-Allow-Methods
What HTTP methods are permissible on this route?
Access-Control-Expose-Headers
When I get a response from the server, what should I (the browser) expose to the client-side?
Access-Control-Allow-Headers
What am I as the client side allowed to send as headers?
Okay, so I figured out the problem.
In a way, I did not have to deal with any of the cors stuff because I believe that was not the main source of the problem.
So, instead of accessing my database data through "GET" and getting the data by doing this:
this.data = (Service.function(bodyValue)).data
I did "POST" to get the data, and accessed the data by simply doing this
const response = Service.function({
id: bodyValue
})
this.data = response.data
This accesses the data without having to get "secured" information from the database, but by accessing the data from the database by getting Observer object info from the database.
The Observer object looks as follows, which treats the user data as an object instead of pure data.
Compared to a data object, where each data {...} has user information.
I am not sure if I am using the correct words, but these are to the extent of my current understanding.
If your origin is from localhost, Chrome usually blocks any CORS request originating from this origin.
You can install this extension:
https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en
Or you can disable the security when running chrome (add the flag):
--disable-web-security

CORS error, but data is fetched regardless

I have a generated React site I am hosting in an S3 bucket. One of my components attempts to fetch something when loaded:
require('isomorphic-fetch')
...
componentDidMount() {
fetch(`${url}`)
.then(res => {
console.log(res);
this.setState({
users: res
})
})
.catch(e => {
// do nothing
})
}
The url I am fetching is an AWS API Gateway. I have enabled CORS there, via the dropdown, with no changes to the default configuration.
In my console, for both the remote site and locally during development, I see:
"Failed to load url: No 'Access-Control-Allow-Origin' header is present on the requested resource." etc
However, in the Chrome Network tab, I can see the request and the response, with status 200, etc. In the console, my console.log and this.setState are never called, however.
I understand that CORS is a common pain point, and that many questions have touched on CORS. My question: Why does the response show no error in the Network tab, while simultaneously erroring in the console?
The fetch(`${url}`) call returns a promise that resolves with a Response object, and that Response object provides methods that resolve with text, JSON data, or a Blob.
So to get the data you want, you need to do something like this:
componentDidMount() {
fetch(`${url}`)
.then(res => res.text())
.then(text => {
console.log(text);
this.setState({
users: text
})
.catch(e => {
// do nothing
})
}
Failed to load url: No 'Access-Control-Allow-Origin' header is present on the requested resource." etc
That means the browser isn’t allowing your frontend code to access the response from the server, because the response doesn’t include the Access-Control-Allow-Origin header.
So in order for the above code to work, you’ll need to fix the server configuration on that server so that it sends the necessary Access-Control-Allow-Origin response header.
However, in the Chrome Network tab, I can see the request and the response, with status 200, etc. In the console, my console.log and this.setState are never called, however.
That’s expected in the case where the server doesn’t send the Access-Control-Allow-Origin response header. In that case, the browser still gets the response — and that’s why you can see it in the devtools Network tab — but just because the browser gets the response doesn’t mean it will expose the response to your frontend JavaScript code.
The browser will only let your code access the response if it includes the Access-Control-Allow-Origin response header; if the response doesn’t include that header, then the browser blocks your code from accessing it.
My question: Why does the response show no error in the Network tab, while simultaneously erroring in the console?
For the reason outlined above. The browser itself runs into no error in getting the response. But your code hits an error because it’s trying to access an res object that’s not there; the browser hasn’t created that res object, because the browser isn’t exposing the response to your code.
You may be seeing the status 200 for the OPTIONS not the GET. There is a setting for CORS to handle legacy, so it won't confuse your client. I had to do that last time in a React app. Your error is that your CORS isn't configured properly (sorry, obviously). Chrome won't let your client tlak to the backend if it doesn't get the headers properly. Other browsers probably also, probably React also. It may be some kind of HTTP protocol if only one side has CORS enabled. Someone can correct me there. It's a similar security consideration as sending a request to HTTP from HTTPS. Chrome blocks it.
It looks to me like it's your backend. CORS isn't active or it would put that header on, and after that, you would see errors about origin mismatch in the frontend client.
In my experience, it's a 2-3 step combo, make sure OPTIONS don't send confusing signals to your client (look for settings to do with 200). This is a config setting in your backend. Then, make sure the backend is configured to use CORS. You very specifically need to enter the origin hostname and port that the backend is to expect traffic from.
I could probably give better input if I see what languages and/or frameworks you are using besides React.
This is what you would do in Express JS and node for your Backend:
const cors = require('cors')
// note http or https
app.use(cors({
origin: 'http://example.com:1337',
//origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
optionsSuccessStatus: 200
// some legacy browsers (IE11, various SmartTVs) choke on 204
}))
My last React app was detonating without optionsSuccessStatus by throwing success when it was fail.
To give you a little bit of imagery to work with, CORS is simple but finicky. It's a simple matter of alignment. Once your backend is configured to a) use CORS and b) know who to accept traffic from, it's done. Once your frontend is configured to handle this traffic, it's done. It's like aligning a square peg in a round hole until you get the config settings aligned.
Try using Postman to send some GET requests to the Backend. You can observe the headers from there.

CORS Header Error when using Authorization Header

So this is my current code
When I delete the Authorization from the headers the request will be successful, and i get the response. But when I use the Authorization header, it will give me this error.
The server is using Python Django and using this libary for CORS Handling
EDIT 1: This is the python server settings
EDIT 2: Add Browser
I use Chrome Version 53.0.2785.143 m (64-bit)
EDIT 3: Postman response
Just got weird response here. When the backend guy tried from his laptop, he got the complete header. like this:
But when i use my laptop, i got this response:
I'm guessing cors is not allowing the Authorization header. So, lets add that the Authorization entry to CORS_ALLOW_HEADERS
CORS_ALLOW_HEADERS = (
...
'Authorization',
...
)
Solved!
It's caused by the App Enlight plugin for monitoring. When I remove it, everything works without errors :)

Unable to get referer headers working

I have a proxy set up for a third party service that at the moment looks like this:
app.use('/service', (req, res) => {
let url = `http://www.service.com/endpoint/${config.POSTCODER_KEY}${req.url}`
req.headers['Referer'] = 'my.domain.com'
console.log(req.headers['Referer'])
req.pipe(request(url)).pipe(res)
})
As you can see I am trying to add Referer header to the request and it seems to be working as console.log prints out 'my.domain.com' however request fails and the error I get back from the service is 403 unauthorised referring to Referer header. When I inspect network in inspector tools my referer is displayed as localhost.
I am testing this in Postman api client (https://www.getpostman.com) by setting Referer to my white listed domain and it works. I'm not sure why it uses localhost with express.
Piping streams together only transfers the data in those streams. Headers are not a part of that. When you req.pipe(request(url)) you're only writing the request body to the proxied request. If you want to set the headers used for the proxied request, you have to pass them to request, like:
req.pipe(request({ url: url, headers: req.headers })).pipe(res);
However, as noted in my answer to your previous question, you will also need to properly set the headers on res when the proxied response arrives.

Categories

Resources