Skip to content

Instantly share code, notes, and snippets.

@pranavraja
Created February 27, 2014 03:32
Show Gist options
  • Save pranavraja/9243868 to your computer and use it in GitHub Desktop.
Save pranavraja/9243868 to your computer and use it in GitHub Desktop.
Go proxy server
package main
import (
"flag"
"fmt"
"io"
"net/http"
"net/url"
"strings"
)
func copyHeader(to, from http.Header) {
for hdr, items := range from {
for _, item := range items {
to.Add(hdr, item)
}
}
}
func extractPath(uri string) string {
u, err := url.Parse(uri)
if err != nil {
return "/"
}
return strings.Split(uri, u.Host)[1]
}
type Proxy struct{}
var prefix, replacement string
func preProcess(r *http.Request) {
if prefix != "" && strings.HasPrefix(r.RequestURI, prefix) {
newUri := strings.Replace(r.RequestURI, prefix, replacement, 1)
r.RequestURI = newUri
u, _ := url.Parse(newUri)
r.URL = u
}
}
func (p Proxy) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Apply modifications to the request beforehand
preProcess(req)
// Work around Go aggressively unescaping the URL path
// e.g. a%2Fb and a/b would previously be indistinguishable,
// which can cause issues.
//
// Consider lyrics.com/artists/AC%2FDC/
//
req.URL.Opaque = extractPath(req.RequestURI)
res, err := http.DefaultTransport.RoundTrip(req)
if err != nil {
fmt.Printf("[%d] %s\n", http.StatusBadGateway, req.RequestURI)
w.WriteHeader(http.StatusBadGateway)
return
}
copyHeader(w.Header(), res.Header)
w.WriteHeader(res.StatusCode)
if res.Body != nil {
io.Copy(w, res.Body)
}
fmt.Printf("[%d] %s\n", res.StatusCode, req.RequestURI)
}
func init() {
flag.StringVar(&prefix, "prefix", "", "URL prefix to match")
flag.StringVar(&replacement, "replacement", "", "URL prefix to replace with")
}
func main() {
flag.Parse()
http.ListenAndServe(":8080", new(Proxy))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment