Writing a Reverse Proxy in just one line with Go

Ben Church
Jul 12, 2018 · 4 min read

Leave your programming language hang ups at the door and come admire the best standard library I’ve ever come across.

Image for post
Image for post
This is all the code you actually require…

Choosing a Programming Language for a project shouldn’t be like declaring who your favourite team is. it should be a matter of pragmatism and choosing the right tool for the right job.

In this post I want to show you when and why Go shines as a language. Specifically I want to show you how rock solid their standard lib is for basic internet programming. Even more specifically… were gonna write a Reverse Proxy!

“Go has a lot going for it but where it really struts it stuff is in these lower level network plumbing tasks, there’s no better language.”

What is a reverse proxy? A big fancy way of saying a traffic forwarder. I get a request send from a client, send that request to another server, receive a response from the server and forward it back to the client. The reverse part of this simply means the proxy itself determines where to send traffic and when

Image for post
Image for post
Just beautiful 😍…

Why is it useful? Because the concept is so simple it can be applied to assist in many different cases: Load balancing, A/B Testing, Caching, Authentication etc…

By the end of this short post you will have learned how to:

Our Reverse Proxy Project

Lets dive into the actual project. What we are going to do is have a web server that:

1. Takes requests

2. Reads the body of a request, specifically the proxy_condition field

3. If the proxy domain is equal to A send traffic to URL 1

4. If the proxy domain is equal to B send traffic to URL 2

5. If the proxy domain is neither then send traffic to the Default URL.

Prerequisites

Setting up our environment

First thing we want to do is input all the required configuration variables into our environment so that we can both use them in our application while keeping them out of source code.

I find the best approach is to create a .env file that contains the desired environment variables.

Below is what I have for this specific project:

This is a habit I picked up from the 12 Factor App

After you save your .env file you can run:

source .env

to configure load the config into your environment any time.

Laying the foundation of our project

Next lets create a file called main.go that does the following:

1. When started logs the PORT, A_CONDITION_URL, B_CONDITION_URL, and DEFAULT_CONDITION_URL environment variables to the console

2. Listen for requests on the path: /

💀Let’s get the skeletons out of the closet so we can move onto the fun stuff.

Now you should be able to run

Parse the request body

Now that we have the skeleton of our project together we want to start creating the logic that will handle parsing the request body. Start by updating handleRequestAndRedirect to parse the proxy_condition value from the request body.

Basic parsing of a JSON blob to a struct in Go.

Use proxy_condition to determine where we send traffic

Now that we have the value of the proxy_condition from the request we will use it to decide where we direct our reverse proxy to. Remember from earlier that we have three cases:

Reverse Proxy to that URL

Finally we are onto the actual reverse proxy! In so many languages a reverse proxy would require a lot of thought and a fair amount of code or at least having to import a sophisticated library.

However Golang’s standard library makes creating a reverse proxy so simple it’s almost unbelievable. Below is essentially the only line of code you need:

httputil.NewSingleHostReverseProxy(url).ServeHTTP(res, req)

Note that in the following code we add a little extra so it can fully support SSL redirection (though not necessary):

The one time in the project it felt like Go was truly getting out of my way.

Start it all up

Ok now that we have this all wired up setup our application on port 1330 and our 3 simple servers on ports 1331–1333 (all in separate terminals):

2. http-server -p 1331

3. http-server -p 1332

4. http-server -p 1333

With all these up and ruuning we can start to send through a requests with a json body in another terminal like so:

curl --request GET \  --url http://localhost:1330/ \  --header 'content-type: application/json' \  --data '{    "proxy_condition": "a"  }'

If your looking for a great HTTP request client I cannot recommend Insomnia enough.

and Viola we can start to see our reverse proxy directing traffic to one of our 3 servers based on what we set in the proxy_condition field!

Image for post
Image for post
Its alive!!!

Wrap Up

Go has a lot going for it but where it really struts it stuff is in these lower level network “plumbing” tasks, there’s no better language. What we’ve written here is simple, performant, reliable and very much ready for use in production.

For simple services I can see myself reaching for Go again in the future.

🧞‍ This is open source! you can find it here on Github

❤️ I only write about programming and remote work. If you follow me on Twitter I won’t waste your time.

HackerNoon.com

#BlackLivesMatter

Sign up for Get Better Tech Emails via HackerNoon.com

By HackerNoon.com

how hackers start their afternoons. the real shit is on hackernoon.com. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Ben Church

Written by

Building Great Products for Amazing companies 👨‍💻🚀 || Remote Engineering Lead || @bnchrch on twitter || https://ben.church || https://github.com/bechurch

HackerNoon.com

Elijah McClain, George Floyd, Eric Garner, Breonna Taylor, Ahmaud Arbery, Michael Brown, Oscar Grant, Atatiana Jefferson, Tamir Rice, Bettie Jones, Botham Jean

Ben Church

Written by

Building Great Products for Amazing companies 👨‍💻🚀 || Remote Engineering Lead || @bnchrch on twitter || https://ben.church || https://github.com/bechurch

HackerNoon.com

Elijah McClain, George Floyd, Eric Garner, Breonna Taylor, Ahmaud Arbery, Michael Brown, Oscar Grant, Atatiana Jefferson, Tamir Rice, Bettie Jones, Botham Jean

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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