mirror of
https://github.com/umputun/reproxy.git
synced 2024-11-26 22:53:47 +03:00
update github.com/go-pkgz/rest
This commit is contained in:
parent
cda43cfb5c
commit
bca30df215
2
go.mod
2
go.mod
@ -8,7 +8,7 @@ require (
|
||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||
github.com/go-pkgz/lgr v0.10.4
|
||||
github.com/go-pkgz/repeater v1.1.3
|
||||
github.com/go-pkgz/rest v1.12.2
|
||||
github.com/go-pkgz/rest v1.14.0
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/prometheus/client_golang v1.12.1
|
||||
|
4
go.sum
4
go.sum
@ -79,8 +79,8 @@ github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw=
|
||||
github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0=
|
||||
github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE=
|
||||
github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw=
|
||||
github.com/go-pkgz/rest v1.12.2 h1:AQ7uuBmMcufbiUBc4IS8aqDNMvRJlhtRpXLSNRitjVo=
|
||||
github.com/go-pkgz/rest v1.12.2/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-pkgz/rest v1.14.0 h1:brDLCzIGoe0IiUZqRFpsiCVM9m3L88A7z62qS0V9Yfk=
|
||||
github.com/go-pkgz/rest v1.14.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
|
23
vendor/github.com/go-pkgz/rest/README.md
generated
vendored
23
vendor/github.com/go-pkgz/rest/README.md
generated
vendored
@ -93,22 +93,32 @@ Adds the HTTP Deprecation response header, see [draft-dalal-deprecation-header-0
|
||||
BasicAuth middleware requires basic auth and matches user & passwd with client-provided checker. In case if no basic auth headers returns
|
||||
`StatusUnauthorized`, in case if checker failed - `StatusForbidden`
|
||||
|
||||
## Rewrite middleware
|
||||
### Rewrite middleware
|
||||
|
||||
Rewrites requests with from->to rule. Supports regex (like nginx) and prevents multiple rewrites. For example `Rewrite("^/sites/(.*)/settings/$", "/sites/settings/$1")` will change request's URL from `/sites/id1/settings/` to `/sites/settings/id1`
|
||||
|
||||
## NoCache middleware
|
||||
### NoCache middleware
|
||||
|
||||
Sets a number of HTTP headers to prevent a router (handler's) response from being cached by an upstream proxy and/or client.
|
||||
|
||||
## Headers middleware
|
||||
### Headers middleware
|
||||
|
||||
Sets headers (passed as key:value) to requests. I.e. `rest.Headers("Server:MyServer", "X-Blah:Foo")`
|
||||
|
||||
## Gzip middleware
|
||||
### Gzip middleware
|
||||
|
||||
Compresses response with gzip.
|
||||
|
||||
### RealIP middleware
|
||||
|
||||
RealIP is a middleware that sets a http.Request's RemoteAddr to the results of parsing either the X-Forwarded-For or X-Real-IP headers.
|
||||
|
||||
### Maybe middleware
|
||||
|
||||
Maybe middleware will allow you to change the flow of the middleware stack execution depending on return
|
||||
value of maybeFn(request). This is useful for example if you'd like to skip a middleware handler if
|
||||
a request does not satisfy the maybeFn logic.
|
||||
|
||||
## Helpers
|
||||
|
||||
- `rest.Wrap` - converts a list of middlewares to nested handlers calls (in reverse order)
|
||||
@ -119,6 +129,8 @@ Compresses response with gzip.
|
||||
- `rest.SendErrorJSON` - makes `{error: blah, details: blah}` json body and responds with given error code. Also, adds context to the logged message
|
||||
- `rest.NewErrorLogger` - creates a struct providing shorter form of logger call
|
||||
- `rest.FileServer` - creates a file server for static assets with directory listing disabled
|
||||
- `realip.Get` - returns client's IP address
|
||||
- `rest.ParseFromTo` - parses "from" and "to" request's query params with various formats
|
||||
|
||||
## Profiler
|
||||
|
||||
@ -133,5 +145,6 @@ Profiler is a convenient subrouter used for mounting net/http/pprof, i.e.
|
||||
return r
|
||||
}
|
||||
```
|
||||
It exposes a whole bunch of `/pprof/*` endpoints as well as `/vars`. Builtin support for `onlyIps` allows to restrict access, which is important if it runs on a publicly exposed port. However, counting on IP check only is not that reliable way to limit request and for production use it would be better to add some sort of auth (for example provided `BasicAuth` middleware) or run with a separate http server, exposed to internal ip/port only.
|
||||
|
||||
It exposes a bunch of `/pprof/*` endpoints as well as `/vars`. Builtin support for `onlyIps` allows restricting access, which is important if it runs on a publicly exposed port. However, counting on IP check only is not that reliable way to limit request and for production use it would be better to add some sort of auth (for example provided `BasicAuth` middleware) or run with a separate http server, exposed to internal ip/port only.
|
||||
|
||||
|
29
vendor/github.com/go-pkgz/rest/logger/logger.go
generated
vendored
29
vendor/github.com/go-pkgz/rest/logger/logger.go
generated
vendored
@ -14,6 +14,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-pkgz/rest/realip"
|
||||
)
|
||||
|
||||
// Middleware is a logger for rest requests.
|
||||
@ -103,7 +105,10 @@ func (l *Middleware) Handler(next http.Handler) http.Handler {
|
||||
rawurl = unescURL
|
||||
}
|
||||
|
||||
remoteIP := l.remoteIP(r)
|
||||
remoteIP, err := realip.Get(r)
|
||||
if err != nil {
|
||||
remoteIP = "unknown ip"
|
||||
}
|
||||
if l.ipFn != nil { // mask ip with ipFn
|
||||
remoteIP = l.ipFn(remoteIP)
|
||||
}
|
||||
@ -169,7 +174,7 @@ func (l *Middleware) formatDefault(r *http.Request, p *logParts) string {
|
||||
}
|
||||
|
||||
// 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"
|
||||
//nolint gosec
|
||||
// nolint gosec
|
||||
func (l *Middleware) formatApacheCombined(r *http.Request, p *logParts) string {
|
||||
username := "-"
|
||||
if p.user != "" {
|
||||
@ -291,17 +296,19 @@ func (l *Middleware) sanitizeQuery(rawQuery string) string {
|
||||
return query.Encode()
|
||||
}
|
||||
|
||||
// remoteIP gets address from X-Forwarded-For and than from request's remote address
|
||||
func (l *Middleware) remoteIP(r *http.Request) (remoteIP string) {
|
||||
// AnonymizeIP is a function to reset the last part of IPv4 to 0.
|
||||
// from 123.212.12.78 it will make 123.212.12.0
|
||||
func AnonymizeIP(ip string) string {
|
||||
if ip == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
if remoteIP = r.Header.Get("X-Forwarded-For"); remoteIP == "" {
|
||||
remoteIP = r.RemoteAddr
|
||||
parts := strings.Split(ip, ".")
|
||||
if len(parts) != 4 {
|
||||
return ip
|
||||
}
|
||||
remoteIP = strings.Split(remoteIP, ":")[0]
|
||||
if strings.HasPrefix(remoteIP, "[") {
|
||||
remoteIP = strings.Split(remoteIP, "]:")[0] + "]"
|
||||
}
|
||||
return remoteIP
|
||||
|
||||
return strings.Join(parts[:3], ".") + ".0"
|
||||
}
|
||||
|
||||
// customResponseWriter is an HTTP response logger that keeps HTTP status code and
|
||||
|
21
vendor/github.com/go-pkgz/rest/middleware.go
generated
vendored
21
vendor/github.com/go-pkgz/rest/middleware.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-pkgz/rest/logger"
|
||||
"github.com/go-pkgz/rest/realip"
|
||||
)
|
||||
|
||||
// Wrap converts a list of middlewares to nested calls (in reverse order)
|
||||
@ -93,7 +94,7 @@ func Headers(headers ...string) func(http.Handler) http.Handler {
|
||||
|
||||
// Maybe middleware will allow you to change the flow of the middleware stack execution depending on return
|
||||
// value of maybeFn(request). This is useful for example if you'd like to skip a middleware handler if
|
||||
// a request does not satisfied the maybeFn logic.
|
||||
// a request does not satisfy the maybeFn logic.
|
||||
// borrowed from https://github.com/go-chi/chi/blob/master/middleware/maybe.go
|
||||
func Maybe(mw func(http.Handler) http.Handler, maybeFn func(r *http.Request) bool) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
@ -106,3 +107,21 @@ func Maybe(mw func(http.Handler) http.Handler, maybeFn func(r *http.Request) boo
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// RealIP is a middleware that sets a http.Request's RemoteAddr to the results
|
||||
// of parsing either the X-Forwarded-For or X-Real-IP headers.
|
||||
//
|
||||
// This middleware should only be used if user can trust the headers sent with request.
|
||||
// If reverse proxies are configured to pass along arbitrary header values from the client,
|
||||
// or if this middleware used without a reverse proxy, malicious clients could set anything
|
||||
// as X-Forwarded-For header and attack the server in various ways.
|
||||
func RealIP(h http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
if rip, err := realip.Get(r); err == nil {
|
||||
r.RemoteAddr = rip
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
80
vendor/github.com/go-pkgz/rest/realip/real.go
generated
vendored
Normal file
80
vendor/github.com/go-pkgz/rest/realip/real.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Package realip extracts a real IP address from the request.
|
||||
package realip
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ipRange struct {
|
||||
start net.IP
|
||||
end net.IP
|
||||
}
|
||||
|
||||
var privateRanges = []ipRange{
|
||||
{start: net.ParseIP("10.0.0.0"), end: net.ParseIP("10.255.255.255")},
|
||||
{start: net.ParseIP("100.64.0.0"), end: net.ParseIP("100.127.255.255")},
|
||||
{start: net.ParseIP("172.16.0.0"), end: net.ParseIP("172.31.255.255")},
|
||||
{start: net.ParseIP("192.0.0.0"), end: net.ParseIP("192.0.0.255")},
|
||||
{start: net.ParseIP("192.168.0.0"), end: net.ParseIP("192.168.255.255")},
|
||||
{start: net.ParseIP("198.18.0.0"), end: net.ParseIP("198.19.255.255")},
|
||||
}
|
||||
|
||||
// Get returns real ip from the given request
|
||||
func Get(r *http.Request) (string, error) {
|
||||
|
||||
for _, h := range []string{"X-Forwarded-For", "X-Real-Ip"} {
|
||||
addresses := strings.Split(r.Header.Get(h), ",")
|
||||
// march from right to left until we get a public address
|
||||
// that will be the address right before our proxy.
|
||||
for i := len(addresses) - 1; i >= 0; i-- {
|
||||
ip := strings.TrimSpace(addresses[i])
|
||||
realIP := net.ParseIP(ip)
|
||||
if !realIP.IsGlobalUnicast() || isPrivateSubnet(realIP) {
|
||||
continue
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
|
||||
// X-Forwarded-For header set but parsing failed above
|
||||
if r.Header.Get("X-Forwarded-For") != "" {
|
||||
return "", fmt.Errorf("no valid ip found")
|
||||
}
|
||||
|
||||
// get IP from RemoteAddr
|
||||
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can't parse ip %q: %w", r.RemoteAddr, err)
|
||||
}
|
||||
if netIP := net.ParseIP(ip); netIP == nil {
|
||||
return "", fmt.Errorf("no valid ip found")
|
||||
}
|
||||
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// inRange - check to see if a given ip address is within a range given
|
||||
func inRange(r ipRange, ipAddress net.IP) bool {
|
||||
// strcmp type byte comparison
|
||||
if bytes.Compare(ipAddress, r.start) >= 0 && bytes.Compare(ipAddress, r.end) < 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isPrivateSubnet - check to see if this ip is in a private subnet
|
||||
func isPrivateSubnet(ipAddress net.IP) bool {
|
||||
if ipCheck := ipAddress.To4(); ipCheck != nil {
|
||||
for _, r := range privateRanges {
|
||||
// check if this ip is in a private range
|
||||
if inRange(r, ipAddress) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
31
vendor/github.com/go-pkgz/rest/rest.go
generated
vendored
31
vendor/github.com/go-pkgz/rest/rest.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -67,3 +68,33 @@ func renderJSONWithStatus(w http.ResponseWriter, data interface{}, code int) {
|
||||
w.WriteHeader(code)
|
||||
_, _ = w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
// ParseFromTo parses from and to query params of the request
|
||||
func ParseFromTo(r *http.Request) (from, to time.Time, err error) {
|
||||
parseTimeStamp := func(ts string) (time.Time, error) {
|
||||
formats := []string{
|
||||
"2006-01-02T15:04:05.000000000",
|
||||
"2006-01-02T15:04:05",
|
||||
"2006-01-02T15:04",
|
||||
"20060102",
|
||||
time.RFC3339,
|
||||
time.RFC3339Nano,
|
||||
}
|
||||
|
||||
for _, f := range formats {
|
||||
if t, e := time.Parse(f, ts); e == nil {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return time.Time{}, errors.Errorf("can't parse date %q", ts)
|
||||
}
|
||||
|
||||
if from, err = parseTimeStamp(r.URL.Query().Get("from")); err != nil {
|
||||
return from, to, errors.Wrap(err, "incorrect from time")
|
||||
}
|
||||
|
||||
if to, err = parseTimeStamp(r.URL.Query().Get("to")); err != nil {
|
||||
return from, to, errors.Wrap(err, "incorrect to time")
|
||||
}
|
||||
return from, to, nil
|
||||
}
|
||||
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@ -26,10 +26,11 @@ github.com/go-pkgz/lgr
|
||||
## explicit; go 1.12
|
||||
github.com/go-pkgz/repeater
|
||||
github.com/go-pkgz/repeater/strategy
|
||||
# github.com/go-pkgz/rest v1.12.2
|
||||
# github.com/go-pkgz/rest v1.14.0
|
||||
## explicit; go 1.16
|
||||
github.com/go-pkgz/rest
|
||||
github.com/go-pkgz/rest/logger
|
||||
github.com/go-pkgz/rest/realip
|
||||
# github.com/golang/protobuf v1.5.2
|
||||
## explicit; go 1.9
|
||||
github.com/golang/protobuf/proto
|
||||
|
Loading…
Reference in New Issue
Block a user