欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

OPTIONS 方法在跨域请求(CORS)中的应用

OPTIONS 方法比较少见,该方法用于请求服务器告知其支持哪些其他的功能和方法。通过 OPTIONS 方法,可以询问服务器具体支持哪些方法,或者服务器会使用什么样的方法来处理一些特殊资源。可以说这是一个探测性的方法,客户端通过该方法可以在不访问服务器上实际资源的情况下就知道处理该资源的最优方式。

既然比较少见,什么情况下会使用这个方法呢?

最近在做跨域文件上传的时候,浏览器会自动发起一个 OPTIONS 方法到服务器。

如果只是普通的 ajax 请求,也不会发起这个请求,只有当 ajax 请求绑定了 upload 的事件并且跨域的时候,就会自动发起这个请求。

var xhr = new XMLHttpRequest();
var url = 'http://api.xxx.com/upload';
xhr.open('POST', url);
xhr.upload.addEventListener('progress', function (){
	// ...
}, false);
xhr.upload.addEventListener('load', function (){
	// ...
}, false);
xhr.upload.addEventListener('error', function (){
	// ...
}, false);
xhr.upload.addEventListener('abort',function (){
	// ...
}, false);
xhr.send(data);

上面的代码是在 xxx.com 域下发起了一个跨域的 POST 请求,期望提交数据到 api.xxx.com 这个域名的服务器,同时在提交数据的时候希望能监测到文件上传的实时进度。

自动发起的 OPTIONS 请求,其请求头包含了的一些关键性字段:

OPTIONS /upload HTTP/1.1
Access-Control-Request-Method: POST
Access-Control-Request-Headers: accept, content-type
Origin: http://xxx.com
...

在这种场景下,客户端发起的这个 OPTIONS 可以说是一个“预请求”,用于探测后续真正需要发起的跨域 POST 请求对于服务器来说是否是安全可接受的,因为跨域提交数据对于服务器来说可能存在很大的安全问题。

请求头 Access-Control-Request-Method 用于提醒服务器在接下来的请求中将会使用什么样的方法来发起请求。

那么在服务端应该如何处理这个 OPTIONS 请求呢?

这里以 node.js 服务器的 Koa 框架为例。在服务端会增加一个 OPTIONS 方法的 /upload 路由来处理客户端的这个请求。

Koa 中使用了一个比较受欢迎的 koa-router 中间件来处理路由,但是该中间件对 OPTIONS 方法默认的处理方式会有点问题。因为在响应上面的 OPTIONS 请求时,需要添加上用于访问控制的响应头。

响应头中关键性的字段:

Access-Control-Allow-Method: POST
Access-Control-Allow-Origin: http://xxx.com

Access-Control-Allow-Method 和 Access-Control-Allow-Origin 分别告知客户端,服务器允许客户端用于跨域的方法和域名。

node.js 的路由代码会是这样的:

router.options('/upload', function* (){
    this.set('Access-Control-Allow-Method', 'POST');
    this.set('Access-Control-Allow-Origin', 'http://xxx.com');
    this.status = 204;
});

上面倒数第二行的代码也很重要,设置响应状态码为 204 是为了告知客户端表示该响应成功了,但是该响应并没有返回任何响应体,如果状态码为 200,还得携带多余的响应体,在这种场景下是完全多余的,只会浪费流量。

关于 204 状态码的意义我经常会在面试的时候问起,这里就是一个实际应用的例子 ^_^

好了,OPTIONS 的请求处理完了,剩下的 POST 请求就简单了,只需在响应头中添加一条和 OPTIONS 一致的允许跨域的域名即可,这里就不重复粘贴代码了。

来自 http://blog.csdn.net/qizhiqq/article/details/71171916

 

HTTP协议中的OPTIONS方法是什么?有什么用?

上传文件时看到再POST之前还有一个OPTIONS请求,这个请求是干什么
关注者
20
 
被浏览
7737
 

3 个回答

HTTP access control (CORS)

OPTIONS请求旨在发送一种“探测”请求以确定针对某个目标地址的请求必须具有怎样的约束(比如应该采用怎样的HTTP方法以及自定义的请求报头),然后根据其约束发送真正的请求。比如针对“跨域资源”的预检(Preflight)请求采用的HTTP方法就是OPTIONS。
HTTP的请求方法OPTIONS
标签: 服务器delete扩展web服务测试ajax
 80059人阅读 评论(6) 收藏 举报
 

目录(?)[+]

 

HTTP请求方法并不是只有GET和POST,只是最常用的。据RFC2616标准(现行的HTTP/1.1)得知,通常有以下8种方法:OPTIONSGETHEAD、POST、PUT、DELETE、TRACE和CONNECT。

官方定义

OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。

该请求方法的响应不能缓存。

如果这个OPTIONS请求包含一个正文(有Content-Length或Transfer-Encoding存在),则必须有Content-Type来指定媒体类型。虽然规范里没有定义这种正文的用法,但是HTTP将来的扩展可能会用它来查询服务器上更详细的信息。不支持该扩展的服务器可以忽略该请求正文。

如果该URI是一个星号(“*”),OPTIONS请求将试图应用于服务器,而不是某个指定资源。由于服务器的通信选项通常依赖于资源,所以此“*”请求只能作为“ping”或者“no-op”方法;或者用来测试服务器的性能。例如,用来测试HTTP/1.1代理。

如果该URI不是星号,则只能用来获取该资源通信中可用的选项。

得到的200响应应该包含一个头域,指明服务器实现的和适用于该资源的可选特征(如:Allow),可能还包括该规范尚未定义的扩展。如果有响应正文,则应包含关于通信选项的信息。本规范没有定义该正文格式,但可能在HTTO将来的扩展中定义。可以利用内容协商来选择合适的响应格式。如果没有响应正文,响应必须包含Content-Length,并且值为“0”。

请求头的Max-Forwards用来请求特定代理。当代理收到一个允许URI转发的OPTIONS请求,则检查Max-Forwards。如果Max-Forwards值为0,则不能转发该消息;相反,代理会将自己的通信选项去响应。如果Max-Forwards是正整数,代理转发请求的时候会将该值减1。如果请求中没有Max-Forwards,转发的请求也不会有。

简而言之

OPTIONS请求方法的主要用途有两个:

1、获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。

2、用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

 

 

 

 

 

The DELETE Method

 

HTTP提供了一个与PUT方法对应的DELETE方法。一个DELETE请求将需要从Web服务器删除的内容指定为请求行中的资源部分。

DELETE方法唯一有趣的地方在于当你接收了一个标识为200 OK的响应的时候,那并不意味着指定的资源已经被删除了。那仅仅说明服务器接收到了删除资源的命令。这一例外允许了出于安全考虑的人为的干预

查看评论
3楼 安静听歌 2017-03-15 18:57发表 [回复]
好愁。。。
2楼 安静听歌 2017-03-15 18:55发表 [回复]
我的在火狐下和iPhone上也是这样,两天了无法解决,options请求之后得到403就没反应了
1楼 yanzhiking 2016-06-03 21:47发表 [回复]
用Ajax 的PUT请求怎么 浏览器不显示是 PUT请求模式而是 OPTIONS,折磨我一天了
function submit(){
$.ajax({
url:"https://~~~",
type:"put",
datatype:"json",
async:ture,
data :{
username:aaa,
grantType:password,
value:1234
}
})}
Re: AndyLeeSharp 2016-12-27 11:56发表 [回复]
回复yanzhiking:因为浏览器先发出options来确定服务器是否允许跨域,如果允许跨域然后才会发出put操作
Re: jianwu5 2017-06-18 11:31发表 [回复]
回复philip1986:正解。
实际有两个请求。


来自  http://blog.csdn.net/leikezhu1981/article/details/7402272


普通分类: