java - Jersey 如何确定应用程序的基本 URI?
问题描述
我有一个在 tomcat 中运行的 java 应用程序。在应用程序的一个端点中,我想返回 See-Other 类型的 HTTP 响应。
@GET
@Path("logout")
@Produces(MediaType.TEXT_HTML)
public Response logOut(@Context HttpServletRequest request) throws URISyntaxException {
// logout logic omitted
Response.ResponseBuilder response = Response.seeOther(new URI("../jsp/login.jsp"));
return response.build();
}
当我在本地机器上测试它时,一切正常。然而,在生产系统上,泽西似乎无法从相对路径“../jsp/login.jsp”中解析正确的主机名。虽然主机名为 myhost,但相对路径解析为 http://localhost:7080/myapplication/jsp/login.jsp。
new URI("../jsp/login.jsp") 返回一个对象,其中所有字段都为空,并且只有 path="../jsp/login.jsp"。由于这个原因,行为的根源必须在 Response 类中。我检查了文档并发现 Response.seeOther 调用了 Response.location 方法。该文件指出
如果提供了相对 URI,它将通过相对于应用程序的基本 URI 解析它被转换为绝对 URI
有谁知道 Jersey 如何确定应用程序的基本 URI?tomcat中是否有一些配置文件或我设置错误的环境变量?
解决方案
应用程序的基本 URI 是使用对象的属性计算的HttpServletRequest
,其形式为:
<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/
和通常由 HTTP 客户端提供,而其余部分由 Tomcat 或您的应用程序的配置修复<serverName>
:<serverPort>
<scheme>
使用 a 的同名属性配置<Connector>
(参见Tomcat 的文档),或者可以由RemoteIpValve
(参见文档)设置,<serverName>
由 HTTP 客户端提供,但可以使用proxyName
连接器的属性覆盖,<serverPort>
由 HTTP 客户端提供,但可以使用proxyPort
连接器的属性或由RemoteIpValve
,<contextPath>
取决于您如何部署应用程序(例如,它取决于webapps
目录中 WAR 文件的名称),<servletPath>
在web.xml
描述符中或通过@ApplicationPath
注解配置。
在您的生产环境中可能发生的情况是 Tomcat 位于反向代理之后。要在这种情况下正确配置基本 URI,您有两种选择:
- 在您的 ,上静态配置 ,
scheme
和的正确值secure
proxyName
proxyPort
<Connector>
- 使用
RemoteIpValve
和 配置代理服务器发送原始Host
标头并添加X-Forwarded-For
和X-Forwarded-Proto
标头。
如果您的代理向 Tomcat 转发不同类型的请求(例如 HTTP 和 HTTPS 请求),那么这RemoteIpValve
是您唯一的选择。
备注: base URI 也可以基于请求 URI,如果您将ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231
属性设置为true
:cf。这个问题。
推荐阅读
- javascript - 循环遍历两个输入的总和,直到加倍(javascript)
- c - 使用 netlink 套接字获取接口的丢弃数据包计数
- json - 对标签强制执行的自定义策略
- reactjs - 如何在 FormControlLabel 上的标签和控件之间添加填充
- python - Python:将数字列表转换为相应的字母
- android - CameraX 错误:减少使用计数的次数多于增加次数
- ruby-on-rails - Ruby 将参数从一个函数传递到另一个函数
- python - XGBoost 产生预测结果和概率
- java - 格式化程序
没有在 REST 应用程序中注册 Spring Boot 容器 - javascript - 对异步操作的未定义响应