Published on

Simple Reverse Proxy

Authors

A server positioned in front of web servers, which relays client requests (such as those made by a web browser) to those web servers, is known as a reverse proxy. These proxies are often utilized to improve security, performance, and dependability.

The example below use 1 web servers backend and 1 as proxy. The proxy for backend will add header information. If we call get request through the frontend server it will call backend server and obviously the header will be updated after the frontend server.


_45
package main
_45
_45
import (
_45
"fmt"
_45
"io"
_45
"log"
_45
"net/http"
_45
"net/http/httptest"
_45
"net/http/httputil"
_45
"net/url"
_45
"github.com/gookit/goutil/dump"
_45
)
_45
_45
func main() {
_45
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_45
dump.P(r.Header)
_45
fmt.Fprintln(w, "this call was relayed by the reverse proxy")
_45
}))
_45
defer backendServer.Close()
_45
_45
rpURL, err := url.Parse(backendServer.URL)
_45
if err != nil {
_45
log.Fatal(err)
_45
}
_45
frontendProxy := httptest.NewServer(&httputil.ReverseProxy{
_45
Rewrite: func(r *httputil.ProxyRequest) {
_45
r.SetXForwarded() // Set X-Forwarded-* headers.
_45
r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
_45
r.SetURL(rpURL) // Forward request to rpURL.
_45
},
_45
})
_45
defer frontendProxy.Close()
_45
_45
resp, err := http.Get(frontendProxy.URL)
_45
if err != nil {
_45
log.Fatal(err)
_45
}
_45
_45
b, err := io.ReadAll(resp.Body)
_45
if err != nil {
_45
log.Fatal(err)
_45
}
_45
_45
fmt.Printf("%s", b)
_45
}

The output from the following example:


_23
❯ go run main.go
_23
PRINT AT main.main.func1(main.go:16)
_23
http.Header { #len=6
_23
"X-Forwarded-Proto": []string [ #len=1,cap=1
_23
string("http"), #len=4
_23
],
_23
"User-Agent": []string [ #len=1,cap=1
_23
string("Go-http-client/1.1"), #len=18
_23
],
_23
"Accept-Encoding": []string [ #len=1,cap=1
_23
string("gzip"), #len=4
_23
],
_23
"X-Additional-Header": []string [ #len=1,cap=1
_23
string("header set by the proxy"), #len=23
_23
],
_23
"X-Forwarded-For": []string [ #len=1,cap=1
_23
string("127.0.0.1"), #len=9
_23
],
_23
"X-Forwarded-Host": []string [ #len=1,cap=1
_23
string("127.0.0.1:52180"), #len=15
_23
],
_23
},
_23
this call was relayed by the reverse proxy

That output show expected results, the response http output from backend server and headers already updated with X-Forwarded-*. I think from the example above can explain how reverse proxy works.