4

Is it possible to change the url of a HTTP-request without redirection?

For example instead of:

request 1

GET /user/abc123/ HTTP/1.1

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

request 2

GET /files/abc123 HTTP/1.1

HTTP/1.1 200 OK
.
.
[filecontent]

I could could respond the file directly, but letting the client know that he got redirected:

single request

GET /user/abc123/ HTTP/1.1

HTTP/1.1 200 OK
Location: /files/abc123
.
.
[filecontent]
Van Coding
  • 24,244
  • 24
  • 88
  • 132

3 Answers3

1

As far as I know, it's not possible to do this with HTTP. Redirection in HTTP specifically means the the client is supposed to send a second a request.

I think what you want is more akin to specifying a "canonical url" for some resources, and then having this canonical url displayed in the browsers location bar.

RFC 6596 specifies a way to specify canonical urls with <link rel="canonical">. However, it does not specify what a browser should do with it, if anything. Google uses it to make better choices about which urls to index.

Other than using <link> tags, it's also possible to specify relationships between resources via the HTTP Link header, i.e. Link: </better-url>; rel=canonical. See http://www.w3.org/wiki/LinkHeader . I'm not sure if this would be picked up by Google though. The page at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=139394 doesn't mention Google supports it. Browsers surely will disregard it, as they do with practically any link tag, stylesheets being the notable exception.

If the content in question is a HTML document, you could use the HTML5 history API for this. Specifically, use the history.replaceState method. I don't think achieving something similar is possible with other types of content.

Edit

Content-Location header may actually fit what you want quite well. From section 14.14 of HTTP 1.1 RFC:

The Content-Location entity-header field MAY be used to supply the resource location for the entity enclosed in the message when that entity is accessible from a location separate from the requested resource's URI. A server SHOULD provide a Content-Location for the variant corresponding to the response entity; especially in the case where a resource has multiple entities associated with it, and those entities actually have separate locations by which they might be individually accessed, the server SHOULD provide a Content-Location for the particular variant which is returned.

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

The value of Content-Location also defines the base URI for the entity.

The Content-Location value is not a replacement for the original requested URI; it is only a statement of the location of the resource corresponding to this particular entity at the time of the request. Future requests MAY specify the Content-Location URI as the request- URI if the desire is to identify the source of that particular entity.

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

See also What is the purpose of the HTTP header field “Content-Location”?

Community
  • 1
  • 1
Myrne Stol
  • 11,222
  • 4
  • 40
  • 48
  • 1
    The Content-Location header really seems to be what I'm looking for, but sadly, I could not find a browser that supports it :( – Van Coding May 08 '13 at 13:38
1

Well, it is possible, but it feels a bit dirty though.

A quick demo:

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);
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • 1
    Yes, this implements what I mentioned above, but sadly, the browser does not display "/files/abc123" in the address bar after requesting "/user/abc123". It just ignores the Location header :( – Van Coding May 08 '13 at 12:45
  • 1
    Ah yes, I think I misunderstood what you want exactly. In that case, at least part of your solution has to be implemented client side, as Meryn already wrote. – robertklep May 08 '13 at 12:50
  • 1
    The Location header has no meaning outside 30x, 201, 202 responses. – Myrne Stol May 08 '13 at 13:18
  • 3
    For me, changing just `req.url` was enough . I got errors if I tried setting `req.path` – `TypeError: Cannot set property path of # which has only a getter`. – metakermit Nov 11 '16 at 09:29
0

This is my simple approach, not just change the originalUrl but the path too. My method suggestions:

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();
});

By this way /not-wanted-route-part/users will became /users

Tiago Gouvêa
  • 15,036
  • 4
  • 75
  • 81