diff --git a/api.go b/api.go index c75d765..5662cc2 100644 --- a/api.go +++ b/api.go @@ -59,6 +59,9 @@ func main() { r.Handle("/sessions/{sessionId}/ws/", server) + // Reverse proxy + r.Host(`{node}.{session}.play-with-docker.com`).Handler(handlers.NewMultipleHostReverseProxy()) + n := negroni.Classic() n.UseHandler(r) diff --git a/handlers/reverseproxy.go b/handlers/reverseproxy.go new file mode 100644 index 0000000..e708b69 --- /dev/null +++ b/handlers/reverseproxy.go @@ -0,0 +1,37 @@ +package handlers + +import ( + "net" + "net/http" + "net/http/httputil" + "strings" + + "github.com/gorilla/mux" +) + +func NewMultipleHostReverseProxy() *httputil.ReverseProxy { + director := func(req *http.Request) { + v := mux.Vars(req) + node := v["node"] + if strings.HasPrefix(node, "ip") { + // Node is actually an ip, need to convert underscores by dots. + ip := strings.Replace(strings.TrimPrefix(node, "ip"), "_", ".", -1) + + if net.ParseIP(ip) == nil { + // Not a valid IP, so treat this is a hostname. + } else { + node = ip + } + } + + // Validate that the node actually exists in the network + // TODO: + + // Only proxy http for now + req.URL.Scheme = "http" + + req.URL.Host = node + } + + return &httputil.ReverseProxy{Director: director} +} diff --git a/services/docker.go b/services/docker.go index 362d91e..39c576c 100644 --- a/services/docker.go +++ b/services/docker.go @@ -52,6 +52,17 @@ func CreateNetwork(name string) error { return nil } +func ConnectNetwork(containerId, networkId string) error { + err := c.NetworkConnect(context.Background(), networkId, containerId, &network.EndpointSettings{}) + + if err != nil { + log.Printf("Connection container to network err [%s]\n", err) + + return err + } + + return nil +} func DeleteNetwork(id string) error { err := c.NetworkRemove(context.Background(), id) diff --git a/services/session.go b/services/session.go index 841fb6d..010c94f 100644 --- a/services/session.go +++ b/services/session.go @@ -109,6 +109,12 @@ func NewSession() (*Session, error) { return nil, err } + // Connect PWD daemon to the new network + if err := ConnectNetwork("pwd", s.Id); err != nil { + log.Println("ERROR NETWORKING") + return nil, err + } + // We store sessions as soon as we create one so we don't delete new sessions on an api restart if err := saveSessionsToDisk(); err != nil { return nil, err