Reverse proxy
A reverse proxy is a type of proxy server that receives a request from a client, forwards it to one or more servers, and relays the response back to the client.
The distinguishing feature of a reverse proxy is that it acts as the entry point for the user's connection to the servers, with which the proxy itself is connected by business logic. It determines which servers the client's request will be forwarded to. The logic of the network behind the proxy remains hidden from the user.
For comparison, a regular (or forward) proxy connects its clients to any server they need. In this case, the proxy sits in front of the user and simply acts as an intermediary in executing the request.
For what purpose to use it
The reverse proxy concept can be applied in various situations:
- Load balancing
- A/B testing
- Resource caching
- Request data compression
- Traffic filtering
- Authorization
Of course, the scope of application is not limited to these six points. The very fact that it's possible to process a request both before and after proxying provides ample room for creativity.
Realization
target := "https://jsonplaceholder.typicode.com"
remote, err := url.Parse(target)
Setting up the target:
- We define where requests will be forwarded to (JSONPlaceholder API)
- url.Parse() converts the string URL into a *url.URL struct
proxy := httputil.NewSingleHostReverseProxy(remote)
Creating the proxy:
- NewSingleHostReverseProxy creates a reverse proxy that forwards requests to the specified URL
- It handles all the complex stuff: copying headers, managing connections, streaming responses
- This one line gives us a fully functional reverse proxy
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.Host = remote.Host
proxy.ServeHTTP(w, r)
}
The request handler:
- http.HandleFunc("/", ...) - registers a handler for all routes (/ matches everything)
- r.Host = remote.Host - CRITICAL LINE! Changes the Host header to match the target server. Without this, the target server sees the request as coming from localhost:4000 and may reject it.
- proxy.ServeHTTP(w, r) - forwards the modified request to the target and sends the response back
http.ListenAndServe(":4000", nil)
Starting the server:
- http.ListenAndServe(":4000", nil) - starts HTTP server on port 4000
- The nil means "use the default router" (where we registered our handler)
Demonstration of Operation
Let's start our proxy server and verify its operation. In the first screenshot, we see the startup process and request handling:
The proxy has successfully started, is listening on port 4000, and is ready to forward requests to the JSONPlaceholder test API.
Now let's make a request to our proxy using curl:
It can be seen that the request has been received
Conclusion
In this article, we have thoroughly explored what a reverse proxy is, why it's needed, and how to implement it in Go. In practice, we created a working proxy server that forwards requests to an external API, logs them, and returns the response to the client.
The source code
The full project code is available on GitHub: https://github.com/Lemper29/ReverseProxyGo




Top comments (0)