118 lines
2.5 KiB
Go
118 lines
2.5 KiB
Go
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.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(1 * 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)
|
|
}
|
|
|
|
}
|