fix(build): make build-web works; gofmt all Go files
This commit is contained in:
+105
-105
@@ -1,105 +1,105 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CSRFProtect returns middleware that validates the Origin header on
|
||||
// state-changing methods (POST, PUT, PATCH, DELETE).
|
||||
//
|
||||
// An origin is trusted if:
|
||||
// 1. It's in the explicit additionalOrigins list, OR
|
||||
// 2. Its hostname matches the configured host, OR
|
||||
// 3. Its hostname matches the request's own Host header (same-origin check)
|
||||
func CSRFProtect(host, port string, additionalOrigins []string) func(http.Handler) http.Handler {
|
||||
originSet := make(map[string]struct{})
|
||||
for _, o := range additionalOrigins {
|
||||
o = strings.TrimSpace(o)
|
||||
if o != "" {
|
||||
originSet[o] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
hostname := host
|
||||
if idx := strings.LastIndex(hostname, ":"); idx > 0 {
|
||||
hostname = hostname[:idx]
|
||||
}
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "POST", "PUT", "PATCH", "DELETE":
|
||||
origin := r.Header.Get("Origin")
|
||||
if origin == "" {
|
||||
referer := r.Header.Get("Referer")
|
||||
if referer != "" {
|
||||
for o := range originSet {
|
||||
if strings.HasPrefix(referer, o) {
|
||||
origin = o
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if origin != "" {
|
||||
// Extract request host for same-origin check
|
||||
reqHost := r.Host
|
||||
if idx := strings.LastIndex(reqHost, ":"); idx > 0 {
|
||||
reqHost = reqHost[:idx]
|
||||
}
|
||||
|
||||
if !isOriginTrusted(origin, hostname, port, reqHost, originSet) {
|
||||
http.Error(w, `{"error":"forbidden origin"}`, http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func isOriginTrusted(origin, host, port, reqHost string, originSet map[string]struct{}) bool {
|
||||
if _, ok := originSet[origin]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
withoutScheme := origin
|
||||
if idx := strings.Index(withoutScheme, "://"); idx >= 0 {
|
||||
withoutScheme = withoutScheme[idx+3:]
|
||||
}
|
||||
if idx := strings.Index(withoutScheme, "/"); idx >= 0 {
|
||||
withoutScheme = withoutScheme[:idx]
|
||||
}
|
||||
|
||||
originHost := withoutScheme
|
||||
originPort := ""
|
||||
if idx := strings.LastIndex(originHost, ":"); idx >= 0 {
|
||||
originPort = originHost[idx+1:]
|
||||
originHost = originHost[:idx]
|
||||
}
|
||||
|
||||
originHost = strings.TrimPrefix(originHost, "[")
|
||||
originHost = strings.TrimSuffix(originHost, "]")
|
||||
|
||||
// Match configured host
|
||||
if host != "" && originHost == host {
|
||||
return true
|
||||
}
|
||||
|
||||
// Match request's own Host header (same-origin)
|
||||
if reqHost != "" && originHost == reqHost {
|
||||
return true
|
||||
}
|
||||
|
||||
// Localhost variants
|
||||
if originHost == "localhost" || originHost == "127.0.0.1" || originHost == "::1" {
|
||||
if port == "" || originPort == "" || originPort == port {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CSRFProtect returns middleware that validates the Origin header on
|
||||
// state-changing methods (POST, PUT, PATCH, DELETE).
|
||||
//
|
||||
// An origin is trusted if:
|
||||
// 1. It's in the explicit additionalOrigins list, OR
|
||||
// 2. Its hostname matches the configured host, OR
|
||||
// 3. Its hostname matches the request's own Host header (same-origin check)
|
||||
func CSRFProtect(host, port string, additionalOrigins []string) func(http.Handler) http.Handler {
|
||||
originSet := make(map[string]struct{})
|
||||
for _, o := range additionalOrigins {
|
||||
o = strings.TrimSpace(o)
|
||||
if o != "" {
|
||||
originSet[o] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
hostname := host
|
||||
if idx := strings.LastIndex(hostname, ":"); idx > 0 {
|
||||
hostname = hostname[:idx]
|
||||
}
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "POST", "PUT", "PATCH", "DELETE":
|
||||
origin := r.Header.Get("Origin")
|
||||
if origin == "" {
|
||||
referer := r.Header.Get("Referer")
|
||||
if referer != "" {
|
||||
for o := range originSet {
|
||||
if strings.HasPrefix(referer, o) {
|
||||
origin = o
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if origin != "" {
|
||||
// Extract request host for same-origin check
|
||||
reqHost := r.Host
|
||||
if idx := strings.LastIndex(reqHost, ":"); idx > 0 {
|
||||
reqHost = reqHost[:idx]
|
||||
}
|
||||
|
||||
if !isOriginTrusted(origin, hostname, port, reqHost, originSet) {
|
||||
http.Error(w, `{"error":"forbidden origin"}`, http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func isOriginTrusted(origin, host, port, reqHost string, originSet map[string]struct{}) bool {
|
||||
if _, ok := originSet[origin]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
withoutScheme := origin
|
||||
if idx := strings.Index(withoutScheme, "://"); idx >= 0 {
|
||||
withoutScheme = withoutScheme[idx+3:]
|
||||
}
|
||||
if idx := strings.Index(withoutScheme, "/"); idx >= 0 {
|
||||
withoutScheme = withoutScheme[:idx]
|
||||
}
|
||||
|
||||
originHost := withoutScheme
|
||||
originPort := ""
|
||||
if idx := strings.LastIndex(originHost, ":"); idx >= 0 {
|
||||
originPort = originHost[idx+1:]
|
||||
originHost = originHost[:idx]
|
||||
}
|
||||
|
||||
originHost = strings.TrimPrefix(originHost, "[")
|
||||
originHost = strings.TrimSuffix(originHost, "]")
|
||||
|
||||
// Match configured host
|
||||
if host != "" && originHost == host {
|
||||
return true
|
||||
}
|
||||
|
||||
// Match request's own Host header (same-origin)
|
||||
if reqHost != "" && originHost == reqHost {
|
||||
return true
|
||||
}
|
||||
|
||||
// Localhost variants
|
||||
if originHost == "localhost" || originHost == "127.0.0.1" || originHost == "::1" {
|
||||
if port == "" || originPort == "" || originPort == port {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user