Search code examples
ruby-on-railspuma

Differentiate incoming requests by bound port using rails and puma


I have a single rails app with two APIs --- one public and one private. Using puma, I have bound this app to ports 3000 and 3001. I have an internal IP address in my google VPC bound to the VM of the rails app on port 3000, and a public IP address bound to port 3001.

What I expected was to be able to understand which source a request came from based on that listener port, but requests only know about the port in the URL, so it's always listed at 80. All requests are coming through a GKE load balancer, so the REMOTE_IP header is always the same.

The only way I've been able to get my desired functionality is by starting two instances of the app, binding one port each, and including an environment variable.

Is it possible to differentiate requests based on the port they were bound to? This would allow me to use one instance of the app instead of two.


Solution

  • I realized I was looking in the wrong place. It doesn't make sense to generate HTTP headers when I was passing data within the same process. I found the data I wanted in the massive request object from inside application controller.

    request.headers['puma.socket'].addr
    # => ["AF_INET", 3001, "127.0.0.1", "127.0.0.1"]
    

    So I have used this to implement the authorization I was looking for:

    case request.headers['puma.socket'].addr[1]
    when 3000 then :private
    when 3001 then :public
    else :unknown