【问题标题】:Angular, content type is not being sent with $httpAngular,内容类型未与 $http 一起发送
【发布时间】:2013-04-18 03:34:22
【问题描述】:

Angular 没有添加正确的内容类型选项,我尝试了以下命令:

$http({
    url: "http://localhost:8080/example/teste",
    dataType: "json",
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    }
}).success(function(response){
    $scope.response = response;
}).error(function(error){
    $scope.error = error;
});

上面的代码生成如下http请求:

POST http://localhost:8080/example/teste HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Content-Type: application/xml
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8080/example/index
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=C404CE2DA653136971DD1A3C3EB3725B

如您所见,内容类型不是“application/json”,而是“application/xml”。我在这里错过了什么吗?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    您需要在请求中包含正文。否则,Angular 会删除内容类型标头。

    data: '' 添加到$http 的参数中。

    【讨论】:

    • 但是如果我想发送一个对象作为数据呢?我正在使用 ASP.NET 通用 HTTP 处理程序,由于某种原因,context.Request.Params["formData"] 不起作用,但是 StackOverflow 帖子让我使用了 string json = new StreamReader(context.Request.InputStream).ReadToEnd();,它有效,但我并不完全放心使用它,因为我会而是按名称访问提交的请求参数值。
    • 天哪,这是救命稻草!!!这是默认的 HTTP 协议行为还是 Angular $http 行为?
    • 对于任何使用Restangular 的人,这里有一个如何实施此解决方案的示例:gist.github.com/sscovil/3bd0da1d98397213df54
    • @josh-lee 为什么我们需要提供data: '' ?这对我来说很奇怪。 GET 请求呢?有什么想法吗?
    【解决方案2】:
    $http({
        url: 'http://localhost:8080/example/teste',
        dataType: 'json',
        method: 'POST',
        data: '',
        headers: {
            "Content-Type": "application/json"
        }
    
    }).success(function(response){
        $scope.response = response;
    }).error(function(error){
        $scope.error = error;
    });
    

    像这样试试。

    【讨论】:

    • 恐怕它在Angular 1.3.14中不起作用,如果没有data,则删除Content-Type。空的data 参数虽然解决了这个问题...
    • 很奇怪!即使对于 GET 请求,我也必须提供数据:'' 字段。虽然我们都知道 GET 不应该有一个身体!知道为什么 angularjs 在没有提供数据的情况下会剥离内容类型的应用程序/标头吗?
    【解决方案3】:
             $http({
                    method: 'GET',
                    url:'/http://localhost:8080/example/test' + toto,
                    data: '',
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }).then(
                    function(response) {
                        return response.data;
                    }, 
                    function(errResponse) {
                        console.error('Error !!');
                        return $q.reject(errResponse);
                    }
    

    【讨论】:

      【解决方案4】:

      太棒了!上面给出的解决方案对我有用。与GET 通话有同样的问题。

       method: 'GET',
       data: '',
       headers: {
              "Content-Type": "application/json"
       }
      

      【讨论】:

      • 请在您的代码 sn-ps 中添加一些格式。并更好地解释自己以避免投票
      • GET 请求不能有正文 (stackoverflow.com/a/983458/2416700) 所以 Content-Type 在这种情况下是没有意义的
      • 这是真的,GET 请求不能有正文,但奇怪的是,当提供数据为空字符串时,只有 content-type 被采用,否则 angularjs 会剥离该标头。 !!
      【解决方案5】:

      如果它对任何人有用。对于 AngularJS 1.5x,我想为所有请求设置 CSRF,我发现当我这样做时:

      $httpProvider.defaults.headers.get = { 'CSRF-Token': afToken }; 
      $httpProvider.defaults.headers.put = { 'CSRF-Token': afToken };
      $httpProvider.defaults.headers.post = { 'CSRF-Token': afToken }; 
      

      Angular 删除了内容类型,所以我不得不添加这个:

      $httpProvider.defaults.headers.common = { "Content-Type": "application/json"};
      

      否则我会收到 415 媒体类型错误。

      所以我这样做是为了为所有请求配置我的应用程序:

      angular.module("myapp.maintenance", [])
          .controller('maintenanceCtrl', MaintenanceCtrl)
          .directive('convertToNumber', ConvertToNumber)
          .config(configure);
      
      MaintenanceCtrl.$inject = ["$scope", "$http", "$sce", "$window", "$document", "$timeout", "$filter", 'alertService'];
      configure.$inject = ["$httpProvider"];
      
      // configure the header tokens for  CSRF for http operations in this module
      function configure($httpProvider) {
      
          const afToken = angular.element('input[id="__AntiForgeryToken"]').attr('value');
      
          $httpProvider.defaults.headers.get = { 'CSRF-Token': afToken }; // only added for GET
          $httpProvider.defaults.headers.put = { 'CSRF-Token': afToken }; // added for PUT
          $httpProvider.defaults.headers.post = { 'CSRF-Token': afToken }; // added for POST
      
          // for some reason if we do the above we have to set the default content type for all 
          // looks like angular clears it when we add our own headers
          $httpProvider.defaults.headers.common = { "Content-Type": "application/json" };
      
      }
      

      【讨论】:

        【解决方案6】:

        只是为了展示如何将 "Content-type" 标头动态添加到每个 POST 请求的示例。在可能的情况下,我将 POST 参数作为查询字符串传递,这是使用 transformRequest 完成的。在这种情况下,它的值为 application/x-www-form-urlencoded

        // set Content-Type for POST requests
        angular.module('myApp').run(basicAuth);
        function basicAuth($http) {
            $http.defaults.headers.post = {'Content-Type': 'application/x-www-form-urlencoded'};
        }
        

        然后从request方法中的拦截器返回config对象之前

        // if header['Content-type'] is a POST then add data
        'request': function (config) {
          if (
            angular.isDefined(config.headers['Content-Type']) 
            && !angular.isDefined(config.data)
          ) {
            config.data = '';
          }
          return config;
        }
        

        【讨论】:

          猜你喜欢
          • 2013-09-02
          • 2016-11-13
          • 1970-01-01
          • 2015-08-01
          • 1970-01-01
          • 2020-01-01
          • 2017-01-24
          • 2016-01-01
          • 1970-01-01
          相关资源
          最近更新 更多