如何强制UriBuilder使用https?

时间:2016-01-18 19:15:50

标签: jersey-2.0 dropwizard mod-proxy

我目前在Apache httpd后面运行Dropwizard作为反向代理,配置如下:

git diff origin/dev dev

使用其他<VirtualHost *:443> <Location /api> ProxyPass "http://my.app.org:8080/api" <Location> ... </VirtualHost> 设置提供静态资产并引入一些身份验证。现在,httpd还执行SSL卸载,因此我的Dropwizard只接收普通的HTTP请求。

在我的Dropwizard API中,我想返回一个Location标题,指示新创建的资源:

Location

这会创建一个@Path("/comment") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) class CommentResource() { @PUT fun create(@Context uri: UriInfo, entity: EventComment): Response { val stored: EventComment = createEntity(entity) return Response.created(uri.baseUriBuilder.path(MessageStream::class.java) .resolveTemplate("realmish", entity.realmId) .path(stored.id.toString()).build()).build() } Response来自Location的标题:

JerseyUriBuilder

其中,在我的仅限SSL的应用中,自然无法加载(我实际上很惊讶这并没有结果呈现为Location http://my.app.org/api/messages/123 - 可能也是{{1}的原因没有帮助)。

我知道我可以使用http://my.app.org:8080/api/messages/123强制该方案为https,但这会重复,并且容易出错。

因此,我的问题:我如何让Jersey生成正确的前端URL或成功地使httpd重写由Dropwizard生成的URL?

2 个答案:

答案 0 :(得分:1)

对于Jersey,您可以使用预匹配的ContainerRequestFilter来重写URI。例如

@PreMatching
public class SchemeRewriteFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext request) throws IOException {
        URI newUri = request.getUriInfo().getRequestUriBuilder().scheme("https").build();
        request.setRequestUri(newUri);
    }
}

然后只需将其注册到Jersey(Dropwizard)

env.jersey().register(SchemeRewriteFilter.class);

修改

以上仅在您使用uriInfo.getAbsolutePathBuilder()时有效。如果您想使用uriInfo.getBaseUriBuilder(),那么您需要使用接受基础uri作为第一个arg的重载setRequestUri

URI newUri = request.getUriInfo().getRequestUriBuilder().scheme("https").build();
URI baseUri = request.getUriInfo().getBaseUriBuilder().scheme("https").build();
request.setRequestUri(baseUri, newUri);

答案 1 :(得分:0)

如果使用Jetty,那么您可以通过在服务器上注册org.eclipse.jetty.server.ForwardedRequestCustomizer来避免黑客入侵。这将查看用于构建基URI的X-Forwarded-*标头。

使用嵌入式Jetty的示例:

Server jettyServer = new Server();
HttpConfiguration config = new HttpConfiguration();
config.addCustomizer(new ForwardedRequestCustomizer());
ServerConnector serverConnector = new ServerConnector(jettyServer, 
                                      new HttpConnectionFactory(config));
serverConnector.setPort(8080);
jettyServer.setConnectors(new Connector[] {serverConnector});

无论你是否支持反向代理,这似乎都有效,所以我不知道为什么它不会默认启用。