POST 的跨源

Cross origin for POST

我有一个带有一些 Jersey 休息服务的 Jetty http 服务器。这些服务是从在 Node 服务器上运行的 React 网站调用的。

由于此设置的跨源性质,我不得不添加一些 HTTP headers。基本上,我所有的网络服务 return a createOkResult() 是按如下方式创建的。

@POST
@Path("orders/quickfilter")
@Consumes(MediaType.APPLICATION_JSON)
public Response getQuickFilterProductionOrders(String data) 
{
  ...
  return createOkResult(json.toString());
}

protected Response createOkResult(Object result)
{
  return buildCrossOrigin(Response.ok().entity(result));
}

protected static Response buildCrossOrigin(Response.ResponseBuilder responseBuilder)
{
  return responseBuilder.header("Access-Control-Allow-Origin", "*")
          .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
          .allow("OPTIONS")
          .build();
}

对于工作正常的 @GET 网络服务。但是当我创建一个 @POST 服务时,我就是无法让它工作。

Web 浏览器(chrome 和 firefox)return 此类错误:

Access to XMLHttpRequest at 'http://localhost:59187/rs/production/orders/quickfilter' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

所以,乍一看我很想认为 header 仍然不见了。问题是,当我使用像 Postman 这样的工具测试此服务时,所有 header 都已到位,服务甚至 return 请求的数据。

这是 POST 请求的屏幕截图。

从我的 front-end(在节点服务器上运行),我使用 axios API,它使用 promises,我的请求如下所示:

const url = "http://localhost:59187/rs/production/orders/quickfilter";
const data = JSON.stringify(request);
const headers = { headers: { "Content-Type": "application/json" } };
const promise = axios.post(url, data, headers);

现在我有一个 HTTP 错误 500,如果我删除内容类型 header,我会得到一个不受支持的媒体异常。所以,我有理由相信内容类型没问题。

Paul Samsotha 为我指出了正确的方向。 我最终向 ServletContextHandler 添加了一个过滤器。与链接的文章不同,我真的不必从头开始创建该过滤器。我可以使用现有的过滤器 class:即 org.eclipse.jetty.servlets.CrossOriginFilter.

FilterHolder filterHolder = context.addFilter(CrossOriginFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
filterHolder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");
filterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");

上面的一些参数可能会被省略,因为它们是默认值。但对我来说似乎至关重要的是将 CHAIN_PREFLIGHT_PARAM 设置为 false

一个好处side-effect,就是我可以简化实际服务的代码。他们不再需要添加特殊的 headers,相比之下,他们现在只需 return Response.ok().entity(result).build();.