Restangular POST returning Access-Control - javascript

I'm using AngularJS Restangular to make a POST to a mock REST API I have created on http://www.mockable.io
My Code is very simple...
RestangularProvider.setBaseUrl("http://demo1461049.mockable.io");
var newBranch = {"test":"test"}
var branches = Restangular.all("branches");
branches.post(newBranch);
The first problem I noticed is that it is doing an OPTIONS request instead of a POST request. I have seen people saying that this is because it is doing a CORS request (Localhost to mockable.io). I haven't managed to work out exactly how CORS works but I set up Mocakable so it would accept OPTIONS. I now get the following error...
Request header field Content-Type is not allowed by Access-Control-Allow-Headers.
I have seen a few threads about this error but they are all from people trying to create their own API (normally ASP.NET). Is this an option that I need to set but cannot because Mockable doesn't allow you to? That would seem strange as the whole point of Mockable is that you make cross-origin requests to it.
Any help would really be appreciated.

The error you get is a server response. Unless you can edit what headers the server allows in regards to CORS your in trobule.
I'am not using mockable myself but they seem to have CORS support so I would be surprised if they didnt have an option to edit CORS headers.
An example for a CORS implementation I have for a private API which is the most common headers:
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
)
Find something similiar for mockable and your home-safe

Related

Cors block while trying to get Instagram access token on client side using react/js

Okay so im trying to get access token im following the main guide provided by facebook app developers which is: https://developers.facebook.com/docs/instagram-basic-display-api/getting-started. Im at step: 5, where i try to exchange my code for access_token. I do post request to https://api.instagram.com/oauth/access_token however i get cors blocked with this error:
Access to XMLHttpRequest at
'https://api.instagram.com/oauth/access_token' from origin
'https://localhost' has been blocked by CORS policy: Request header
field content-type is not allowed by Access-Control-Allow-Headers in
preflight response.
I literlly tried everything. Adding headers to axios, using ngrok to get an actual secure https: and not self made cert (for dev mode ofc). I also changed the app ouath urls. What could the problem be?
Yeap i allowed urls i did everything. I tried https://cors-anywhere.herokuapp.com/https://api.instagram.com/oauth/access_token it didn't work, it says bad request. However i managed to solve it with an extra library called axios-oauth-client: https://www.npmjs.com/package/axios-oauth-client. After implementing this library and instead of doing axios.post(url, data) but using this library and passing the data in there everything works fine and i get the access token. Something with the headers might have been the problem

Calling Yelp API from frontend JavaScript code running in a browser

Would really appreciate anyone's help. I am relatively new to developing in React, using Mac OSX and Chrome as my browser. I have a small application that attempts to make an async GET request from Yelp Fusion's API using 'isomorphic-fetch', but receive the following error:
Fetch API cannot load https://api.yelp.com/v3/businesses/search?[remaining URL] Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have done a lot of searching to see what responses to identical issues already exist, but I am left even more confused in how to tackle my problem with my relatively new knowledge to this kind of development environment. (Answers that seem particularly helpful are: Response to preflight request doesn't pass access control check and API Request with HTTP Authorization Header inside of componentDidMount, but I do not really understand how to actually implement those solutions with my environment. Any attempts I make seem incorrect and do not result in a change.).
As a side note: I have installed the Allow-Control-Allow-Origin: * extension on my Chrome browser, but I receive the same error - just a shortened, less elaborate description of it:
Fetch API cannot load https://api.yelp.com/v3/businesses/search?[remaining URL]. Response for preflight has invalid HTTP status code 500
The following is how I call the fetch in my code:
var options = (
method: 'get',
headers: new Headers({
'Access-Control-Allow-Origin': '*',
'Authorization': [my token]
'Content-Type': 'application/json'
})
}
return fetch(url, options);
Is this an issue due to the syntax of my header with Yelp Fusion's OAUTH2 token requirements, do I need to do something proxy-related, or is the reason because of something else? If proxy-related, currently I am running a fully client-driven application and do not use server-side code at all. Would this still be possible given my environment? Any guidance as to which direction I should go and clarification of my misconceptions would be greatly appreciated.
Again, thank you for your help for a growing developer.
This cause of the problem is that https://api.yelp.com/ doesn’t support CORS.
And there’s nothing you can in your own application code to fix that—no matter what you try, you can’t change the fact that https://api.yelp.com/ doesn’t support CORS.
Apparently the Yelp API does support JSONP though; see for example Yelp API Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
So using https://api.jquery.com/jquery.getjson/ or similar in your frontend code would allow you make requests to the Yelp API cross-origin from your frontend code.
A related issue in the GitHub issue tracker for the Yelp API examples repo confirms no CORS:
TL;DR: No CORS is not supported by api.yelp.com
And another related issue:
As I answered in #99 , we do not provide the CORS headers necessary to use clientside js to directly make requests to the api.
Both of the comments cited above are from a Yelp engineer.
So what the means is, there’s no way your frontend JavaScript code can make requests directly to Yelp API endpoints and get normal responses (as opposed to JSONP responses).
Specifically, because responses from the https://api.yelp.com/v3/businesses/search API endpoint don’t include the Access-Control-Allow-Origin response header, browsers will not allow your frontend JavaScript code to access those responses.
Also, because your request includes the Authorization and a Content-Type header with the value application/json, your browser does a CORS preflight options request before ever attempting the actual GET request you’re trying to send.
And that preflight is what’s specifically failing in this case. But any other request you make from the frontend code to that API endpoint would also fail—even if it didn’t trigger a preflight.

Google Timezone API request CORS error

I try to request the Google Timezone API from an AngularJS app.
But when I'm making my request I got this error in the preflight request :
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/timezone/json?location=48.8709,2.3561&timestamp=14912286400&key=MY_KEY. Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
Here is my Google API configuration :
I've tried to disable preflight request by setting header with Content-Type: 'text/plain', but there is always a preflight request.
Do you think the error mentioned above is caused by the preflight request or do you think I should look in another direction ?
Thanks in advance
EDIT : I know how to enable CORS on my server, this is not the point. What I want is to access Google API from my AngularJS app without creating à WS on my server (if it's possible). If I don't have choice I'll do it, but in this case I know how to do it.
ANSWER : Thanks to #Sebas I solved my problem with the window.fetch() API. This doesn't work on IE, but there is a great polyfill here : https://github.com/github/fetch.
I don't know if it's the best option to deal with my problem, but it works.

Http-Method changes from POST to OPTIONS when changing Content-Type

I am using closure library to do a simple POST. I think XhrIo should work because from my machine when I use any other rest client ,like Firefox browser app RESTClient or Chrome's Simple Rest Client , I can make POST request to the server and content type is application/json.
But from my application I am unable to make a post.
I am using the following code
xhr = new goog.net.XhrIo;
xhr.send('http://myhost:8181/customer/add','POST', goog.json.serialize(data));
If I leave the headers default, I get this
Encoding: UTF-8
Http-Method: POST
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
If I try to change the header by passing {'content-type':'application/json'} as 4th parameter, header changes to
Http-Method: OPTIONS
Content-Type:
Shouldn't I be able to change headers appropriately with Closure library just as RESTClient does with XMLHttpRequest using JQuery ?
How else can the header be altered to make it appear like this
Encoding: UTF-8
Http-Method: POST
Content-Type: application/json;charset=UTF-8
Appreciate any help
Eddie
When you add a header to an XHR object, most browsers will do a preflight request, which is the OPTIONS method that you are seeing. There is not a way to circumvent this if you are adding custom headers, unfortunately. The POST will be sent after the OPTIONS.
This article explains the OPTIONS request a bit. I ran into issues with the preflight a while back, if that is any help.
If you have specific issues with the OPTIONS request you should edit your question to include them; otherwise, this is expected behavior.
FWIW mine also failed to update the type when I specified...
{'content-type':'application/json'}
However, if I corrected the case to
{'Content-Type':'application/json'}
... it worked.
Go figure.
If you are pass Content-Type on authorization request it will convert POST method to OPTIONS method so while we are use ouath and passing authorization token that time do not required Content-Type.
So do not pass Content-Type on all authorization request it won't change your method POST to OPTIONS

jQuery, CORS, JSON (without padding) and authentication issues

I have two domains. I'm trying to access a JSON object from one domain through a page on another. I've read everything I could find regarding this issue, and still can't figure this out.
The domain serving the JSON has the following settings:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
Header set Access-Control-Allow-Headers "origin, authorization, accept"
From my other domain, I'm calling the following:
$.ajax({
type:'get',
beforeSend: function(xhr) {
var auth = // authentication;
xhr.setRequestHeader("Authorization", "Basic " + auth);
}
url:myUrl,
dataType:'json',
error: function(xhr, textStatus, errorThrown) { console.log(textStatus, errorThrown); }
})
I know that 'auth' is initialized properly (logged and checked). However, this does not work. In Firefox's Console, I get
Request URL: ...
Request Method:
OPTIONS
Status Code:
HTTP/1.1 401 Authorization Required
If I get rid of the beforeSend:... part, I see the following
Request Method:
GET
Status Code:
HTTP/1.1 401 Authorization Required
However, the domain serving JSON also can serve JSONP. I don't want to use this, mainly because the application will be running constantly on a dedicated browser, and I'm worried about this issue. More importantly, I would really like to know what is actually wrong with what I am doing. I know that for practical purposes there are various ways to overcome the JSONP memory leak (such as not using jQuery).
At any rate, when I did use JSONP, my code looked like this:
$.ajax({
url:newUrl,
dataType:'jsonp',
jsonp:'jsonp'
}).done(function(d){console.log(d)})
This gets the following
Request Method:
GET
Status Code:
HTTP/1.1 200 OK
after it prompts me with an alert box for a username and password.
Is there a fundamental difference in the way jQuery handles JSONP requests as opposed to JSON requests? And if so, how can I fix this?
Thanks.
Edit: Here's what I did find.
Basically, because I need authentication, the GET request is sending an Authorization header. However, this is not a "simple" header, and so the browser is sending a pre-flight request (the OPTIONS). This preflight request doesn't have any authentication, though, and so the server was rejecting it. The "solution" was to set the server to let OPTIONS request not require authentication, and report an HTTP status of 200 to it.
Reference: http://www.kinvey.com/blog/item/61-kinvey-adds-cross-origin-resource-sharing-cors
mail-archive[.com]/c-user#axis.apache.org/msg00790.html (not allowed to post more links)
Unfortunately, the "solution" is only working on Firefox and not Chrome. Chrome simply shows the request in red, but doesn't give me any more info on why it failed.
Edit 2: Fixed on Chrome: The server I was trying to get data from had a security certificate which was not trusted. The preflight request on Chrome failed because of this. Solution
superuser[.com]/questions/27268/how-do-i-disable-the-warning-chrome-gives-if-a-security-certificate-is-not-trust (not allowed to post more links)
Welp, now that I have enough rep a while later, I might as well answer this question and accept it.
When you attempt to send a GET json request to a server with headers, the browser first sends an OPTION request to make sure that you can access it. Unfortunately, this OPTION request cannot carry with it any authentication. This means that if you want to send a GET with auth, the server must allow an OPTION without auth. Once I did this, things started working.
Some examples available here may illustrate further how access control can be combined with CORS. Specifically the credentialed GET example. Access control requires that the request set the withCredentials flag to true on the XMLHttpRequest, and for the server handling the OPTIONS method to do two things:
Set Access-Control-Allow-Credentials: true
Not use a wildcard * in the Access-Control-Allow-Origin header. This has to be set to the origin exactly according to the MDN docs on HTTP access control (CORS).
Essentially, the thing processing the OPTIONS request needs to send back appropriate response headers so you can make that credentialed request.
In your question you stated that the service you are interacting with is returning Access-Control-Allow-Origin: *, which is not compatible with a credentialed cross-domain request. This needs to return the origin specifically.
The aforementioned MDN Http Access Control (CORS) documentation also links to the Server-Side Access Control documentation outlining how a server would potentially respond to various cross domain requests - including handling a cross domain credentialed POST request that requires you to send back the correct headers in response to the OPTIONS method. You can find that example here.
Why don't you try typing the URL you are fetching the JSON from into your browser and seeing what happens. It sounds like you literally just need to authenticate into this other website to access it.
If your site needs to work in other browsers like IE, you WILL need JSONP, by the way. The security won't allow the cross site request to work. The headers won't change that. I believe you will also need to add a security policy in your headers.

Categories

Resources