vendor: github.com/gorilla/handlers v1.5.2 (#4211)

This commit is contained in:
Milos Gajdos 2024-01-16 17:06:16 +07:00 committed by GitHub
commit 6926aea0ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 161 additions and 98 deletions

2
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/docker/go-metrics v0.0.1 github.com/docker/go-metrics v0.0.1
github.com/go-jose/go-jose/v3 v3.0.1 github.com/go-jose/go-jose/v3 v3.0.1
github.com/google/uuid v1.3.1 github.com/google/uuid v1.3.1
github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1 github.com/gorilla/mux v1.8.1
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 github.com/hashicorp/golang-lru/arc/v2 v2.0.5
github.com/klauspost/compress v1.17.4 github.com/klauspost/compress v1.17.4

5
go.sum
View file

@ -76,7 +76,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -136,8 +135,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=

20
vendor/github.com/gorilla/handlers/.editorconfig generated vendored Normal file
View file

@ -0,0 +1,20 @@
; https://editorconfig.org/
root = true
[*]
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4
[*.md]
indent_size = 4
trim_trailing_whitespace = false
eclint_indent_style = unset

2
vendor/github.com/gorilla/handlers/.gitignore generated vendored Normal file
View file

@ -0,0 +1,2 @@
# Output of the go test coverage tool
coverage.coverprofile

View file

@ -1,22 +1,27 @@
Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved. Copyright (c) 2023 The Gorilla Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright notice, this * Redistributions of source code must retain the above copyright
list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Redistributions in binary form must reproduce the above copyright notice, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
this list of conditions and the following disclaimer in the documentation "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
and/or other materials provided with the distribution. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

34
vendor/github.com/gorilla/handlers/Makefile generated vendored Normal file
View file

@ -0,0 +1,34 @@
GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '')
GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest
GO_SEC=$(shell which gosec 2> /dev/null || echo '')
GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest
GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '')
GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest
.PHONY: verify
verify: sec govulncheck lint test
.PHONY: lint
lint:
$(if $(GO_LINT), ,go install $(GO_LINT_URI))
@echo "##### Running golangci-lint #####"
golangci-lint run -v
.PHONY: sec
sec:
$(if $(GO_SEC), ,go install $(GO_SEC_URI))
@echo "##### Running gosec #####"
gosec ./...
.PHONY: govulncheck
govulncheck:
$(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI))
@echo "##### Running govulncheck #####"
govulncheck ./...
.PHONY: test
test:
@echo "##### Running tests #####"
go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./...

View file

@ -1,9 +1,9 @@
gorilla/handlers # gorilla/handlers
================
[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers)
[![CircleCI](https://circleci.com/gh/gorilla/handlers.svg?style=svg)](https://circleci.com/gh/gorilla/handlers)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge)
![Testing](https://github.com/gorilla/handlers/actions/workflows/test.yml/badge.svg)
[![Codecov](https://codecov.io/github/gorilla/handlers/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/handlers)
[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge)
Package handlers is a collection of handlers (aka "HTTP middleware") for use Package handlers is a collection of handlers (aka "HTTP middleware") for use
with Go's `net/http` package (or any framework supporting `http.Handler`), including: with Go's `net/http` package (or any framework supporting `http.Handler`), including:

View file

@ -21,12 +21,11 @@ type canonical struct {
// //
// Example: // Example:
// //
// r := mux.NewRouter() // r := mux.NewRouter()
// canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302) // canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302)
// r.HandleFunc("/route", YourHandler) // r.HandleFunc("/route", YourHandler)
//
// log.Fatal(http.ListenAndServe(":7000", canonical(r)))
// //
// log.Fatal(http.ListenAndServe(":7000", canonical(r)))
func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler { func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler {
fn := func(h http.Handler) http.Handler { fn := func(h http.Handler) http.Handler {
return canonical{h, domain, code} return canonical{h, domain, code}

View file

@ -44,13 +44,13 @@ type flusher interface {
Flush() error Flush() error
} }
func (w *compressResponseWriter) Flush() { func (cw *compressResponseWriter) Flush() {
// Flush compressed data if compressor supports it. // Flush compressed data if compressor supports it.
if f, ok := w.compressor.(flusher); ok { if f, ok := cw.compressor.(flusher); ok {
f.Flush() _ = f.Flush()
} }
// Flush HTTP response. // Flush HTTP response.
if f, ok := w.w.(http.Flusher); ok { if f, ok := cw.w.(http.Flusher); ok {
f.Flush() f.Flush()
} }
} }

View file

@ -26,14 +26,14 @@ type cors struct {
type OriginValidator func(string) bool type OriginValidator func(string) bool
var ( var (
defaultCorsOptionStatusCode = 200 defaultCorsOptionStatusCode = http.StatusOK
defaultCorsMethods = []string{"GET", "HEAD", "POST"} defaultCorsMethods = []string{http.MethodGet, http.MethodHead, http.MethodPost}
defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"} defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
// (WebKit/Safari v9 sends the Origin header by default in AJAX requests) // (WebKit/Safari v9 sends the Origin header by default in AJAX requests).
) )
const ( const (
corsOptionMethod string = "OPTIONS" corsOptionMethod string = http.MethodOptions
corsAllowOriginHeader string = "Access-Control-Allow-Origin" corsAllowOriginHeader string = "Access-Control-Allow-Origin"
corsExposeHeadersHeader string = "Access-Control-Expose-Headers" corsExposeHeadersHeader string = "Access-Control-Expose-Headers"
corsMaxAgeHeader string = "Access-Control-Max-Age" corsMaxAgeHeader string = "Access-Control-Max-Age"
@ -101,10 +101,8 @@ func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !ch.isMatch(method, defaultCorsMethods) { if !ch.isMatch(method, defaultCorsMethods) {
w.Header().Set(corsAllowMethodsHeader, method) w.Header().Set(corsAllowMethodsHeader, method)
} }
} else { } else if len(ch.exposedHeaders) > 0 {
if len(ch.exposedHeaders) > 0 { w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
}
} }
if ch.allowCredentials { if ch.allowCredentials {
@ -141,22 +139,21 @@ func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// CORS provides Cross-Origin Resource Sharing middleware. // CORS provides Cross-Origin Resource Sharing middleware.
// Example: // Example:
// //
// import ( // import (
// "net/http" // "net/http"
// //
// "github.com/gorilla/handlers" // "github.com/gorilla/handlers"
// "github.com/gorilla/mux" // "github.com/gorilla/mux"
// ) // )
// //
// func main() { // func main() {
// r := mux.NewRouter() // r := mux.NewRouter()
// r.HandleFunc("/users", UserEndpoint) // r.HandleFunc("/users", UserEndpoint)
// r.HandleFunc("/projects", ProjectEndpoint) // r.HandleFunc("/projects", ProjectEndpoint)
//
// // Apply the CORS middleware to our top-level router, with the defaults.
// http.ListenAndServe(":8000", handlers.CORS()(r))
// }
// //
// // Apply the CORS middleware to our top-level router, with the defaults.
// http.ListenAndServe(":8000", handlers.CORS()(r))
// }
func CORS(opts ...CORSOption) func(http.Handler) http.Handler { func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
return func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler {
ch := parseCORSOptions(opts...) ch := parseCORSOptions(opts...)
@ -174,7 +171,7 @@ func parseCORSOptions(opts ...CORSOption) *cors {
} }
for _, option := range opts { for _, option := range opts {
option(ch) _ = option(ch) //TODO: @bharat-rajani, return error to caller if not nil?
} }
return ch return ch

View file

@ -35,7 +35,7 @@ func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
sort.Strings(allow) sort.Strings(allow)
w.Header().Set("Allow", strings.Join(allow, ", ")) w.Header().Set("Allow", strings.Join(allow, ", "))
if req.Method == "OPTIONS" { if req.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} else { } else {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
@ -44,7 +44,7 @@ func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP // responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
// status code and body size // status code and body size.
type responseLogger struct { type responseLogger struct {
w http.ResponseWriter w http.ResponseWriter
status int status int
@ -97,7 +97,7 @@ func isContentType(h http.Header, contentType string) bool {
// Only PUT, POST, and PATCH requests are considered. // Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler { func ContentTypeHandler(h http.Handler, contentTypes ...string) 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 == "PUT" || r.Method == "POST" || r.Method == "PATCH") { if !(r.Method == http.MethodPut || r.Method == http.MethodPost || r.Method == http.MethodPatch) {
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
return return
} }
@ -108,7 +108,10 @@ func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
return return
} }
} }
http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType) http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q",
r.Header.Get("Content-Type"),
contentTypes),
http.StatusUnsupportedMediaType)
}) })
} }
@ -133,12 +136,12 @@ const (
// Form method takes precedence over header method. // Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler { func HTTPMethodOverrideHandler(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 == "POST" { if r.Method == http.MethodPost {
om := r.FormValue(HTTPMethodOverrideFormKey) om := r.FormValue(HTTPMethodOverrideFormKey)
if om == "" { if om == "" {
om = r.Header.Get(HTTPMethodOverrideHeader) om = r.Header.Get(HTTPMethodOverrideHeader)
} }
if om == "PUT" || om == "PATCH" || om == "DELETE" { if om == http.MethodPut || om == http.MethodPatch || om == http.MethodDelete {
r.Method = om r.Method = om
} }
} }

View file

@ -18,7 +18,7 @@ import (
// Logging // Logging
// LogFormatterParams is the structure any formatter will be handed when time to log comes // LogFormatterParams is the structure any formatter will be handed when time to log comes.
type LogFormatterParams struct { type LogFormatterParams struct {
Request *http.Request Request *http.Request
URL url.URL URL url.URL
@ -27,7 +27,7 @@ type LogFormatterParams struct {
Size int Size int
} }
// LogFormatter gives the signature of the formatter function passed to CustomLoggingHandler // LogFormatter gives the signature of the formatter function passed to CustomLoggingHandler.
type LogFormatter func(writer io.Writer, params LogFormatterParams) type LogFormatter func(writer io.Writer, params LogFormatterParams)
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its // loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
@ -46,7 +46,10 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
h.handler.ServeHTTP(w, req) h.handler.ServeHTTP(w, req)
if req.MultipartForm != nil { if req.MultipartForm != nil {
req.MultipartForm.RemoveAll() err := req.MultipartForm.RemoveAll()
if err != nil {
return
}
} }
params := LogFormatterParams{ params := LogFormatterParams{
@ -76,7 +79,7 @@ const lowerhex = "0123456789abcdef"
func appendQuoted(buf []byte, s string) []byte { func appendQuoted(buf []byte, s string) []byte {
var runeTmp [utf8.UTFMax]byte var runeTmp [utf8.UTFMax]byte
for width := 0; len(s) > 0; s = s[width:] { for width := 0; len(s) > 0; s = s[width:] { //nolint: wastedassign //TODO: why width starts from 0and reassigned as 1
r := rune(s[0]) r := rune(s[0])
width = 1 width = 1
if r >= utf8.RuneSelf { if r >= utf8.RuneSelf {
@ -191,7 +194,7 @@ func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int
func writeLog(writer io.Writer, params LogFormatterParams) { func writeLog(writer io.Writer, params LogFormatterParams) {
buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size) buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
buf = append(buf, '\n') buf = append(buf, '\n')
writer.Write(buf) _, _ = writer.Write(buf)
} }
// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format. // writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
@ -204,7 +207,7 @@ func writeCombinedLog(writer io.Writer, params LogFormatterParams) {
buf = append(buf, `" "`...) buf = append(buf, `" "`...)
buf = appendQuoted(buf, params.Request.UserAgent()) buf = appendQuoted(buf, params.Request.UserAgent())
buf = append(buf, '"', '\n') buf = append(buf, '"', '\n')
writer.Write(buf) _, _ = writer.Write(buf)
} }
// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in // CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
@ -212,7 +215,7 @@ func writeCombinedLog(writer io.Writer, params LogFormatterParams) {
// //
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format. // See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
// //
// LoggingHandler always sets the ident field of the log to - // LoggingHandler always sets the ident field of the log to -.
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler { func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
return loggingHandler{out, h, writeCombinedLog} return loggingHandler{out, h, writeCombinedLog}
} }
@ -226,19 +229,18 @@ func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
// //
// Example: // Example:
// //
// r := mux.NewRouter() // r := mux.NewRouter()
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// w.Write([]byte("This is a catch-all route")) // w.Write([]byte("This is a catch-all route"))
// }) // })
// loggedRouter := handlers.LoggingHandler(os.Stdout, r) // loggedRouter := handlers.LoggingHandler(os.Stdout, r)
// http.ListenAndServe(":1123", loggedRouter) // http.ListenAndServe(":1123", loggedRouter)
//
func LoggingHandler(out io.Writer, h http.Handler) http.Handler { func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
return loggingHandler{out, h, writeLog} return loggingHandler{out, h, writeLog}
} }
// CustomLoggingHandler provides a way to supply a custom log formatter // CustomLoggingHandler provides a way to supply a custom log formatter
// while taking advantage of the mechanisms in this package // while taking advantage of the mechanisms in this package.
func CustomLoggingHandler(out io.Writer, h http.Handler, f LogFormatter) http.Handler { func CustomLoggingHandler(out io.Writer, h http.Handler, f LogFormatter) http.Handler {
return loggingHandler{out, h, f} return loggingHandler{out, h, f}
} }

View file

@ -18,7 +18,7 @@ var (
var ( var (
// RFC7239 defines a new "Forwarded: " header designed to replace the // RFC7239 defines a new "Forwarded: " header designed to replace the
// existing use of X-Forwarded-* headers. // existing use of X-Forwarded-* headers.
// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43 // e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43.
forwarded = http.CanonicalHeaderKey("Forwarded") forwarded = http.CanonicalHeaderKey("Forwarded")
// Allows for a sub-match of the first value after 'for=' to the next // Allows for a sub-match of the first value after 'for=' to the next
// comma, semi-colon or space. The match is case-insensitive. // comma, semi-colon or space. The match is case-insensitive.
@ -67,7 +67,9 @@ func ProxyHeaders(h http.Handler) http.Handler {
func getIP(r *http.Request) string { func getIP(r *http.Request) string {
var addr string var addr string
if fwd := r.Header.Get(xForwardedFor); fwd != "" { switch {
case r.Header.Get(xForwardedFor) != "":
fwd := r.Header.Get(xForwardedFor)
// Only grab the first (client) address. Note that '192.168.0.1, // Only grab the first (client) address. Note that '192.168.0.1,
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
// the first may represent forwarding proxies earlier in the chain. // the first may represent forwarding proxies earlier in the chain.
@ -76,17 +78,15 @@ func getIP(r *http.Request) string {
s = len(fwd) s = len(fwd)
} }
addr = fwd[:s] addr = fwd[:s]
} else if fwd := r.Header.Get(xRealIP); fwd != "" { case r.Header.Get(xRealIP) != "":
// X-Real-IP should only contain one IP address (the client making the addr = r.Header.Get(xRealIP)
// request). case r.Header.Get(forwarded) != "":
addr = fwd
} else if fwd := r.Header.Get(forwarded); fwd != "" {
// match should contain at least two elements if the protocol was // match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be // specified in the Forwarded header. The first element will always be
// the 'for=' capture, which we ignore. In the case of multiple IP // the 'for=' capture, which we ignore. In the case of multiple IP
// addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only // addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only
// extract the first, which should be the client IP. // extract the first, which should be the client IP.
if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 { if match := forRegex.FindStringSubmatch(r.Header.Get(forwarded)); len(match) > 1 {
// IPv6 addresses in Forwarded headers are quoted-strings. We strip // IPv6 addresses in Forwarded headers are quoted-strings. We strip
// these quotes. // these quotes.
addr = strings.Trim(match[1], `"`) addr = strings.Trim(match[1], `"`)

View file

@ -36,12 +36,12 @@ func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
// //
// Example: // Example:
// //
// r := mux.NewRouter() // r := mux.NewRouter()
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// panic("Unexpected error!") // panic("Unexpected error!")
// }) // })
// //
// http.ListenAndServe(":1123", handlers.RecoveryHandler()(r)) // http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler { func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
return func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler {
r := &recoveryHandler{handler: h} r := &recoveryHandler{handler: h}
@ -50,20 +50,22 @@ func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
} }
// RecoveryLogger is a functional option to override // RecoveryLogger is a functional option to override
// the default logger // the default logger.
func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption { func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption {
return func(h http.Handler) { return func(h http.Handler) {
r := h.(*recoveryHandler) r := h.(*recoveryHandler) //nolint:errcheck //TODO:
// @bharat-rajani should return type-assertion error but would break the API?
r.logger = logger r.logger = logger
} }
} }
// PrintRecoveryStack is a functional option to enable // PrintRecoveryStack is a functional option to enable
// or disable printing stack traces on panic. // or disable printing stack traces on panic.
func PrintRecoveryStack(print bool) RecoveryOption { func PrintRecoveryStack(shouldPrint bool) RecoveryOption {
return func(h http.Handler) { return func(h http.Handler) {
r := h.(*recoveryHandler) r := h.(*recoveryHandler) //nolint:errcheck //TODO:
r.printStack = print // @bharat-rajani should return type-assertion error but would break the API?
r.printStack = shouldPrint
} }
} }

4
vendor/modules.txt vendored
View file

@ -243,8 +243,8 @@ github.com/googleapis/gax-go/v2
github.com/googleapis/gax-go/v2/apierror github.com/googleapis/gax-go/v2/apierror
github.com/googleapis/gax-go/v2/apierror/internal/proto github.com/googleapis/gax-go/v2/apierror/internal/proto
github.com/googleapis/gax-go/v2/internal github.com/googleapis/gax-go/v2/internal
# github.com/gorilla/handlers v1.5.1 # github.com/gorilla/handlers v1.5.2
## explicit; go 1.14 ## explicit; go 1.20
github.com/gorilla/handlers github.com/gorilla/handlers
# github.com/gorilla/mux v1.8.1 # github.com/gorilla/mux v1.8.1
## explicit; go 1.20 ## explicit; go 1.20