mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Move macaron to chi (#14293)
Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		
							
								
								
									
										21
									
								
								vendor/github.com/go-chi/cors/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/go-chi/cors/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com> | ||||
| 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. | ||||
							
								
								
									
										39
									
								
								vendor/github.com/go-chi/cors/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/go-chi/cors/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| # 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{"*"}, | ||||
|     // 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). | ||||
							
								
								
									
										400
									
								
								vendor/github.com/go-chi/cors/cors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								vendor/github.com/go-chi/cors/cors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,400 @@ | ||||
| // 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 | ||||
| } | ||||
							
								
								
									
										70
									
								
								vendor/github.com/go-chi/cors/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								vendor/github.com/go-chi/cors/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| 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 >= '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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user