修复由 java servlet 服务的 HTML 中的相对路径(针对 HTML5 pushstate)
Fix relative paths in HTML served by java servlet (for HTML5 pushstate)
我正在尝试修改具有 servlet (RootResource.java) 的 Jetty 服务器,它以某种方式神奇地获取并使用:
@Singleton
@Path("/")
public class RootResource {
@Context
private ServletContext servletContext;
@GET
@Path("react-client/{path: .*\..+$}")
public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
// This doesn't work, a resolved relative resource is not relative
// to the /react-client base. See description of problem.
final String pathToResource = httpServletRequest.getRequestURI();
return serveStaticContent(pathToResource);
}
@GET
@Path("react-client/{path: .*$}")
public Response serveReactClientIndexPage(@Context HttpServletRequest httpServletRequest) {
return serveStaticContent("/react-client/index.html");
}
private Response serveStaticContent(String pathToResource) {
final String type = this.servletContext.getMimeType(pathToResource);
final Response.ResponseBuilder response = Response.ok(servletContext.getResourceAsStream(pathToResource)).type(type);
return response.build();
}
}
想法是对 react-client/some/path
和 return react-client/index.html
的内容进行 GET 请求。本质上使 Jetty 表现得像一个使用客户端路由的 webapp 服务器。
我遇到的问题是 index.html
中的相对路径仅在路径深度为一级时才有效 例如react-client/products
.
<script src="./webapp.js"></script>
在这种情况下,在 index.html 中找到了上面的 javascript 文件,因为 webapp.js
是一个存在于 react-client/webapp.js
.
的文件
一旦我尝试更深入 link 例如react-client/products/97357361
失败,因为 servlet 试图在 react-client/products/webapp.js
中查找不存在的 webapp.js
。
如何让它始终像来自 /react-client
一样请求资源?谢谢
我尝试了很多东西,比如过滤器和 rewrite handlers 但 Jetty 从来没有提供过原始未解析的相对导入(例如 ./webapp
)所以我从来没有机会重写相对资源。
最后我不得不用黑客来检测它们,因为我知道它们几乎都是从 /static/
子目录请求的(我不得不为 favicon.ico
添加一个硬编码异常和 manifest.json
.
@GET
@Path("react-client/{path: .*\..+$}")
public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
final String pathToResource = httpServletRequest.getRequestURI();
Pattern p = Pattern.compile("/react-client/(.+?(?=static/|favicon.ico))", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(pathToResource);
String resolveResourcePath = m.replaceAll("/react-client/");
return serveStaticContent(resolveResourcePath);
}
对它不满意,但它有效。
因为您的 index.html
可以被多个 url 访问,例如
- /react-client/products
- /react-client/products/97357361
- /react-client/some
- /react-client/some/路径
在 HTML 页面的 header 添加一个 <base>
标签可能是明智的。
<head>
...
<base href="https://www.yourwebsite.com/react-content/" />
<script src="./script.js"></script>
...
</head>
这将告诉浏览器将页面中找到的任何相对路径解析为相对于 https://www.yourwebsite.com/react-content/
因此,根据上面的示例,<script src="./script.js"></script>
将作为 "https://www.yourwebsite.com/react-content/script.js"
向服务器请求,而不管当前 url 用于访问此页面。
然后,您可以在 Jetty 上还原这些设置并保持简单。
我正在尝试修改具有 servlet (RootResource.java) 的 Jetty 服务器,它以某种方式神奇地获取并使用:
@Singleton
@Path("/")
public class RootResource {
@Context
private ServletContext servletContext;
@GET
@Path("react-client/{path: .*\..+$}")
public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
// This doesn't work, a resolved relative resource is not relative
// to the /react-client base. See description of problem.
final String pathToResource = httpServletRequest.getRequestURI();
return serveStaticContent(pathToResource);
}
@GET
@Path("react-client/{path: .*$}")
public Response serveReactClientIndexPage(@Context HttpServletRequest httpServletRequest) {
return serveStaticContent("/react-client/index.html");
}
private Response serveStaticContent(String pathToResource) {
final String type = this.servletContext.getMimeType(pathToResource);
final Response.ResponseBuilder response = Response.ok(servletContext.getResourceAsStream(pathToResource)).type(type);
return response.build();
}
}
想法是对 react-client/some/path
和 return react-client/index.html
的内容进行 GET 请求。本质上使 Jetty 表现得像一个使用客户端路由的 webapp 服务器。
我遇到的问题是 index.html
中的相对路径仅在路径深度为一级时才有效 例如react-client/products
.
<script src="./webapp.js"></script>
在这种情况下,在 index.html 中找到了上面的 javascript 文件,因为 webapp.js
是一个存在于 react-client/webapp.js
.
一旦我尝试更深入 link 例如react-client/products/97357361
失败,因为 servlet 试图在 react-client/products/webapp.js
中查找不存在的 webapp.js
。
如何让它始终像来自 /react-client
一样请求资源?谢谢
我尝试了很多东西,比如过滤器和 rewrite handlers 但 Jetty 从来没有提供过原始未解析的相对导入(例如 ./webapp
)所以我从来没有机会重写相对资源。
最后我不得不用黑客来检测它们,因为我知道它们几乎都是从 /static/
子目录请求的(我不得不为 favicon.ico
添加一个硬编码异常和 manifest.json
.
@GET
@Path("react-client/{path: .*\..+$}")
public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
final String pathToResource = httpServletRequest.getRequestURI();
Pattern p = Pattern.compile("/react-client/(.+?(?=static/|favicon.ico))", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(pathToResource);
String resolveResourcePath = m.replaceAll("/react-client/");
return serveStaticContent(resolveResourcePath);
}
对它不满意,但它有效。
因为您的 index.html
可以被多个 url 访问,例如
- /react-client/products
- /react-client/products/97357361
- /react-client/some
- /react-client/some/路径
在 HTML 页面的 header 添加一个 <base>
标签可能是明智的。
<head>
...
<base href="https://www.yourwebsite.com/react-content/" />
<script src="./script.js"></script>
...
</head>
这将告诉浏览器将页面中找到的任何相对路径解析为相对于 https://www.yourwebsite.com/react-content/
因此,根据上面的示例,<script src="./script.js"></script>
将作为 "https://www.yourwebsite.com/react-content/script.js"
向服务器请求,而不管当前 url 用于访问此页面。
然后,您可以在 Jetty 上还原这些设置并保持简单。