公司在开发一个后台系统时需要使用百度的UEditor富文本编辑器,应用的场景如下:
- UEditor的所有图片、js等静态资源在一个专有的静态服务器上;
- 图片上传在另外一台服务器上;
因为公司内部会使用chrome来进行后台管理,因此在跨域解决方案上,选择了设置h5中的Access-Control-Allow-Origin header。
但在开发测试时,发现在上传多图片时,浏览器确实向指定的后端发送了上传的请求,但UEditor却一直报上传失败的错误,因为是第一次做这种跨域的项目,因此有些想不通,在仔细查看请求后发现,浏览器发送的这个上传请求的请求方式不是常见的get、post方式,而是OPTIONS.
OPTIONS请求有什么作用?百度后精简的两句话介绍其作用:
- 获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。
- 用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。
从上述表述来看,其实这个OPTIONS请求只是试探作用,并不会携带任何真实的上传数据,在本项目中是为了确认将要接收上传数据的后端是否允许跨域,如果OPTIONS请求获取的header中Access-Control-Allow-Origin符合要求,将会再发送一次POST请求,将真实数据上传。
但浏览器在这个项目中只发送了一次OPTIONS请求,说明这个请求中Access-Control-Allow-Origin不符合要求,也就是不允许跨域,经检查,已经在spring mvc中使用拦截器对每一个请求都设置了可跨域的header。
因此我在这个拦截器中进行断点,结果是OPTIONS请求压根没有进入到这个断点,由此说明OPTIONS请求被spring mvc框架拒之门外了。
找到原因后,再次度娘,果然,spring mvc框架默认不支持OPTIONS请求,如果需要支持,需要在项目的web.xml文件中加入如下初始化参数:
<servlet>
<servlet-name>ModelViewController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/servlet-context.xml</param-value>
</init-param>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
设置完成后再次上传图片,会发现在上传的第一次请求OPTIONS的header正确设置了跨域,并随后有了POST请求,上传成功!