package web import ( "fmt" "log" "net" "net/http/httputil" "net/url" "time" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "github.com/google/uuid" "git.jmbit.de/jmb/podterminal/pods" ) var proxies = make(map[string]*httputil.ReverseProxy) func Run(listener net.Listener) error { router := setupRouter() err := router.RunListener(listener) if err != nil { return err } return nil } func setupRouter() *gin.Engine { gin.ForceConsoleColor() gin.SetMode("release") router := gin.New() store := cookie.NewStore([]byte(uuid.NewString())) router.Use(gin.Recovery()) router.Use(sessions.Sessions("session", store)) router.Use(urlLog()) router.Use(containerProxy) // router.Any("/", containerProxy) return router } func urlLog() gin.HandlerFunc { return func(c *gin.Context) { log.Printf( "[INFO] %s: %s: %s", c.Request.RemoteAddr, c.Request.Method, c.Request.URL, ) } } func createReverseProxy(backendService string) (*httputil.ReverseProxy, error) { var err error backendURL, err := url.Parse(backendService) if err != nil { log.Printf("Could not parees backend URL: %v", err) } proxy := &httputil.ReverseProxy{ Rewrite: func(request *httputil.ProxyRequest) { request.SetURL(backendURL) request.Out.Host = request.In.Host }, } return proxy, err } func containerProxy(c *gin.Context) { session := sessions.Default(c) if session.Get("ct") == nil { ct, err := pods.CreateContainer() if err != nil { c.HTML(500, "Error", fmt.Sprintf("Could not create Container: %v", err)) c.Abort() } err = pods.StartContainer(ct) if err != nil { c.HTML(500, "Error", fmt.Sprintf("Could not start Container: %v", err)) c.Abort() } // Hack to wait for Container to start up and get assigned an IP time.Sleep(3 * time.Second) ctip, err := pods.GetContainerIP(ct) if err != nil { c.HTML(500, "Error", fmt.Sprintf("Could not get Container ip: %v", err)) c.Abort() } proxies[ct], err = createReverseProxy(fmt.Sprintf("http://%s:3000", ctip)) if err != nil { c.HTML(500, "Error", fmt.Sprintf("Could not create Container Proxy: %v", err)) c.Abort() } session.Set("ct", ct) session.Save() c.Redirect(301, "/") } else { sessionID := session.Get("ct") switch sessionID.(type) { case string: default: c.HTML(500, "Error", "SessionID is not a string") c.Abort() } id := session.Get("ct").(string) proxy := proxies[id] proxy.ServeHTTP(c.Writer, c.Request) } }