问题
How could request headers be different for the same call and for the same JS code from the same browser?
I have one web API project and I am calling a method in this API from two different projects (CORS calls), using $http.get
method of AngularJs 1.X
.
$http.get("http://local.api:9002/api/default/get")
.then(function success(response, status, headers, config) {
console.info(response);
},
function error(response, status, headers, config) {
console.info(response);
}
);
This is the same code that is being used from both front-end UIs to call the API.
However, for one the call succeeds and for the other it fails, stating below error.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Upon observation, I have found a difference in request headers for both the calls.
Requests Header for call that succeeds - AngularJS v1.6.4
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Host:local.api:9002
Origin:http://local.ui.one:9001
Referer:http://local.ui.one:9001/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36
Response Header for the call that succeeds
Access-Control-Allow-Origin:http://local.ui.one:9001
Cache-Control:no-cache
Content-Length:19
Content-Type:application/json; charset=utf-8
Date:Fri, 05 May 2017 01:05:05 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Request Header for call that fails - AngularJS v1.2.17
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Access-Control-Request-Headers:cache-control,if-modified-since,pragma,x-requested-with
Access-Control-Request-Method:GET
Connection:keep-alive
Host:local.api:9002
Origin:http://local.ui.two:9003
Referer:http://local.ui.two:9003/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36
Response header for call that fails
Cache-Control:no-cache
Content-Length:113
Content-Type:application/json; charset=utf-8
Date:Fri, 05 May 2017 01:22:14 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
These are the two request headers that are additional in the second call.
Access-Control-Request-Headers:cache-control,if-modified-since,pragma,x-requested-with
Access-Control-Request-Method:GET
Note:
- My UI one and API are in the same
Visual Studio Solution
, while UI two is in a differentSolution
. I believe this could not be the reason but I could be wrong. - I have different AngularJS versions in both the UI projects. Could this be a possible reason?
EDIT
As suggested by @Phil, I updated my backend API to handle the preflight requests coming from my 2nd UI project.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//Some API routes here...
var enableCorsAttribute = new EnableCorsAttribute(
// Comma separated whitelist of allowed domains, notice no slash ('/') at the end of domain
"http://local.ui.two:9003,http://local.ui.one:9001",
// Allowed Custom Headers
"Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, If-Modified-Since, Pragma",
// Allowed methods
"GET, PUT, POST, DELETE, OPTIONS"
);
config.EnableCors(enableCorsAttribute);
}
}
And registered this WebApiConfig in Global.asax
.
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
And it started handling the calls from 2nd UI project as well, though the request headers were different.
回答1:
For call that fails - AngularJS v1.2.17
Access-Control-Request-Headers:cache-control,if-modified-since,pragma,x-requested-with Access-Control-Request-Method:GET
This to me looks like the browser is doing a CORS pre-flight check to get permission to include non-standard headers. Look in the app to see why it is adding those non-standard headers.
Versions of AngularJS before v1.1.1 used to include x-request-with
as a default and cause this problem.
Check for a config block that changes $httpProvider.defaults
.
For the list of allowed headers that won't trigger a pre-flight request, see MDN HTTP Reference - Access_control_CORS (Simple Requests)
回答2:
Here's my guess...
Older versions of Angular added the x-requested-with
header. This has since been dropped. This header causes your CORS request to be non-simple which triggers a pre-flight OPTIONS
request. Looks like your backend isn't set up to handle these requests.
You can work around this in the older Angular version by removing the header in your config
function
delete $httpProvider.defaults.headers.common['X-Requested-With'];
The key was this line in what I assume is the request headers for the OPTIONS
request
Access-Control-Request-Headers:cache-control,if-modified-since,pragma,x-requested-with
If you want your API to work correctly with cross-origin requests, it should respond correctly to pre-flight OPTIONS
requests.
来源:https://stackoverflow.com/questions/43794831/why-there-are-different-request-headers-for-same-ajax-call