Конечная точка SSL с Heroku и 303

Я создал конечную точку SSL с герою. У меня есть тестовая среда и живая среда. У меня есть вызов REST, который генерирует 303. Поскольку Heroku обрабатывает SSL в этом маршрутизаторе, я не уверен, как я могу определить, должен ли мой SEE OTHER URL-адрес создать URI на основе HTTP или HTTPS. Вот пример кода:

@GET
@Path( "/job/{jobId}" )
public Response getCallStatus( @PathParam( "jobId" ) Long jobId, @Context UriInfo uriInfo ) throws Exception {
 if ( !jobService.isDone( jobId ) )
 return build( Response.ok( POLLING_FREQUENCY ) );

 URI jobLocation = uriInfo.getAbsolutePathBuilder().path( "result" ).build();
 return build( Response.seeOther( jobLocation ) );
}

Поскольку мой сервер не обрабатывает SSL (heroku is), абсолютный путь для вызова REST будет использовать HTTP вместо HTTPS. Если я буду жестко кодировать HTTPS, я сломаю свои модульные тесты или другую среду, для которой не требуется протокол HTTPS.

Есть предположения? Или я не понимаю, как героику это делает?

2 ответа

Ладно, так вот ответ. Heroku НЕ отправляет запрос в виде HTTPS. Из-за этого вам нужно заглянуть в заголовок x-fowarded-proto, чтобы решить, что такое местоположение 303, которое вы должны отправить обратно своему клиенту. Вышеприведенный пример кода изменился бы примерно так:

@GET
@Path( "/job/{jobId}" )
public Response getCallStatus( @PathParam( "jobId" ) Long jobId, @Context UriInfo uriInfo, @Context HttpHeaders headers ) throws Exception {
 if ( !jobService.isDone( jobId ) )
 return build( Response.ok( POLLING_FREQUENCY ) );

 UriBuilder builder = uriInfo.getAbsolutePathBuilder().path( "result" );
 String scheme = headers.getHeaderString( "x-forwarded-proto" );
 if ( scheme != null )
 builder.scheme( scheme );

 return build( Response.seeOther( builder.build() ) );
}

Это в основном это.

Но лучший способ справиться с этим, который не потребовал бы ЛЮБЫХ изменений в закодированном методе REST, заключался бы в том, чтобы добавить фильтр запроса контейнера следующим образом:

@PreMatching
public class HerokuContainerRequestFilter implements ContainerRequestFilter {

 @Override
 public void filter( ContainerRequestContext ctx ) throws IOException {
 List<string> schemes = ctx.getHeaders().get( "x-forwarded-proto" );
 if ( schemes != null && !schemes.isEmpty() ) {
 String scheme = schemes.get( 0 );
 UriBuilder builder = ctx.getUriInfo().getRequestUriBuilder();
 ctx.setRequestUri( builder.scheme( scheme ).build() );
 }
 }
}
</string>

Затем вы просто зарегистрируете этот фильтр с помощью RestConfig следующим образом:

public class RestApplication extends ResourceConfig {

 public RestApplication() {

 packages( "com.myapp.rest.service" );

 // along with any other providers, etc that you register
 register( HerokuContainerRequestFilter.class );
 }
}


Хотя ответ user1888440 полностью работает, я бы предпочел настроить переадресацию https на уровне сервера.

Например, если вы используете встроенный причал, поскольку вы являетесь веб-сервером heroku, вы можете использовать встроенный причал org.eclipse.jetty.server.ForwardedRequestCustomizer:

Настроить запросы для перенаправления прокси.

Этот пользовательский интерфейс просматривает HTTP-запрос для заголовков, которые указывают, что он был перенаправлен одним или несколькими прокси. В частности, обрабатываются:

<ul> <li> X-Forwarded-Host</li> <li> X-Forwarded-сервер</li> <li> X-Forwarded-For</li> <li> X-Forwarded-Прото</li> </ul>

Если эти заголовки присутствуют, объект запроса обновляется, так что прокси не рассматривается как другая конечная точка соединения, на которое был отправлен запрос

Поэтому вместо запуска вашего сервера:

Server server = new Server(port);

Вы можете использовать:

Server server = new Server();
 HttpConfiguration httpConfiguration = new HttpConfiguration();
 httpConfiguration.addCustomizer(new ForwardedRequestCustomizer());
 ServerConnector serverConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration));
 serverConnector.setPort(port);
 server.addConnector(serverConnector);

licensed under cc by-sa 3.0 with attribution.