重新加载页面给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来加载应用程序:
我写了一个简单的连接中间件来模拟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中删除'#':
-
在你的_Layout页面设置你的基础href:
<head> <base href="/"> </head>
-
然后,在你的angular度应用程序configuration中添加以下内容:
$locationProvider.html5Mode(true)
-
上面会从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="/">