当前位置: 首页 > 知识库问答 >
问题:

CORS标头上的OPTIONS请求与Jersey

孙正业
2023-03-14
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface CorsHeaders {}

@Path("api")
class MyApi {
  @CorsHeaders
  @GET
  public Response m() {
    return Response.ok().build();
  }
}

@Provider
class CorsFilter implements ContainerResponseFilter {
  @Context private ResourceInfo resourceInfo;

  @Override 
  public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
    if (resourceInfo.getResourceMethod().getAnnotation(CorsHeaders.class) != null) {
      responseContext.getHeaders().add(/* appropriate headers here*/);
    }
  }
}

我可以通过在API类中添加@options@corsheaders public Response options(){return Response.ok().build();}方法(在相同的@path)来解决这一问题,但我希望不必对所有方法都这样做。

在处理一个选项请求时,如何找出实际的(Get/Post)资源方法?

共有1个答案

宿楚青
2023-03-14

我担心你想要完成的,实际上是不可能的,以一个好的方式使用当前的版本,而不改变泽西本身。

无论如何,我也不确定使用@provider来处理特定于请求的过滤器是否是正确的方法。但我是谁,我说我实际上是自己做的。当然,也可以在resourceConfig中注册过滤器。一般来说,我建议看一下@namebinding,但在这种情况下,仅使用泽西样式的名称绑定是不够的。使用@namebinding您不必自己检查注释,因为Jersey已经为您做了这件事。

不幸的是,在使用@namebinding时,也会出现“自动生成”选项处理程序的问题。我做了大量的挖掘(一些最相关的类/方法是OptionsMethodProcessorWADLModelProcessorResourceModelConfigurator#initServerRuntime ApplicationHandler#Initialize),但没有找到适当地挂钩到进程的方法。以下是处理COR所需要的:

@NameBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CrossOrigin {
}


@CrossOrigin
public class CrossOriginResponseFilter implements ContainerResponseFilter {
    public void filter(ContainerRequestContext requestContext,  
                       ContainerResponseContext responseContext)
    throws IOException {
        // do Cross Origin stuff
    }
}

@Path("ress")
public class MyResource {
    @CrossOrigin
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response save(DetailsDTO details) {
         // do something with the details
    }
}
[ResourceMethod{
    httpMethod=POST, consumedTypes=[application/json], 
    producedTypes=[application/json], suspended=false, suspendTimeout=0, 
    suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class de.example.MyResource, 
    handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@2c253414]}, definitionMethod=public javax.ws.rs.core.Response de.example.MyResource.save(de.example.DetailsDTO),
    parameters=[Parameter [type=class de.example.DetailsDTO, source=null, defaultValue=null]],
    responseType=class javax.ws.rs.core.Response},
    nameBindings=[interface de.example.CrossOrigin]},
ResourceMethod{
    httpMethod=OPTIONS, consumedTypes=[*/*], 
    producedTypes=[application/vnd.sun.wadl+xml], suspended=false, 
    suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, 
    invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.WadlModelProcessor$OptionsHandler, 
    handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@949030f]}, 
    definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object), 
    parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]], responseType=class javax.ws.rs.core.Response},
    nameBindings=[]},
ResourceMethod{
    httpMethod=OPTIONS, consumedTypes=[*/*], producedTypes=[text/plain], 
    suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, 
    invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$PlainTextOptionsInflector,
    handlerConstructors=[]}, definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object), 
    parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]], 
    responseType=class javax.ws.rs.core.Response}, nameBindings=[]},
ResourceMethod{
    httpMethod=OPTIONS, consumedTypes=[*/*], producedTypes=[*/*], 
    suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, 
    invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$GenericOptionsInflector,
    handlerConstructors=[]}, definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object), 
    parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]], responseType=class javax.ws.rs.core.Response}, 
    nameBindings=[]}]

但现在您可以通过创建另一个筛选器来使用名称绑定信息自己处理预飞行请求:

@Provider
@Priority(1)
public class CrossOriginResponseFilter implements ContainerRequestFilter {
    Resource res = ((ContainerRequest)requestContext)
        .getUriInfo().getMatchedResourceMethod().getParent();

    if (res.getResourceMethods().get(0).getNameBindings().contains(CrossOrigin.class)) {
        // handlePreflightRequest and abort: requestContext.abortWith(builder.build());
    }
}

有趣的是,提取的资源res将只包含与实际请求URI和方法以及自动生成的选项处理程序相匹配的相关资源方法,正如您在上面资源方法的运行时表示中所看到的。示例资源实际上有更多的方法、POSTs和GETS。因此您可以在此处使用.get(0)访问所需的信息。

但要当心!我没有检查这是否是真的,或者只是当您(例如)用单独的路径注释资源方法时。所以也许有更多的匹配工作要做比我这里的简单版本。

 类似资料:
  • 问题内容: 我有一个简单的PHP脚本,正在尝试跨域CORS请求: 但是我仍然得到错误: 请求标头字段不允许 我有什么想念的吗? 问题答案: 不允许作为可接受的值,请参阅此处的Mozilla文档。 您应该发送可接受的标头(而不是如星号所示)而不是星号。

  • 问题内容: 我最近将服务器从Rackspace CloudSites(在Apache / Linux上运行)移至Windows Azure网站。自迁移以来,由于CORS,我们REST API上的所有jQuery AJAX请求都开始失败。 我们使用自定义标头,因此jQuery在运行实际的API调用之前发出飞行前HTTP OPTIONS请求。问题是OPTIONS请求似乎没有到达我的PHP代码,而是由其

  • 在调试我遇到的CORS问题时,我发现了以下行为。Chrome发出以下选项预检请求(由Chrome本身在CURL中重写): 以下情况下服务器对此请求的响应: 是响应“无效CORS请求”的主体。如果我重复该请求,删除标头“Access Control request Method”(仅该标头),则OPTIONS请求将成功,并得到以下响应: 然而,有问题的头是CORS规范标准头,所以它不应该阻止请求成功

  • 我正在使用CakePHP3开发RESTAPI。我想公开启用它,这样任何人都可以调用API。因此,我添加了如下定义的cors标题:http://book.cakephp.org/3.0/en/controllers/request-response.html#setting-跨源请求头 我已经在Dispatcher上实现了EventListener。在调度和调度之前。发货前,准备cors标题。 但问

  • 问题内容: 我已经创建了两个Web应用程序-客户端和服务应用程序。 当客户端和服务应用程序部署在同一Tomcat实例中时,它们之间的交互就很好。 但是,当将应用程序部署到单独的Tomcat实例(不同的计算机)中时,请求发送服务应用程序时出现以下错误。 我的客户端应用程序使用JQuery,HTML5和Bootstrap。 如下所示进行AJAX呼叫服务: 我的服务应用程序使用Spring MVC,Sp

  • 我是一个使用angular的新手,我正在努力学习一点,但我不能使用令牌进行简单的获取。我做了很多研究,最后总是得到这段代码。 对于我的后端,我使用Kotlin/Springboot并配置了Cors。 即使如此,当尝试这样做请求我得到这个错误。 访问位于“”的XMLHttpRequesthttp://localhost:5000/api-v1/来源的帐户/列表 -- 果心js:15713错误Http