Create Cors handler with permissive configuration (#7186)

Create new Cors handler allowing all origins with all standard
methods with any header and credentials.

Fixes #7181
master
kannappanr 6 years ago committed by GitHub
parent 9a65f6dc97
commit df418a2783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      cmd/generic-handlers.go
  2. 20
      vendor/github.com/rs/cors/README.md
  3. 134
      vendor/github.com/rs/cors/cors.go
  4. 1
      vendor/github.com/rs/cors/go.mod
  5. 9
      vendor/github.com/rs/cors/utils.go
  6. 5
      vendor/vendor.json

@ -381,37 +381,9 @@ type resourceHandler struct {
handler http.Handler handler http.Handler
} }
// List of default allowable HTTP methods.
var defaultAllowableHTTPMethods = []string{
http.MethodGet,
http.MethodPut,
http.MethodHead,
http.MethodPost,
http.MethodDelete,
http.MethodOptions,
}
// setCorsHandler handler for CORS (Cross Origin Resource Sharing) // setCorsHandler handler for CORS (Cross Origin Resource Sharing)
func setCorsHandler(h http.Handler) http.Handler { func setCorsHandler(h http.Handler) http.Handler {
commonS3Headers := []string{ c := cors.AllowAll()
"Date",
"ETag",
"Server",
"Connection",
"Accept-Ranges",
"Content-Range",
"Content-Encoding",
"Content-Length",
"Content-Type",
"x-amz-request-id",
}
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: defaultAllowableHTTPMethods,
AllowedHeaders: []string{"*"},
ExposedHeaders: commonS3Headers,
AllowCredentials: true,
})
return c.Handler(h) return c.Handler(h)
} }

@ -49,6 +49,14 @@ The server now runs on `localhost:8080`:
{"hello": "world"} {"hello": "world"}
### Allow * With Credentials Security Protection
This library has been modified to avoid a well known security issue when configured with `AllowedOrigins` to `*` and `AllowCredentials` to `true`. Such setup used to make the library reflects the request `Origin` header value, working around a security protection embedded into the standard that makes clients to refuse such configuration. This behavior has been removed with [#55](https://github.com/rs/cors/issues/55) and [#57](https://github.com/rs/cors/issues/57).
If you depend on this behavior and understand the implications, you can restore it using the `AllowOriginFunc` with `func(origin string) {return true}`.
Please refer to [#55](https://github.com/rs/cors/issues/55) for more information about the security implications.
### More Examples ### More Examples
* `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go) * `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
@ -56,6 +64,11 @@ The server now runs on `localhost:8080`:
* [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go) * [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
* [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go) * [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
* [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go) * [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
* [HttpRouter](https://github.com/julienschmidt/httprouter): [examples/httprouter/server.go](https://github.com/rs/cors/blob/master/examples/httprouter/server.go)
* [Gorilla](http://www.gorillatoolkit.org/pkg/mux): [examples/gorilla/server.go](https://github.com/rs/cors/blob/master/examples/gorilla/server.go)
* [Buffalo](https://gobuffalo.io): [examples/buffalo/server.go](https://github.com/rs/cors/blob/master/examples/buffalo/server.go)
* [Gin](https://gin-gonic.github.io/gin): [examples/gin/server.go](https://github.com/rs/cors/blob/master/examples/gin/server.go)
* [Chi](https://github.com/go-chi/chi): [examples/chi/server.go](https://github.com/rs/cors/blob/master/examples/chi/server.go)
## Parameters ## Parameters
@ -63,8 +76,10 @@ Parameters are passed to the middleware thru the `cors.New` method as follow:
```go ```go
c := cors.New(cors.Options{ c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"}, AllowedOrigins: []string{"http://foo.com", "http://foo.com:8080"},
AllowCredentials: true, AllowCredentials: true,
// Enable Debugging for testing, consider disabling in production
Debug: true,
}) })
// Insert the middleware // Insert the middleware
@ -72,7 +87,8 @@ handler = c.Handler(handler)
``` ```
* **AllowedOrigins** `[]string`: 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 penality. Only one wildcard can be used per origin. The default value is `*`. * **AllowedOrigins** `[]string`: 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 penality. Only one wildcard can be used per origin. The default value is `*`.
* **AllowOriginFunc** `func (origin string) bool`: A custom function to validate the origin. It take 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 (origin string) bool`: A custom function to validate the origin. It takes the origin as an argument and returns true if allowed, or false otherwise. If this option is set, the content of `AllowedOrigins` is ignored.
* **AllowOriginRequestFunc** `func (r *http.Request origin string) bool`: A custom function to validate the origin. It takes the HTTP Request object and the origin as argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` and `AllowOriginFunc` is ignored
* **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`). * **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`).
* **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests. * **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests.
* **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification * **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification

134
vendor/github.com/rs/cors/cors.go generated vendored

@ -5,8 +5,8 @@ as defined by http://www.w3.org/TR/cors/
You can configure it by passing an option struct to cors.New: You can configure it by passing an option struct to cors.New:
c := cors.New(cors.Options{ c := cors.New(cors.Options{
AllowedOrigins: []string{"foo.com"}, AllowedOrigins: []string{"foo.com"},
AllowedMethods: []string{"GET", "POST", "DELETE"}, AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete},
AllowCredentials: true, AllowCredentials: true,
}) })
@ -26,9 +26,6 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"github.com/rs/xhandler"
"golang.org/x/net/context"
) )
// Options is a configuration container to setup the CORS middleware. // Options is a configuration container to setup the CORS middleware.
@ -36,7 +33,7 @@ type Options struct {
// AllowedOrigins is a list of origins a cross-domain request can be executed from. // 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. // 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 // An origin may contain a wildcard (*) to replace 0 or more characters
// (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penality. // (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty.
// Only one wildcard can be used per origin. // Only one wildcard can be used per origin.
// Default value is ["*"] // Default value is ["*"]
AllowedOrigins []string AllowedOrigins []string
@ -44,8 +41,12 @@ type Options struct {
// as argument and returns true if allowed or false otherwise. If this option is // as argument and returns true if allowed or false otherwise. If this option is
// set, the content of AllowedOrigins is ignored. // set, the content of AllowedOrigins is ignored.
AllowOriginFunc func(origin string) bool AllowOriginFunc func(origin string) bool
// AllowOriginFunc is a custom function to validate the origin. It takes the HTTP Request object and the origin as
// argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins`
// and `AllowOriginFunc` is ignored.
AllowOriginRequestFunc func(r *http.Request, origin string) bool
// AllowedMethods is a list of methods the client is allowed to use with // AllowedMethods is a list of methods the client is allowed to use with
// cross-domain requests. Default value is simple methods (GET and POST) // cross-domain requests. Default value is simple methods (HEAD, GET and POST).
AllowedMethods []string AllowedMethods []string
// AllowedHeaders is list of non simple headers the client is allowed to use with // AllowedHeaders is list of non simple headers the client is allowed to use with
// cross-domain requests. // cross-domain requests.
@ -55,12 +56,12 @@ type Options struct {
// ExposedHeaders indicates which headers are safe to expose to the API of a CORS // ExposedHeaders indicates which headers are safe to expose to the API of a CORS
// API specification // API specification
ExposedHeaders []string 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 // MaxAge indicates how long (in seconds) the results of a preflight request
// can be cached // can be cached
MaxAge int MaxAge int
// AllowCredentials indicates whether the request can include user credentials like
// cookies, HTTP authentication or client side SSL certificates.
AllowCredentials bool
// OptionsPassthrough instructs preflight to let other potential next handlers to // OptionsPassthrough instructs preflight to let other potential next handlers to
// process the OPTIONS method. Turn this on if your application handles OPTIONS. // process the OPTIONS method. Turn this on if your application handles OPTIONS.
OptionsPassthrough bool OptionsPassthrough bool
@ -72,35 +73,38 @@ type Options struct {
type Cors struct { type Cors struct {
// Debug logger // Debug logger
Log *log.Logger Log *log.Logger
// Set to true when allowed origins contains a "*"
allowedOriginsAll bool
// Normalized list of plain allowed origins // Normalized list of plain allowed origins
allowedOrigins []string allowedOrigins []string
// List of allowed origins containing wildcards // List of allowed origins containing wildcards
allowedWOrigins []wildcard allowedWOrigins []wildcard
// Optional origin validator function // Optional origin validator function
allowOriginFunc func(origin string) bool allowOriginFunc func(origin string) bool
// Set to true when allowed headers contains a "*" // Optional origin validator (with request) function
allowedHeadersAll bool allowOriginRequestFunc func(r *http.Request, origin string) bool
// Normalized list of allowed headers // Normalized list of allowed headers
allowedHeaders []string allowedHeaders []string
// Normalized list of allowed methods // Normalized list of allowed methods
allowedMethods []string allowedMethods []string
// Normalized list of exposed headers // Normalized list of exposed headers
exposedHeaders []string 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 allowCredentials bool
maxAge int
optionPassthrough bool optionPassthrough bool
} }
// New creates a new Cors handler with the provided options. // New creates a new Cors handler with the provided options.
func New(options Options) *Cors { func New(options Options) *Cors {
c := &Cors{ c := &Cors{
exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey), exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey),
allowOriginFunc: options.AllowOriginFunc, allowOriginFunc: options.AllowOriginFunc,
allowCredentials: options.AllowCredentials, allowOriginRequestFunc: options.AllowOriginRequestFunc,
maxAge: options.MaxAge, allowCredentials: options.AllowCredentials,
optionPassthrough: options.OptionsPassthrough, maxAge: options.MaxAge,
optionPassthrough: options.OptionsPassthrough,
} }
if options.Debug { if options.Debug {
c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags) c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags)
@ -112,8 +116,10 @@ func New(options Options) *Cors {
// Allowed Origins // Allowed Origins
if len(options.AllowedOrigins) == 0 { if len(options.AllowedOrigins) == 0 {
// Default is all origins if options.AllowOriginFunc == nil && options.AllowOriginRequestFunc == nil {
c.allowedOriginsAll = true // Default is all origins
c.allowedOriginsAll = true
}
} else { } else {
c.allowedOrigins = []string{} c.allowedOrigins = []string{}
c.allowedWOrigins = []wildcard{} c.allowedWOrigins = []wildcard{}
@ -128,7 +134,7 @@ func New(options Options) *Cors {
break break
} else if i := strings.IndexByte(origin, '*'); i >= 0 { } else if i := strings.IndexByte(origin, '*'); i >= 0 {
// Split the origin in two: start and end string without the * // Split the origin in two: start and end string without the *
w := wildcard{origin[0:i], origin[i+1 : len(origin)]} w := wildcard{origin[0:i], origin[i+1:]}
c.allowedWOrigins = append(c.allowedWOrigins, w) c.allowedWOrigins = append(c.allowedWOrigins, w)
} else { } else {
c.allowedOrigins = append(c.allowedOrigins, origin) c.allowedOrigins = append(c.allowedOrigins, origin)
@ -139,7 +145,7 @@ func New(options Options) *Cors {
// Allowed Headers // Allowed Headers
if len(options.AllowedHeaders) == 0 { if len(options.AllowedHeaders) == 0 {
// Use sensible defaults // Use sensible defaults
c.allowedHeaders = []string{"Origin", "Accept", "Content-Type"} c.allowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With"}
} else { } else {
// Origin is always appended as some browsers will always request for this header at preflight // Origin is always appended as some browsers will always request for this header at preflight
c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey) c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey)
@ -155,7 +161,7 @@ func New(options Options) *Cors {
// Allowed Methods // Allowed Methods
if len(options.AllowedMethods) == 0 { if len(options.AllowedMethods) == 0 {
// Default is spec's "simple" methods // Default is spec's "simple" methods
c.allowedMethods = []string{"GET", "POST"} c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead}
} else { } else {
c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper)
} }
@ -163,16 +169,34 @@ func New(options Options) *Cors {
return c return c
} }
// Default creates a new Cors handler with default options // Default creates a new Cors handler with default options.
func Default() *Cors { func Default() *Cors {
return New(Options{}) return New(Options{})
} }
// 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 // Handler apply the CORS specification on the request, and add relevant CORS headers
// as necessary. // as necessary.
func (c *Cors) Handler(h http.Handler) http.Handler { func (c *Cors) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" { if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" {
c.logf("Handler: Preflight request") c.logf("Handler: Preflight request")
c.handlePreflight(w, r) c.handlePreflight(w, r)
// Preflight requests are standalone and should stop the chain as some other // Preflight requests are standalone and should stop the chain as some other
@ -192,32 +216,9 @@ func (c *Cors) Handler(h http.Handler) http.Handler {
}) })
} }
// HandlerC is net/context aware handler
func (c *Cors) HandlerC(h xhandler.HandlerC) xhandler.HandlerC {
return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
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 {
h.ServeHTTPC(ctx, w, r)
} else {
w.WriteHeader(http.StatusOK)
}
} else {
c.logf("Handler: Actual request")
c.handleActualRequest(w, r)
h.ServeHTTPC(ctx, w, r)
}
})
}
// HandlerFunc provides Martini compatible handler // HandlerFunc provides Martini compatible handler
func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) { func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" { if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" {
c.logf("HandlerFunc: Preflight request") c.logf("HandlerFunc: Preflight request")
c.handlePreflight(w, r) c.handlePreflight(w, r)
} else { } else {
@ -228,7 +229,7 @@ func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
// Negroni compatible interface // Negroni compatible interface
func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
if r.Method == "OPTIONS" { if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" {
c.logf("ServeHTTP: Preflight request") c.logf("ServeHTTP: Preflight request")
c.handlePreflight(w, r) c.handlePreflight(w, r)
// Preflight requests are standalone and should stop the chain as some other // Preflight requests are standalone and should stop the chain as some other
@ -252,7 +253,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
headers := w.Header() headers := w.Header()
origin := r.Header.Get("Origin") origin := r.Header.Get("Origin")
if r.Method != "OPTIONS" { if r.Method != http.MethodOptions {
c.logf(" Preflight aborted: %s!=OPTIONS", r.Method) c.logf(" Preflight aborted: %s!=OPTIONS", r.Method)
return return
} }
@ -267,7 +268,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
c.logf(" Preflight aborted: empty origin") c.logf(" Preflight aborted: empty origin")
return return
} }
if !c.isOriginAllowed(origin) { if !c.isOriginAllowed(r, origin) {
c.logf(" Preflight aborted: origin '%s' not allowed", origin) c.logf(" Preflight aborted: origin '%s' not allowed", origin)
return return
} }
@ -282,7 +283,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders)
return return
} }
headers.Set("Access-Control-Allow-Origin", origin) 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 // 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 // by Access-Control-Request-Method (if supported) can be enough
headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod)) headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod))
@ -306,7 +311,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
headers := w.Header() headers := w.Header()
origin := r.Header.Get("Origin") origin := r.Header.Get("Origin")
if r.Method == "OPTIONS" { if r.Method == http.MethodOptions {
c.logf(" Actual request no headers added: method == %s", r.Method) c.logf(" Actual request no headers added: method == %s", r.Method)
return return
} }
@ -316,7 +321,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
c.logf(" Actual request no headers added: missing origin") c.logf(" Actual request no headers added: missing origin")
return return
} }
if !c.isOriginAllowed(origin) { if !c.isOriginAllowed(r, origin) {
c.logf(" Actual request no headers added: origin '%s' not allowed", origin) c.logf(" Actual request no headers added: origin '%s' not allowed", origin)
return return
} }
@ -330,7 +335,11 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
return return
} }
headers.Set("Access-Control-Allow-Origin", origin) if c.allowedOriginsAll {
headers.Set("Access-Control-Allow-Origin", "*")
} else {
headers.Set("Access-Control-Allow-Origin", origin)
}
if len(c.exposedHeaders) > 0 { if len(c.exposedHeaders) > 0 {
headers.Set("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", ")) headers.Set("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", "))
} }
@ -349,7 +358,10 @@ func (c *Cors) logf(format string, a ...interface{}) {
// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests // isOriginAllowed checks if a given origin is allowed to perform cross-domain requests
// on the endpoint // on the endpoint
func (c *Cors) isOriginAllowed(origin string) bool { func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool {
if c.allowOriginRequestFunc != nil {
return c.allowOriginRequestFunc(r, origin)
}
if c.allowOriginFunc != nil { if c.allowOriginFunc != nil {
return c.allowOriginFunc(origin) return c.allowOriginFunc(origin)
} }
@ -378,7 +390,7 @@ func (c *Cors) isMethodAllowed(method string) bool {
return false return false
} }
method = strings.ToUpper(method) method = strings.ToUpper(method)
if method == "OPTIONS" { if method == http.MethodOptions {
// Always allow preflight requests // Always allow preflight requests
return true return true
} }

1
vendor/github.com/rs/cors/go.mod generated vendored

@ -0,0 +1 @@
module github.com/rs/cors

@ -12,7 +12,7 @@ type wildcard struct {
} }
func (w wildcard) match(s string) bool { 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) return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix)
} }
// convert converts a list of string using the passed converter function // convert converts a list of string using the passed converter function
@ -39,19 +39,20 @@ func parseHeaderList(headerList string) []string {
headers := make([]string, 0, t) headers := make([]string, 0, t)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
b := headerList[i] b := headerList[i]
if b >= 'a' && b <= 'z' { switch {
case b >= 'a' && b <= 'z':
if upper { if upper {
h = append(h, b-toLower) h = append(h, b-toLower)
} else { } else {
h = append(h, b) h = append(h, b)
} }
} else if b >= 'A' && b <= 'Z' { case b >= 'A' && b <= 'Z':
if !upper { if !upper {
h = append(h, b+toLower) h = append(h, b+toLower)
} else { } else {
h = append(h, b) h = append(h, b)
} }
} else if b == '-' || b == '_' || (b >= '0' && b <= '9') { case b == '-' || b == '_' || (b >= '0' && b <= '9'):
h = append(h, b) h = append(h, b)
} }

@ -836,9 +836,10 @@
"revisionTime": "2018-08-08T20:39:25Z" "revisionTime": "2018-08-08T20:39:25Z"
}, },
{ {
"checksumSHA1": "hev23KrSfQ4KfosxH+gJKziFVtA=",
"path": "github.com/rs/cors", "path": "github.com/rs/cors",
"revision": "a62a804a8a009876ca59105f7899938a1349f4b3", "revision": "76f58f330d76a55c5badc74f6212e8a15e742c77",
"revisionTime": "2016-06-18T04:49:35+05:30" "revisionTime": "2019-01-16T17:59:10Z"
}, },
{ {
"path": "github.com/rs/xhandler", "path": "github.com/rs/xhandler",

Loading…
Cancel
Save