(接上篇)node
上面已经提到,在用angular2调用后台接口的时候,遇到了两个问题一、请求头没有cookies;二、对两次请求,node后端都开了一个新的线程。对于这两个问题,其实我认为解决了请求头cookie的问题,后面的问题天然解决。对于cookie有什么做用,为何要有这个cookie,看下图先后端请求模式。json
不难看出,这个cookie是获取session会话中信息的凭证,只有向后台传送匹配的cookie,才能获得相应的信息,不然将建立新的session。后端
到这里,来看下XMLHttpRequest.withCredentials这个属性,度娘解释以下api
XMLHttpRequest.withCredentials 属性是一个Boolean类型,它指示了是否该使用相似cookies,authorization headers(头部受权)或者TLS客户端证书这一类资格证书来建立一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。 此外,这个指示也会被用作响应中cookies 被忽视的标示。默认值是false。 若是在发送来自其余域的XMLHttpRequest请求以前,未设置withCredentials 为true,那么就不能为它本身的域设置cookie值。而经过设置withCredentials 为true得到的第三方cookies,将会依旧享受同源策略,所以不能被经过document.cookie或者从头部相应请求的脚本等访问。
angular2中http显然也是基于xml的请求,一定有这个属性。再看下http接口的请求接口说明。默认状况下,通常浏览器的CORS跨域请求都是不会发送cookie等认证信息到服务端的,除非指定了xhr.withCredentials = true,可是只有客户端单方面的设置了这个值还不行,服务端也须要赞成才能够,因此服务端也须要设置好返回头Access-Control-Allow-Credentials: true;还有一点要注意的,返回头Access-Control-Allow-Origin的值不能为星号,必须是指定的域,不然cookie等认证信息也是发送不了。跨域
Interface Details url : string method : string|RequestMethod search : string|URLSearchParams|{[key: string]: any | any[]} params : string|URLSearchParams|{[key: string]: any | any[]} headers : Headers body : any withCredentials : boolean responseType : ResponseContentType
问题找到了,就是这货!再修改下请求代码浏览器
再来看下请求头信息服务器
显然,请求头都已经被加上了cookie,并且这个cookie都是匹配的,看似没什么问题,可是再看看请求接口的response,没有任何信息,但后台明显有返回信息,并且这个response并不是每次都不返回任何信息,存在偶然性。cookie
到这里,明显就出现了另外一个问题,就是跨域,看看浏览器的console信息就知道了session
XMLHttpRequest cannot load http://neil.com:8090/api/send. The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
到这里,问题清晰了,只要解决跨域问题,整个流程就跑通。网上也有不少办法处理跨域,但若是不想用jsonp呢,那只能从服务器上动刀子。查了些资料,最靠普的无非在服务端加上request头部设置angular2
//设置跨域访问 app.all('*', function (req, res, next) { res.header("Access-Control-Allow-Origin", "http://neil.com:4200"); //设置跨域访问 res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With'); res.header("Content-Type", "application/x-www-form-urlencoded"); next(); });
这里说明下,‘Access-Control-Allow-Origin’必须设置请求侧的域名,否则没法跨域,不能解决问题。
如今,问题已经所有处理。