Created
November 28, 2014 16:01
-
-
Save ericchiang/52102659be8d2b10a52a to your computer and use it in GitHub Desktop.
HTTP Proxy Pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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