plugins/viewhtml: add image proxy
This commit is contained in:
parent
8c4fd20e27
commit
a8a3c82579
2 changed files with 72 additions and 8 deletions
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -80,8 +80,10 @@ func (san *sanitizer) sanitizeImageURL(src string) string {
|
|||
return "about:blank"
|
||||
}
|
||||
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
// TODO: mid support?
|
||||
if !strings.EqualFold(u.Scheme, "cid") || san.msg == nil {
|
||||
case "cid":
|
||||
if san.msg == nil {
|
||||
return "about:blank"
|
||||
}
|
||||
|
||||
|
@ -91,6 +93,19 @@ func (san *sanitizer) sanitizeImageURL(src string) string {
|
|||
}
|
||||
|
||||
return part.URL(true).String()
|
||||
case "https":
|
||||
if !proxyEnabled {
|
||||
return "about:blank"
|
||||
}
|
||||
|
||||
proxyURL := url.URL{Path: "/proxy"}
|
||||
proxyQuery := make(url.Values)
|
||||
proxyQuery.Set("src", u.String())
|
||||
proxyURL.RawQuery = proxyQuery.Encode()
|
||||
return proxyURL.String()
|
||||
default:
|
||||
return "about:blank"
|
||||
}
|
||||
}
|
||||
|
||||
func (san *sanitizer) sanitizeCSSDecls(decls []*css.Declaration) []*css.Declaration {
|
||||
|
|
Loading…
Reference in a new issue