如何将 CORS headers 设置为内部服务器错误响应?

How to set CORS headers into internal server error responses?

我有一个 java 应用服务器,它有一个由 resteasy 提供的 REST 接口,我有下面的 CORS 过滤器

@Provider
public class CORSFilter implements ContainerResponseFilter {

    public void filter(ContainerRequestContext cReq, ContainerResponseContext cResp) {
        cResp.getHeaders().add("Access-Control-Allow-Origin", "*");
        cResp.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, auth-token");
        cResp.getHeaders().add("Access-Control-Allow-Credentials", "true");
        cResp.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
        cResp.getHeaders().add("Access-Control-Max-Age", "1209600");
    }

}

具有 CORS headers 的所有请求 return:

OPTIONS 200 OK
Access-Control-Allow-Credentials:"true"
Access-Control-Allow-Headers:"origin, content-type, accept, authorization, auth-token"
Access-Control-Allow-Methods:"GET, POST, PUT, DELETE, OPTIONS, HEAD"
Access-Control-Allow-Origin:"*"
Access-Control-Max-Age:"1209600"
Allow:"HEAD, GET, OPTIONS"
Connection:"keep-alive"
Content-Length:"18"
Content-Type:"text/plain"
Date:"Thu, 15 Jan 2015 15:23:01 GMT"
Server:"WildFly/8"

除非我有一个内部异常 returns 错误代码 500:

GET 500 Internal Server Error
Connection:"keep-alive"
Content-Length:"8228"
Content-Type:"text/html; charset=UTF-8"
Date:"Thu, 15 Jan 2015 15:23:01 GMT"

如何让 500 个回复包含那些 headers?

使用 ExceptionMapper:

@Provider
public class CorsExceptionMapper implements ExceptionMapper<Exception> {

    @Override
    public Response toResponse(Exception ex) {
        ResponseBuilder responseBuilder = Response.serverError();
        responseBuilder.header("Access-Control-Allow-Origin", "*");
        responseBuilder.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, auth-token");
        responseBuilder.header("Access-Control-Allow-Credentials", "true");
        responseBuilder.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
        responseBuilder.header("Access-Control-Max-Age", "1209600");
        return responseBuilder.build();
    }

}

为避免 headers 重复,您应该使用:

cResp.getHeaders().putSingle() 

ContainerResponseFilter.

ExceptionMapper 并非在我发现的所有情况下都有效。似乎还有一些其他的容器响应,我们需要另一种过滤器类型。特别是对j_security_check(FORM登录)don't get CORS headers added请求的响应。因此,我没有同时使用 ContainerResponseFilterExceptionMapper 并且在没有 CORS headers 的情况下仍然有一些响应,而是选择了 Undertow 过滤器。缺点是它仅适用于 Undertow-based 服务器(Jboss EAP、Wildfly、Wildfly Swarm),但优点是它适用于 所有 响应。

我编写了一个用于添加 CORS headers 的特定过滤器,它作为 JBoss 模块安装并且可以从 standalone.xml 进行配置。在这里找到它:

undertow-cors-filter

下载 .zip 文件并将其解压缩到您的 Wildfly 根文件夹中。然后在standalone.xml中添加一个filter配置:

<filters>
  <filter name="undertow-cors-filter" class-name="com.stijndewitt.undertow.cors.Filter" module="com.stijndewitt.undertow.cors">
    <param name="urlPattern" value="^http(s)?://([^/]+)(:([^/]+))?(/([^/])+)?/api(/.*)?$" />
    <param name="policyClass" value="com.stijndewitt.undertow.cors.AllowMatching" />
    <param name="policyParam" value="^http(s)?://(www\.)?example\.(com|org)$" />   
  </filter>
</filters>

host元素中添加一个filter-ref(仍在standalone.xml中):

<host name="default-host" alias="localhost">
  <filter-ref name="undertow-cors-filter" />
</host>

这将添加 CORS headers 允许来源 http(s)://(www.)example.(com|org) 访问路径段 "/api" 下的 URL 请求的所有响应.

更改 filter 定义中的 param 以配置行为。有 3 个策略 类 可用,AllowAllAllowMatchingWhitelist,如果需要,您可以编写自己的自定义策略。