Recently I ran into a situation where I wanted to proxy the calls made by a client application (i.e. javascript AJAX calls) for a web application that was hosted on another machine.
So the configuration looked something like below:
https://www.mywebsite.com -> user machine (javascript) -> https://api.mywebsite.com/api-1/endpoint
I didn't want to run "www.mywebsite.com" code on my machine, I wanted to run the deployed website in my browser, but I wanted all calls to "api.mywebsite.com/api-1" to be routed to my local development environment so I could either debug or mock the API responses as I wanted.
The solution comprised of 3 basic elements:
- An Nginx reverse proxy running in Docker on my machine
- Self signed SSL certificates for TLS termination in Nginx
- Running Chrome with custom host resolver rules (this could also be done in /etc/hosts but I only wanted a temporary solution)
If your API calls don't use HTTPS then you don't need the TLS termination, but in my case I do need it so I created some self-signed certificates that I will later trust within Chrome:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx-selfsigned.key -out nginx-selfsigned.crt
Now create a reverse-proxy Nginx configuration file, like below:
server {
listen 0.0.0.0:80;
listen 0.0.0.0:443 ssl;
server_name host.docker.internal;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
location /api-1/ {
proxy_pass http://host.docker.internal:5001/;
}
}
This essentially now routes the traffics from "https://localhost/api-1" to "http://host-machine:5001/" which is where I can run the development mode API.
With those things in place, whenever I want to the run the deployed website against my local machine APIs, I can use the below commands:
docker run --rm \
-p 80:80 -p 443:443 \
--name nginx-reverse-proxy \
--add-host=host.docker.internal:host-gateway \
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf \
-v $(pwd)/nginx-selfsigned.crt:/etc/ssl/certs/server.crt \
-v $(pwd)/nginx-selfsigned.key:/etc/ssl/certs/server.key \
nginx &
google-chrome https://www.mywebsite.com/ --host-resolver-rules="MAP api.mywebsite.com 127.0.0.1"
The first time you run it, Chrome won't trust your SSL certs, but if you open an API URL in a new tab and manually trust it, then the clientside calls will work :)