Angular: Custom headers are ignored by $http and $resource. Why?

女生的网名这么多〃 提交于 2019-12-03 12:26:54
Spiny Norman

I think your answer is here. According to the wiki, A JSONP call is executed through injection of a <script> tag to load the script from the host server, which responds by calling your callback, passing the data. A <script> tag generates a regular browser request (not an XmlHttpRequest), and the browser will send its own Accept header (it also sends its own User-Agent header, for example).

I would hope there is an easier client-side way to do this, but I think the only way may be the one suggested in the referenced post:

So, if you want to be able to set request headers for cross domain calls you will have to setup a server side script on your domain that will delegate the call to the remote domain (and set the respective headers) and then send the AJAX request to your script.

EDIT: here is a (rejected) jQuery bug report about this same problem.

Some more background info:

In angular, callbacks are managed automagically, so if your say this:

$http({
    method: "JSONP",
    url: "http://headers.jsontest.com?callback=JSON_CALLBACK",
}).success(function(data) {
    console.log('Return value:');
    console.log(data);
}).error(function(data) {
    console.log('Error!');
    console.log(data);
})

a <script> tag will be created that looks more or less like this:

<script type="application/javascript"
        src="http://headers.jsontest.com/?callback=angular.callbacks._1">
</script>

The content of the response to http://headers.jsontest.com/?callback=angular.callbacks._1 will be:

angular.callbacks._1({key1: "value1", key2: "value2"});

angular.callbacks._1 will contain your success function, and it will be called with the data.

While what you have is supposed to work according to the docs, my experience has been a bit different. To get around this issue, we did the following:

Create a "base controller" that gets added to the page either on the body or html tag. In that controller, make the assignment using $http instead of $httpProvider. Because your base controller loads when the initial page loads, it is there for all other controllers and services that will run in your app.

I don't know why this works and the proscribed method does not, and I'd love to see an answer to your question that is better than this work-around, but at least this can get you moving forward with development again.

The following works for me - however, I do that during "runtime" with $http and I am not using $httpProvider during bootstrapping.

function SomeCtrl($http) {

    $http.defaults.transformRequest.push(function (data, headersGetter) {
        headersGetter().Accept = "application/json, text/javascript";
        return data;
    });

}

Edit

Here is a working jsFiddle version. Check the request which is done with Developer Tools/Firebug and see that "application/json, text/javascript" is requested.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!