update bluemonday and related deps

This commit is contained in:
Umputun
2021-04-23 03:44:17 -05:00
parent df4b0c80ac
commit 52084e0510
335 changed files with 32184 additions and 8505 deletions
+35
View File
@@ -0,0 +1,35 @@
package rest
import (
"crypto/sha1" //nolint not used for cryptography
"fmt"
"net/http"
"strings"
"time"
)
// CacheControl is a middleware setting cache expiration. Using url+version for etag
func CacheControl(expiration time.Duration, version string) func(http.Handler) http.Handler {
etag := func(r *http.Request, version string) string {
s := fmt.Sprintf("%s:%s", version, r.URL.String())
return fmt.Sprintf("%x", sha1.Sum([]byte(s))) //nolint
}
return func(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
e := `"` + etag(r, version) + `"`
w.Header().Set("Etag", e)
w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d, no-cache", int(expiration.Seconds())))
if match := r.Header.Get("If-None-Match"); match != "" {
if strings.Contains(match, e) {
w.WriteHeader(http.StatusNotModified)
return
}
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
+21
View File
@@ -0,0 +1,21 @@
package rest
import (
"fmt"
"net/http"
"time"
)
// Deprecation adds a header 'Deprecation: version="version", date="date" header'
// see https://tools.ietf.org/id/draft-dalal-deprecation-header-00.html
func Deprecation(version string, date time.Time) func(http.Handler) http.Handler {
f := func(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
headerVal := fmt.Sprintf("version=\"%s\", date=\"%s\"", version, date.Format(time.RFC3339))
w.Header().Set("Deprecation", headerVal)
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
return f
}
+49
View File
@@ -0,0 +1,49 @@
package rest
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
)
// FileServer returns http.FileServer handler to serve static files from a http.FileSystem,
// prevents directory listing.
// - public defines base path of the url, i.e. for http://example.com/static/* it should be /static
// - local for the local path to the root of the served directory
func FileServer(public, local string) (http.Handler, error) {
root, err := filepath.Abs(local)
if err != nil {
return nil, fmt.Errorf("can't get absolute path for %s: %w", local, err)
}
if _, err = os.Stat(root); os.IsNotExist(err) {
return nil, fmt.Errorf("local path %s doesn't exist: %w", root, err)
}
return http.StripPrefix(public, http.FileServer(noDirListingFS{http.Dir(root)})), nil
}
type noDirListingFS struct{ fs http.FileSystem }
// Open file on FS, for directory enforce index.html and fail on a missing index
func (fs noDirListingFS) Open(name string) (http.File, error) {
f, err := fs.fs.Open(name)
if err != nil {
return nil, err
}
s, err := f.Stat()
if err != nil {
return nil, err
}
if s.IsDir() {
index := strings.TrimSuffix(name, "/") + "/index.html"
if _, err := fs.fs.Open(index); err != nil {
return nil, err
}
}
return f, nil
}
+57
View File
@@ -0,0 +1,57 @@
package rest
import (
"context"
"net/http"
"net/url"
"path"
"regexp"
"strings"
)
// Rewrite middleware with from->to rule. Supports regex (like nginx) and prevents multiple rewrites
// example: Rewrite(`^/sites/(.*)/settings/$`, `/sites/settings/$1`
func Rewrite(from, to string) func(http.Handler) http.Handler {
reFrom := regexp.MustCompile(from)
f := func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// prevent double rewrites
if ctx != nil {
if _, ok := ctx.Value(contextKey("rewrite")).(bool); ok {
next.ServeHTTP(w, r)
return
}
}
if !reFrom.MatchString(r.URL.Path) {
next.ServeHTTP(w, r)
return
}
ru := reFrom.ReplaceAllString(r.URL.Path, to)
cru := path.Clean(ru)
if strings.HasSuffix(ru, "/") { // don't drop trailing slash
cru += "/"
}
u, e := url.Parse(cru)
if e != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
r.Header.Set("X-Original-URL", r.URL.RequestURI())
r.URL.Path = u.Path
r.URL.RawPath = u.RawPath
if u.RawQuery != "" {
r.URL.RawQuery = u.RawQuery
}
ctx = context.WithValue(ctx, contextKey("rewrite"), true)
next.ServeHTTP(w, r.WithContext(ctx))
}
return http.HandlerFunc(fn)
}
return f
}