Build Simple Proxy in Golang Based on XML Request

qomarullah
3 min readNov 24, 2018

Just story

Photo by Paulius Dragunas on Unsplash

A few days ago, I got challenged to move some features from the old system to the new backend system. Because this is a partial migration so we need to route several existing API services to the other endpoint. Basically, we can use haproxy or nginx as a proxy to route endpoint based on location path (eg Http: // xxxx / endpoint-A, http: // xxxx / endpoint-B) but another challenges is we have to route based on content request.

Therefore we have to build a proxy service that has the capabilities to intercept payload and forward the request based on its payload.

Client → Proxy → Server A Or Server B

The proxy serves request body in form XML (soap message). Proxy reads the entire body to get a specific value of a field. Then we compare this value with parameters that already defined in config file.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns6:Request
<Header>
<Version>1.0</Version>
<CommandID>PreValidation</CommandID>
<LanguageCode>id</LanguageCode>
<ConversationID>1234</ConversationID>
<KeyOwner>1</KeyOwner>
<Timestamp>20181107114023</Timestamp>
</Header>
<Body>
....
</Body>
</ns6:Request>
</soap:Body>
</soap:Envelope>

I found this article near to my solution problem, i use it as core solution, so you can jump to this article or continue with my version. the different is about parsing JSON format, and i add some simple feature how to monitoring this proxy.

Frontend Server

Start the server

This is sample code we can start the server, all request will be pass to handleRequestAndRedirect in line 2.

2. Parse Body Request

Because my specific problem is routing based on content XML, this code shows how to parse XML in go. We can learn from it that every part level XML should be defined in each struct.

below is tools to generate struct from XML or JSON

3. Backend Proxy !!

This is the main function reverse proxy

4. Configuration

As we plan before, we will route the correct endpoint based on parameter from config file. So we can use some library to load variable from config file,

go get github.com/subosito/gotenv

example config file in .env

PORT=8080
RTO=10000
WTO=15000
PREVALIDATION=”http://localhost:8081"
DEFAULT_URL=”http://localhost:8082"

5. Monitoring

This is simplest way to monitor metric is use expvar, it can be use for monitoring metric cpu, memmory or even our custom variable metric like counter or latency of functions.

This metric then can be export to show in dashboard monitoring (ex. using promotheus and grafana). For simple test monitor monitoring we also can use this tool expvarmon

go get github.com/divan/expvarmon

with starting command like this

expvarmon -ports=”8080" -vars=”elapsed,succeed,failed,mem:memstats.Alloc,mem:memstats.Sys,mem:memstats.HeapAlloc,mem:memstats.HeapInuse,duration:memstats.PauseNs,duration:memstats.PauseTotalNs”

Thanks for reading.. You can see this project on https://github.com/qomarullah/proxy-content

Bye..

Refference

https://coderwall.com/p/cp5fya/measuring-execution-time-in-go

https://github.com/divan/expvarmon

https://medium.com/r/?url=https%3A%2F%2Fhackernoon.com%2Fwriting-a-reverse-proxy-in-just-one-line-with-go-c1edfa78c84b

--

--