While HaProxy has many uses, I’ll show how HaProxy can act as HTTP proxy. Why might you need it? For example, in order to forward HTTP traffic between 2 unreachable networks. As always, Docker will help us to raise a fully functional demo. Keep reading to find out how 🙂
Install on your machine:
The tutorial assumes familiarity with:
- basic HaProxy functionality.
- basic git, docker and docker-compose commands.
In short, we’ll have 2 networks A and B. Network A includes HTTP client which wants to access HTTP server in Network B. Sadly, 2 networks are unreachable. However, there’s a green host which belongs to both networks. What can we do to connect both networks? There could be many solutions, of course. I’ve chosen HTTP proxy one. To demonstrate the idea, we’ll use HaProxy. Specifically, it will forward requests from HTTP client in network A to HTTP server in network B.
To illustrate the architecture, see simple diagram below:
HaProxy as HTTP proxy demo
As always, clone sample project from my github. Compose file describes our architecture.
There I defined 3 services:
c. Below, we’ll describe each in short.
Our HTTP client is a basic Python HTTP client based on
requests library. We would like to test that HaProxy forwards requests to
http_server . To this end, let’s send single request to our proxy using
import requests if __name__ == '__main__': r = requests.get('http://http_proxy') print(r.text)
Next, we have
http_server. To simplify things, I selected HashiCorp HTTP echo server which is based on
hashicorp/http-echo docker image. As the name suggests, it returns the text it was started with. Naturally, I’ve started it with
hello world text, as you can see in
command . Note that HTTP server listensat port 5678.
HaProxy as HTTP proxy
Lastly, we have HaProxy named as
http_proxy in Compose file. You can find HTTP proxy configuration in
haproxy.cfg mapped to
http_proxy service using Docker Volumes.
The most interesting configuration is below:
frontend myfrontend bind :80 default_backend demo_server backend demo_server http-request set-header Host http_server server demo_server http_server:5678 check
As you can see, HaProxy just forwards all HTTP requests it receives on port 80 to
http_server at port 5678. Note that HaProxy connects to HTTP server by service name.
Let’s raise our demo stack using
docker-compose -p demo up http_client command. As expected, our HTTP client gets
hello world text in the response.
Creating network "demo_default" with the default driver Creating demo_http_server_1 ... done Creating demo_http_proxy_1 ... done Creating demo_http_client_1 ... done Attaching to demo_http_client_1 http_client_1 | "hello world" http_client_1 | demo_http_client_1 exited with code 0
Note that while we start just
http_client in the above command, all services are started. Why? Because,
depends_on in Compose file guarantees desired services start order. Of course, start order may not be enough for the success of HTTP request, as
http_proxy may not be available for some time after start. More advanced usage of
depends_on may help. See this answer for more details.
Thanks for your attention! As always, feel free to share and comment.
Bonus: Watch recommended HTTP courses on Pluralsight:
Sign up using this link to get exclusive discounts like 50% off your first month or 15% off an annual subscription)
Purchase highly-rated Load Balancing with HAProxy: Open-source technology for better scalability, redundancy and availability in your IT infrastructure book on Amazon.