aboutsummaryrefslogtreecommitdiff
path: root/plugins/viewhtml/plugin.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/viewhtml/plugin.go')
-rw-r--r--plugins/viewhtml/plugin.go49
1 files changed, 49 insertions, 0 deletions
diff --git a/plugins/viewhtml/plugin.go b/plugins/viewhtml/plugin.go
index f22364e..b34372f 100644
--- a/plugins/viewhtml/plugin.go
+++ b/plugins/viewhtml/plugin.go
@@ -1,10 +1,59 @@
package koushinviewhtml
import (
+ "io"
+ "mime"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+
"git.sr.ht/~emersion/koushin"
+ "github.com/labstack/echo/v4"
+)
+
+var (
+ proxyEnabled = true
+ proxyMaxSize = 5 * 1024 * 1024 // 5 MiB
)
func init() {
p := koushin.GoPlugin{Name: "viewhtml"}
+
+ p.GET("/proxy", func(ctx *koushin.Context) error {
+ if !proxyEnabled {
+ return echo.NewHTTPError(http.StatusForbidden, "proxy disabled")
+ }
+
+ u, err := url.Parse(ctx.QueryParam("src"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid URL")
+ }
+
+ if u.Scheme != "https" {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid scheme")
+ }
+
+ resp, err := http.Get(u.String())
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+
+ mediaType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
+ if err != nil || !strings.HasPrefix(mediaType, "image/") {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid resource type")
+ }
+
+ size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
+ if err != nil || size > proxyMaxSize {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid resource length")
+ }
+
+ ctx.Response().Header().Set("Content-Length", strconv.Itoa(size))
+ lr := io.LimitedReader{resp.Body, int64(proxyMaxSize)}
+ return ctx.Stream(http.StatusOK, mediaType, &lr)
+ })
+
koushin.RegisterPluginLoader(p.Loader())
}