1

我将 html5Mode=true 与 AngularJS 路由一起使用。工作正常。当我使用 IE 访问该站点时,Angular 路由会退回到像http://example.com/#!/route-name这样的 Hashbang URI 。没关系。除了在 Express 中,我需要知道路线,因为它告诉我要从 Express 提供哪个 html 文件。url 的 # 部分不会发送到服务器。

我的问题是,如何让我的服务器知道在 IE 中使用 hashbang 路由请求哪个 AngularJS 路由?我正在考虑以某种方式配置 Angular 以将路由作为我可以快速读取的 http 标头发送,但我不知道该怎么做。有任何想法吗?

更新:根据我得到的反馈,让我告诉你该网站有模板。一个用于主页,一个用于所有其他页面。他们都非常不同。根据路由,服务器需要知道何时为主页提供文件,何时为其他页面提供文件。

4

3 回答 3

1

我有一个类似的问题,我需要 URL 的参数,然后再被重定向删除。由于 URL 是从原始 URL 以角度重定向的,因此前一个 URL 位于引用标头中。

所以我使用这个 express 3.x 中间件将原始参数从引用者重写为对根 URL 的请求的查询:

var _ = require('lodash');
var url = require('url');
var qs = require('querystring');

app.use(function(req, res, next) {    
    if (req.url === '/' && req.headers && req.headers.referer) {
        var referer = url.parse(req.headers.referer);

        // rewrite original parameters
        _.forEach(qs.parse(referer.query), function(value, key) {
            req.query[key] = value;
        });

        // do something with pathname
        console.log(referer.pathname);
    }
});

您可以对路径执行相同的操作,即在referer.pathname.

于 2015-03-10T13:16:24.717 回答
1

只是要明确一点:这不会在主页请求上发送 hashbang。根据HTTP 规范,没有办法做到这一点。

可以在随后的 AJAX 请求中发送它,但这并不能真正帮助您解决这个问题。除了不支持不支持html5mode的浏览器外,没有其他解决办法。

浏览器不会自动将 hashbang 发送到服务器,所以是的,您需要手动发送。使用标题是一个不错的选择。

看看docs$httpProvider.interceptors_

您可以注册一个请求拦截器$http(AngularJS 在内部使用它来处理任何 AJAX 请求,您也应该如此)附加一个自定义标头。然后,您可以使用以下方法将该标头值设置为实际的 hashbang $location.path()

var app = angular.module('MyApp',[]);

app.factory('httpInterceptor', function($q, $location) {
    return {
        'request': function(config) {
            if(config.url.indexOf('product')) {
                config.headers.Hashbang = $location.path();
            }
            return config;
        }
    };
});

app.config(function($httpProvider) {
    $httpProvider.interceptors.push('httpInterceptor');
});

app.controller('Ctrl', function($scope, $http) {
    $http({method: 'GET', url: '/echo/json/'}).
    success(function(data, status, headers, config) {
        console.log(data);
    });
});

这是小提琴。你可以像这样测试它。查看开发人员工具中发送的标头。

请注意,我没有使用真正的 hashbang ( #!) 进行测试,而只是使用哈希,因为小提琴不允许这样做。

于 2014-08-12T13:19:17.567 回答
0

根据 Sergiu Paraschiv 的回答,似乎没有客户端答案。所以我研究了一个服务器端解决方案,它只需要客户端上的一件事。确保您始终像在链接到 /xxxxx 而不是 /#!/xxxxx 的 html5Mode 中那样链接。

然后在html5Mode 和 IE9 及更低版本中,AngularJS 将所​​有 /xxxxx 重定向到 /#!/xxxxx。在 Express 中,这使 url / 和referer /xxxxx。您可以很容易地检查这一点。

如果你想迎合 IE8 及更低版本,不幸的是 Angular 在这种重定向到 /#!/xxxxx 的回退场景中使用了 window.location.href。参见github/angular.js/src/ng/browser.js第 169 行。使用 window.location.href 会导致 IE8 及更低版本 发送referer。

这是一个服务器端 (Express 3.x) 解决方案,它从引用者值或 IE8 及更低版本的 previousUrl 会话变量中解析 A​​ngular hashbang 路由。

app.use(function(req, res, next) {
  if (req.url.match(/\/api/))
    return next(); // /api/something should proceed to next in middleware
  console.log(req.url, req.headers)
  //IE does not support html5Mode so /xxxxx is redirected to /#!/xxxxx
  //effectively making the url / and the referer /xxxxx
  //I check for that here and if xxxxx is not home I present page.html

  if (req.headers['user-agent'] &&
    req.headers['user-agent'].match(/MSIE ([7-8]{1}[.0-9]*)/) &&
    req.url.match(/^\/[\w-]+$/)
  ) {
    //However IE8 does not report the referer when doing a redirect using window.locarion.href
    //so I store the initially requested url /xxxxx in session...
    req.session.previousUrl = req.url;
    //console.log('IE8 saving the url here', req.session.previousUrl);
  }
  if (req.headers['user-agent'] &&
    req.headers['user-agent'].match(/MSIE ([7-8]{1}[.0-9]*)/) &&
    !req.headers['referer'] &&
    req.url === '/' &&
    req.session.previousUrl &&
    req.session.previousUrl !== '/home'
  ) {
    //continuation on the IE* referer story (aka the next redirected request)...
    //... and checked for the url stored in session here ;)
    return res.sendfile('public\\page.html'); 
  }
  if (req.headers['user-agent'] &&
    req.headers['user-agent'].match(/MSIE ([7-9]{1}[.0-9]*)/) &&
    req.url === '/' &&
    req.headers['referer'] &&
    req.headers['referer'].match(/^https?:\/\/(?:www)?\.example\.com\/(?!home$)([\w-]+)$/)
  ) {
    return res.sendfile('public\\page.html'); 
  }
  if (req.url.match(/\/home|\/$/))
    return res.sendfile('public\\home.html'); //for the home pages we're going to use home.html

  res.sendfile('public\\page.html'); //for everything else we're going to use page.html
});

我确信在某些情况下会失败,但它在我的测试中对我有用,如果失败,那只会在 IE9 浏览器中失败(根据正则表达式)。

于 2014-08-13T08:03:29.703 回答