【问题标题】:http - change request url?http - 更改请求网址?
【发布时间】:2013-05-08 10:08:26
【问题描述】:

是否可以在不重定向的情况下更改 HTTP 请求的 url?

例如代替:

请求 1

GET /user/abc123/ HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: /files/abc123

请求 2

GET /files/abc123 HTTP/1.1

HTTP/1.1 200 OK
.
.
[filecontent]

我可以直接响应文件,但要让客户知道他被重定向了:

单个请求

GET /user/abc123/ HTTP/1.1

HTTP/1.1 200 OK
Location: /files/abc123
.
.
[filecontent]

【问题讨论】:

标签: node.js http


【解决方案1】:

据我所知,使用 HTTP 无法做到这一点。 HTTP 中的重定向特别意味着客户端应该发送第二个请求。

我认为你想要的更像是为某些资源指定一个“规范 url”,然后在浏览器的位置栏中显示这个规范的 url。

RFC 6596 指定使用<link rel="canonical"> 指定规范网址的方法。但是,它没有指定浏览器应该如何处理它(如果有的话)。 Google 使用它来更好地选择要索引的网址。

除了使用<link>标签外,还可以通过HTTP Link标头指定资源之间的关系,即Link: </better-url>; rel=canonical。见http://www.w3.org/wiki/LinkHeader。不过,我不确定这是否会被 Google 采纳。 http://support.google.com/webmasters/bin/answer.py?hl=en&answer=139394 的页面没有提到谷歌支持它。浏览器肯定会忽略它,就像几乎所有链接标签一样,样式表是一个明显的例外。

如果相关内容是 HTML 文档,您可以使用 HTML5 history API。具体来说,使用history.replaceState 方法。我认为其他类型的内容不可能实现类似的效果。

编辑

Content-Location 标头实际上可能非常适合您想要的。 来自 HTTP 1.1 RFC 的第 14.14 节:

Content-Location 实体标头字段可用于为包含在消息中的实体提供资源位置,当该实体可从与请求资源的 URI 不同的位置访问时。服务器应该为对应于响应实体的变体提供内容位置;特别是在资源有多个与之关联的实体的情况下,并且这些实体实际上具有单独的位置,可以通过这些位置单独访问它们,服务器应该为返回的特定变体提供 Content-Location。

  Content-Location = "Content-Location" ":"
                     ( absoluteURI | relativeURI )

Content-Location 的值还定义了实体的基本 URI。

Content-Location 值不能替代原始请求的 URI;它只是在请求时与该特定实体对应的资源位置的声明。如果希望识别特定实体的来源,未来的请求可以指定 Content-Location URI 作为 request-URI。

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

另见What is the purpose of the HTTP header field “Content-Location”?

【讨论】:

  • Content-Location 标头似乎确实是我正在寻找的东西,但遗憾的是,我找不到支持它的浏览器:(
【解决方案2】:

嗯,这可能的,但感觉有点脏。

快速演示:

var express = require('express');
var app     = express();

app.get('/user/abc123', function(req, res, next) {
  req.path = req.url = '/files/abc123';
  next();
});

app.get('/files/abc123', function(req, res) {
  res.set('Location', req.url);
  res.send('files!');
});

app.listen(3012);

【讨论】:

  • 是的,这实现了我上面提到的,但遗憾的是,浏览器在请求“/user/abc123”后,并没有在地址栏中显示“/files/abc123”。它只是忽略了 Location 标头:(
  • 啊,是的,我想我误解了你到底想要什么。在这种情况下,至少部分解决方案必须在客户端实现,正如 Meryn 已经写的那样。
  • Location 标头在 30x、201、202 响应之外没有意义。
  • 对我来说,只更改req.url 就足够了。如果我尝试设置 req.pathTypeError: Cannot set property path of #<IncomingMessage> which has only a getter,则会出现错误。
【解决方案3】:

这是我的简单方法,不仅要更改 originalUrl,还要更改 path。我的方法建议:

app.use(function(req, res, next) {
    console.log("request", req.originalUrl);
    const removeOnRoutes = '/not-wanted-route-part';
    req.originalUrl = req.originalUrl.replace(removeOnRoutes,'');
    req.path = req.path.replace(removeOnRoutes,'');
    return next();
});

这样/not-wanted-route-part/users就会变成/users

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 2013-11-08
    • 2018-07-04
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2021-01-08
    • 2018-11-15
    相关资源
    最近更新 更多