The story goes that we have a web-app running on AWS Elastic Container Service in a Docker container and is served with nginx. It is exposed to the internet via a public-facing load balancer.
We also have an API service in another container that the web-app will have to access to perform some tasks. It is resolved in an internal/private load balancer. Now if we were to call the API directly with the internal load balancer API URI, we will get a CORS issue as it’s trying to access something on a different domain.
Creating a proxy_pass
To fix this, we create a rule in the nginx.conf
of the web-app to proxy a path of the nginx server of the web-app to point to the internal load balancer API URI which will be used by the app to access the API.
location /some-service-api/ {
proxy_pass http://internal-load-balancer-url/some-service-api/;
}
Stale IP
This looks fine and dandy, however an issue will arise when the container has been running for a certain period of time. The IP address that is resolved when we pass the URI to proxy_pass will become stale as the IP address of the load balancer is dynamic in AWS. Therefore the location will be pointing to a stale IP that is no longer in use.
Resolving dynamic IP address of load balancer URI
To fix the above issue, we add a resolver IP address which will be the IP in your internal network VPC. Then we create a variable and set it to the URI and pass that variable into proxy_pass
. This will make the IP address be dynamically resolved so that the location will always be pointing to the correct IP address of your internal load balancer.
location /some-service-api/ {
resolver 10.1.0.2;
set $some_service_uri_var http://internal-load-balancer-url/some-service-api/;
proxy_pass $some_service_uri_var;
}
Great, that works, but now if your API has endpoint paths, you may start getting 404s.
The final fix (I promise) – getting path parameters
To fix, we need to grab the path parameters by first using a nginx global variable: $request_uri
which contains the path of the request (e.g. /some-service-api/users?id=2). We then grab everything after the first trailing slash and put it in a $path_remainder
variable. Then when we set the internal load balancer API URI variable, we append the $path_remainder
then pass the final variable into proxy_pass
.
location /some-service-api/ {
resolver 10.1.0.2;
if ($request_uri ~* "/some-service-api/(.*$)") {
set $path_remainder $1;
}
set $some_service_uri_var http://internal-load-balancer-url/some-service-api/$path_remainder;
proxy_pass $some_service_uri_var;
}
Okay, we’re done. Hope you find this useful and that Google will point more people like you here who are having this issue as I had to look deep and hard and go through many sources to combine the knowledge to put this solution together. Also, forgive my lack of in-depth knowledge in nginx as I’m still a bit of a n00b ;). Cheers.
Recent Comments