Vue路由器历史模式返回404错误

Posted

技术标签:

【中文标题】Vue路由器历史模式返回404错误【英文标题】:Vue router history-mode returing 404 error 【发布时间】:2021-09-27 08:14:51 【问题描述】:

我有一个在 tomcat 中运行的具有历史模式的 vue 应用程序。 当访问 www.mywebapp.com/faq 或 mywebapp.com/other 或 ../post/99 等时,它首先似乎工作正常。刷新页面似乎也可以正常工作。

但是,当我在浏览器控制台中仔细查看时,我发现我收到了一条错误消息。

"Failed to load resource: the server responded with a status of 404 ()"

页面在重定向我之前返回 404 错误,然后页面加载。

在非常慢的互联网连接上,404 错误会在加载之前存在较长时间。

有人知道我在这里缺少什么吗?我添加了以下代码来尝试处理它,但没有成功。

我的路由器是这样的:

  export const router = new Router(
  mode: 'history',
  base: '/',
  routes: [
  
  name: 'home',
  path: '/',
  component: Home
  ,
  ....,
  
   path: '*',
  component: ErrorLanding,
  name: 'NotFound'
  ,
  ],
  scrollBehavior(to, from, savedPosition) 
      return x:0, y: 0
  
  );
  router.beforeEach((to, from, next) => 
   const publicPages = ['/', '/login', '/register', 
       '/help', '/ticket', '/about' ];
   const authRequired = !publicPages.includes(to.path);
   const loggedIn = localStorage.getItem('user');
    const redirect = to.path;

   if (authRequired && loggedIn === null) 
    if(to.meta.authRequired === false) 
      next();
    
    else
    next( name: 'Login', query:  redirect: redirect  );

     else 
    next();
    
   );

我的 vue.config.js 看起来像这样:

   module.exports = 
   devServer: 
   port: 80,     
   proxy: "http://localhost/*"
   ,
   publicPath: process.env.NODE_ENV === 'production'
   ? '/'
   : '/'
   

最后,我在 dist/ROOT/WEB-INF/ 中有一个 web.xml 文件,代码如下:

  <?xml version="1.0" encoding="ISO-8859-1"?>
   <web-app xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
   version="3.0" 
   metadata-complete="true">
  <display-name>my app</display-name>
  <description>
     this is my app description
  </description>
  <error-page>  
   <error-code>404</error-code>  
   <location>/</location>  
  </error-page>  
</web-app>

更新

当我将这行代码添加到 server.xml 时

   <Valve 
   className="org.apache.catalina.valves.rewrite.RewriteValve"/>

并创建一个我添加到 Catalina/localhost/ 的 rewrite.config 文件 有了这个信息:

   RewriteCond %REQUEST_PATH !-f
   RewriteRule ^/(.*) /index.html 

它正在工作,我不再收到任何错误消息。 但现在我有一个新问题。我通过 Vuex 填充的数组正在返回无限循环。这怎么可能?

更新

我已尝试将此添加到 rewrite.config 文件中:

RewriteRule ^/api1/ - [L,NC]
RewriteRule ^/api2/ - [L,NC]
RewriteRule ^/api3/ - [L,NC]
RewriteRule ^/api4/ - [L,NC]
RewriteRule ^/api5/ - [L,NC]
RewriteRule ^/api6/ - [L,NC]
RewriteCond %REQUEST_PATH !-f
RewriteRule ^/(.*) /index.html

更新 已解决 下面必须添加到 rewrite.config 文件中。

 RewriteRule ^/myapi1/.* - [L,NC]
 RewriteRule ^/myapi2/.* - [L,NC]
 RewriteRule ^/myapi3/.* - [L,NC]
 RewriteRule ^/myapi4/.* - [L,NC]
 RewriteRule ^/myapi5/.* - [L,NC]
 RewriteRule ^/host-manager/.* - [L,NC]
 RewriteRule ^/manager/.* - [L,NC]
 RewriteCond %REQUEST_PATH !-f
 RewriteRule ^/(.*) /index.html

非常感谢@Michal Levy 的帮助!!

【问题讨论】:

router.vuejs.org/guide/essentials/history-mode.html#apache 嗨,Michal,谢谢,但这些服务器配置都不适合我,因为我使用的是 tomcat 而不是 apache。 抱歉,对 Java 不太了解 - 认为 TomCat 运行在 Apache 后面... medium.com/@nithin.biliya/… - 它适用于 Angular,但没关系,因为问题是一样的...... 嗨@MichalLevý,当按照说明修复该链接中的深层链接问题时,它可以工作。我现在可以访问直接链接,而不会在控制台中收到任何错误消息,但是现在我的数组上出现了一个无限循环,它是通过 vuex 填充的。有什么想法吗? 【参考方案1】:

问题是使用Vue路由器的历史模式导致的,在docs中有很好的描述

使用历史模式时,URL 看起来“正常”,例如http://oursite.com/user/id。但是问题来了:由于我们的应用是单页客户端应用,没有适当的服务器配置,如果用户直接在浏览器中访问http://oursite.com/user/id,将会收到 404 错误。要解决此问题,您需要做的就是向您的服务器添加一个简单的包罗万象的后备路由。如果 URL 不匹配任何静态资源,它应该提供与您的应用相同的 index.html 页面。

还有很多示例如何针对大量服务器执行此操作 - 不是针对 Tomcat 的...

要在 Tomcat 中配置“SPA fallback”(通用名称),您必须:

    server.xml 中配置 RewriteValve

编辑~/conf/server.xml,在主机部分添加以下阀门,如下所示:

<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Host>
    将重写规则写入rewrite.config

创建目录结构 — ~/conf/Catalina/localhost/ 并在其中创建 rewrite.config 文件,内容如下:

RewriteCond %REQUEST_PATH !-f
RewriteRule ^/(.*) /index.html

Source

注意:请注意,上述重写规则会导致您的服务器为任何与“常规文件”不匹配的请求返回index.html(请参阅Rewrite Valve Docs)。因此如果您的服务器也提供某种 API(例如 REST),您需要修改重写规则以不重写对 API 的请求。

例如,如果您的 API 在 /api/... 上提供服务,您的重写规则应如下所示:

# match any URL starting with `/api/`, do not rewrite and don't process other rules...
RewriteRule ^/api/ - [L]
RewriteCond %REQUEST_PATH !-f
RewriteRule ^/(.*) /index.html

【讨论】:

嗨@Michal,我有6 个不同的API,那么那些重写规则会是什么样子?只需添加 6 行 RewriteRule ^/api/ - [L] ??没用 使用 6 种不同的重写规则或更改正则表达式以匹配您的用例。另请注意,规则默认区分大小写,要使其不区分大小写,请使用 [L,NC] 而不是 [L]。更改配置时不要忘记重新启动服务器! 我在 rewrite.config 中添加了 6 种不同的重写规则,全部使用 L,NC。但是重启tomcat甚至整个VPS后仍然是同样的问题。检查更新的问题,该格式有任何问题吗?【参考方案2】:

@Michal Levys 的回答是正确的,只是需要针对我的情况进行一些小的调整。 要解决此问题,必须将以下内容添加到 rewrite.config。

  RewriteRule ^/myapi1/.* - [L,NC]
  RewriteRule ^/myapi2/.* - [L,NC]
  RewriteRule ^/myapi3/.* - [L,NC]
  RewriteRule ^/myapi4/.* - [L,NC]
  RewriteRule ^/myapi5/.* - [L,NC]
  RewriteRule ^/host-manager/.* - [L,NC]
  RewriteRule ^/manager/.* - [L,NC]
  RewriteCond %REQUEST_PATH !-f
  RewriteRule ^/(.*) /index.html

【讨论】:

以上是关于Vue路由器历史模式返回404错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在不更改 Vue 中的 url 的情况下返回 404 错误?

Vue的路由模式处理404

NGINX + Vue HTML 模式配置给出 404

Vue.js 路由器:历史模式和 AWS S3 (RoutingRules)

如何使用与普通路由不同的模板处理 vue-router 的 404 错误

使用 vue3 路由重新加载页面时出现错误 404