We're having an issue with restangular and handling errors from the API. If the API responds with a 200, then everything works perfectly. However, when the API returns a 409 we receive a lovely:
XMLHttpRequest cannot load https://**token=*. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:9000' is therefore not allowed access.
Response headers from a valid post operation:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Authorization, Accept, X-Authorization, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, If-Modified-Since
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:http://127.0.0.1:9000
Access-Control-Max-Age:1728000
Cache-Control:private, must-revalidate
Connection:keep-alive
Content-Type:text/html; charset=utf-8
Date:Fri, 29 Aug 2014 21:55:51 GMT
ETag:"*****"
Server:nginx/1.6.0
X-Frame-Options:SAMEORIGIN
X-Powered-By:HHVM/3.3.0-dev+2014.08.22
Response headers from a post operation with a 409 response captured from postman:
Cache-Control →no-cache
Connection →keep-alive
Content-Encoding →gzip
Content-Type →text/html; charset=utf-8
Date →Fri, 29 Aug 2014 21:56:59 GMT
Server →nginx/1.6.0
Transfer-Encoding →chunked
X-Frame-Options →SAMEORIGIN
X-Powered-By →HHVM/3.3.0-dev+2014.08.22
Any attempt to catch the response.status or error handling as outlined in the
restangular docs results in this:
config: Object
data: ""
headers: function (name) {
status: 0
statusText: ""
I always have a status of 0.
Let me know if you need to see any additional information.
This really has nothing to do with restangular but with your webserver config.
What is happening is that your webserver isn't set up to return the CORS headers in case an error occurs.
Because of this you can not access any of the returned data from the ajax request, even tough data was actually returned. You won't even be able to see it in chrome's network inspector ( except for the status code and headers ). Additionally, because this is a security violation, you can't even access the status code, headers or anything from javascript everything is being blocked.
You will however be able to see it in a proxy like fiddler or charles, or when you make the request directly to the api server ( in case of a GET request ), because a request was actually made and data will have been returned, the browsers security policies just denies access to it trough AJAX because of the missing CORS headers.
This doesn't mean you can just fire off ajax requests to any other domain and possibly interact with it. The only reason your requests are going trough in the first place is because the preflight OPTION request is set up to allow CORS
Solution:
Set up your WebServer to include CORS headers in case an error response is generated, the headers you are looking for are all available in the valid response you supplied ( Access-Control-* ).
Related
I have deployed my front-end angular app with keycloak enabled. Also have a java rest based back-end for communication. When i run the app keycloak shows the login page, Then after i login it does not shows anything.
XMLHttpRequest cannot load http://test.ssdiary.com:2222/auth/realms/app1/protocol/openid-connect/token. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://test.ssdiary.com', but only one is allowed. Origin 'http://test.ssdiary.com' is therefore not allowed access.
GET http://test.ssdiary.com:2222/auth/realms/app1/protocol/openid-connect/login…ame.html/init?client_id=srms-frontend&origin=http%3A%2F%2Ftest.ssdiary.com 403 (Forbidden)strong text
Header from network tab
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, authorization, content-type, x-requested-with
Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1
Connection:keep-alive
Content-Length:0
Date:Fri, 09 Jun 2017 04:57:38 GMT
Server:WildFly/10
X-Powered-By:Undertow/1
Please read the specifications of the Access-Control-Allow-Origin header here.
For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.
You are setting Access-Control-Allow-Credentials:true in your request. Thus, multiple origins are not allowed to access the returned content. Try to send a single origin as the value of Access-Control-Allow-Origin from your server.
I'm having a problem where by the cross origin requests from my Angular JS application work fine in Chrome but not in Firefox.
The error received in firefox is:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://api.domain.eu/join/joinstatus. (Reason:
CORS header 'Access-Control-Allow-Origin' does not match
'https://www.domain.eu, https://www.domain.eu').
I can make requests successfully until I add an Authorization header to the request.
My server (ASP.Net Web API running on IIS) has the following headers set up:
Access-Control-Allow-Origin: https://www.domain.eu
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Firefox successfully pre-flights the request with an OPTIONS request. Looking through this I can see the sent Origin header is contained in the returned Access-Control-Allow-Origin header.
In fact, for some reason the returned Access-Control-Allow-Origin header has my domain name twice (despite specifying it once in config) e.g.
Access-Control-Allow-Origin: https://www.domain.eu, https://www.domain.eu
That aside what is the difference between Firefox and Chrome in this regard?
What else do I need to do so that this will work in Firefox?
UPDATE
I have noticed that if I set my headers as follows...
`Access-Control-Allow-Origin: https://www.domain.eu'
... then the pre-flight OPTIONS request works fine. The Access-Control-Allow-Origin header is the same in both the request and the response. However the actual GET request then fails with the error above.
If I modify my headers as follows:
Access-Control-Allow-Origin: https://www.domain.eu, https://www.domain.eu
... (which is what Firefox alluded to in the error), then the actual pre-flight OPTIONS request fails as this time Firefox just expects a single value of https://www.domain.eu in the header.
Try:
Access-Control-Allow-Origin: https://www.domain.eu, https://domain.eu
Access-Control-Allow-Origin: https://*.domain.eu, http://*.domain.eu
Access-Control-Allow-Origin: domain.eu
Access-Control-Allow-Origin: *.domain.eu
EDIT:
Try:
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Access-Control-Request-Method: GET, POST, OPTIONS, PUT, DELETE
Docs:
Access-Control-Allow-Origin
A returned resource may have one Access-Control-Allow-Origin header, with the following syntax:
Access-Control-Allow-Origin: <origin> | *
The origin parameter specifies a URI that may access the resource. The browser must enforce this. For requests without credentials, the server may specify * as a wildcard, thereby allowing any origin to access the resource.
For example, to allow http://mozilla.com to access the resource, you can specify:
Access-Control-Allow-Origin: http://mozilla.com
You must only specify a single URI or *
This problem was caused by essentially having the wrong combination of NuGet packages in my solution. Owin and Web API CORS had both been used causing the headers to get mixed up.
I resolved this by going back to basics and working out what packages I needed and the problem went away.
you need to enable CORS in your web API project.
Check this out!
I'm currently deploying a basic API to my live server and I'm running into (what I think is) a CORS problem but there is some behavior going on that I can't explain.
I'm communicating from an AngularJS front-end to a Laravel 5 (+ laravel-cors) back-end.
I started testing with a simple jQuery AJAX call (below) and when I make a request from my local Vagrant environment (http://dev.example.local/test.html) to http://api.example.com/v1/matches I get an error about Access-Control-Allow-Origin. The weird thing is that the request does come through because the information is stored in the database via the Laravel-based API correctly.
$.ajax({
method: 'POST',
url: 'http://api.example.com/v1/players',
data: {
"username": "username",
"first_name": "First",
"last_name": "Last",
"nickname": ""
}
}).always(function(r) {
console.log(r);
});
Error:
XMLHttpRequest cannot load http://api.example.com/v1/players. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://other.example.com' is therefore not allowed access.
The console.log(r) returns {readyState: 0, responseJSON: undefined, status: 0, statusText: "error"}
I developed the application locally using a Homestead VM (API) and a Vagrant environment (application) and it's working correctly within these environments...
Some observations:
Each of these requests shows up with Method: POST, Status: 200 OK, Type: xhr in my Chrome Developer Tools.
Tools like Postman and PhpStorm's RESTful service tester correctly execute the request and the data is added without errors.
Any ideas on how to further debug this problem are welcome... I've been trying to wrap my head around this for the entire day now and I just don't know what's causing it.
Your server must return an appropriate Access-Control-Allow-Origin header in the response. For example, if the request is being sent from http://stackoverflow.com, then your server must return this header: Access-Control-Allow-Origin: http://stackoverflow.com. You can determine, server-side, what the origin is by looking at the Origin header on the request. If your server does not return this header in the response, you will not have any access to the properties of the response browser-side (such as the status code, headers, or message body). The Same Origin Policy is at the center of this restriction.
The reason you are not seeing any similar issues when the request is sent by Postman or PhpStorm's RESTful service tester is due to the fact that these services do not send an Origin header with the request, as they are not subject to the Same Origin policy. By default, the browser will append this header to any cross-origin ajax requests, as browsers are subject to the Same Origin Policy. In my previous scenario, the request header would look like this: Origin: http://stackoverflow.com. Browsers that implement the CORS spec are required to add this request header so the server is able to determine if the origin of the request has been whitelisted for cross-origin ajax requests. If this is the case, the server will return the proper Access-Control-Allow-Origin header. If not, it can simply omit the header. Browsers that do not implement the CORS spec will simply refuse to send such an ajax request.
Regarding your bewilderment as to why the request is being sent in the first place, that comes down to a distinction between "simple" and "non-simple" CORS requests. For simple CORS requests, the request will always be sent to the server, but the client/JS will not be able to parse the response without proper acknowledgement from the server. Some CORS requests are not simple, so to speak. These are, for example, DELETE or PATCH requests, or POST/GET requests that contain non-standard headers (such as X-headers or a Content-Type of "application/json" as opposed to "multipart/form-data"). In other words, a request is not simple if it cannot be sent without JavaScript. For example, a <form> submit, or a GET request from a <script src="..."> will always send "simple" requests. For non-simple requests, the browser must "preflight" the request. This means that the browser sends an intermediate request, called a preflight, before the original request. This preflight request is an OPTIONS request. The server must than return headers in the response to this preflight that acknowledge any non-standard properties of the original request. If it does, then the browser will send the original request.
You can read more about preflighting and CORS in general on MDN.
Basically I am using a POST method but it automatically gets converted to OPTIONS method. I know browser does this but also read that it is fine and should get response as 201, but in my case it is not behaving as expected, I have also tried Access-Control-Allow-Methods in request headers but didn't get anything.
This is what my Request looks like:
OPTIONS http://xyz/abc
Accept: application/json
Content-Type: application/json
Response:
405, Method Not Allowed
Access-Control-Allow-Origin: *
Date: Tue, 05 May 2015 06:15:19 GMT
Connection: close
Accept-Ranges: bytes
Access-Control-Allow-Headers: authorization, content-type
Content-Length: 0
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD
Can anyone tell me the cause of this issue and what could be the exact reason for the same after having enough research everything looks fine at my end.
Thanks in advance.
You are probably seeing pre-flight check during a POST-request in cross-origin resource sharing. I don't know how your webserver needs to be setup to support this, but this Wikipedia article might be a first help: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
The easiest solution is to do the POST request on the same origin as the where you are loading the web-page from. A reverse proxy might be a reasonable solution.
basically my problems is use set-cookie header with angular (looks like he is ignored even with the withCredentials set to true) but here is the problem if i make the same request the cookies go, but if i change the path does't work.
Example;
POST http://localhost/app/api/oauth/ HTTP/1.1
[other headers and payload]
then i get the answer:
HTTP/1.1 200 OK
Set-Cookie: ; expires=Wed, 31-Mar-2015 01:34:53 GMT
and send a request to access a resource:
GET http://localhost/app/api/oauth/test HTTP/1.1
Cookie:blah=something;
until now evething is ok, but when i try to access other resources on my server:
GET http://localhost/app/api/othercontroller/test HTTP/1.1
the cookie is not send anymore, only if i access some path after the path that create the cookie.
that is what network monitor show me. But i can't see that blah coockie on the resource tab (on cookie area).
Note: i already try use secure cookie or not and use http only cookie or not and all combinations between both of then. And i try don't use CORS or enable CORS, but anyone work too.
Anyone know what can be ?
Thanks for you time and patience.
I'm pasting my suggestion from my comment.
Your initial cookie is set in a response of a HTTP endpoint path that is deeper than your second request.
Set-Cookie: ; Domain=foo.com; Path=/; expires=Wed, 31-Mar-2015 01:34:53 GMT
You may specify where to put your cookie by specifying a Path parameter in your response header like given above.