AngularJS和NodeJS http-server:重写URL

我使用NodeJS http-server来编写AngularJS应用程序。
我有一个问题。 当我尝试直接访问浏览器中的URL时,Angular不会拦截URL来显示内容。
如果我手动键入URL: http : //127.0.0.1 : 8080/ #! /客户它的工作,但不是当我直接input: http : //127.0.0.1 : 8080 /clients

我想要http://127.0.0.1:8080/# 作为http服务器中的默认值。

我在AngularJS中使用html5模式和哈希前缀:

$locationProvider.html5Mode(true); $locationProvider.hashPrefix('!'); 

有没有一种方法来重写http-server的URL与地址之前的默认/#!/

注意 :下面是一个更复杂的Express.js URL重写情况的例子,你可能不希望“捕获所有”路由,而是在视图和服务器端API的路由之间进行区分。 我所能find的所有解决scheme都只显示了一种通用的方法,它不适用于需要访问服务器端路由的应用程序的实际应用。 如果你只是想要“全部捕捉”,请参阅本答案底部的其他黄色注释,​​以获得如何设置的链接。

如果你closureshtml5模式,默认情况下,你应该使用hashbang( #! )模式…打开html5Mode可以让你删除hashbang( #! ),如果你愿意的话。

以下是关于不同模式的更多信息: https : //docs.angularjs.org/guide/$location

HTML5模式启用,给你正常看,非hashbangurl。 通常情况下,当启用HTML5模式时,你会遇到你所描述的问题,你的应用中的页面会在内部加载OK,但是如果你尝试直接在浏览器中inputURL(或者通过书签访问它)得到一个Cannot GET错误。

首先,确保你已经在你的主索引文件的<head>设置了一个<base>标签,如下所示:

 <head> <!-- all your script tags, etc etc --> <base href="/"> <!-- rest of your front-end dependencies etc --> </head> 

这样Angular会知道哪个是你的主要索引来加载内部的部分。

其次,我会尝试告诉你我是如何着手重写Express的URL,以解决你所描述的问题。 我的答案可能有些不完整,因为我还在学习,事实上,我不完全明白,为什么在Angular中启用了HTML5模式后,路由无法正常工作。 解决这个问题的方法也许可以有更好的办法,而不是解决我的问题。

看来,一旦我切换到HTML5模式,Angular拦截了我的路线,当我试图使用$http服务来请求服务器端API路线时,造成了一个问题。

似乎开启HTML5模式基本上接pipe了我的所有路由,我不得不find一种方式告诉Express要么通过一个pathAngular或继续使用next()的路线(远离angularnext() 。 这是我最好的评估。

我做了什么:

  1. 启用HTML5模式(如您在示例中所做的那样),并在我的索引文件中设置一个<base> (如上所述)。

  2. 在ExpressJS中使用本地express.Router()重写了我的路由:

    • 请参阅: https : //expressjs.com/en/guide/routing.html
    • 在该页面的最底部是指令express.Router()
    • 我会告诉你我是如何做到的

我的方法/伪代码:

我在我的路由器中设置了一个方法,这样如果传入的请求包含/api/ (通过正则expression式检查),我将调用ExpressJS的next()方法,并继续沿着路由,这将击中服务器控制器。 否则,如果URL不包含/api/ ,那么我将传递适当的查看页面,Angular接pipe了这个页面。

我如何设置我的express.Router()

  1. 我在我的应用程序中创build了一个middleware文件夹,并创build了一个名为api-check.js的文件。

     // Setup any Dependencies: var express = require('express'), router = express.Router(), // very important! path = require('path'); // Setup Router Middleware: /* Notes: The `apiChecker` function below will run any time a request is made. The API Checker will do a regex comparison to see if the request URL contained the `/api/` pattern, to which instead of serving the HTML file for HTML5 mode, it will instead `next()` along so the API route can reach the appropriate server-side controller. */ router.use(function apiChecker (req, res, next) { console.log('/// ROUTER RUNNING ///'); // will print on every route console.log('URL:', req.originalUrl); // will show requested URL var regex = /(\/api\/)/g; // pattern which checks for `/api/` in the URL if (regex.test(req.originalUrl)) { // if the URL contains the pattern, then `next()` console.log('THIS IS AN API REQUEST'); // api detected next(); } else { // if the URL does not contain `/api`: res.sendFile(path.join(__dirname, './../../client/index.html')); // delivers index.html which angular-route will then load appropriate partial } }) module.exports = router; // exports router (which now has my apiChecked method attached to it) 

我如何将express.Router()添加到我的Express App中:

取决于你的代码是如何模块化的,只要继续,在正确的地方require你的模块(你将不得不根据你的项目调整直接path),然后app.use()模块拦截所有的路由和引导他们到您的路由器:

 // Get Router: var apiCheck = require('./../middleware/api-check'); // Use Router to intercept all routes: app.use('/*', apiCheck); 

现在,任何路由(因此/* )都将通过express.Router() apiChecker()函数进行评估。 如果请求的URL包含/api ,则next()将被调用,服务器端控制器将被访问。 否则,如果在URL中未检测到/api slug,则会发送主index.html基本文件,以便Angular可以通过$routeProvider传递相应的视图。

注意 :如果你不需要在传入的路由之间进行区分,只是想“捕获所有”传入的路由并交回你的<base>索引文件,你可以按照另一个stackoverflow的答案在这里做的概述。 该答案使用app.get()来捕获所有的GET请求来交还你的索引。 如果您还需要捕获POST请求或其他请求,则可以使用app.all()代替上述示例中的app.get() 。 这将捕获所有路由,无论是GETPOST等。请阅读Express文档 。

这是我的个人解决scheme,可能会更好,但是这解决了我的问题! 将有兴趣知道别人推荐! 当然,这样做的缺点是我必须build立所有我的内部apipath来包含/api/ ,但是这样做总体来看似乎是可以的,甚至有助于避免我的路线从前面混淆侧观。

希望这至less有所帮助,让我知道如果你需要任何澄清:)