package main import ( "bytes" "io" "io/ioutil" "log" "mime" "net/http" "net/url" "path" "strings" "github.com/gin-gonic/gin" ) var ( BaseURL = "/" DevProxy string indexTmpl []byte ) func getIndexHtml(w io.Writer, file io.Reader) []byte { if indexTmpl, err := ioutil.ReadAll(file); err != nil { log.Println("Cannot read whole index.html: ", err) return nil } else { good_base := []byte(path.Clean(path.Join(BaseURL+"/", "nuke"))[:len(path.Clean(path.Join(BaseURL+"/", "nuke")))-4]) indexTmpl = bytes.Replace( bytes.Replace( bytes.Replace( indexTmpl, []byte(``), []byte(``), -1, ), []byte("\"/_app/"), append([]byte("\""), append(good_base, '_', 'a', 'p', 'p', '/')...), -1, ), []byte("base: \""), append([]byte("base: \""), good_base[:len(good_base)-1]...), -1, ) w.Write(indexTmpl) return indexTmpl } } func serveOrReverse(forced_url string, baseURL string) func(c *gin.Context) { return func(c *gin.Context) { if DevProxy != "" { if u, err := url.Parse(DevProxy); err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) } else { if forced_url != "" { u.Path = path.Join(u.Path, forced_url) } else { u.Path = path.Join(u.Path, strings.TrimPrefix(c.Request.URL.Path, baseURL)) } if r, err := http.NewRequest(c.Request.Method, u.String(), c.Request.Body); err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) } else if resp, err := http.DefaultClient.Do(r); err != nil { http.Error(c.Writer, err.Error(), http.StatusBadGateway) } else { defer resp.Body.Close() for key := range resp.Header { c.Writer.Header().Add(key, resp.Header.Get(key)) } c.Writer.WriteHeader(resp.StatusCode) if r.URL.Path == path.Join(u.Path, "/") { getIndexHtml(c.Writer, resp.Body) } else { io.Copy(c.Writer, resp.Body) } } } } else { if forced_url != "" { c.Request.URL.Path = forced_url } else { c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, baseURL) } if c.Request.URL.Path == "/" { if len(indexTmpl) == 0 { if file, err := Assets.Open("index.html"); err != nil { log.Println("Unable to open index.html: ", err) } else { defer file.Close() indexTmpl = getIndexHtml(c.Writer, file) } } else { c.Writer.Write(indexTmpl) } } else if baseURL != "/" { if file, err := Assets.Open(c.Request.URL.Path); err != nil { http.FileServer(Assets).ServeHTTP(c.Writer, c.Request) } else { defer file.Close() c.Writer.Header().Add("Content-Type", mime.TypeByExtension(path.Ext(c.Request.URL.Path))) getIndexHtml(c.Writer, file) } } else { http.FileServer(Assets).ServeHTTP(c.Writer, c.Request) } } } } func declareStaticRoutes(router *gin.RouterGroup, baseURL string) { router.GET("/", serveOrReverse("", baseURL)) router.GET("/exercices", serveOrReverse("/", baseURL)) router.GET("/exercices/*_", serveOrReverse("/", baseURL)) router.GET("/export", serveOrReverse("/", baseURL)) router.GET("/teams", serveOrReverse("/", baseURL)) router.GET("/teams/*_", serveOrReverse("/", baseURL)) router.GET("/themes", serveOrReverse("/", baseURL)) router.GET("/themes/*_", serveOrReverse("/", baseURL)) router.GET("/_app/*_", serveOrReverse("", baseURL)) router.GET("/.svelte-kit/*_", serveOrReverse("", baseURL)) router.GET("/node_modules/*_", serveOrReverse("", baseURL)) router.GET("/@vite/*_", serveOrReverse("", baseURL)) router.GET("/@fs/*_", serveOrReverse("", baseURL)) router.GET("/@id/*_", serveOrReverse("", baseURL)) router.GET("/src/*_", serveOrReverse("", baseURL)) }