Skip to content

Instantly share code, notes, and snippets.

@ericchiang
Created November 28, 2014 16:01
Show Gist options
  • Save ericchiang/52102659be8d2b10a52a to your computer and use it in GitHub Desktop.
Save ericchiang/52102659be8d2b10a52a to your computer and use it in GitHub Desktop.
HTTP Proxy Pass
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
"sync"
)
type RoundRobinner struct {
handlers []*httputil.ReverseProxy
next int
lock *sync.Mutex
}
// By defining this function we can use RoundRobiner as an http.Handler
func (rr *RoundRobinner) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if len(rr.handlers) == 0 {
http.Error(w, "404 not found", http.StatusNotFound)
return
}
rr.lock.Lock()
handler := rr.handlers[rr.next]
rr.next = (rr.next + 1) % len(rr.handlers)
rr.lock.Unlock()
handler.ServeHTTP(w, r)
}
// NewRoundRobiner returns an http.Handler which round robins evenly to the
// provided urls.
func NewRoundRobinner(urls []*url.URL) *RoundRobinner {
handlers := make([]*httputil.ReverseProxy, len(urls))
for i := range urls {
handlers[i] = httputil.NewSingleHostReverseProxy(urls[i])
}
var mutex sync.Mutex
return &RoundRobinner{handlers: handlers, next: 0, lock: &mutex}
}
// StartListeners starts serves on given ports which print the port they're running on
func StartListeners(ports []string) error {
listenErrors := make(chan error)
for _, port := range ports {
handler := func(port string) http.Handler {
handlerFunc := func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("You are currently being served by port: " + port))
}
return http.HandlerFunc(handlerFunc)
}(port)
go func(port string, h http.Handler) {
listenErrors <- http.ListenAndServe(":"+port, h)
}(port, handler)
}
return <-listenErrors
}
func main() {
host := "127.0.0.1"
ports := []string{"3031", "3032", "3033"}
urls := make([]*url.URL, len(ports))
var err error
for i := range urls {
urls[i], err = url.Parse("http://" + host + ":" + ports[i] + "/")
if err != nil {
log.Fatal(err)
}
}
rr := NewRoundRobinner(urls)
go func() {
log.Fatal(StartListeners(ports))
}()
log.Fatal(http.ListenAndServe(":3034", rr))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment