【问题标题】:Jersey jax.rs client 2.5 follow redirect from HTTP to HTTPSJersey jax.rs 客户端 2.5 遵循从 HTTP 到 HTTPS 的重定向
【发布时间】:2014-03-13 18:10:12
【问题描述】:

我有一个设置,其中托管我的 REST 服务器的 tomcat 服务器将调用从 HTTP(端口 9080)重定向到 HTTPS(端口 9443)。

我正在使用 jersey 2.5 实现,无法配置客户端以遵循重定向。

我发现了这个 SO 问题 (Jersey client doesn't follow redirects),但是它是为 jersey 1.X 系列提供的,并且 API 已更改。

我尝试使用以下测试代码使其适应 2.5:

 SSLContextProvider ssl = new TrustAllSSLContextImpl(); // just trust all certs
 Response response  =     ClientBuilder.newBuilder()
     .sslContext(ssl.getContext()).newClient()
     .register(LoggingFilter.class)
     .target("http://testhost.domain.org:9080/rest.webapp/api/v1/hello/")
     .property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE)
     .request().get();   
 Assertions.assertThat(response.getStatus()).isNotEqualTo(302);

由于客户端似乎没有遵循重定向而失败。以下是日志过滤器提供的内容:

Feb 14, 2014 12:23:45 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Sending client request on thread main
1 > GET http://testhost.domain.org:9080/rest.webapp/api/v1/hello/

Feb 14, 2014 12:23:45 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Client response received on thread main
1 < 302
1 < Cache-Control: private
1 < Content-Length: 0
1 < Date: Fri, 14 Feb 2014 11:38:59 GMT
1 < Expires: Thu, 01 Jan 1970 01:00:00 CET
1 < Location: https://testhost.domain.org:9443/rest.webapp/api/v1/hello/
1 < Server: Apache-Coyote/1.1

从球衣文档中,我了解到需要做的就是将 ClientProperties.FOLLOW_REDIRECTS 属性添加到客户端,但这显然不是这种情况。我还发现消息表明可能是客户端过滤器需要遵循重定向,但没有找到这方面的示例或指南。

因此,如果有人对 jax.rs 和重定向有一定的经验,可以向我指出一些方向/文档/示例代码,我将不胜感激。

【问题讨论】:

    标签: rest tomcat redirect jersey-2.0 jersey-client


    【解决方案1】:

    发生这种情况是因为如果 URL 方案在重定向期间发生更改,Http(s)UrlConnection 不遵循重定向(参见例如HTTPURLConnection Doesn't Follow Redirect from HTTP to HTTPS)。所以可能的解决方案是use alternative client transport connector

    这可能看起来像

    SSLContextProvider ssl = new TrustAllSSLContextImpl(); // just trust all certs
    
    JerseyClientBuilder clientBuilder = new JerseyClientBuilder()
     .sslContext(ssl.getContext())
     .register(LoggingFilter.class);
    clientBuilder.getConfiguration().connectorProvider(new org.glassfish.jersey.apache.connector.ApacheConnectorProvider());
    
    JerseyClient client = clientBuilder.build();
    
    Response response = client    
     .target("http://testhost.domain.org:9080/rest.webapp/api/v1/hello/")
     .property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE)
     .request().get();
    Assertions.assertThat(response.getStatus()).isNotEqualTo(302);
    

    【讨论】:

      【解决方案2】:

      正确的做法是:

      webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE);
      

      【讨论】:

      • 你确定最后一个参数是 "false" 吗?在我看来,这只是禁用重定向:)
      • 这应该是webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE),正如之前的评论者所指出的那样。
      • 这只适用于泽西岛; ClientProperties 是一个 Jersey 类。 JAX-RS 尚未指定任何重定向处理选项
      • 这是错误的;这只会在协议更改时启用重定向,而不是重定向 HTTP->HTTPS。此外,无论如何,此设置已经默认为“true”。
      • -1 因为这只是球衣,但原作者明确要求 JAX-RS(这是他目前正在使用的球衣实现的标准)。
      【解决方案3】:

      好吧,我终于用过滤器解决了这个问题,不确定这是最好的解决方案,感谢任何 cmets:

      public class FollowRedirectFilter implements ClientResponseFilter
      {
         @Override
         public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException
         {
            if (responseContext.getStatusInfo().getFamily() != Response.Status.Family.REDIRECTION)
               return;
      
            Response resp = requestContext.getClient().target(responseContext.getLocation()).request().method(requestContext.getMethod());
      
            responseContext.setEntityStream((InputStream) resp.getEntity());
            responseContext.setStatusInfo(resp.getStatusInfo());
            responseContext.setStatus(resp.getStatus());
         }
      }
      

      【讨论】:

      • 我在这里找到了答案stackoverflow.com/questions/1884230/…:出于安全原因,从 http 到 https 的重定向不起作用。
      • 不要忘记 a) 在客户端用 @javax.ws.rs.ext.Provider 和 b) register 注释过滤器。
      • @FrankNeblung:根据注册方式,可能不需要注释。但它肯定需要向 JAX-RS 注册。
      • 虽然这在成功遵循重定向的意义上确实有效,但它存在一些问题。当我尝试使用它时, response.getMediaType() 返回的 Content-Type 是第一个请求返回的 Content-Type,而不是重定向请求。因此,像这样重用 ResponseContext 似乎不是一个干净的解决方案。
      猜你喜欢
      • 2010-12-25
      • 2012-07-27
      • 2016-12-01
      • 2018-05-11
      • 2018-03-24
      • 2012-11-09
      • 2015-03-01
      • 1970-01-01
      相关资源
      最近更新 更多