AngularJS $http POST request - angularjs

When I'm making POST request with headers as content-type: application/JSON headers don't set a cookie in Request Headers. But when I change the headers as content-type: application/x-www-form-urlencoded headers set a cookie in Request Headers.
Server accepts application/JSON format.
Also, I have already given with-credentials: true on the client side.

Though the code is not available, I assume that setting the path parameter of the cookie will do the trick for you. The following may help:
cookies problem in PHP and AJAX
Why is the browser not setting cookies after an AJAX request returns?

Related

Getting Access-Control-Allow-Headers in preflight error

I have created angular js app in which I have integrate twitch api , the api is
return $http({
url: "https://api.twitch.tv/kraken/streams",
method: "GET",
params: { channel: channel, limit: 1 },
headers: { "Client-Id": "XXXXXXXXXXXXXXX" }
})
the problem is when I reload the page the api is working but when my state changes without page reload I am getting cross origin error from this api.
the error is
Failed to load https://api.twitch.tv/kraken/streams?channel=eliazOne&limit=1: Request header field RefreshToken is not allowed by Access-Control-Allow-Headers in preflight response.
anyone has idea how to resolve cross error
When you make a request to a different domain this is called a cross domain request. Also known as a CORS request.
When you POST / PUT data to a different domain it will make an OPTIONS request first. This is to ensure that the server has Access-Control-Allow-Headers in place on the response. These headers should permit access to the domain you are making the request from. If these headers are not present then when the OPTIONS request is made it will fail and the POST / PUT will never be made.
See here for more info https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests
The simple answer is to just add these headers to your server.
I don't know if this is something Angular does on its own by default or if it's a bug elsewhere in your code, but you or Angular is sending a RefreshToken header as part of your failing request, which is not allowed per Access-Control-Allow-Headers response header in the pre-flight OPTIONS request.
$ curl -XOPTIONS https://api.twitch.tv/kraken/streams -is | grep Headers
Access-Control-Allow-Headers: Accept, Accept-Language, Authorization, Client-Id, Twitch-Api-Token, X-Forwarded-Proto, X-Requested-With, X-Csrf-Token, Content-Type, X-Device-Id
This is something all cross-origin requests do. The browser sends an OPTIONS request to make sure the real request it's about to make is allowed by the criteria set by the cross-origin server.
You need to add a ?callback=? with the URL you are passing along with a callback function. Please follow the link How to use JQuery to Access Twitch streams
This is JQuery example but the concept is same.
$.getJSON('https://api.twitch.tv/kraken/streams/' + name + '?callback=?',
function(channel){
if (channel["stream"] == null) {
$("#all").append("<p>" + channel._links.self + "</p>");
}
else {
$("#all").append("<p>Fail</p>");
}
});
});

Access-Control-Allow-Origin error but request goes through

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.

AngularJS ignoring Set-Cookie header in certain cases

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.

Restangular error handling results in CORS issue?

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-* ).

Suppress OPTIONS Requests in Angular CORS

If I have foreknowledge that CORS calls made with Angular will, indeed, work, can I suppress the OPTIONS calls so that they don't continue needlessly occurring in production?
This OPTIONS request tells the client if a CORS request will be allowed; and, for those requests, which methods (GET, POST, PUT, etc.) can be executed.
According to W3c options call is not required if you are implementing only simple methods: GET/POST/HEAD.
So where you set your Access-Control-Allow-Methods if it is * try changing it to "GET,POST" and based on the standard (if the browser follows), your browser doesn't need to fire the options call.
To avoid the OPTIONS request you need to make sure that your request is a "simple" request.
A simple cross-site request is one that:
Only uses GET, HEAD or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
Does not set custom headers with the HTTP Request (such as X-Modified, etc.)
Check that Angular isn't setting x-requested-with or anything else unexpected.

Resources