我目前在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?
答案 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});
无论你是否支持反向代理,这似乎都有效,所以我不知道为什么它不会默认启用。