Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the full URL for a request in Hapi

Tags:

url

hapijs

In my hapijs app, given a Request object, how can I find the original, unparsed, unmodified URL?

function getRequestUrl (request) {
    return ...; // What goes here?
}

I've found that I can piece it together somewhat from Request.info.host, Request.path, and Request.query, but it lacks the scheme (ie, http vs https), and is a bit of a kludge. Isn't the plain URL available somewhere?

like image 582
gilly3 Avatar asked Aug 05 '15 18:08

gilly3


1 Answers

The full URL isn't stored somewhere you can get it. You need to build it yourself from the parts:

const url = request.connection.info.protocol + '://' + request.info.host + request.url.path;

Even though it might seem kludgey, it makes sense if you think about it because there is no original, unparsed, unmodified URL. The HTTP request that goes over the wire doesn't contain the URL as typed into the browser address bar for instance:

GET /hello?a=1&b=2 HTTP/1.1      // request.url.path
Host: localhost:4000             // request.info.host
Connection: keep-alive
Accept-Encoding: gzip, deflate, sdch
...

And you only know the protocol based on whether the hapi server connection is in TLS mode or not (request.connection.info.protocol).

Things to be aware of

If you check either:

request.connection.info.uri or request.server.info.uri

the reported hostname will be the hostname of the actual machine that the server is running on (the output of hostname on *nix). If you want the actual host the person typed in the browser (which might be different) you need to check request.info.host which is parsed from the HTTP request's Host header)

Proxies and X-Forwarded-Proto header

If your request got passed through a proxy(ies)/load balancers/HTTPS terminators, it's possible somewhere along the line HTTPS traffic got terminated and was sent to your server on an HTTP connection, in this case you'll want use the value of the x-forwarded-proto header if it's there:

const url = (request.headers['x-forwarded-proto'] || request.connection.info.protocol) + '://' + request.info.host + request.url.path;

With template strings:

const url = `${request.headers['x-forwarded-proto'] || request.connection.info.protocol}://${request.info.host}${request.url.path}`;
like image 135
Matt Harrison Avatar answered Oct 16 '22 07:10

Matt Harrison