DEV Community

Cover image for Reverse proxy in Go
Another
Another

Posted on

Reverse proxy in Go

#go

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.

Reverse Proxy

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.

Forward Proxy

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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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:

Reverse proxy server

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:

Reverse proxy client

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)