YML Innovation Lab
Published in

YML Innovation Lab

Reverse Proxy In Go

In computer networks, a reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client as if they originated from the Web server itself. Contrary to a forward proxy, which is an intermediary for its associated clients to contact any server, a reverse proxy is an intermediary for its associated servers to be contacted by any client.

There are many tools like Fiddler, Tinyproxy which can help you to do that and mainly used for debugging the web.

Reverse proxy with some modification can help to modify/filter/route the request to fetch resource. If you have many services running in a same instance then you can use the reveres proxy to route the appropriate request to appropriate resource.

Goal

This post which is kind of tutorial will explain the things involved to develop the reverse proxy which will intercept the http calls, print request / response body and help in performance analysis through response time etc.

Don’t know Go

If you want to learn and try out this one, learn go lang from here.

Packages

Golang comes with packages to build up nice apps. For Reverse Proxy we have to play with http package.

Go’s Http Package

Golang’s net/http pkg comes with most of implementations that are required for Client-Server communications. All you need to do is understand the functionality and use it whenever it is required.

There is singleHostReverseProxy function already.

func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy

We just need to send a url to the function which return reverseProxy.

func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

Then if we call ServeHTTP function,it will the http request to appropriate service. That’s it. Let’s try in deep now.

Use Case

Suppose you have a service which is accessible through http at some port, but you don’t want it to be exposed or you want to add some custom rules or you want to do some performance analysis on the interface then you can use the Reverse Proxy.

Implementation

In this example, we will demonstrate role of our reverse proxy by forwarding all web request from server one (running on arbitrary 9090 port) to another server somewhere, let’s say http://127.0.0.1:8080

  • Reverse proxy golang server will be running at 9090 port.
  • All request made to the server will be transparently forward to targeted webserver and response sent to first server.
  • Before forwarding the request, Request body will be captured. Thanks to ReadAll and NopCloser functions of ioutil pkg which helps to copy the request body without modifying the request buffer.
  • We also captured the time took by original webserver for serving the request for every path.

Routing Traffic

Let’s have a simple struct called Prox which will be handling the business logic of Reverse Proxy.

Here are some examples of struct usage and pointers method receivers with Go receivers.

Simple Proxy

As you can see there is no much code. We just need to send the target url and NewProxy function will return a Prox struct object.

Since we wanted to capture the request/response body or add some custom rules for every request we have to alter the transport interface. So we created our own RoundTrip function of transport and assigned it to the proxy.Transport we created before.

Thanks to time package of Go, We can measure time taken by the function, in our case response time from the original server. We modified our Roundtrip function to measure the time taken for each path. We added code such that for a particular path we have the number of http calls made, time taken for all the calls, average time etc.

Main Go File

Go’s Flag pkg helps to accept the command line arguments while running the program. We can set http port (Where the proxy server will be running) and Redirect url (Where the http request needs to be routed) through command line arguments.

If the arguments are not set while running the program , default port set is 9090 and the requests will be routed to the http://127.0.0.1:8080.

If you would like to try please go through the source code in Github from here.

Run Command

If you want to host ReverseProxy on 9090 and redirect the request to the port 5000 , run following command

./ReverseProxy -port=9090 -url=http://localhost:5000

or

./ReverseProxy

Output

When you run the ReverseProxy server, It will print the port where Reverse Proxy is running and where it is redirecting the request to.

Following screenshot shows the things that are captured after making one of the login POST request through reverse proxy.

That’s it !!

Future Scope

We were inspired by a tool called ngrok — A tool help you expose local internet to public internet. Our goal is some what similar to that of ngrok tool with some major improvements.

Until next time , happy coding!!

References

https://en.wikipedia.org/wiki/Reverse_proxy

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store