POST的交叉原点

时间:2018-10-24 15:26:33

标签: post cors jersey axios

我有一台Jetty http服务器,上面有一些泽西岛休息服务。这些服务是从运行在Node服务器上的React网站调用的。

由于此设置具有跨源特性,因此我不得不添加一些HTTP标头。基本上,我所有的Web服务都返回一个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 Web服务。但是,当我创建@POST服务时,我只是无法使其正常工作。

Web浏览器(chrome和firefox)返回以下错误:

  

CORS策略已阻止从来源“ render_to”访问“ http://localhost:59187/rs/production/orders/quickfilter”处的XMLHttpRequest:请求的资源上没有“ Access-Control-Allow-Origin”标头。

因此,乍一看,我会以为标题仍然缺失。问题是,当我使用Postman之类的工具测试此服务时,所有标头都就位,并且该服务甚至返回了所请求的数据。

http://localhost:3000

这是POST请求的屏幕截图。

从前端(在节点服务器上运行)开始,我使用axios API,该API使用Promise,并且我的请求如下所示:

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,如果删除内容类型标头,则会得到不受支持的媒体异常。因此,我有理由相信内容类型是可以的。

1 个答案:

答案 0 :(得分:0)

Paul Samsotha向我指出了正确的方向。 我最终向ServletContextHandler添加了一个过滤器。与链接的文章不同,我实际上不必从头开始创建该过滤器。我可以使用一个现有的过滤器类: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

一个不错的副作用是,我可以简化实际服务的代码。他们不再需要添加特殊的标头,相比之下,它们现在只需返回Response.ok().entity(result).build();