hapi — Detect and Get the Client IP Address

The Future Studio team (and company) is based in Germany and due to that fact, we needed to comply the VAT rules of the European Union while launching the Future Studio University. Precisely, because we’re located inside the EU, we need to make sure everyone enrolling from a EU country needs to pay the VAT rate of that country.

Well, you already did the catch in your mind that the location is somewhat related to the user’s IP address. To determine your location, we use IP geo location and preselect your country within the enrollment form. We’ve published an open source hapi plugin called hapi-geo-locate that adds the geo-location functionality to your hapi project.

This guide shows you how to access the client IP address in two different ways: running your hapi server with and without a reverse proxy.

Before jumping right into the technical details, have a look at other tutorials within this extensive hapi series.

hapi Series Overview

Detect the Client IP Address

There’s a straight forward way to determine the user’s IP address from a given request. The request.info object provides information about the incoming request and includes details like the received time, host and hostname and also the remoteAddress which includes the user’s IP as a value.

server.route({  
  method: 'GET',
  path: '/',
  handler: function (request, reply) {
    const ip = request.info.remoteAddress
    return reply('client IP: ' + ip)
  }
})

That’s it, you’ve the client IP address available for further processing. Ok, to be honest: this isn’t the way that works in all setups. We need to have a look at proxied requests as well. But before diving into that, you can test the code snippet from above.

If you want to verify this functionality, run a sample hapi server with the route from above and request it right from your local machine. You’ll see the 127.0.0.1 result for the user’s IP address within request.info.remoteAddress. If you access the same server from your phone within your private home network, you’ll see the phone’s IP address which is different from 127.0.0.1.

There’s a downside of this approach when running your hapi server behind a reverse proxy: the proxy will be the client and therefore all your requests would have the IP address of your proxy. Read on to get the trick on how to get the user’s IP address in those situations.

Client IP Address Behind a Reverse Proxy

A setup where the hapi server runs behind a reverse proxy (like nginx) requires extra programming effort to extract the correct client IP address. Because the proxy is the termination to the Internet and forwards the request internally, you’ll receive the proxy’s IP address within request.info.remoteAddress for all requests.

That’s why proxies offer the feature to store the actual request IP address within an HTTP header. Using nginx as an example, you’d either check within your hapi server for request headers like x-forwarded-for or real_ip. That depends on your nginx configuration and is beyond the scope of this tutorial. Here, we’re focused on the hapi configuration.

The proxied header (e.g. x-forwarded-for) includes the client IP and all proxy IPs the request went through in a comma separated list. The user’s IP is at the first position:

'x-forwarded-for': '1.2.3.4, 5.6.7.8, 10.11.12.13'  

In the example above, 1.2.3.4 is the user’s IP address and 5.6.7.8 and 10.11.12.13 are IP addresses from proxy servers your request went through on its way to your application.

To extract the user’s IP address from the forwarded reverse proxy header, you need to fetch the first address:

server.route({  
  method: 'GET',
  path: '/',
  handler: function (request, reply) {
    const xFF = request.headers['x-forwarded-for']
    const ip = xFF ? xFF.split(',')[0] : request.info.remoteAddress

    return reply('client IP: ' + ip)
  }
})

The code snippet above combines both ways to fetch the client IP: the proxy header and hapi’s remoteAddress.

Please notice that a value received within the proxied header is preferred over the IP provided by hapi. And the reason for that: hapi will always provide an IP address but it’s not always the correct one.

You can simply adjust the header to your needs if you’re behind another reverse proxy or web server.

Outlook

In situations where you need to rely on the user’s IP address, it’s important to make sure you’re actually determining the correct one. Depending on your setup, please have the functionality in place to get the correct IP address even though your hapi server runs behind a reverse proxy.

We’re happy to hear your thoughts and comments. Please don’t hesitate to use the comments below or find us on Twitter @futurestud_io. Let us know what you think!

Enjoy coding & make it rock!


Additional Resources

  • hapi-geo-locate plugin to geo locate requests by IP address and provide request.location within your route handlers

Explore the Library

Find interesting tutorials and solutions for your problems.