120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
"github.com/pocketbase/pocketbase"
|
|
"github.com/pocketbase/pocketbase/apis"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
)
|
|
|
|
func main() {
|
|
app := pocketbase.New()
|
|
|
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
|
_, err := e.Router.AddRoute(echo.Route{
|
|
Method: http.MethodGet,
|
|
Path: "/cors",
|
|
Handler: func(c echo.Context) error {
|
|
return corsProxyHandler(c)
|
|
},
|
|
Middlewares: []echo.MiddlewareFunc{
|
|
apis.ActivityLogger(app),
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
|
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
|
// add new "GET /hello" route to the app router (echo)
|
|
e.Router.GET("/*", apis.StaticDirectoryHandler(os.DirFS("./pb_public"), false))
|
|
return nil
|
|
})
|
|
|
|
app.OnFileDownloadRequest().Add(func(e *core.FileDownloadEvent) error {
|
|
|
|
if strings.HasSuffix(e.ServedPath, ".html") {
|
|
e.HttpContext.Response().Header().Set("Content-Disposition", "inline")
|
|
e.HttpContext.Response().Header().Set("Content-Security-Policy", "")
|
|
}
|
|
log.Println(e.ServedPath)
|
|
log.Println(e.HttpContext)
|
|
return nil
|
|
})
|
|
|
|
if err := app.Start(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func corsProxyHandler(c echo.Context) error {
|
|
// Get the target URL from the request query string
|
|
url := c.QueryParam("url")
|
|
if url == "" {
|
|
return c.JSON(http.StatusBadRequest, "url param is required")
|
|
}
|
|
|
|
// Fetch the resource from the target URL
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
return c.JSON(http.StatusInternalServerError, "Failed to fetch the URL")
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// If the content is a .m3u8 file, rewrite the URLs
|
|
if strings.HasSuffix(url, ".m3u8") {
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return c.JSON(http.StatusInternalServerError, "Failed to read response body")
|
|
}
|
|
|
|
proxyBaseURL := c.Scheme() + "://" + c.Request().Host + c.Path() + "?url=" + url[:strings.LastIndex(url, "/")+1]
|
|
|
|
// Rewrite the URLs in the .m3u8 file
|
|
lines := strings.Split(string(bodyBytes), "\n")
|
|
for i, line := range lines {
|
|
if strings.HasSuffix(line, ".ts") {
|
|
lines[i] = proxyBaseURL + line
|
|
}
|
|
}
|
|
modifiedContent := strings.Join(lines, "\n")
|
|
|
|
// Write the modified content to the response
|
|
c.Response().Header().Set("Content-Type", resp.Header.Get("Content-Type"))
|
|
c.Response().WriteHeader(resp.StatusCode)
|
|
_, err = io.Copy(c.Response().Writer, bytes.NewReader([]byte(modifiedContent)))
|
|
if err != nil {
|
|
return c.JSON(http.StatusInternalServerError, "Failed to copy modified response body")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Copy the headers from the fetched response to the proxy response
|
|
for key, values := range resp.Header {
|
|
for _, value := range values {
|
|
c.Response().Header().Add(key, value)
|
|
}
|
|
}
|
|
|
|
// Copy the status code from the fetched response to the proxy response
|
|
c.Response().WriteHeader(resp.StatusCode)
|
|
|
|
// Copy the body from the fetched response to the proxy response
|
|
_, err = io.Copy(c.Response().Writer, resp.Body)
|
|
if err != nil {
|
|
return c.JSON(http.StatusInternalServerError, "Failed to copy response body")
|
|
}
|
|
|
|
return nil
|
|
}
|