Skip to content

Instantly share code, notes, and snippets.

@fiorix
Created June 27, 2014 03:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fiorix/fe0cee2d2fc583f6f56a to your computer and use it in GitHub Desktop.
Save fiorix/fe0cee2d2fc583f6f56a to your computer and use it in GitHub Desktop.
HTTP reverse proxy that uses Redis for vhost routing.
// HTTP reverse proxy that uses Redis for vhost routing.
//
// ADDR=:8080 REDIS=127.0.0.1:6379 go run proxy.go
// redis-cli set localhost:8080 http://sports.yahoo.com
// curl -v localhost:8080
package main
import (
"errors"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"time"
"github.com/fiorix/go-redis/redis"
)
func main() {
http.HandleFunc("/", ProxyHandler)
http.ListenAndServe(os.Getenv("ADDR"), nil)
}
var rc = redis.New(os.Getenv("REDIS"))
var err503 = errors.New(http.StatusText(http.StatusServiceUnavailable))
func ProxyHandler(w http.ResponseWriter, r *http.Request) {
u, err := getURL(r)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
r.Host = u.Host
st := time.Now()
httputil.NewSingleHostReverseProxy(u).ServeHTTP(w, r)
log.Printf("Proxied %s%s for %s in %s",
u, r.URL.Path, r.RemoteAddr, time.Since(st),
)
}
func getURL(r *http.Request) (*url.URL, error) {
targetURL, err := rc.Get(r.Host)
if err != nil {
return nil, err
}
if len(targetURL) == 0 {
return nil, err503
}
return url.Parse(targetURL)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment