手机wap前端开发标准 |
前端手机开发手指按下抬起事件 |
手机前端开发 |
一丶概述
最近小组做的项目中,前后端需要跨域通信,本打算直接使用jsonp来实现。但是这对前后端代码改动有点大,而且jsonp仅支持get请求。最后决定使用CORS的方式来实现,过程中各种的坑啊。这里为大家介绍下CORS及各种遇到的问题解决方案。
二丶什么是CORS
CORS是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制。使用CORS,可以通过普通的XMLHttpRequest发起请求和获得数据,并且支持各种类型请求。说白了就是利用XMLHttpRequest来实现跨站通信,而不是仅仅遵循同源策略,再也不用为了ajax能跨域写苦逼的jsonp了。 CORS技术现在已经被广泛的支持了。
三丶CORS使用方法及场景举例
所谓的跨域请求,从本质上来说并不是浏览器对其他域名的请求不能发送,而是请求可以正常发起,但是浏览器在收到服务器信息后就屏蔽掉了,并向前端报错(跨域)。如图所示,跨域请求结果被屏蔽。
解决方案,服务器在响应HTTP头部加入 **Access-Control-Allow-Origin:***即可,这样就表示服务端同意任意域名的请求。一般我们会指定可响应的域名如:Access-Control-Allow-Origin: http://b.com, http://c.com 等。这样浏览器在检测到服务端HTTP头部的时候就可以不再拦截响应。 请求头部: 响应头部: 就在我们以为轻松搞定的时候,我们又遇到了问题。前端要给后端传json格式的数据于是在http头部加入了 content-type: application/json, access_token等信息。请求再次失败,通过观察控制台信息我们发现,多了一个请求options: 原来在CORS中的请求分为两种:简单请求和复杂请求
####简单请求:
1. 只使用**GET**,**HEAD**或者**POST**。如果使用POST来发送数据到服务器,那么使用HTTP POST请求发送到服务器的数据的Content-Type为以下几种之一:**application/x-www-form-urlencoded**,**multipart/form-data**以及**text/plain**。
2. 不使用HTTP请求发送定制请求头(例如X-Modified等)
在简单请求下,我们只需要像上面所说设置Access-Control-Allow-Origin头部即可。
####复杂请求
1. 使用了除**GET**,**HEAD**和**POST**以外的方法。如果使用POST方法发送请求数据时的Content-Type不是application/x-www-form-urlencoded,multipart/form-data或者text/plaint。例如,如果POST请求向服务器使用application/xml或者text/xml向服务器发送请求,那么这个请求就是preflighted的。
2. 设置了定制请求头的请求(例如,请求使用了例如X-PINGOTHER这样的请求头)
这类请求在发送正式请求之前会发送一个**Preflighted(预请求)**,**Preflighted**请求首先通过HTTP **OPTIONS**方法请求其他域上的资源,以确定发送实际的请求是否安全。这样做,是因为跨站请求可能会对目的站点的数据造成破坏。我们第二次发的请求是一个复杂请求,服务端没有响应options的方法,导致预请求失败,之后的请求也就终止了。我们看一下复杂请求下的HTTP报文。
Prelignted请求头部:
可以看到报文头部信息为OPTIONS请求 预请求服务端响应报文
预请求响应只要返回一个2xx表示成功的响应信息即可说明服务端同意了跨域请求,这里我们选择204的状态码作为响应状态。因为204表示响应成功,并且没有结果返回的状态。这样节省了传输信息的事件,加快了预请求的处理。
预处理结束后,事情并没有就此解决。错误信息再次传来。
原来我们自定义了头部信息,还要在响应报文中加入Access-Control-Allow-Headers来指出服务端允许的复杂请求需要的自定义头部信息。注意这里不能用*来表示所有,只能一个个添加。例如:“Access-Control-Allow-Methods” : “PUT,POST,GET,DELETE,OPTIONS”。这样就齐活了,总算是数据可以流通了。这里我建议在服务端响应部分也加入 “Access-Control-Allow-Methods” : “PUT,POST,GET,DELETE,OPTIONS”来指出可接受的请求类型。
最后我们的服务端响应头部信息:
别急我们还没有结束
####附带凭证信息的请求
我手贱的在xhr中加入了 **xhr.withCredentials = true** 因为跨源请求默认请求头部中不提供凭据(cookie、HTTP认证及客户端SSL证明等)。为了能把这些信息带上,我们设置了withCredentials为true。浏览器再次报错,通过检查我们发现,如果你设置了withCredentials为true那么 **Access-Control-Allow-Origin**就不能用** *** ,必须使用明确的域名。而且还要为你的响应头加上**"Access-Control-Allow-Credentials":"true"**信息。
最后我列出CORS中可能使用的头部信息供大家参考:
** HTTP响应头**:**Access-Control-Allow-Origin**,**Access-Control-Expose-Headers**,**Access-Control-Max-Age**,**Access-Control-Allow-Credentials**,**Access-Control-Allow-Methods**,**Access-Control-Allow-Headers**
**HTTP请求头**:**Origin**,**Access-Control-Request-Method**,**Access-Control-Request-Headers**
附上用node.js跨域请求服务端的简单配置
**javascript 代码**
const express = require(‘express’),
app = express()
//统一拦截请求设置头部信息,响应预请求
app.all(‘*’, function(req, res, next) {
res.set({
‘Access-Control-Allow-Origin’: ‘*’,
‘Access-Control-Allow-Headers’: ‘Content-Type,access_token,user_id’,
‘Access-Control-Allow-Methods’: ‘PUT,POST,GET,DELETE,OPTIONS’,
})
if (req.method == ‘OPTIONS’) {
res.send(204)
} else {
next()
}
})
app.post(‘/data’, function(req, res) {
res.json({
status: ‘success’,
text: ‘返回数据’,
})
})
app.listen(3000, ‘127.0.0.1’, function() {
console.log(‘服务器启动了’)
})
四丶跨域请求的其他方案
这里列举一下其他常用的跨域方案,仅供参考。
1.** jsonp**:利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
2. **postMessage**:postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
3. **websocket**:WebSocket实现了全双工通信,使web上的真正的实时通信成为可能。浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
4. **SSE**:Server-Sent Events(SSE)功能,允许服务端推送数据到客户端(通常叫数据推送)。已经在浏览器上普遍支持,然而IE和Edge全系列不支持。
5. **ServiceWorker**:一个 service worker 是一段运行在浏览器后台进程里的脚本,它独立于当前页面,提供了那些不需要与web页面交互的功能在网页背后悄悄执行的能力。在将来,基于它可以实现消息推送,静默更新以及地理围栏等服务,但是目前它首先要具备的功能是拦截和处理网络请求,包括可编程的响应缓存管理。简而言之,这是让浏览器具有服务器功能的API,有了他还跨域个球球。不过这只是实验中API目前只有chrome和firfox高版本浏览器支持。
前端开发监听手机调试 |
手机站前端开发 |
前端开发 手机适配 |
评论前必须登录!
注册