Cross-domain JQuery AJAX POST 在 OPTIONS returns 200 之后没有完成
Cross-domain JQuery AJAX POST doesn't complete after OPTIONS returns 200
我有一个带有 cross-origin 过滤器 (org.eclipse.jetty.servlets.CrossOriginFilter) 设置的嵌入式 Jetty v9.2.10 服务器。服务器上有一个 REST 服务,我正在尝试 POST 使用 jQuery。 POST 尝试到达 Firefox 中的 OPTIONS 请求;交换如下:
请求headers
Host: localhost:8402
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
回复headers
Allow: HEAD, POST, GET, OPTIONS
Content-Length: 24
Content-Type: text/plain
Date: Wed, 12 Aug 2015 00:57:35 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Server: Jetty(9.2.10.v20150310)
(值得注意的是,我希望在响应中出现的 Access-Control headers 中的 none 就在那里。)如果我在 Chrome 中尝试它,它网络调试器告诉我对 OPTIONS 请求的响应是不安全的,所以我什至看不到返回的内容,但这可能是一个单独的问题。
这是发出请求的 JavaScript:
$(document).ready(function(){
var queryString = URI.parseQuery(URI(window.location.href).search());
var cred = "/*a really long token*/";
$.ajax({
type: "POST",
url: "https://localhost:8402/api/v1/resource/agent/" + queryString.agentId + "/connector?token=" + cred,
data: {
//some JSON
},
success: function(data,status){
alert("Response: " + data + "\nStatus: " + status);
},
crossDomain: true,
contentType: 'application/json'
});
});
这是我在服务器上设置 CORS 过滤器的方法:
private void addCorsFilter(ServletContextHandler servletHandler)
{
FilterHolder corsFilter = servletHandler.addFilter(CrossOriginFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
// this string is set to "http(s?)://localhost*" as I have everything running locally right now, but setting to "*" doesn't make a difference
String studioDomain = environmentVariableReader.read(Constants.Env.STUDIO_DOMAIN);
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, studioDomain);
corsFilter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD,PUT,OPTIONS");
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
corsFilter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
logger.info("cross-origin filter allowing {}", studioDomain);
}
我尝试使用两个答案 here 中的说明设置 CrossOriginFilter——以及对许多字段使用通配符——但大多数配置都给我相同的结果。如果有帮助,我可以提供相关的 Jetty 日志。
原来这个问题与这里的任何事情都无关。过滤实际上是由 Guice 处理的,只有在它通过它知道的过滤器并尝试使用它注入的 servlet 为请求提供服务之后,它才会委托给 Jetty 的过滤器链。我不知道这一点,所以我没有将 CrossOriginFilter
添加到 Guice 的 ServletModule
。因此,Guice 尝试使用它注入的 RESTEasy 调度程序 servlet 来为请求提供服务(因此响应看起来像默认值 HttpServlet.doOptions()
)并且不会使用 Jetty 的过滤器链,因为请求已得到服务。
我有一个带有 cross-origin 过滤器 (org.eclipse.jetty.servlets.CrossOriginFilter) 设置的嵌入式 Jetty v9.2.10 服务器。服务器上有一个 REST 服务,我正在尝试 POST 使用 jQuery。 POST 尝试到达 Firefox 中的 OPTIONS 请求;交换如下:
请求headers
Host: localhost:8402
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
回复headers
Allow: HEAD, POST, GET, OPTIONS
Content-Length: 24
Content-Type: text/plain
Date: Wed, 12 Aug 2015 00:57:35 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Server: Jetty(9.2.10.v20150310)
(值得注意的是,我希望在响应中出现的 Access-Control headers 中的 none 就在那里。)如果我在 Chrome 中尝试它,它网络调试器告诉我对 OPTIONS 请求的响应是不安全的,所以我什至看不到返回的内容,但这可能是一个单独的问题。
这是发出请求的 JavaScript:
$(document).ready(function(){
var queryString = URI.parseQuery(URI(window.location.href).search());
var cred = "/*a really long token*/";
$.ajax({
type: "POST",
url: "https://localhost:8402/api/v1/resource/agent/" + queryString.agentId + "/connector?token=" + cred,
data: {
//some JSON
},
success: function(data,status){
alert("Response: " + data + "\nStatus: " + status);
},
crossDomain: true,
contentType: 'application/json'
});
});
这是我在服务器上设置 CORS 过滤器的方法:
private void addCorsFilter(ServletContextHandler servletHandler)
{
FilterHolder corsFilter = servletHandler.addFilter(CrossOriginFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
// this string is set to "http(s?)://localhost*" as I have everything running locally right now, but setting to "*" doesn't make a difference
String studioDomain = environmentVariableReader.read(Constants.Env.STUDIO_DOMAIN);
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, studioDomain);
corsFilter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD,PUT,OPTIONS");
corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
corsFilter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
logger.info("cross-origin filter allowing {}", studioDomain);
}
我尝试使用两个答案 here 中的说明设置 CrossOriginFilter——以及对许多字段使用通配符——但大多数配置都给我相同的结果。如果有帮助,我可以提供相关的 Jetty 日志。
原来这个问题与这里的任何事情都无关。过滤实际上是由 Guice 处理的,只有在它通过它知道的过滤器并尝试使用它注入的 servlet 为请求提供服务之后,它才会委托给 Jetty 的过滤器链。我不知道这一点,所以我没有将 CrossOriginFilter
添加到 Guice 的 ServletModule
。因此,Guice 尝试使用它注入的 RESTEasy 调度程序 servlet 来为请求提供服务(因此响应看起来像默认值 HttpServlet.doOptions()
)并且不会使用 Jetty 的过滤器链,因为请求已得到服务。