重新加载页面给AngularJS HTML5模式提供了错误的GET请求

我想为我的应用程序启用HTML5模式。 我已经把下面的代码放在configuration中,如下所示:

return app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider) { $locationProvider.html5Mode(true); $locationProvider.hashPrefix = '!'; $routeProvider.when('/', { templateUrl: '/views/index.html', controller: 'indexCtrl' }); $routeProvider.when('/about',{ templateUrl: '/views/about.html', controller: 'AboutCtrl' }); 

正如你所看到的,我使用了$locationProvider.html5mode并且在ng-ref中我改变了所有的链接来排除/#/

问题

目前,我可以去localhost:9000/并看到索引页面,并导航到其他页面,如localhost:9000/about

但是,刷新localhost:9000/about页面时会发生此问题。 我得到以下输出: Cannot GET /about

如果我看networking电话:

 Request URL:localhost:9000/about Request Method:GET 

而如果我第一次去localhost:9000/然后点击一个button导航到/about我得到:

 Request URL:http://localhost:9000/views/about.html 

它使页面完美呈现。

我怎样才能启用angular度得到正确的页面,当我刷新?

先谢谢你。

从angular度文档

服务器端
使用这种模式需要在服务器端重写URL,基本上你必须重写所有的链接到你的应用程序的入口点(例如index.html)

原因是当你第一次访问页面( /about ),例如刷新后,浏览器无法知道这不是一个真正的URL,所以它继续并加载它。 但是,如果你已经加载了根页面和所有的JavaScript代码,那么当你导航到/about Angular的时候,可以在浏览器试图打开服务器并相应处理之前进入

有几件事情要设置,所以你的浏览器中的链接将看起来像http://yourdomain.com/path ,这些是你的angular度configuration+服务器端

1)AngularJS

 $routeProvider .when('/path', { templateUrl: 'path.html', }); $locationProvider .html5Mode(true); 

2)服务器端,只需将.htaccess放入根文件夹并粘贴

 RewriteEngine On Options FollowSymLinks RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /#/$1 [L] 

更有趣的东西阅读有关angularjs html5模式和每个不同的环境所需的configurationhttps://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server -to-work-with-html5mode另外这个问题可能会帮助你$位置/切换html5和hashbang模式/链接重写

我有一个类似的问题,我解决了它:

  • 在索引页面使用<base href="/index.html">

  • 在节点/ Express服务器中使用捕获所有路由中间件如下(放在路由器之后):

 app.use(function(req, res) { res.sendfile(__dirname + '/Public/index.html'); }); 

我认为这应该让你启动和运行。

如果你使用apache服务器,你可能想mod_rewrite你的链接。 这并不难。 只是在configuration文件中的一些变化。

所有这一切都假设你已经在angularjs上启用了html5mode。 现在。 注意在angular1.2中,实际上不再推荐声明一个基本的url。

BrowserSync和Gulp的解决scheme。

https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643

首先安装connect-history-api-fallback

 npm --save-dev install connect-history-api-fallback 

然后将其添加到您的gulpfile.js中:

 var historyApiFallback = require('connect-history-api-fallback'); gulp.task('serve', function() { browserSync.init({ server: { baseDir: "app", middleware: [ historyApiFallback() ] } }); }); 

您需要configuration您的服务器重写所有index.html来加载应用程序:

https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode

我写了一个简单的连接中间件来模拟grunt项目的URL重写。 https://gist.github.com/muratcorlu/5803655

你可以这样使用:

 module.exports = function(grunt) { var urlRewrite = require('grunt-connect-rewrite'); // Project configuration. grunt.initConfig({ connect: { server: { options: { port: 9001, base: 'build', middleware: function(connect, options) { // Return array of whatever middlewares you want return [ // redirect all urls to index.html in build folder urlRewrite('build', 'index.html'), // Serve static files. connect.static(options.base), // Make empty directories browsable. connect.directory(options.base) ]; } } } } }) }; 

如果你使用MVC与AngularJS进行.NET堆栈,那么你需要做的就是从url中删除'#':

  1. 在你的_Layout页面设置你的基础href: <head> <base href="/"> </head>

  2. 然后,在你的angular度应用程序configuration中添加以下内容: $locationProvider.html5Mode(true)

  3. 上面会从url中删除'#',但是页面刷新将不起作用,例如,如果你在“yoursite.com/about”页面刷新,将会给你一个404。这是因为MVC不知道angular度路由,通过MVC模式将寻找一个“about”的MVC页面,该页面在MVC路由path中不存在。 解决这个问题的方法是将所有MVC页面请求发送到单个MVC视图,您可以通过添加捕获所有url的路由


 routes.MapRoute( name: "App", url: "{*url}", defaults: new { controller = "Home", action = "Index" } ); 

IIS URL重写规则,以防止HTML5模式页面刷新后发生404错误

用于在Windows上的IIS下angular运行

 <rewrite> <rules> <rule name="AngularJS" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite> 

NodeJS / ExpressJS在html5mode中刷新页面后避免404错误的路由

用于Node / Express下的angular度运行

 var express = require('express'); var path = require('path'); var router = express.Router(); // serve angular front end files from root path router.use('/', express.static('app', { redirect: false })); // rewrite virtual urls to angular app to enable refreshing of internal pages router.get('*', function (req, res, next) { res.sendFile(path.resolve('app/index.html')); }); module.exports = router; 

更多信息: AngularJS – 启用HTML5模式页面刷新没有404错误在NodeJS和IIS

正如其他人所说的,你需要在服务器上重写路由并设置<base href="/"/>

对于gulp-connect

npm install connect-pushstate

 var gulp = require('gulp'), connect = require('gulp-connect'), pushState = require('connect-pushstate/lib/pushstate').pushState; ... connect.server({ ... middleware: function (connect, options) { return [ pushState() ]; } ... }) .... 

我使用Apache(xampp)在我的开发环境和生产上的apache,添加:

 errorDocument 404 /index.html 

到.htaccess解决了我这个问题。

我解决了

 test: { options: { port: 9000, base: [ '.tmp', 'test', '<%= yeoman.app %>' ], middleware: function (connect) { return [ modRewrite(['^[^\\.]*$ /index.html [L]']), connect.static('.tmp'), connect().use( '/bower_components', connect.static('./bower_components') ), connect.static('app') ]; } } }, 

我从更大的问题回答这个问题:

当我添加$ locationProvider.html5Mode(true)时,我的网站将不允许粘贴url。 html5Mode为true时如何configuration我的服务器?

如果启用了html5Mode,则#字符将不再用于您的url。 #符号很有用,因为它不需要服务器端configuration。 没有#,url看起来好多了,但是它也需要服务器端重写。 这里有些例子:

对于使用AngularJS的Express Rewrites,您可以使用以下更新来解决此问题:

 app.get('/*', function(req, res) { res.sendFile(path.join(__dirname + '/public/app/views/index.html')); }); 

 <!-- FOR ANGULAR ROUTING --> <base href="/"> 

 app.use('/',express.static(__dirname + '/public')); 

对于Grunt和Browsersync, 在这里使用connect-modrewrite

 var modRewrite = require('connect-modrewrite'); browserSync: { dev: { bsFiles: { src: [ 'app/assets/css/*.css', 'app/*.js', 'app/controllers/*.js', '**/*.php', '*.html', 'app/jade/includes/*.jade', 'app/views/*.html', ], }, options: { watchTask: true, debugInfo: true, logConnections: true, server: { baseDir :'./', middleware: [ modRewrite(['!\.html|\.js|\.jpg|\.mp4|\.mp3|\.gif|\.svg\|.css|\.png$ /index.html [L]']) ] }, ghostMode: { scroll: true, links: true, forms: true } } } }, 

我相信你的问题是关于服务器。 关于HTML5模式的angular度文档(在您的问题中的链接)指出:

服务器端使用这种模式需要在服务器端重写URL,基本上你必须重写所有的链接到你的应用程序的入口点(例如index.html)

我相信你将需要设置一个URL重写从/关于/。

我们在Express中有一个服务器redirect:

 app.get('*', function(req, res){ res.render('index'); }); 

而且即使在添加了<base href="/" />之后,我们仍然遇到页面刷新问题。

解决scheme:确保您使用的页面中的真实链接进行导航; 不要在URL中input路由,否则会得到页面刷新。 (愚蠢的错误,我知道)

😛

如果您在本地工作,则可以使用:connect-modrewrite

看到这个教程: http : //ericduran.io/2013/05/31/angular-html5Mode-with-yeoman/

我发现更好的Grunt插件,如果你有你的index.html和Gruntfile.js在同一目录下的工作;

 https://npmjs.org/package/grunt-connect-pushstate 

之后在你的Gruntfile中:

  var pushState = require('grunt-connect-pushstate/lib/utils').pushState; connect: { server: { options: { port: 1337, base: '', logger: 'dev', hostname: '*', open: true, middleware: function (connect, options) { return [ // Rewrite requests to root so they may be handled by router pushState(), // Serve static files connect.static(options.base) ]; } }, } }, 

我之前也有同样的问题,刷新页面时,浏览器会将其地址栏的值发送到服务器,这显然会失败(因为它是一个重写的地址)。

你也应该在服务器端完成你的URL重写逻辑。 看到下面的链接,这是我发现如何做到这一点的最好的例子,它适用于我:

https://github.com/bdunklau/LittleBlueBird/wiki/URL-Rewriting-and-HTML5-in-AngularJS

基本上你只需要将所有请求redirect到你的主页内容容器(大多数情况下是index.html)。

 I solved same problem using modRewrite. AngularJS is reload page when after # changes. But HTML5 mode remove # and invalid the reload. So we should reload manually. # install connect-modrewrite $ sudo npm install connect-modrewrite --save # gulp/build.js 'use strict'; var gulp = require('gulp'); var paths = gulp.paths; var util = require('util'); var browserSync = require('browser-sync'); var modRewrite = require('connect-modrewrite'); function browserSyncInit(baseDir, files, browser) { browser = browser === undefined ? 'default' : browser; var routes = null; if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) { routes = { '/bower_components': 'bower_components' }; } browserSync.instance = browserSync.init(files, { startPath: '/', server: { baseDir: baseDir, middleware: [ modRewrite([ '!\\.\\w+$ /index.html [L]' ]) ], routes: routes }, browser: browser }); } 

我有与JHipster生成的Java +angular应用程序相同的问题。 我用filter解决了它,并在属性中的所有angular页面列表:

application.yml:

 angular-pages: - login - settings ... 

AngularPageReloadFilter.java

 public class AngularPageReloadFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.getRequestDispatcher("index.html").forward(request, response); } } 

WebConfigurer.java

 private void initAngularNonRootRedirectFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) { log.debug("Registering angular page reload Filter"); FilterRegistration.Dynamic angularRedirectFilter = servletContext.addFilter("angularPageReloadFilter", new AngularPageReloadFilter()); int index = 0; while (env.getProperty("angular-pages[" + index + "]") != null) { angularRedirectFilter.addMappingForUrlPatterns(disps, true, "/" + env.getProperty("angular-pages[" + index + "]")); index++; } angularRedirectFilter.setAsyncSupported(true); } 

希望对别人有帮助。

Gulp + browserSync:

通过npm安装connect-history-api-fallback,稍后configuration你的服务吞吐任务

 var historyApiFallback = require('connect-history-api-fallback'); gulp.task('serve', function() { browserSync.init({ proxy: { target: 'localhost:' + port, middleware: [ historyApiFallback() ] } }); }); 

您的服务器端代码是JAVA,然后按照以下步骤

第1步:下载urlrewritefilter JAR 点击这里并保存pathWEB-INF / lib

第2步:启用HTML5模式$ locationProvider.html5Mode(true);

第3步:设置基本URL <base href="/example.com/"/>

第4步:复制并粘贴到您的WEB.XML

  <filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> 

第5步:在WEN-INF / urlrewrite.xml中创build文件

  <urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/index.html</to> </rule> <!--Write every state dependent on your project url--> <rule> <from>/example</from> <to>/index.html</to> </rule> </urlrewrite> 

最后,我有办法解决这个问题的服务器端,因为它更像是AngularJs本身的问题,我正在使用1.5 Angularjs和我得到同样的问题,重新加载页面。 但是,在我的server.js文件中添加下面的代码后,它是保存我的一天, 但它不是一个合适的解决scheme或不是一个好方法。

 app.use(function(req, res, next){ var d = res.status(404); if(d){ res.sendfile('index.html'); } }); 

我有这个简单的解决scheme,我一直在使用和它的作品。

在App / Exceptions / Handler.php中

在顶部添加:

 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 

然后在render方法里面

 public function render($request, Exception $exception) { ....... if ($exception instanceof NotFoundHttpException){ $segment = $request->segments(); //eg. http://site.dev/member/profile //module => member // view => member.index //where member.index is the root of your angular app could be anything :) if(head($segment) != 'api' && $module = $segment[0]){ return response(view("$module.index"), 404); } return response()->fail('not_found', $exception->getCode()); } ....... return parent::render($request, $exception); } 

只需在web.config中写出一条规则

 <system.webServer> <rewrite> <rules> <rule name="AngularJS Routes" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite> </system.webServer> 

在索引中添加这个

 <base href="/">