package web import ( "fmt" "log" "net/http" "net/http/httputil" "net/url" "time" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/spf13/viper" "git.jmbit.de/jmb/podterminal/pods" ) func createReverseProxy(backendService string) (*httputil.ReverseProxy, error) { var err error log.Println("Creating reverse Proxy for ", backendService) backendURL, err := url.Parse(backendService) if err != nil { log.Printf("Could not parse backend URL: %v", err) } proxy := &httputil.ReverseProxy{ Rewrite: func(request *httputil.ProxyRequest) { request.SetURL(backendURL) request.Out.Host = request.In.Host }, // ModifyResponse: func(response *http.Response) error { // if response.StatusCode == http.StatusBadGateway { // waitForAnswer(backendURL.String()) // response.StatusCode = 200 // response.Header.Set("Location", "/") // } // return nil // }, } return proxy, err } func containerProxy(c *gin.Context) { session := sessions.Default(c) sessionID := "" if session.Get("ct") == nil { session.Set("ready", false) session.Save() log.Println("Creating Container for Session ", sessionID) ct, err := pods.CreateContainer() session.Set("ct", ct) session.Save() if err != nil { c.HTML(500, "Error", fmt.Sprintf("[%s] Could not create Container: %v", sessionID, err)) session.Delete("ct") session.Save() c.Abort() return } err = pods.StartContainer(ct) if err != nil { c.HTML(500, "Error", fmt.Sprintf("[%s] Could not start Container: %v", sessionID, err)) session.Delete("ct") session.Save() c.Abort() return } ctip, err := pods.GetContainerIP(ct) if err != nil { c.HTML(500, "Error", fmt.Sprintf("[%s] Could not get Container ip: %v", sessionID, err)) session.Delete("ct") session.Save() c.Abort() return } // Soft fail Skel // _ = pods.CopySkelToContainer(ct) err = waitForAnswer(fmt.Sprintf("http://%s:%d", ctip, viper.GetInt("container_port"))) proxies[ct], err = createReverseProxy( fmt.Sprintf("http://%s:%d", ctip, viper.GetInt("container_port")), ) if err != nil { c.HTML( 500, "Error", fmt.Sprintf("[%s] Could not create Container Proxy: %v", sessionID, err), ) session.Delete("ct") session.Save() c.Abort() return } if err != nil { c.HTML( 500, "Error", fmt.Sprintf("[%s] Timed out waiting for Container: %v", sessionID, err), ) session.Delete("ct") session.Save() c.Abort() return } session.Set("ready", true) session.Save() c.HTML(200, "", clientReloadContent) return } else { if session.Get("ready").(bool) == false { time.Sleep(2 * time.Second) c.Redirect(307, "/") return } id := session.Get("ct").(string) proxy := proxies[id] if proxy != nil { proxy.ServeHTTP(c.Writer, c.Request) } else { session.Delete("ct") session.Delete("ready") session.Save() c.Abort() return } } } func waitForAnswer(url string) error { retries := 0 var err error for retries < 50 { err = nil response, err := http.Get(url) if err != nil { log.Printf("Error connecting to %s: %v", url, err) } if response.StatusCode == 200 { return nil } retries++ time.Sleep(500 * time.Millisecond) } log.Println("Timed out waiting for Container") return err }