java - 带有 Angular URL 重写的嵌入式 Jetty
问题描述
我正在使用 Jetty 部署 WebSocket 和 Angular 应用程序。在开发中一切正常,但在生产中我遇到的问题是,在刷新前端或输入 url 时,我从服务器收到一个 404,表明给定的资源不存在。现在我正在尝试创建一个重写规则来将请求重定向到我的 index.html。初始化我的服务器如下所示:
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(config.getServer().getPort());
server.addConnector(connector);
RewriteHandler rewriteHandler = new RewriteHandler();
rewriteHandler.setRewriteRequestURI(true);
rewriteHandler.setRewritePathInfo(false);
rewriteHandler.setOriginalPathAttribute("requestedPath");
/*
RedirectRegexRule rule1 = new RedirectRegexRule();
rule1.setRegex("/(.+)");
rule1.setLocation("/index.html");
rewriteHandler.addRule(rule1);
*/
URL webRootLocation = this.getClass().getResource("/frontend/index.html");
if (webRootLocation == null)
throw new IllegalStateException("Unable to determine webroot URL location");
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$","/"));
logger.debug("Web Root URI: {}",webRootUri);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.setBaseResource(Resource.newResource(webRootUri));
contextHandler.setWelcomeFiles(new String[]{ "index.html" });
rewriteHandler.setHandler(contextHandler);
ServerContainer container = WebSocketServerContainerInitializer.initialize(contextHandler);
List<Class<? extends Encoder>> encoders = new ArrayList<>();
encoders.add(MessageEncoder.class);
List<Class<? extends Decoder>> decoders = new ArrayList<>();
decoders.add(MessageDecoder.class);
ServerEndpointConfig endpointConfig = ServerEndpointConfig.Builder
.create(AppEndpoint.class, "/wss-test")
.encoders(encoders)
.decoders(decoders)
.configurator(new AppEndpointConfig(config, factory))
.build();
container.addEndpoint(endpointConfig);
//server.setHandler(contextHandler);
HandlerList handlerList = new HandlerList();
handlerList.setHandlers(new Handler[]{rewriteHandler, contextHandler});
server.setHandler(handlerList);
contextHandler.addServlet(DefaultServlet.class, "/");
server.start();
// server.dump(System.err);
server.join();
我的 Angular 前端编译在应用程序的资源文件夹中,该文件夹由服务器提供服务 - 例如:localhost:8080/
. 如果我的应用程序localhost:8080/some/path
正常运行,但刷新页面时我得到一个some/path
未知的 404。使用重写规则(注释掉)我ERR_TOO_MANY_REDIRECTIONS
也找不到延迟加载的资源/模块。关于如何为 Angular 应用程序使用 Jetty 重写的任何建议,因为我没有关于如何在此处继续的胶水,或者 Jetty 不支持angular 部署建议的 apache 重写之类的东西
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
解决方案
对于任何为此寻找解决方案的人,我使它与 Jettys 一起工作RewriteHandler
。我的服务器设置现在如下所示:
server = new Server(config.getServer().getPort());
RewriteHandler rewriteHandler = new RewriteHandler();
rewriteHandler.setRewriteRequestURI(true);
rewriteHandler.setRewritePathInfo(false);
rewriteHandler.setOriginalPathAttribute("requestedPath");
RewriteRegexRule rule1 = new RewriteRegexRule();
rule1.setRegex("^((?!"+wsPath+"|\\.js|\\.css|\\.jpe?g|\\.png).)*$");
rule1.setReplacement("/index.html");
rewriteHandler.addRule(rule1);
URL webRootLocation = this.getClass().getResource("/frontend/index.html");
if (webRootLocation == null)
throw new IllegalStateException("Unable to determine Web-Root URL location");
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$","/"));
logger.debug("Web-Root URI: {}",webRootUri);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.setBaseResource(Resource.newResource(webRootUri));
contextHandler.setWelcomeFiles(new String[]{ "index.html" });
rewriteHandler.setHandler(contextHandler);
// Initialize WebSocket
ServerContainer container = WebSocketServerContainerInitializer.initialize(contextHandler);
List<Class<? extends Encoder>> encoders = new ArrayList<>();
encoders.add(MessageEncoder.class);
List<Class<? extends Decoder>> decoders = new ArrayList<>();
decoders.add(MessageDecoder.class);
ServerEndpointConfig endpointConfig = ServerEndpointConfig.Builder
.create(AppEndpoint.class, "/" + wsPath)
.encoders(encoders)
.decoders(decoders)
.configurator(new AppEndpointConfig(config, factory))
.build();
container.addEndpoint(endpointConfig);
server.setHandler(rewriteHandler);
contextHandler.addServlet(DefaultServlet.class, "/");
server.start();
server.join();
这并不理想,因为只有特定的文件结尾与正则表达式匹配,但它确实适用于 Jetty 内构建和部署的 Angular 应用程序。如果使用 RESTful API,则必须定义一些正则表达式以匹配 API 的路径,如wsPath
我示例中的(简单字符串)。
推荐阅读
- go - 使用iota时,我很困惑
- reactjs - 使用 Shadow-CLJS 将 react-table 导入 ClojureScript
- java - 如何将属性放在项目之外并同时加载属性项目属性和外部项目属性?
- tcl - 使用 TDBC 检索与 ResultSetMetaData (JDBC) 相当的内容
- python - 如何检查文件是否存在于另一个文件夹中
- azure - 使用 Application Insights 更改用于登录 ASP.NET Core 的 Instrumentation 密钥
- java - org.springframework.web.servlet.PageNotFound noHandlerFound 找不到 HTTP 请求的映射
- javascript - 登录并重定向到主页时无法获取uid
- javascript - (反应)由于 .map() 函数,我得到了多个数组,如何将状态设置为一个数组?
- java - Netty TCP 服务器 - 在创建通道之前拒绝 IP