From 30a0f8a71bc1f21e90ec3bfcc40ac15bb28bc519 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 18 Jul 2024 11:05:23 +0200 Subject: [PATCH] fix(ocis): get rid of go-chi/cors lib Signed-off-by: jkoberg --- go.mod | 3 +- go.sum | 2 - ocis-pkg/middleware/header.go | 5 +- vendor/github.com/go-chi/cors/LICENSE | 21 -- vendor/github.com/go-chi/cors/README.md | 39 --- vendor/github.com/go-chi/cors/cors.go | 400 ------------------------ vendor/github.com/go-chi/cors/utils.go | 70 ----- vendor/modules.txt | 3 - 8 files changed, 4 insertions(+), 539 deletions(-) delete mode 100644 vendor/github.com/go-chi/cors/LICENSE delete mode 100644 vendor/github.com/go-chi/cors/README.md delete mode 100644 vendor/github.com/go-chi/cors/cors.go delete mode 100644 vendor/github.com/go-chi/cors/utils.go diff --git a/go.mod b/go.mod index 1a15692b35..da3ced6e81 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/gabriel-vasile/mimetype v1.4.4 github.com/ggwhite/go-masker v1.1.0 github.com/go-chi/chi/v5 v5.1.0 - github.com/go-chi/cors v1.2.1 github.com/go-chi/render v1.0.3 github.com/go-jose/go-jose/v3 v3.0.3 github.com/go-ldap/ldap/v3 v3.4.8 @@ -79,6 +78,7 @@ require ( github.com/r3labs/sse/v2 v2.10.0 github.com/riandyrn/otelchi v0.8.0 github.com/rogpeppe/go-internal v1.12.0 + github.com/rs/cors v1.11.0 github.com/rs/zerolog v1.33.0 github.com/shamaton/msgpack/v2 v2.2.0 github.com/sirupsen/logrus v1.9.3 @@ -304,7 +304,6 @@ require ( github.com/prometheus/statsd_exporter v0.22.8 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/rivo/uniseg v0.4.2 // indirect - github.com/rs/cors v1.11.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/russellhaering/goxmldsig v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 6e82bdab6b..2d1002aa40 100644 --- a/go.sum +++ b/go.sum @@ -1143,8 +1143,6 @@ github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= -github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= diff --git a/ocis-pkg/middleware/header.go b/ocis-pkg/middleware/header.go index 2e82d65931..44dbd706bc 100644 --- a/ocis-pkg/middleware/header.go +++ b/ocis-pkg/middleware/header.go @@ -7,7 +7,7 @@ import ( "github.com/owncloud/ocis/v2/ocis-pkg/cors" - chicors "github.com/go-chi/cors" + rscors "github.com/rs/cors" ) // NoCache writes required cache headers to all requests. @@ -31,10 +31,11 @@ func Cors(opts ...cors.Option) func(http.Handler) http.Handler { Str("allowed_headers", strings.Join(options.AllowedHeaders, ", ")). Bool("allow_credentials", options.AllowCredentials). Msg("setup cors middleware") - return chicors.Handler(chicors.Options{ + c := rscors.New(rscors.Options{ AllowedOrigins: options.AllowedOrigins, AllowedMethods: options.AllowedMethods, AllowedHeaders: options.AllowedHeaders, AllowCredentials: options.AllowCredentials, }) + return c.Handler } diff --git a/vendor/github.com/go-chi/cors/LICENSE b/vendor/github.com/go-chi/cors/LICENSE deleted file mode 100644 index aee6182f9a..0000000000 --- a/vendor/github.com/go-chi/cors/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2014 Olivier Poitrey -Copyright (c) 2016-Present https://github.com/go-chi authors - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/go-chi/cors/README.md b/vendor/github.com/go-chi/cors/README.md deleted file mode 100644 index b41686b6af..0000000000 --- a/vendor/github.com/go-chi/cors/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# CORS net/http middleware - -[go-chi/cors](https://github.com/go-chi/cors) is a fork of [github.com/rs/cors](https://github.com/rs/cors) that -provides a `net/http` compatible middleware for performing preflight CORS checks on the server side. These headers -are required for using the browser native [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). - -This middleware is designed to be used as a top-level middleware on the [chi](https://github.com/go-chi/chi) router. -Applying with within a `r.Group()` or using `With()` will not work without routes matching `OPTIONS` added. - -## Usage - -```go -func main() { - r := chi.NewRouter() - - // Basic CORS - // for more ideas, see: https://developer.github.com/v3/#cross-origin-resource-sharing - r.Use(cors.Handler(cors.Options{ - // AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts - AllowedOrigins: []string{"https://*", "http://*"}, - // AllowOriginFunc: func(r *http.Request, origin string) bool { return true }, - AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, - AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, - ExposedHeaders: []string{"Link"}, - AllowCredentials: false, - MaxAge: 300, // Maximum value not ignored by any of major browsers - })) - - r.Get("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("welcome")) - }) - - http.ListenAndServe(":3000", r) -} -``` - -## Credits - -All credit for the original work of this middleware goes out to [github.com/rs](github.com/rs). diff --git a/vendor/github.com/go-chi/cors/cors.go b/vendor/github.com/go-chi/cors/cors.go deleted file mode 100644 index 8df81636e3..0000000000 --- a/vendor/github.com/go-chi/cors/cors.go +++ /dev/null @@ -1,400 +0,0 @@ -// cors package is net/http handler to handle CORS related requests -// as defined by http://www.w3.org/TR/cors/ -// -// You can configure it by passing an option struct to cors.New: -// -// c := cors.New(cors.Options{ -// AllowedOrigins: []string{"foo.com"}, -// AllowedMethods: []string{"GET", "POST", "DELETE"}, -// AllowCredentials: true, -// }) -// -// Then insert the handler in the chain: -// -// handler = c.Handler(handler) -// -// See Options documentation for more options. -// -// The resulting handler is a standard net/http handler. -package cors - -import ( - "log" - "net/http" - "os" - "strconv" - "strings" -) - -// Options is a configuration container to setup the CORS middleware. -type Options struct { - // AllowedOrigins is a list of origins a cross-domain request can be executed from. - // If the special "*" value is present in the list, all origins will be allowed. - // An origin may contain a wildcard (*) to replace 0 or more characters - // (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty. - // Only one wildcard can be used per origin. - // Default value is ["*"] - AllowedOrigins []string - - // AllowOriginFunc is a custom function to validate the origin. It takes the origin - // as argument and returns true if allowed or false otherwise. If this option is - // set, the content of AllowedOrigins is ignored. - AllowOriginFunc func(r *http.Request, origin string) bool - - // AllowedMethods is a list of methods the client is allowed to use with - // cross-domain requests. Default value is simple methods (HEAD, GET and POST). - AllowedMethods []string - - // AllowedHeaders is list of non simple headers the client is allowed to use with - // cross-domain requests. - // If the special "*" value is present in the list, all headers will be allowed. - // Default value is [] but "Origin" is always appended to the list. - AllowedHeaders []string - - // ExposedHeaders indicates which headers are safe to expose to the API of a CORS - // API specification - ExposedHeaders []string - - // AllowCredentials indicates whether the request can include user credentials like - // cookies, HTTP authentication or client side SSL certificates. - AllowCredentials bool - - // MaxAge indicates how long (in seconds) the results of a preflight request - // can be cached - MaxAge int - - // OptionsPassthrough instructs preflight to let other potential next handlers to - // process the OPTIONS method. Turn this on if your application handles OPTIONS. - OptionsPassthrough bool - - // Debugging flag adds additional output to debug server side CORS issues - Debug bool -} - -// Logger generic interface for logger -type Logger interface { - Printf(string, ...interface{}) -} - -// Cors http handler -type Cors struct { - // Debug logger - Log Logger - - // Normalized list of plain allowed origins - allowedOrigins []string - - // List of allowed origins containing wildcards - allowedWOrigins []wildcard - - // Optional origin validator function - allowOriginFunc func(r *http.Request, origin string) bool - - // Normalized list of allowed headers - allowedHeaders []string - - // Normalized list of allowed methods - allowedMethods []string - - // Normalized list of exposed headers - exposedHeaders []string - maxAge int - - // Set to true when allowed origins contains a "*" - allowedOriginsAll bool - - // Set to true when allowed headers contains a "*" - allowedHeadersAll bool - - allowCredentials bool - optionPassthrough bool -} - -// New creates a new Cors handler with the provided options. -func New(options Options) *Cors { - c := &Cors{ - exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey), - allowOriginFunc: options.AllowOriginFunc, - allowCredentials: options.AllowCredentials, - maxAge: options.MaxAge, - optionPassthrough: options.OptionsPassthrough, - } - if options.Debug && c.Log == nil { - c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags) - } - - // Normalize options - // Note: for origins and methods matching, the spec requires a case-sensitive matching. - // As it may error prone, we chose to ignore the spec here. - - // Allowed Origins - if len(options.AllowedOrigins) == 0 { - if options.AllowOriginFunc == nil { - // Default is all origins - c.allowedOriginsAll = true - } - } else { - c.allowedOrigins = []string{} - c.allowedWOrigins = []wildcard{} - for _, origin := range options.AllowedOrigins { - // Normalize - origin = strings.ToLower(origin) - if origin == "*" { - // If "*" is present in the list, turn the whole list into a match all - c.allowedOriginsAll = true - c.allowedOrigins = nil - c.allowedWOrigins = nil - break - } else if i := strings.IndexByte(origin, '*'); i >= 0 { - // Split the origin in two: start and end string without the * - w := wildcard{origin[0:i], origin[i+1:]} - c.allowedWOrigins = append(c.allowedWOrigins, w) - } else { - c.allowedOrigins = append(c.allowedOrigins, origin) - } - } - } - - // Allowed Headers - if len(options.AllowedHeaders) == 0 { - // Use sensible defaults - c.allowedHeaders = []string{"Origin", "Accept", "Content-Type"} - } else { - // Origin is always appended as some browsers will always request for this header at preflight - c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey) - for _, h := range options.AllowedHeaders { - if h == "*" { - c.allowedHeadersAll = true - c.allowedHeaders = nil - break - } - } - } - - // Allowed Methods - if len(options.AllowedMethods) == 0 { - // Default is spec's "simple" methods - c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead} - } else { - c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) - } - - return c -} - -// Handler creates a new Cors handler with passed options. -func Handler(options Options) func(next http.Handler) http.Handler { - c := New(options) - return c.Handler -} - -// AllowAll create a new Cors handler with permissive configuration allowing all -// origins with all standard methods with any header and credentials. -func AllowAll() *Cors { - return New(Options{ - AllowedOrigins: []string{"*"}, - AllowedMethods: []string{ - http.MethodHead, - http.MethodGet, - http.MethodPost, - http.MethodPut, - http.MethodPatch, - http.MethodDelete, - }, - AllowedHeaders: []string{"*"}, - AllowCredentials: false, - }) -} - -// Handler apply the CORS specification on the request, and add relevant CORS headers -// as necessary. -func (c *Cors) Handler(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { - c.logf("Handler: Preflight request") - c.handlePreflight(w, r) - // Preflight requests are standalone and should stop the chain as some other - // middleware may not handle OPTIONS requests correctly. One typical example - // is authentication middleware ; OPTIONS requests won't carry authentication - // headers (see #1) - if c.optionPassthrough { - next.ServeHTTP(w, r) - } else { - w.WriteHeader(http.StatusOK) - } - } else { - c.logf("Handler: Actual request") - c.handleActualRequest(w, r) - next.ServeHTTP(w, r) - } - }) -} - -// handlePreflight handles pre-flight CORS requests -func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { - headers := w.Header() - origin := r.Header.Get("Origin") - - if r.Method != http.MethodOptions { - c.logf("Preflight aborted: %s!=OPTIONS", r.Method) - return - } - // Always set Vary headers - // see https://github.com/rs/cors/issues/10, - // https://github.com/rs/cors/commit/dbdca4d95feaa7511a46e6f1efb3b3aa505bc43f#commitcomment-12352001 - headers.Add("Vary", "Origin") - headers.Add("Vary", "Access-Control-Request-Method") - headers.Add("Vary", "Access-Control-Request-Headers") - - if origin == "" { - c.logf("Preflight aborted: empty origin") - return - } - if !c.isOriginAllowed(r, origin) { - c.logf("Preflight aborted: origin '%s' not allowed", origin) - return - } - - reqMethod := r.Header.Get("Access-Control-Request-Method") - if !c.isMethodAllowed(reqMethod) { - c.logf("Preflight aborted: method '%s' not allowed", reqMethod) - return - } - reqHeaders := parseHeaderList(r.Header.Get("Access-Control-Request-Headers")) - if !c.areHeadersAllowed(reqHeaders) { - c.logf("Preflight aborted: headers '%v' not allowed", reqHeaders) - return - } - if c.allowedOriginsAll { - headers.Set("Access-Control-Allow-Origin", "*") - } else { - headers.Set("Access-Control-Allow-Origin", origin) - } - // Spec says: Since the list of methods can be unbounded, simply returning the method indicated - // by Access-Control-Request-Method (if supported) can be enough - headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod)) - if len(reqHeaders) > 0 { - - // Spec says: Since the list of headers can be unbounded, simply returning supported headers - // from Access-Control-Request-Headers can be enough - headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", ")) - } - if c.allowCredentials { - headers.Set("Access-Control-Allow-Credentials", "true") - } - if c.maxAge > 0 { - headers.Set("Access-Control-Max-Age", strconv.Itoa(c.maxAge)) - } - c.logf("Preflight response headers: %v", headers) -} - -// handleActualRequest handles simple cross-origin requests, actual request or redirects -func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { - headers := w.Header() - origin := r.Header.Get("Origin") - - // Always set Vary, see https://github.com/rs/cors/issues/10 - headers.Add("Vary", "Origin") - if origin == "" { - c.logf("Actual request no headers added: missing origin") - return - } - if !c.isOriginAllowed(r, origin) { - c.logf("Actual request no headers added: origin '%s' not allowed", origin) - return - } - - // Note that spec does define a way to specifically disallow a simple method like GET or - // POST. Access-Control-Allow-Methods is only used for pre-flight requests and the - // spec doesn't instruct to check the allowed methods for simple cross-origin requests. - // We think it's a nice feature to be able to have control on those methods though. - if !c.isMethodAllowed(r.Method) { - c.logf("Actual request no headers added: method '%s' not allowed", r.Method) - - return - } - if c.allowedOriginsAll { - headers.Set("Access-Control-Allow-Origin", "*") - } else { - headers.Set("Access-Control-Allow-Origin", origin) - } - if len(c.exposedHeaders) > 0 { - headers.Set("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", ")) - } - if c.allowCredentials { - headers.Set("Access-Control-Allow-Credentials", "true") - } - c.logf("Actual response added headers: %v", headers) -} - -// convenience method. checks if a logger is set. -func (c *Cors) logf(format string, a ...interface{}) { - if c.Log != nil { - c.Log.Printf(format, a...) - } -} - -// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests -// on the endpoint -func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool { - if c.allowOriginFunc != nil { - return c.allowOriginFunc(r, origin) - } - if c.allowedOriginsAll { - return true - } - origin = strings.ToLower(origin) - for _, o := range c.allowedOrigins { - if o == origin { - return true - } - } - for _, w := range c.allowedWOrigins { - if w.match(origin) { - return true - } - } - return false -} - -// isMethodAllowed checks if a given method can be used as part of a cross-domain request -// on the endpoint -func (c *Cors) isMethodAllowed(method string) bool { - if len(c.allowedMethods) == 0 { - // If no method allowed, always return false, even for preflight request - return false - } - method = strings.ToUpper(method) - if method == http.MethodOptions { - // Always allow preflight requests - return true - } - for _, m := range c.allowedMethods { - if m == method { - return true - } - } - return false -} - -// areHeadersAllowed checks if a given list of headers are allowed to used within -// a cross-domain request. -func (c *Cors) areHeadersAllowed(requestedHeaders []string) bool { - if c.allowedHeadersAll || len(requestedHeaders) == 0 { - return true - } - for _, header := range requestedHeaders { - header = http.CanonicalHeaderKey(header) - found := false - for _, h := range c.allowedHeaders { - if h == header { - found = true - break - } - } - if !found { - return false - } - } - return true -} diff --git a/vendor/github.com/go-chi/cors/utils.go b/vendor/github.com/go-chi/cors/utils.go deleted file mode 100644 index 3fe5a5aeeb..0000000000 --- a/vendor/github.com/go-chi/cors/utils.go +++ /dev/null @@ -1,70 +0,0 @@ -package cors - -import "strings" - -const toLower = 'a' - 'A' - -type converter func(string) string - -type wildcard struct { - prefix string - suffix string -} - -func (w wildcard) match(s string) bool { - return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) -} - -// convert converts a list of string using the passed converter function -func convert(s []string, c converter) []string { - out := []string{} - for _, i := range s { - out = append(out, c(i)) - } - return out -} - -// parseHeaderList tokenize + normalize a string containing a list of headers -func parseHeaderList(headerList string) []string { - l := len(headerList) - h := make([]byte, 0, l) - upper := true - // Estimate the number headers in order to allocate the right splice size - t := 0 - for i := 0; i < l; i++ { - if headerList[i] == ',' { - t++ - } - } - headers := make([]string, 0, t) - for i := 0; i < l; i++ { - b := headerList[i] - if b >= 'a' && b <= 'z' { - if upper { - h = append(h, b-toLower) - } else { - h = append(h, b) - } - } else if b >= 'A' && b <= 'Z' { - if !upper { - h = append(h, b+toLower) - } else { - h = append(h, b) - } - } else if b == '-' || b == '_' || b == '.' || (b >= '0' && b <= '9') { - h = append(h, b) - } - - if b == ' ' || b == ',' || i == l-1 { - if len(h) > 0 { - // Flush the found header - headers = append(headers, string(h)) - h = h[:0] - upper = true - } - } else { - upper = b == '-' - } - } - return headers -} diff --git a/vendor/modules.txt b/vendor/modules.txt index f6b9458d59..e803797203 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -825,9 +825,6 @@ github.com/go-asn1-ber/asn1-ber ## explicit; go 1.14 github.com/go-chi/chi/v5 github.com/go-chi/chi/v5/middleware -# github.com/go-chi/cors v1.2.1 -## explicit; go 1.14 -github.com/go-chi/cors # github.com/go-chi/render v1.0.3 ## explicit; go 1.16 github.com/go-chi/render