Simple Reverse Proxy

1 min read Tweet this post

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.

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"net/http/httputil"
	"net/url"
	"github.com/gookit/goutil/dump"
)

func main() {
	backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		dump.P(r.Header)
		fmt.Fprintln(w, "this call was relayed by the reverse proxy")
	}))
	defer backendServer.Close()

	rpURL, err := url.Parse(backendServer.URL)
	if err != nil {
		log.Fatal(err)
	}
	frontendProxy := httptest.NewServer(&httputil.ReverseProxy{
		Rewrite: func(r *httputil.ProxyRequest) {
      r.SetXForwarded()     // Set X-Forwarded-* headers.
      r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
			r.SetURL(rpURL) // Forward request to rpURL.
		},
	})
	defer frontendProxy.Close()

	resp, err := http.Get(frontendProxy.URL)
	if err != nil {
		log.Fatal(err)
	}

	b, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%s", b)
}

The output from the following example:

 go run main.go
PRINT AT main.main.func1(main.go:16)
http.Header { #len=6
  "X-Forwarded-Proto": []string [ #len=1,cap=1
    string("http"), #len=4
  ],
  "User-Agent": []string [ #len=1,cap=1
    string("Go-http-client/1.1"), #len=18
  ],
  "Accept-Encoding": []string [ #len=1,cap=1
    string("gzip"), #len=4
  ],
  "X-Additional-Header": []string [ #len=1,cap=1
    string("header set by the proxy"), #len=23
  ],
  "X-Forwarded-For": []string [ #len=1,cap=1
    string("127.0.0.1"), #len=9
  ],
  "X-Forwarded-Host": []string [ #len=1,cap=1
    string("127.0.0.1:52180"), #len=15
  ],
},
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.

programming go