$http 服务

参考 : https://docs.angularjs.org/api/ng/service/$http

$http 是angular 封装好的 XMLHttpRequest 请求

内部还涉及到了

$httpBackend, $httpProvider, $q  (angular的promise), $cacheFactory (angular的cache机制) 等等

angular 的思想偏向restful概念, 所以都有 GET,POST,PUT,DELTE,PATCH,HEAD 等

angular 默认的请求头 

Accept: application/json, text/plain 接受json和text

Content-Type : application/json  

如果要修改默认设置的话可以在app.config上做修改 

var app = angular.module("app", []);

app.config(function ($httpProvider) {           

    log(angular.toJson($httpProvider.defaults)); //可以看看其它默认

    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; //我们常用的form 

    $httpProvider.defaults.headers.put["Content-Type"] = "application/x-www-form-urlencoded";

    $httpProvider.defaults.headers.patch["Content-Type"] = "application/x-www-form-urlencoded";

});

只要是default的headers,在每次发送请求的时候都会带上。

所以如果我们每个请求都有用到一些自定义的header,我们也可以写入在default.headers中 

$httpProvider.defaults.headers.common["myHeader"] = "myheaderValue";//common 表示不管任何的 method POST,GET,PUT等

这些default的header是可以在每一次我们发请求的时候通过参数来覆盖掉.

另外$http service 也提供了一个defaults的指针 (注: $httpProvider.defaults === $http.defaults )

app.controller("ctrl", function ($scope, $http) {

    $http.defaults.headers.common["myHeader"] = "abc";          

});

 

$httpProvider.defaults.transformRequest & transformResponse 

这是angular提供给我们的2个接口,在请求发送前和响应还没有触发callback前对post data 和 response data做一些处理 

它们是个数组类型,我们可以push一些函数进去 (angular默认对request和response都放入了一个方法,post的时候如果data是对象将json化,响应时如果data是json类型,将解析成对象)

在每一次的请求,我们依然可以覆盖整个数组.

var app = angular.module("app", []);

app.config(function ($httpProvider) {            

    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

    $httpProvider.defaults.transformRequest.shift(); //把angular default的去掉

    $httpProvider.defaults.transformRequest.push(function (postData) { //这个function不是依赖注入哦

        if (angular.isObject(postData)) { 

            return $.param(postData); //如果postData是对象就把它转成param string 返回, 这里借用了jQuery方法

        }

        return postData;

    });

    $httpProvider.defaults.transformResponse.push(function (responseData) {

        log(angular.toJson(responseData)); //响应的数据可以做一些处理

        return "data";

    });

});

app.controller("ctrl", function ($scope, $http) {

    $http({

        method: "POST",

        url: "handle.ashx",

        data: {

            key: "value"

        },

        transformResponse: [], //每一次请求也可以覆盖default

        transformResponse: $http.defaults.transformResponse.concat([function () { return "abc" }]) //如果default要保留要concat

    }).success(function (responseData) {

        log(responseData === "abc"); //true

    });

});

 

$httpProvider.defaults.cache

angular 默认cahce = false, 一样可以通过defaults去设置每个请求(当然只有GET请求可以cache)

我们也可以在每次请求覆盖设置

当同时发送2个没有缓存的请求时,angular也能处理,只发送一次(不错哦).

var app = angular.module("app", []);

app.config(function ($httpProvider) {

    $httpProvider.defaults.cache = true;          

});

app.controller("ctrl", function ($scope, $http) {

    //并发但是只会发送一个请求

    $http.get("handle.ashx");

    $http.get("handle.ashx");

     

    //我们可以为每次请求要不要使用缓存或者缓存数据

    $http({

        url: "handle.ashx",

        method: "GET",

        cahce: true

    });

    $http({

        url: "handle.ashx", 

        method: "GET",

        cache : false //强制不使用缓存,即使已存在

    });

});

  

$httpProvider.interceptors (interceptors 中文是拦截的意思)

除了之前介绍过的 transform 可以对数据做一些处理, angular也提供了另外4个时刻,分别是 onRequest, onRequestFail, onResponse, onResponseFail 

让我们做一些而外处理. 比如当我们server返回500的时候,可能我们想做一个通用的alert,或是request fail 的话自动调整一下config在尝试请求等等.

    //interceptors是数组,放入的是可以依赖注入的方法哦!

    $httpProvider.interceptors.push(["$q", function ($q) {

        return {

            request: function (config) { //config = {method, postData, url, headers} 等                            

                return config; //返回一个新的config,可以做一些统一的验证或者调整等.

            },

            requestError: function (rejection) {                      

                return $q.reject(rejection); //必须返回一个promise对象                                              

            },

            response: function (response) {                     

                return response; //这里也可以返回 promise, 甚至是把它给 $q.reject掉

            },

            responseError: function (rejection) { //rejection = { config, data, status, statusText, headers }                

                return $q.reject(rejection); //必须返回一个promise对象                  

            }

        };

    }]);

和 transform 的执行次序是这样的 interceptors.request -> transformRequest -> transformResponse -> interceptors.response

 

安全问题 ( JSON Vulnerability Protection & Cross Site Request Forgery (XSRF) Protection) 参考 : http://bijian1013.iteye.com/blog/2112233

json漏洞可以参考 : http://blog.roodo.com/rocksaying/archives/2955557.html

我个人没有理解很多,觉得只有jsonp可能引发此问题,但是jsonp一般都是非敏感数据,所以我就没认真对待了,高手可以提点我一下 ^^ 

XSRF 大家应该很熟悉了,参考 : http://blog.csdn.net/xcyuzhen/article/details/6255038

angular 对XSRF的防范是这样的,在第一次请求的时候服务器返回一个 "XSRF-TOKEN" 的cookie, 值是一个唯一的随机值,

那么之后每个$http请求都会附上一个 "X-XSRF-TOKEN" 的header, 值就是刚才那个随机数, 那么服务器可以做一个对比来确认身份。

这里给一个ASP.NET的例子

protected void Page_Load(object sender, EventArgs e)

{

    if (!IsPostBack)

    {

        //当用户登入后, 访问页面

        string ANGULAR_XSRF_COOKIE_KEY = "XSRF-TOKEN";

        var token = Session["pageToken"];

        if (token == null)

        {

            string pageToken = Guid.NewGuid().ToString(); //随机数

            Session["pageToken"] = pageToken;

            Response.Cookies.Add(new HttpCookie(ANGULAR_XSRF_COOKIE_KEY)

            {

                Value = pageToken,

                Expires = DateTime.Now.AddDays(1)  //配合前台logout洗掉   

            });

        }

    }

}

$http请求基本上什么都不需要做 

public void ProcessRequest (HttpContext context) 

{

    string ANGULAR_XSRF_HEADER_KEY= "X-XSRF-TOKEN";

    string pageToken = context.Request.Headers.Get(ANGULAR_XSRF_HEADER_KEY).ToString(); //从header提取

    if(context.Session["pageToken"].ToString() == pageToken) //对比是否一直

    {

        //pass

    }   

    context.Response.ContentType = "text/plain";

    context.Response.Write(context.Request.ContentType + "123");

}

更新 : 2015-05-08

$http 返回的是一个扩展了的 promise 对象

它有多了一些属性,比如 success , error (当然原本的then 还是有的)

success 和 then 是不太一样的,then 就是典型的promise实现啦,你返回另一个promise or value 它会串连下去,

但是 success 就不会,它只能算一个void,它的返回值是被忽视的。

success(function(data){}) , then(function(response){}) ; 前者的 arguments 是response.data , 后者是整个 response 对象

$http({

    url: "//localhost:14431/api/products",

    method: "get"

}).then(function (response) { 

    success.apply(window, [response.data, response.status, response.headers, response.config]); //大概是这样调用的

    return response;

});

 

所以用的时候要注意哦!

 

你可能感兴趣的:(http)