Van Coding
Van Coding

Reputation: 24534

http - change request url?

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]

Upvotes: 5

Views: 19019

Answers (3)

Tiago Gouvêa
Tiago Gouvêa

Reputation: 16740

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

Upvotes: 0

Myrne Stol
Myrne Stol

Reputation: 11438

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”?

Upvotes: 1

robertklep
robertklep

Reputation: 203241

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

Upvotes: 1

Related Questions