Jersey jax.rs client 2.5 follow redirect from HTTP to HTTPS
Asked Answered
D

3

14

I have a setup where tomcat server hosting my REST servers redirects calls from HTTP (port 9080) to HTTPS ( port 9443 ).

I'm using jersey 2.5 implementation and cannot manage to configure the clients to follow redirections.

I've found this SO question( Jersey client doesn't follow redirects ), however it's provided for jersey 1.X series and the API has changed.

I've tried to adapt it for 2.5 with the following test code :

 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);

Which fails as the client does not seem to follow the redirections. Here is what the logging filter provides :

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

From the jersey doc I understood that all that needs to be done is to add the ClientProperties.FOLLOW_REDIRECTS property to the client, but this obviously not to be the case.I've also found messages indicating that maybe a client side filter is required to follow the redirections, but found no examples or guidelines on this.

So if anyone having some experience with jax.rs and redirection could point me to some directions/docs/example code I'd really appreciate.

Disputable answered 14/2, 2014 at 11:39 Comment(0)
B
15

correct way to do this is:

webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE);
Basle answered 14/8, 2014 at 6:50 Comment(5)
are you sure that the last param is "false" ? Seems to me that this simply disables the redirection :)Disputable
This should be webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE), as the prior commenter noted.Thorncombe
This only works for Jersey only; ClientProperties is a Jersey class. JAX-RS doesn't specify any redirect handling options, yetSoutherly
This is wrong; this will only enable redirects if the protocol does not change, not redirects HTTP->HTTPS. Also, this setting is already "true" by default anyway.Plasmolysis
-1 because this is jersey only, but the original author explicitely asked for JAX-RS (which is a standard implemented by jersey which he is currently using).Libove
D
10

Well I finally figured this out using a filter, not sure this is the best solution, any comments are appreciated :

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());
   }
}
Disputable answered 14/2, 2014 at 17:19 Comment(4)
I found an answer here #1884730: there redirect from http to https doesn't work for security reasons.Cavender
do not forget to a) Annotate the Filter with @javax.ws.rs.ext.Provider and b) register it at the Client.Pemba
@FrankNeblung: Depending on how it is registered, the annotation may not be required. But it definitely needs to be registered with JAX-RS.Plasmolysis
While this does work in the sense that it successfully follows the redirect, it has some issues. When I tried to use it, the Content-Type as returned by response.getMediaType() was the Content-Type returned by the first request, not by the redirected request. So it seems that re-using the ResponseContext like this is not a clean solution.Plasmolysis
C
2

This happens because Http(s)UrlConnection doesn't follow redirect if URL scheme changes during the redirect (see e.g. HTTPURLConnection Doesn't Follow Redirect from HTTP to HTTPS ). So the possible solution is to use alternative client transport connector.

This could look like

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);
Cavender answered 12/1, 2017 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.