Jersey 如何确定应用程序的基本 URI?
How does Jersey determine the base URI of an application?
我在 tomcat 中有一个 java 应用程序 运行。在应用程序的一个端点中,我想 return 类型为 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();
}
当我在本地机器上测试时,一切正常。然而,在生产系统上,jersey 似乎无法从相对路径“../jsp/login.jsp”解析正确的主机名。尽管主机名为 myhost,但相对路径被解析为 http://localhost:7080/myapplication/jsp/login.jsp.
new URI("../jsp/login.jsp") returns 一个对象,其中所有字段都是空的,只有 path="../jsp/login。 jsp”。因此,行为的根源必须在响应 class 中。我检查了文档并发现 Response.seeOther 调用了 Response.location 方法。文档指出
If a relative URI is supplied it will be converted into an absolute
URI by resolving it relative to the base URI of the application
有谁知道 Jersey 如何确定应用程序的基本 URI?是不是tomcat里面有什么配置文件或者是我设置的环境变量错了?
应用程序的基本 URI 是使用 HttpServletRequest
object 的属性计算的,其形式为:
<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/
<serverName>
和 <serverPort>
通常由 HTTP 客户端提供,其余由 Tomcat 或您的应用程序配置修复:
<scheme>
使用<Connector>
的同名属性配置(参见Tomcat's documentation) or can be set by the RemoteIpValve
(cf. documentation),
<serverName>
由 HTTP 客户端提供,但可以使用连接器的 proxyName
属性覆盖,
<serverPort>
由 HTTP 客户端提供,但可以使用连接器的 proxyPort
属性或 RemoteIpValve
、 覆盖
<contextPath>
取决于您部署应用程序的方式(例如,它取决于 webapps
目录中 WAR 文件的名称),
<servletPath>
在web.xml
描述符或通过@ApplicationPath
注解配置。
您的生产环境中可能发生的情况是 Tomcat 在 反向代理 后面。要在这种情况下正确配置基本 URI,您有两种选择:
- 在
<Connector>
、 上静态配置 scheme
、secure
、proxyName
和 proxyPort
的正确值
- 使用
RemoteIpValve
并配置代理服务器发送原Host
header并添加X-Forwarded-For
和X-Forwarded-Proto
header s.
如果您的代理将不同类型的请求转发给 Tomcat(例如 HTTP 和 HTTPS 请求),RemoteIpValve
是您唯一的选择。
备注:如果将ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231
属性设置为true
,base URI也可以基于请求URI:cf . this question.
我在 tomcat 中有一个 java 应用程序 运行。在应用程序的一个端点中,我想 return 类型为 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();
}
当我在本地机器上测试时,一切正常。然而,在生产系统上,jersey 似乎无法从相对路径“../jsp/login.jsp”解析正确的主机名。尽管主机名为 myhost,但相对路径被解析为 http://localhost:7080/myapplication/jsp/login.jsp.
new URI("../jsp/login.jsp") returns 一个对象,其中所有字段都是空的,只有 path="../jsp/login。 jsp”。因此,行为的根源必须在响应 class 中。我检查了文档并发现 Response.seeOther 调用了 Response.location 方法。文档指出
If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the base URI of the application
有谁知道 Jersey 如何确定应用程序的基本 URI?是不是tomcat里面有什么配置文件或者是我设置的环境变量错了?
应用程序的基本 URI 是使用 HttpServletRequest
object 的属性计算的,其形式为:
<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/
<serverName>
和 <serverPort>
通常由 HTTP 客户端提供,其余由 Tomcat 或您的应用程序配置修复:
<scheme>
使用<Connector>
的同名属性配置(参见Tomcat's documentation) or can be set by theRemoteIpValve
(cf. documentation),<serverName>
由 HTTP 客户端提供,但可以使用连接器的proxyName
属性覆盖,<serverPort>
由 HTTP 客户端提供,但可以使用连接器的proxyPort
属性或RemoteIpValve
、 覆盖
<contextPath>
取决于您部署应用程序的方式(例如,它取决于webapps
目录中 WAR 文件的名称),<servletPath>
在web.xml
描述符或通过@ApplicationPath
注解配置。
您的生产环境中可能发生的情况是 Tomcat 在 反向代理 后面。要在这种情况下正确配置基本 URI,您有两种选择:
- 在
<Connector>
、 上静态配置 - 使用
RemoteIpValve
并配置代理服务器发送原Host
header并添加X-Forwarded-For
和X-Forwarded-Proto
header s.
scheme
、secure
、proxyName
和 proxyPort
的正确值
如果您的代理将不同类型的请求转发给 Tomcat(例如 HTTP 和 HTTPS 请求),RemoteIpValve
是您唯一的选择。
备注:如果将ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231
属性设置为true
,base URI也可以基于请求URI:cf . this question.