I am currently developing a dashboard which consumes the Mention API. However, I am having difficulties due to the CORS policy.
If the dashboard is opened on Chrome or another browser that has a strict CORS policy, they make a preflight OPTIONS request each time, but these appear to not be supported by the Mention API.
Therefore, every time I do something like:
this.mentionAPI = axios.create({
baseURL: 'https://web.mention.net/api/accounts/my-account-id',
headers: {
'Authorization': 'Bearer my-access-token',
}
});
this.mentionAPI.get('/alerts')
.then((response) => {
console.log(response);
})
.catch((response) => {
console.log(response);
});
I get a response with the status 405 Method Not Allowed. This suggests that the OPTIONS requests are not handled by the Mention API at all.
Naturally, in my case I can just make sure that the browser is configured to not perform preflight requests. After all, my use case prescribes just one client, which I control completely. Alternatively, I could build a server-side service to make the requests on my behalf, however it seems like hunting a fly with cannon, since client side JavaScript is more than capable to perform everything else.
Any help on this issue would be really appreciated. Perhaps I'm misunderstanding how the API is intended to be consumed?
Related
I know questions like that have been asked tons of times already but I still was not able to find a solution or even an explanation for that manner.
I work on a project that needs the best possible resolution on YouTube thumbnails. I used the following url https://i.ytimg.com/vi/VIDEOID/maxresdefault.jpg however I found out that on rare occasions this does not work and I get a placeholder image, and a status of 404, back. In that case I would like to use https://i.ytimg.com/vi/VIDEOID/hqdefault.jpg.
To check if an image exists I tried to make a fetch-request using JavaScript:
const url = "https://i.ytimg.com/vi/VIDEOID/hqdefault.jpg"
fetch(url).then(res => console.log(res.status))
But I get an error stating that the CORS-Header 'Access-Control-Allow-Origin' is missing. I tried setting it and several other headers I found but to no avail. It only works if I send the request in no-cors mode, but then the status is always 0 and all the other data seems to be missing aswell.
I also tested the request in Postman where it worked and even copied the JavaScript-Fetch-Snipped that Postman gave me:
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch("https://i.ytimg.com/vi/VIDEOID/maxresdefault.jpg", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
I read that this is a problem from the Server and Youtube is restricting this, but why does it work in Postman and why does it work when using <cfhttp> in ColdFusion? Also the status-code even shows up in the console within the CORS-Error message...
Why? explained:
The CORS policy is implemented in browsers to allow sharing resources between websites while preventing websites from attacking each other:
SOP (same origin policy) prevents web sites from attacking each other but does not allow any sharing between origins.
CORS (cross origin resource sharing) relaxes SOP restrictions, but requires specific server headers/configuration.
These policies only apply inside a browser. Presumably Postman and Coldfusion work because they are making direct HTTP requests outside the context of a browser script. Which leads to how to work-around CORS restrictions...
Solutions:
3 Ways to Fix the CORS Error — and How the Access-Control-Allow-Origin Header Works explains how to bypass CORS restrictions. They all work by manipulating the request headers/origin:
Browser extension. (Not sure if this still works in 2022. Only works if user installs browser extension.)
3rd party request proxy. (The proxy linked in the demo is now limited due to abuse.)
Build your own proxy.
Realistically, option #3 is the only real solution. SvelteKit endpoints make it super simple to proxy requests.
Following code is working properly for me and I am always getting 200 status ok
Something similar implementation can be done
//import fetch from 'node-fetch';
const fetch = require('node-fetch');
loaddata();
async function loaddata(){
var Headers="{headers: {'Access-Control-Allow-Origin': '*'}";
var requestOptions = {
method: 'GET',
redirect: 'follow',
};
const response = await fetch('https://i.ytimg.com/vi/9DCwyuH29SI/hqdefault.jpg',requestOptions,Headers);
console.log(response);
}
I am trying to integrate Yammer API in my Vue.JS project, for Http calls I am using Vue-Resource plugin. While making GET Http call to get posts from Yammer it gives me following error -
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I tried postman tool and that gives successful response, but when I try to run the same thing in my Vue.JS project using Vue-Resource plugin it wont work.
The Vue.JS code snippet -
function(){
this.$http.get("https://www.yammer.com/api/v1/messages/my_feed.json").then((data)=>{
console.log(data);
});
In main.vue file i have -
Vue.http.interceptors.push((request, next) => {
request.headers.set('Authorization', 'Bearer my_yammer_token')
request.headers.set('Accept', '*/*')
next()
})
Then I tried the code snippets provided by Postman tool for jquery, that too not working.
jQuery code -
var settings = {
"url": "https://www.yammer.com/api/v1/messages/my_feed.json",
"method": "GET",
"timeout": 0,
"headers": {
"Authorization": "Bearer my_yammer_token",
"Cookie": "yamtrak_id=some_token; _session=some_token"
},
};
$.ajax(settings).done(function (response) {
console.log(response);
});
Though, I found similar questions but nothing worked for me.
I am working this to resolve from last 2 days but getting failed again and again. Please guide/help me.
A browser has higher security requirements than a request in PostMan. In a browser, you are only allowed to make XHR requests to your own current host (combination of domain + port) but not to other remote hosts. To nevertheless make a request to a remote host, you can use the browser built-in CORS. By using this, your browser makes a pre-flight request to the remote host to ask if the current page is allowed to request from that host. This is done via the Access-Control response headers. In your case, this header is probably missing or not allowing your page to access, which is why the request does not go through. Please read further into that topic.
However, in your case, using CORS probably won't be a solution for two reasons: To use CORS, the remote host must present a header which allows every requesting host (*) or your specific one. If you cannot set that setting anywhere on the remote host, it won't work. Second, it is not safe to place your authorization token into client-side JavaScript code. Everybody can just read your JS code and extract the authorization token. For that reason, you usually make the actual API call from the server-side and then pass the data to the client. You can use your own authentication/authorization against your server and then use the static authorization key on the server to request the data from the remote host. In that case, you'll never expose the authorization key to your user. Also, on the server-side, you do not have to deal with CORS as it works just like PostMan or curl as opposed to a browser.
I'm trying to get XML data with a fetch() request and the appropriate header.
The request succeeds but the reponse is empty. The weird part is that the browsers networking tab in the debugger gives me a 200 OK and has the requested Response payload but I can't seem to get this data even though it's present. Any clues as to why?
Snapshot of the debugger
data = {
get:(url)=>{
return new Promise(resolve => {
let auth = new Headers({
"username":key.user,
"password":key.password,
"Accept":"application/xml"
})
fetch(url,{
method:"get",
mode:"no-cors",
headers: auth,
credentials:"include"
})
.then(response => console.log(response))
//empty response
})
}
}
You are making a cross-origin request but you said mode:"no-cors",.
mode:"no-cors", means "If I need permission to do something cross-origin, then don't ask for it, and don't throw an error".
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.
Since you need permission to read data from a cross-origin request, it is failing silently (because you explicitly told it to do so).
Use mode: "cors".
What works
I have a simple word game I've built. It works great. One thing users have requested is a word validity check. I am running the oxford dictionary api on an AWS Lambda Proxy/Node.js end-point, which works great when I access the APIGateway uri via the browser.
I chose an AWS Lambda function in order to protect my Oxford API key, and have more direct CORS control.
Steps taken
I have enabled CORS in the AWS APIGateway, and using a "*" wildcard during development.
I started to code the addition to the game, using my local server, # 127.0.0.1.
Error encountered
I have run into the following issue:
myproject.html:57 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://XXXXXXXXXXX.execute-api.us-east-2.amazonaws.com/prod/dictionary?word=help with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
getWord # myproject.html:57
(anonymous) # myproject.html:67
The client code
I am using a simple fetch:
var base_url = "https://XXXXXXXXXXX.execute-api.us-east-2.amazonaws.com/prod/dictionary?word=";
getWord = function(word){
fetch(base_url+word, {
headers: {
'content-type': 'application/json'
},
method: 'GET',
mode: 'cors'
}).then(function(response) {
console.log(response);
});
}
The question
I have never heard of CORB. I don't understand what is triggering CORB, and what the steps are to resolve this. How are CORB issues resolved?
I just needed to persevere apparently. Just in case anyone ever runs into this:
Despite APIGateway CORS enablement, CORS authority is passed to the lambda function with Lambda proxy integration enabled. Although the initial URI request was accepted at the APIgateway, it ultimately failed due to lack of headers in the lambda response. Somehow This triggered CORB instead of CORS. I don't know why.
The answer is to ensure CORS is enabled in the APIgateway and that the lambda function response callback pattern contains a "Access-Control-Allow-Origin" header.
I had similar issue. I suggest using POSTMAN for debugging it as it shows headers and allows you to tweak whatever is needed in your request.
In my case I had to re-deploy my API after adding the header.
Attaching screenshot in case it might be of help to some users:
Integration response:
Method response:
Postman's headers response - working:
I am struggling with fetch over CORS, with authorization:
const token = 'this.is.secret!';
fetch('http://corsserver/api/hello', {
method: 'get',
credentials: 'include',
mode: 'cors',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(response => {
console.log(response);
}).catch(error => {
console.log(error);
});
When I run this request, Chrome sets the header as:
Request Method:OPTIONS
I look this up and it's a preflighted request.
I mean, that's really cool and stuff. However I can't figure out how to send the actual request after the preflight comes back okay! What's the next step? How do I send the GET request?
I'm missing something very basic here.
Browsers will automatically send the actual GET request if the OPTIONS request is successful. But if the OPTIONS request isn’t successful, browsers will never make the GET request.
And there’s no way make that GET request without the browser doing the OPTIONS request.
So if the browser isn’t doing the GET, it can only mean the OPTIONS must be failing, and you need to find out why. The browser should be logging a message with the reason to its devtools console, so you should start by checking there (and then either edit/update the question to add that info, or post a new separate more-specific question with the error message).
One guess for what the problem could be: Maybe the server is requiring authentication for the OPTIONS request. If so, you need to fix it so that the server doesn’t—because when the browser makes the OPTIONS request, it doesn’t send the Authorization header+value from your code.
Instead in fact the whole purpose of the OPTIONS request in this case is for the browser to ask, Are you OK with getting cross-origin requests that have an Authorization request header?, and for the server to respond in way that indicates if it allows the Authorization header.
So because of that, the server must be configured to respond to any OPTIONS requests (from allowed origins at least) with a 2xx success response, without requiring authentication.
The way you’d know whether the server is requiring authentication for that OPTIONS request is if the CORS message your browser is logging shows a 401 status for the OPTIONS response.
Example code for handling the OPTIONS in a Node.js server environment:
if (req.method === 'OPTIONS') {
res.send();
return;
}
…to make the server send a 200 response with no response body, which is what you want for this. Do note that this explicitly allows all OPTION requests.