From df32d622f4bc28f4fd63dec060386f30e07f60ef Mon Sep 17 00:00:00 2001 From: rekby Date: Sat, 1 Feb 2020 20:58:12 +0300 Subject: [PATCH 1/3] vendor --- go.mod | 1 + go.sum | 2 + vendor/golang.org/x/xerrors/LICENSE | 27 +++ vendor/golang.org/x/xerrors/PATENTS | 22 ++ vendor/golang.org/x/xerrors/README | 2 + vendor/golang.org/x/xerrors/adaptor.go | 193 ++++++++++++++++++ vendor/golang.org/x/xerrors/codereview.cfg | 1 + vendor/golang.org/x/xerrors/doc.go | 22 ++ vendor/golang.org/x/xerrors/errors.go | 33 +++ vendor/golang.org/x/xerrors/fmt.go | 187 +++++++++++++++++ vendor/golang.org/x/xerrors/format.go | 34 +++ vendor/golang.org/x/xerrors/frame.go | 56 +++++ vendor/golang.org/x/xerrors/go.mod | 3 + .../golang.org/x/xerrors/internal/internal.go | 8 + vendor/golang.org/x/xerrors/wrap.go | 106 ++++++++++ vendor/modules.txt | 3 + 16 files changed, 700 insertions(+) create mode 100644 vendor/golang.org/x/xerrors/LICENSE create mode 100644 vendor/golang.org/x/xerrors/PATENTS create mode 100644 vendor/golang.org/x/xerrors/README create mode 100644 vendor/golang.org/x/xerrors/adaptor.go create mode 100644 vendor/golang.org/x/xerrors/codereview.cfg create mode 100644 vendor/golang.org/x/xerrors/doc.go create mode 100644 vendor/golang.org/x/xerrors/errors.go create mode 100644 vendor/golang.org/x/xerrors/fmt.go create mode 100644 vendor/golang.org/x/xerrors/format.go create mode 100644 vendor/golang.org/x/xerrors/frame.go create mode 100644 vendor/golang.org/x/xerrors/go.mod create mode 100644 vendor/golang.org/x/xerrors/internal/internal.go create mode 100644 vendor/golang.org/x/xerrors/wrap.go diff --git a/go.mod b/go.mod index ea63e713..07044ddc 100644 --- a/go.mod +++ b/go.mod @@ -15,5 +15,6 @@ require ( go.uber.org/zap v1.11.0 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) diff --git a/go.sum b/go.sum index 00051700..4d7dafb4 100644 --- a/go.sum +++ b/go.sum @@ -135,6 +135,8 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vendor/golang.org/x/xerrors/LICENSE b/vendor/golang.org/x/xerrors/LICENSE new file mode 100644 index 00000000..e4a47e17 --- /dev/null +++ b/vendor/golang.org/x/xerrors/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2019 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 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. diff --git a/vendor/golang.org/x/xerrors/PATENTS b/vendor/golang.org/x/xerrors/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/xerrors/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/xerrors/README b/vendor/golang.org/x/xerrors/README new file mode 100644 index 00000000..aac7867a --- /dev/null +++ b/vendor/golang.org/x/xerrors/README @@ -0,0 +1,2 @@ +This repository holds the transition packages for the new Go 1.13 error values. +See golang.org/design/29934-error-values. diff --git a/vendor/golang.org/x/xerrors/adaptor.go b/vendor/golang.org/x/xerrors/adaptor.go new file mode 100644 index 00000000..4317f248 --- /dev/null +++ b/vendor/golang.org/x/xerrors/adaptor.go @@ -0,0 +1,193 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +import ( + "bytes" + "fmt" + "io" + "reflect" + "strconv" +) + +// FormatError calls the FormatError method of f with an errors.Printer +// configured according to s and verb, and writes the result to s. +func FormatError(f Formatter, s fmt.State, verb rune) { + // Assuming this function is only called from the Format method, and given + // that FormatError takes precedence over Format, it cannot be called from + // any package that supports errors.Formatter. It is therefore safe to + // disregard that State may be a specific printer implementation and use one + // of our choice instead. + + // limitations: does not support printing error as Go struct. + + var ( + sep = " " // separator before next error + p = &state{State: s} + direct = true + ) + + var err error = f + + switch verb { + // Note that this switch must match the preference order + // for ordinary string printing (%#v before %+v, and so on). + + case 'v': + if s.Flag('#') { + if stringer, ok := err.(fmt.GoStringer); ok { + io.WriteString(&p.buf, stringer.GoString()) + goto exit + } + // proceed as if it were %v + } else if s.Flag('+') { + p.printDetail = true + sep = "\n - " + } + case 's': + case 'q', 'x', 'X': + // Use an intermediate buffer in the rare cases that precision, + // truncation, or one of the alternative verbs (q, x, and X) are + // specified. + direct = false + + default: + p.buf.WriteString("%!") + p.buf.WriteRune(verb) + p.buf.WriteByte('(') + switch { + case err != nil: + p.buf.WriteString(reflect.TypeOf(f).String()) + default: + p.buf.WriteString("") + } + p.buf.WriteByte(')') + io.Copy(s, &p.buf) + return + } + +loop: + for { + switch v := err.(type) { + case Formatter: + err = v.FormatError((*printer)(p)) + case fmt.Formatter: + v.Format(p, 'v') + break loop + default: + io.WriteString(&p.buf, v.Error()) + break loop + } + if err == nil { + break + } + if p.needColon || !p.printDetail { + p.buf.WriteByte(':') + p.needColon = false + } + p.buf.WriteString(sep) + p.inDetail = false + p.needNewline = false + } + +exit: + width, okW := s.Width() + prec, okP := s.Precision() + + if !direct || (okW && width > 0) || okP { + // Construct format string from State s. + format := []byte{'%'} + if s.Flag('-') { + format = append(format, '-') + } + if s.Flag('+') { + format = append(format, '+') + } + if s.Flag(' ') { + format = append(format, ' ') + } + if okW { + format = strconv.AppendInt(format, int64(width), 10) + } + if okP { + format = append(format, '.') + format = strconv.AppendInt(format, int64(prec), 10) + } + format = append(format, string(verb)...) + fmt.Fprintf(s, string(format), p.buf.String()) + } else { + io.Copy(s, &p.buf) + } +} + +var detailSep = []byte("\n ") + +// state tracks error printing state. It implements fmt.State. +type state struct { + fmt.State + buf bytes.Buffer + + printDetail bool + inDetail bool + needColon bool + needNewline bool +} + +func (s *state) Write(b []byte) (n int, err error) { + if s.printDetail { + if len(b) == 0 { + return 0, nil + } + if s.inDetail && s.needColon { + s.needNewline = true + if b[0] == '\n' { + b = b[1:] + } + } + k := 0 + for i, c := range b { + if s.needNewline { + if s.inDetail && s.needColon { + s.buf.WriteByte(':') + s.needColon = false + } + s.buf.Write(detailSep) + s.needNewline = false + } + if c == '\n' { + s.buf.Write(b[k:i]) + k = i + 1 + s.needNewline = true + } + } + s.buf.Write(b[k:]) + if !s.inDetail { + s.needColon = true + } + } else if !s.inDetail { + s.buf.Write(b) + } + return len(b), nil +} + +// printer wraps a state to implement an xerrors.Printer. +type printer state + +func (s *printer) Print(args ...interface{}) { + if !s.inDetail || s.printDetail { + fmt.Fprint((*state)(s), args...) + } +} + +func (s *printer) Printf(format string, args ...interface{}) { + if !s.inDetail || s.printDetail { + fmt.Fprintf((*state)(s), format, args...) + } +} + +func (s *printer) Detail() bool { + s.inDetail = true + return s.printDetail +} diff --git a/vendor/golang.org/x/xerrors/codereview.cfg b/vendor/golang.org/x/xerrors/codereview.cfg new file mode 100644 index 00000000..3f8b14b6 --- /dev/null +++ b/vendor/golang.org/x/xerrors/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/vendor/golang.org/x/xerrors/doc.go b/vendor/golang.org/x/xerrors/doc.go new file mode 100644 index 00000000..eef99d9d --- /dev/null +++ b/vendor/golang.org/x/xerrors/doc.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package xerrors implements functions to manipulate errors. +// +// This package is based on the Go 2 proposal for error values: +// https://golang.org/design/29934-error-values +// +// These functions were incorporated into the standard library's errors package +// in Go 1.13: +// - Is +// - As +// - Unwrap +// +// Also, Errorf's %w verb was incorporated into fmt.Errorf. +// +// Use this package to get equivalent behavior in all supported Go versions. +// +// No other features of this package were included in Go 1.13, and at present +// there are no plans to include any of them. +package xerrors // import "golang.org/x/xerrors" diff --git a/vendor/golang.org/x/xerrors/errors.go b/vendor/golang.org/x/xerrors/errors.go new file mode 100644 index 00000000..e88d3772 --- /dev/null +++ b/vendor/golang.org/x/xerrors/errors.go @@ -0,0 +1,33 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +import "fmt" + +// errorString is a trivial implementation of error. +type errorString struct { + s string + frame Frame +} + +// New returns an error that formats as the given text. +// +// The returned error contains a Frame set to the caller's location and +// implements Formatter to show this information when printed with details. +func New(text string) error { + return &errorString{text, Caller(1)} +} + +func (e *errorString) Error() string { + return e.s +} + +func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } + +func (e *errorString) FormatError(p Printer) (next error) { + p.Print(e.s) + e.frame.Format(p) + return nil +} diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go new file mode 100644 index 00000000..829862dd --- /dev/null +++ b/vendor/golang.org/x/xerrors/fmt.go @@ -0,0 +1,187 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" + + "golang.org/x/xerrors/internal" +) + +const percentBangString = "%!" + +// Errorf formats according to a format specifier and returns the string as a +// value that satisfies error. +// +// The returned error includes the file and line number of the caller when +// formatted with additional detail enabled. If the last argument is an error +// the returned error's Format method will return it if the format string ends +// with ": %s", ": %v", or ": %w". If the last argument is an error and the +// format string ends with ": %w", the returned error implements an Unwrap +// method returning it. +// +// If the format specifier includes a %w verb with an error operand in a +// position other than at the end, the returned error will still implement an +// Unwrap method returning the operand, but the error's Format method will not +// return the wrapped error. +// +// It is invalid to include more than one %w verb or to supply it with an +// operand that does not implement the error interface. The %w verb is otherwise +// a synonym for %v. +func Errorf(format string, a ...interface{}) error { + format = formatPlusW(format) + // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter. + wrap := strings.HasSuffix(format, ": %w") + idx, format2, ok := parsePercentW(format) + percentWElsewhere := !wrap && idx >= 0 + if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) { + err := errorAt(a, len(a)-1) + if err == nil { + return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} + } + // TODO: this is not entirely correct. The error value could be + // printed elsewhere in format if it mixes numbered with unnumbered + // substitutions. With relatively small changes to doPrintf we can + // have it optionally ignore extra arguments and pass the argument + // list in its entirety. + msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) + frame := Frame{} + if internal.EnableTrace { + frame = Caller(1) + } + if wrap { + return &wrapError{msg, err, frame} + } + return &noWrapError{msg, err, frame} + } + // Support %w anywhere. + // TODO: don't repeat the wrapped error's message when %w occurs in the middle. + msg := fmt.Sprintf(format2, a...) + if idx < 0 { + return &noWrapError{msg, nil, Caller(1)} + } + err := errorAt(a, idx) + if !ok || err == nil { + // Too many %ws or argument of %w is not an error. Approximate the Go + // 1.13 fmt.Errorf message. + return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)} + } + frame := Frame{} + if internal.EnableTrace { + frame = Caller(1) + } + return &wrapError{msg, err, frame} +} + +func errorAt(args []interface{}, i int) error { + if i < 0 || i >= len(args) { + return nil + } + err, ok := args[i].(error) + if !ok { + return nil + } + return err +} + +// formatPlusW is used to avoid the vet check that will barf at %w. +func formatPlusW(s string) string { + return s +} + +// Return the index of the only %w in format, or -1 if none. +// Also return a rewritten format string with %w replaced by %v, and +// false if there is more than one %w. +// TODO: handle "%[N]w". +func parsePercentW(format string) (idx int, newFormat string, ok bool) { + // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go. + idx = -1 + ok = true + n := 0 + sz := 0 + var isW bool + for i := 0; i < len(format); i += sz { + if format[i] != '%' { + sz = 1 + continue + } + // "%%" is not a format directive. + if i+1 < len(format) && format[i+1] == '%' { + sz = 2 + continue + } + sz, isW = parsePrintfVerb(format[i:]) + if isW { + if idx >= 0 { + ok = false + } else { + idx = n + } + // "Replace" the last character, the 'w', with a 'v'. + p := i + sz - 1 + format = format[:p] + "v" + format[p+1:] + } + n++ + } + return idx, format, ok +} + +// Parse the printf verb starting with a % at s[0]. +// Return how many bytes it occupies and whether the verb is 'w'. +func parsePrintfVerb(s string) (int, bool) { + // Assume only that the directive is a sequence of non-letters followed by a single letter. + sz := 0 + var r rune + for i := 1; i < len(s); i += sz { + r, sz = utf8.DecodeRuneInString(s[i:]) + if unicode.IsLetter(r) { + return i + sz, r == 'w' + } + } + return len(s), false +} + +type noWrapError struct { + msg string + err error + frame Frame +} + +func (e *noWrapError) Error() string { + return fmt.Sprint(e) +} + +func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } + +func (e *noWrapError) FormatError(p Printer) (next error) { + p.Print(e.msg) + e.frame.Format(p) + return e.err +} + +type wrapError struct { + msg string + err error + frame Frame +} + +func (e *wrapError) Error() string { + return fmt.Sprint(e) +} + +func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } + +func (e *wrapError) FormatError(p Printer) (next error) { + p.Print(e.msg) + e.frame.Format(p) + return e.err +} + +func (e *wrapError) Unwrap() error { + return e.err +} diff --git a/vendor/golang.org/x/xerrors/format.go b/vendor/golang.org/x/xerrors/format.go new file mode 100644 index 00000000..1bc9c26b --- /dev/null +++ b/vendor/golang.org/x/xerrors/format.go @@ -0,0 +1,34 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +// A Formatter formats error messages. +type Formatter interface { + error + + // FormatError prints the receiver's first error and returns the next error in + // the error chain, if any. + FormatError(p Printer) (next error) +} + +// A Printer formats error messages. +// +// The most common implementation of Printer is the one provided by package fmt +// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message +// typically provide their own implementations. +type Printer interface { + // Print appends args to the message output. + Print(args ...interface{}) + + // Printf writes a formatted string. + Printf(format string, args ...interface{}) + + // Detail reports whether error detail is requested. + // After the first call to Detail, all text written to the Printer + // is formatted as additional detail, or ignored when + // detail has not been requested. + // If Detail returns false, the caller can avoid printing the detail at all. + Detail() bool +} diff --git a/vendor/golang.org/x/xerrors/frame.go b/vendor/golang.org/x/xerrors/frame.go new file mode 100644 index 00000000..0de628ec --- /dev/null +++ b/vendor/golang.org/x/xerrors/frame.go @@ -0,0 +1,56 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +import ( + "runtime" +) + +// A Frame contains part of a call stack. +type Frame struct { + // Make room for three PCs: the one we were asked for, what it called, + // and possibly a PC for skipPleaseUseCallersFrames. See: + // https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169 + frames [3]uintptr +} + +// Caller returns a Frame that describes a frame on the caller's stack. +// The argument skip is the number of frames to skip over. +// Caller(0) returns the frame for the caller of Caller. +func Caller(skip int) Frame { + var s Frame + runtime.Callers(skip+1, s.frames[:]) + return s +} + +// location reports the file, line, and function of a frame. +// +// The returned function may be "" even if file and line are not. +func (f Frame) location() (function, file string, line int) { + frames := runtime.CallersFrames(f.frames[:]) + if _, ok := frames.Next(); !ok { + return "", "", 0 + } + fr, ok := frames.Next() + if !ok { + return "", "", 0 + } + return fr.Function, fr.File, fr.Line +} + +// Format prints the stack as error detail. +// It should be called from an error's Format implementation +// after printing any other error detail. +func (f Frame) Format(p Printer) { + if p.Detail() { + function, file, line := f.location() + if function != "" { + p.Printf("%s\n ", function) + } + if file != "" { + p.Printf("%s:%d\n", file, line) + } + } +} diff --git a/vendor/golang.org/x/xerrors/go.mod b/vendor/golang.org/x/xerrors/go.mod new file mode 100644 index 00000000..870d4f61 --- /dev/null +++ b/vendor/golang.org/x/xerrors/go.mod @@ -0,0 +1,3 @@ +module golang.org/x/xerrors + +go 1.11 diff --git a/vendor/golang.org/x/xerrors/internal/internal.go b/vendor/golang.org/x/xerrors/internal/internal.go new file mode 100644 index 00000000..89f4eca5 --- /dev/null +++ b/vendor/golang.org/x/xerrors/internal/internal.go @@ -0,0 +1,8 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +// EnableTrace indicates whether stack information should be recorded in errors. +var EnableTrace = true diff --git a/vendor/golang.org/x/xerrors/wrap.go b/vendor/golang.org/x/xerrors/wrap.go new file mode 100644 index 00000000..9a3b5103 --- /dev/null +++ b/vendor/golang.org/x/xerrors/wrap.go @@ -0,0 +1,106 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xerrors + +import ( + "reflect" +) + +// A Wrapper provides context around another error. +type Wrapper interface { + // Unwrap returns the next error in the error chain. + // If there is no next error, Unwrap returns nil. + Unwrap() error +} + +// Opaque returns an error with the same error formatting as err +// but that does not match err and cannot be unwrapped. +func Opaque(err error) error { + return noWrapper{err} +} + +type noWrapper struct { + error +} + +func (e noWrapper) FormatError(p Printer) (next error) { + if f, ok := e.error.(Formatter); ok { + return f.FormatError(p) + } + p.Print(e.error) + return nil +} + +// Unwrap returns the result of calling the Unwrap method on err, if err implements +// Unwrap. Otherwise, Unwrap returns nil. +func Unwrap(err error) error { + u, ok := err.(Wrapper) + if !ok { + return nil + } + return u.Unwrap() +} + +// Is reports whether any error in err's chain matches target. +// +// An error is considered to match a target if it is equal to that target or if +// it implements a method Is(error) bool such that Is(target) returns true. +func Is(err, target error) bool { + if target == nil { + return err == target + } + + isComparable := reflect.TypeOf(target).Comparable() + for { + if isComparable && err == target { + return true + } + if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { + return true + } + // TODO: consider supporing target.Is(err). This would allow + // user-definable predicates, but also may allow for coping with sloppy + // APIs, thereby making it easier to get away with them. + if err = Unwrap(err); err == nil { + return false + } + } +} + +// As finds the first error in err's chain that matches the type to which target +// points, and if so, sets the target to its value and returns true. An error +// matches a type if it is assignable to the target type, or if it has a method +// As(interface{}) bool such that As(target) returns true. As will panic if target +// is not a non-nil pointer to a type which implements error or is of interface type. +// +// The As method should set the target to its value and return true if err +// matches the type to which target points. +func As(err error, target interface{}) bool { + if target == nil { + panic("errors: target cannot be nil") + } + val := reflect.ValueOf(target) + typ := val.Type() + if typ.Kind() != reflect.Ptr || val.IsNil() { + panic("errors: target must be a non-nil pointer") + } + if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) { + panic("errors: *target must be interface or implement error") + } + targetType := typ.Elem() + for err != nil { + if reflect.TypeOf(err).AssignableTo(targetType) { + val.Elem().Set(reflect.ValueOf(err)) + return true + } + if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { + return true + } + err = Unwrap(err) + } + return false +} + +var errorType = reflect.TypeOf((*error)(nil)).Elem() diff --git a/vendor/modules.txt b/vendor/modules.txt index 6153c078..01755c8d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -69,5 +69,8 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm +# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 +golang.org/x/xerrors +golang.org/x/xerrors/internal # gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2 From d2af41ca57ebfd7a91206dc4d0abeac9c51c73a2 Mon Sep 17 00:00:00 2001 From: rekby Date: Sat, 1 Feb 2020 21:01:44 +0300 Subject: [PATCH 2/3] remove log files --- .gitignore | 2 + internal/proxy/transport.go | 64 ++++++++++++++++++++++++++++++++ internal/proxy/transport_test.go | 39 +++++++++++++++++++ lets-proxy.log | 7 ---- lets-proxy2.log | 10 ----- 5 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 internal/proxy/transport.go create mode 100644 internal/proxy/transport_test.go delete mode 100644 lets-proxy.log delete mode 100644 lets-proxy2.log diff --git a/.gitignore b/.gitignore index ae830506..c9aa6460 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ .vscode/ lets-proxy.iml log.txt +lets-proxy.log +lets-proxy2.log storage/ output/ config.toml diff --git a/internal/proxy/transport.go b/internal/proxy/transport.go new file mode 100644 index 00000000..ca858abb --- /dev/null +++ b/internal/proxy/transport.go @@ -0,0 +1,64 @@ +package proxy + +import ( + "crypto/tls" + "net" + "net/http" + "strings" + "time" + + "go.uber.org/zap" + + zc "github.com/rekby/zapcontext" +) + +// copy from go 1.10, need for compile with go 1.10 compiler +// https://github.com/golang/go/blob/b0cb374daf646454998bac7b393f3236a2ab6aca/src/net/http/transport.go#L40 +var defaultTransport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, +} + +type Transport struct { + IgnoreHttpsCertificate bool +} + +func (t Transport) RoundTrip(req *http.Request) (*http.Response, error) { + return t.getTransport(req).RoundTrip(req) +} + +func (t Transport) getTransport(req *http.Request) *http.Transport { + logger := zc.L(req.Context()) + + if req.URL.Scheme == ProtocolHTTP { + logger.Debug("Use default http transport") + return defaultTransport + } + + host := req.Host + if strings.Contains(host, ":") { //strip port + parts := strings.SplitN(host, ":", 2) + host = parts[0] + } + + var transport http.Transport + transport = *defaultTransport + transport.TLSClientConfig = &tls.Config{ServerName: host} + transport.TLSClientConfig.InsecureSkipVerify = t.IgnoreHttpsCertificate + + logger.Debug("Use https transport", + zap.Bool("ignore_cert", transport.TLSClientConfig.InsecureSkipVerify), + zap.String("tls_server_name", host), + zap.String("header_host", req.Header.Get("HOST")), + ) + + return &transport +} diff --git a/internal/proxy/transport_test.go b/internal/proxy/transport_test.go new file mode 100644 index 00000000..266de127 --- /dev/null +++ b/internal/proxy/transport_test.go @@ -0,0 +1,39 @@ +package proxy + +import ( + "net/http" + "testing" + + "github.com/rekby/lets-proxy2/internal/th" + + "github.com/maxatome/go-testdeep" +) + +func TestTransport_GetTransport(t *testing.T) { + ctx, flush := th.TestContext() + defer flush() + + td := testdeep.NewT(t) + + tr := Transport{} + r, _ := http.NewRequest(http.MethodGet, "http://www.ru", nil) + r = r.WithContext(ctx) + httpTransport := tr.getTransport(r) + td.True(httpTransport == defaultTransport) // equal pointers + + tr = Transport{IgnoreHttpsCertificate: false} + r, _ = http.NewRequest(http.MethodGet, "https://www.ru", nil) + r = r.WithContext(ctx) + httpTransport = tr.getTransport(r) + td.True(httpTransport != defaultTransport) // different pointers + td.Cmp(httpTransport.TLSClientConfig.ServerName, "www.ru") + td.Cmp(httpTransport.TLSClientConfig.InsecureSkipVerify, false) + + tr = Transport{IgnoreHttpsCertificate: true} + r, _ = http.NewRequest(http.MethodGet, "https://www.ru", nil) + r = r.WithContext(ctx) + httpTransport = tr.getTransport(r) + td.True(httpTransport != defaultTransport) // different pointers + td.Cmp(httpTransport.TLSClientConfig.ServerName, "www.ru") + td.Cmp(httpTransport.TLSClientConfig.InsecureSkipVerify, true) +} diff --git a/lets-proxy.log b/lets-proxy.log deleted file mode 100644 index b91d961d..00000000 --- a/lets-proxy.log +++ /dev/null @@ -1,7 +0,0 @@ -2019-05-12T15:04:39.883+0300 info cmd/log.go:72 Initialize log on level {"level": "info"} -2019-05-12T15:04:39.884+0300 info cmd/main.go:57 StartAutoRenew program version {"version": "Version: 'custom', Os: 'darwin', Arch: 'amd64'"} -2019-05-12T15:04:39.884+0300 info cmd/main.go:60 Create storage dir -2019-05-12T15:04:39.886+0300 info tlslistener/tlslistenershandler.go:75 StartAutoRenew handleListeners -2019-05-12T15:04:39.886+0300 info proxy/config.go:72 Create same ip director {"port": 80} -2019-05-12T15:04:39.886+0300 info cmd/main.go:89 Apply proxy config -2019-05-12T15:04:39.886+0300 info proxy/http-proxy.go:73 Http builtin reverse proxy start diff --git a/lets-proxy2.log b/lets-proxy2.log deleted file mode 100644 index 9f020480..00000000 --- a/lets-proxy2.log +++ /dev/null @@ -1,10 +0,0 @@ -2019-05-12T01:15:34.794+0300 info cmd/log.go:72 Initialize log on level {"level": "info"} -2019-05-12T01:15:34.794+0300 info cmd/main.go:57 StartAutoRenew program version {"version": "Version: 'custom', Os: 'darwin', Arch: 'amd64'"} -2019-05-12T01:15:34.794+0300 info cmd/main.go:60 Create storage dir -2019-05-12T01:15:35.258+0300 info acme_client_manager/client_manager.go:150 Generate account key -2019-05-12T01:15:36.633+0300 info acme_client_manager/client_manager.go:155 Register acme account -2019-05-12T01:15:36.634+0300 info acme_client_manager/client_manager.go:81 Marshal account state to json -2019-05-12T01:15:36.635+0300 info tlslistener/tlslistenershandler.go:75 StartAutoRenew handleListeners -2019-05-12T01:15:36.636+0300 info proxy/config.go:72 Create same ip director {"port": 80} -2019-05-12T01:15:36.636+0300 info cmd/main.go:89 Apply proxy config -2019-05-12T01:15:36.636+0300 info proxy/http-proxy.go:73 Http builtin reverse proxy start From cbffc073f8624093b267e07adbcf962083ca8568 Mon Sep 17 00:00:00 2001 From: rekby Date: Sat, 1 Feb 2020 21:02:46 +0300 Subject: [PATCH 3/3] Add https backend support --- README_DEV.md | 3 +++ cmd/a_main-packr.go | 2 +- cmd/static/default-config.toml | 9 ++++++- internal/proxy/config.go | 11 ++++++++ internal/proxy/config_test.go | 48 +++++++++++++++++++++++++++++++++- internal/proxy/directors.go | 14 +++++++++- internal/proxy/http-proxy.go | 1 - 7 files changed, 83 insertions(+), 5 deletions(-) diff --git a/README_DEV.md b/README_DEV.md index 7f6bdb1f..c74f155d 100644 --- a/README_DEV.md +++ b/README_DEV.md @@ -12,6 +12,9 @@ If use docker-machine - need ```docker-machine ssh -L 4001:localh FAKE_DNS may be different for other OS. For example for mac os - need run other image and ping host.docker.internal for see IP for host. +```bash +docker run --rm alpine ping host.docker.internal +``` https://docs.docker.com/docker-for-mac/networking/#/known-limitations-use-cases-and-workarounds diff --git a/cmd/a_main-packr.go b/cmd/a_main-packr.go index b4541952..f7353e9d 100644 --- a/cmd/a_main-packr.go +++ b/cmd/a_main-packr.go @@ -7,5 +7,5 @@ import "github.com/gobuffalo/packr" // You can use the "packr clean" command to clean up this, // and any other packr generated files. func init() { - packr.PackJSONBytes("static", "default-config.toml", "\"IyMgQVRURU5USU9OCiMgaXQgaXMgZXhhbXBsZSBmaWxlIG9ubHkuIEl0IGJ1aWx0aW4gaW4gYmluYXJ5IGFuZCBkb24ndCByZWFkIGZyb20gZmlsZSBzeXN0ZW0uCiMgY2hhbmdlcyBpbiBjb25maWdfZGVmYXVsdC50b21sIGhhdmUgbm8gcmVhbCBlZmZlY3QuCgpbR2VuZXJhbF0KCiMgU2Vjb25kcyBmb3IgaXNzdWUgZXZlcnkgY2VydGlmaWNhdGUuIENhbmNlbCBpc3N1ZSBhbmQgcmV0dXJuIGVycm9yIGlmIHRpbWVvdXQuCklzc3VlVGltZW91dCA9IDMwMAoKIyBQYXRoIHRvIGRpciwgd2hpY2ggd2lsbCBzdG9yZSBzdGF0ZSBhbmQgY2VydGlmaWNhdGVzClN0b3JhZ2VEaXIgPSAic3RvcmFnZSIKCiMgU3RvcmUgLmpzb24gaW5mbyB3aXRoIGNlcnRpZmljYXRlIG1ldGFkYXRhIG5lYXIgY2VydGlmaWNhdGUuClN0b3JlSlNPTk1ldGFkYXRhID0gdHJ1ZQoKIyBEaXJlY3RvcnkgdXJsIG9mIGFjbWUgc2VydmVyLgojVGVzdCBzZXJ2ZXI6IGh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2RpcmVjdG9yeQpBY21lU2VydmVyID0gImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9kaXJlY3RvcnkiCgojIEluY2x1ZGUgb3RoZXIgY29uZmlnIGZpbGVzCiMgSXQgc3VwcG9ydCBnbG9iIHN5bnRheAojIElmIGl0IGhhcyBwYXRoIHdpdGhvdXQgdGVtcGxhdGUgLSB0aGUgZmlsZSBtdXN0IGV4aXN0LgojIEZvciBhbGxvdyBvcHRpb25hbCBpbmNsdWRlIGZpbGUgLSBpdCBjYW4gY29udGFpbiBzb21lIGdsb2Igc3ltYm9sCiMgSW5jbHVkZWQgY29uZmlncyBtZXJnZSB3aXRoIGN1cnJlbnQgcmVhZGVkIHN0YXRlLgojIGV4YW1wbGU9WyAiY29uZmlnLnRvbVtsXSIgXQpJbmNsdWRlQ29uZmlncyA9IFtdCgojIEZvciBwcmV2ZW50IGluZmluaXRlIGxvb3AgYW5kIGNvbnN1bWUgYWxsIG1lbW9yeSBpZiBjeWNsZSBpbiBpbmNsdWRlcwpNYXhDb25maWdGaWxlc1JlYWQgPSAxMDAwMAoKW0xvZ10KRW5hYmxlTG9nVG9GaWxlID0gdHJ1ZQpFbmFibGVMb2dUb1N0ZEVyciA9IHRydWUKCiMgdmVyYm9zZSBsZXZlbCBvZiBsb2csIG9uZSBvZjogZGVidWcsIGluZm8sIHdhcm5pbmcsIGVycm9yLCBmYXRhbApMb2dMZXZlbCA9ICJpbmZvIgoKIyBFbmFibGUgc2VsZiBsb2cgcm90YXRpbmcKRW5hYmxlUm90YXRlID0gdHJ1ZQoKIyBFbmFibGUgZGV2ZWxvcGVyIG1vZGU6IG1vcmUgc3RhY2t0cmFjZXMgYW5kIHBhbmljIChzdG9wIHByb2dyYW0pIG9uIHNvbWUgaW50ZXJuYWwgZXJyb3JzLgpEZXZlbG9wZXJNb2RlID0gZmFsc2UKCiMgUGF0aCB0byBsb2cgZmlsZQpGaWxlID0gImxldHMtcHJveHkubG9nIgoKIyBSb3RhdGUgbG9nIGlmIGN1cnJlbnQgZmlsZSBzaXplIG1vcmUgdGhhbiBYIE1CClJvdGF0ZUJ5U2l6ZU1CID0gMTAwCgojIENvbXByZXNzIG9sZCBsb2cgd2l0aCBnemlwIGFmdGVyIHJvdGF0ZQpDb21wcmVzc1JvdGF0ZWQgPSBmYWxzZQoKIyBEZWxldGUgb2xkIGJhY2t1cHMgYWZ0ZXIgWCBkYXlzLiAwIGZvciBkaXNhYmxlLgpNYXhEYXlzID0gMTAKCiMgRGVsZXRlIG9sZCBiYWNrdXBzIGlmIG9sZCBmaWxlIG51bWJlciBtb3JlIHRoZW4gWC4gMCBmb3IgZGlzYWJsZS4KTWF4Q291bnQgPSAxMAoKW1Byb3h5XQoKIyBEZWZhdWx0IHJ1bGUgb2Ygc2VsZWN0IGRlc3RpbmF0aW9uIGFkZHJlc3MuCiNJdCBjYW4gYmU6IElQICh3aXRoIGRlZmF1bHQgcG9ydCA4MCksIDpQb3J0IChkZWZhdWx0IC0gc2FtZSBJUCBhcyByZWNlaXZlIGNvbm5lY3Rpb24pLCBJUHY0OlBvcnQgb3IgW0lQdjZdOlBvcnQKRGVmYXVsdFRhcmdldCA9ICI6ODAiCgojIEFmdGVyIEtlZXBBbGl2ZVRpbWVvdXRTZWNvbmRzIG9mIGluYWN0aXZlIGluY29taW5nIGNvbm5lY3Rpb24gd2lsbCBjbG9zZS4KS2VlcEFsaXZlVGltZW91dFNlY29uZHMgPSA5MDAKCiMgQXJyYXkgb2YgJy0nIHNlcGFyYXRlZCBwYWlycyBvciBJUDpQb3J0LiBGb3IgZXhhbXBsZToKIyBbCiMgICAiMS4yLjMuNDo0NDMtMi4yLjIuMjoxMjM0IiwKIyAgICIzLjMuMy4zOjMzMy1bOjoxXTo5NCIKIyAiXQojIE1lYW46IGNvbm5lY3Rpb25zLCBhY2NlcHRlZCBvbiAxLjIuMy40OjQ0MyBzZW5kIHRvIHNlcnZlciAyLjIuMi4yOjEyMzQKIyBhbmQgY29ubmVjdGlvbnMgYWNjZXB0ZWQgb24gMy4zLjMuMzozMzMgc2VuZCB0byBpcHY2IDo6MSBwb3J0IDk0ClRhcmdldE1hcCA9IFtdCgojIEFycmF5IG9mIGNvbG9uIHNlcGFyYXRlZCBIZWFkZXJOYW1lOkhlYWRlclZhbHVlIGZvciBhZGQgdG8gcmVxdWVzdCBmb3IgYmFja2VuZC4ge3tWYWx1ZX19IGlzIHNwZWNpYWwgZm9ybXMsIHdoaWNoIGNhbgojIGludGVybmFsbHkgcGFyc2luZy4gTm93IGl0IHN1cHBvcnQgb25seSBzcGVjaWFsIHZhbHVlczoKIyB7e0NPTk5FQ1RJT05fSUR9fSAtIElkIG9mIGFjY2VwdGVkIGNvbm5lY3Rpb24sIGdlbmVyYXRlZCBieSBsZXRzLXByb3h5CiMge3tIVFRQX1BST1RPfX0gLSBzZXQgdG8gaHR0cC9odHRwcyBkZXBlbmRlbmNlIGluY29taW5nIGNvbm5lY3Rpb25zIGhhbmRsZWQKIyB7e1NPVVJDRV9JUH19IC0gUmVtb3RlIElQIG9mIGluY29taW5nIGNvbm5lY3Rpb24KIyB7U09VUkNFX1BPUlR9fSAtIFJlbW90ZSBwb3J0IG9mIGluY29taW5nIGNvbm5lY3Rpb24KIyB7e1NPVVJDRV9JUH19Ont7U09VUkNFX1BPUlR9fSAtIFJlbW90ZSBJUDpQb3J0IG9mIGluY29taW5nIGNvbm5lY3Rpb24uCiMgTm93IGl0IGFjY2VwdGVkIG9ubHkgdGhpcyBzcGVjaWFsIHZhbHVlcywgd2hpY2ggbXVzdCBiZSBleGF4bHR5IGVxdWFsIHRvIGV4YW1wbGVzLiBBbGwgb3RoZXIgdmFsdWVzIHNlbmQgYXMgaXMuCiMgQnV0IGl0IGNhbiBjaGFuZ2UgYW5kIGV4dGVuZCBpbiBmdXR1cmUuIERvZXNuJ3QgdXNlIHt7Li4ufX0gYXMgb3duIHZhbHVlcy4KIyBFeGFtcGxlOgojIFsiSVA6e3tTT1VSQ0VfSVB9fSIsICJQcm94eTpsZXRzLXByb3h5IiwgIlByb3RvY29sOnt7SFRUUF9QUk9UT319IiBdCkhlYWRlcnMgPSBbXQoKW0NoZWNrRG9tYWluc10KCiMgQWxsb3cgZG9tYWluIGlmIGl0IHJlc29sdmVyIGZvciBvbmUgb2YgcHVibGljIElQcyBvZiB0aGlzIHNlcnZlci4KSVBTZWxmID0gdHJ1ZQoKIyBBbGxvdyBkb21haW4gaWYgaXQgcmVzb2x2ZXIgZm9yIG9uZSBvZiB0aGUgaXBzLgpJUFdoaXRlTGlzdCA9ICIiCgojIFJlZ2V4cCBpbiBnb2xhbmcgc3ludGF4IG9mIGJsYWNrbGlzdGVkIGRvbWFpbiBmb3IgaXNzdWUgY2VydGlmaWNhdGUuCiNUaGlzIGxpc3Qgb3ZlcnJpZGVkIGJ5IHdoaXRlbGlzdC4KQmxhY2tMaXN0ID0gIiIKCiMgUmVnZXhwIGluIGdvbGFuZyBzeW50YXggb2Ygd2hpdGVsaXN0IGRvbWFpbnMgZm9yIGlzc3VlIGNlcnRpZmljYXRlLgojV2hpdGVsaXN0IG5lZWQgZm9yIGFsbG93IHBhcnQgb2YgZG9tYWlucywgd2hpY2ggZXhjbHVkZWQgYnkgYmxhY2tsaXN0LgojCldoaXRlTGlzdCA9ICIiCgojIENvbW1hIHNlcGFyYXRlZCBkbnMgc2VydmVyLCB1c2VkIGZvciByZXNvbHZlIGlwOnBvcnQgYWRkcmVzcyBvZiBkb21haW5zIHdoaWxlIGNoZWNrIGl0LgojIGlmIGVtcHR5IC0gdXNlIHN5c3RlbSBkbnMgcmVzb2x2ZXIgKHVzdWFsbHkgaW5jbHVkZSBob3N0cyBmaWxlLCBjYWNoZSwgZXRjKQojIGlmIHNldCAtIHVzZSBkaXJlY3QgZG5zIHF1ZXJpZXMgZm9yIHNlcnZlcnMsIHdpdGhvdXQgc2VsZiBjYWNoZS4KIyBpZiBzZXQgbW9yZSwgdGhhbiBvbmUgZG5zIHNlcnZlciAtIHNlbmQgcXVlcmllcyBpbiBwYXJhbGxlbCB0byBhbGwgc2VydmVycy4KIyBlcnJvciByZXN1bHRzIGZyb20gcGFydCBvZiBzZXJ2ZXJzIC0gaWdub3JlLiBOZWVkIG1pbmltdW0gb25lIGFuc3dlci4KIyBpZiBkaWZmZXJlbnQgZG5zIHNlcnZlcnMgcmV0dXJuIGRpZmZlcmVudCBpcCBhZGRyZXNzZXMgLSBhbGwgb2YgdGhlbSB1c2UgZm9yIGNoZWNrCiMgRXhhbXBsZTogIjguOC44Ljg6NTMsMS4xLjEuMTo1Myw3Ny44OC44Ljg6NTMsWzJhMDI6NmI4OjpmZWVkOjBmZl06NTMsWzIwMDE6NDg2MDo0ODYwOjo4ODg4XTo1MyIKUmVzb2x2ZXIgPSAiIgoKCgpbTGlzdGVuXQoKIyBCaW5kIGFkZHJlc3NlcyBmb3IgVExTIGxpc3RlbmVycwpUTFNBZGRyZXNzZXMgPSBbIjo0NDMiXQoKIyBCaW5kIGFkZHJlc3NlcyB3aXRob3V0IFRMUyBzZWN1cmUgKGZvciBIVFRQIHJldmVyc2UgcHJveHkgYW5kIGh0dHAtMDEgdmFsaWRhdGlvbiB3aXRob3V0IHJlZGlyZWN0IHRvIGh0dHBzKQpUQ1BBZGRyZXNzZXMgPSBbXQoKW1Byb2ZpbGVyXQpFbmFibGUgPSBmYWxzZQoKIyBJUCBuZXR3b3JrcyBmb3IgYWxsb3cgdG8gdXNlIHByb2ZpbGVyLgojIERlZmF1bHQgLSBkZW55IGZyb20gYWxsLgojIEV4YW1wbGU6CiMgWyAiMS4yLjMuNC8zMiIsICIxOTIuMTY4LjAuMC8yNCIsICI6OjEvMTI4IiBdCkFsbG93ZWROZXR3b3JrcyA9IFtdCkJpbmRBZGRyZXNzID0gImxvY2FsaG9zdDozMTM0NCIK\"") + packr.PackJSONBytes("static", "default-config.toml", "\"IyMgQVRURU5USU9OCiMgaXQgaXMgZXhhbXBsZSBmaWxlIG9ubHkuIEl0IGJ1aWx0aW4gaW4gYmluYXJ5IGFuZCBkb24ndCByZWFkIGZyb20gZmlsZSBzeXN0ZW0uCiMgY2hhbmdlcyBpbiBjb25maWdfZGVmYXVsdC50b21sIGhhdmUgbm8gcmVhbCBlZmZlY3QuCgpbR2VuZXJhbF0KCiMgU2Vjb25kcyBmb3IgaXNzdWUgZXZlcnkgY2VydGlmaWNhdGUuIENhbmNlbCBpc3N1ZSBhbmQgcmV0dXJuIGVycm9yIGlmIHRpbWVvdXQuCklzc3VlVGltZW91dCA9IDMwMAoKIyBQYXRoIHRvIGRpciwgd2hpY2ggd2lsbCBzdG9yZSBzdGF0ZSBhbmQgY2VydGlmaWNhdGVzClN0b3JhZ2VEaXIgPSAic3RvcmFnZSIKCiMgU3RvcmUgLmpzb24gaW5mbyB3aXRoIGNlcnRpZmljYXRlIG1ldGFkYXRhIG5lYXIgY2VydGlmaWNhdGUuClN0b3JlSlNPTk1ldGFkYXRhID0gdHJ1ZQoKIyBEaXJlY3RvcnkgdXJsIG9mIGFjbWUgc2VydmVyLgojVGVzdCBzZXJ2ZXI6IGh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2RpcmVjdG9yeQpBY21lU2VydmVyID0gImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9kaXJlY3RvcnkiCgojIEluY2x1ZGUgb3RoZXIgY29uZmlnIGZpbGVzCiMgSXQgc3VwcG9ydCBnbG9iIHN5bnRheAojIElmIGl0IGhhcyBwYXRoIHdpdGhvdXQgdGVtcGxhdGUgLSB0aGUgZmlsZSBtdXN0IGV4aXN0LgojIEZvciBhbGxvdyBvcHRpb25hbCBpbmNsdWRlIGZpbGUgLSBpdCBjYW4gY29udGFpbiBzb21lIGdsb2Igc3ltYm9sCiMgSW5jbHVkZWQgY29uZmlncyBtZXJnZSB3aXRoIGN1cnJlbnQgcmVhZGVkIHN0YXRlLgojIGV4YW1wbGU9WyAiY29uZmlnLnRvbVtsXSIgXQpJbmNsdWRlQ29uZmlncyA9IFtdCgojIEZvciBwcmV2ZW50IGluZmluaXRlIGxvb3AgYW5kIGNvbnN1bWUgYWxsIG1lbW9yeSBpZiBjeWNsZSBpbiBpbmNsdWRlcwpNYXhDb25maWdGaWxlc1JlYWQgPSAxMDAwMAoKW0xvZ10KRW5hYmxlTG9nVG9GaWxlID0gdHJ1ZQpFbmFibGVMb2dUb1N0ZEVyciA9IHRydWUKCiMgdmVyYm9zZSBsZXZlbCBvZiBsb2csIG9uZSBvZjogZGVidWcsIGluZm8sIHdhcm5pbmcsIGVycm9yLCBmYXRhbApMb2dMZXZlbCA9ICJpbmZvIgoKIyBFbmFibGUgc2VsZiBsb2cgcm90YXRpbmcKRW5hYmxlUm90YXRlID0gdHJ1ZQoKIyBFbmFibGUgZGV2ZWxvcGVyIG1vZGU6IG1vcmUgc3RhY2t0cmFjZXMgYW5kIHBhbmljIChzdG9wIHByb2dyYW0pIG9uIHNvbWUgaW50ZXJuYWwgZXJyb3JzLgpEZXZlbG9wZXJNb2RlID0gZmFsc2UKCiMgUGF0aCB0byBsb2cgZmlsZQpGaWxlID0gImxldHMtcHJveHkubG9nIgoKIyBSb3RhdGUgbG9nIGlmIGN1cnJlbnQgZmlsZSBzaXplIG1vcmUgdGhhbiBYIE1CClJvdGF0ZUJ5U2l6ZU1CID0gMTAwCgojIENvbXByZXNzIG9sZCBsb2cgd2l0aCBnemlwIGFmdGVyIHJvdGF0ZQpDb21wcmVzc1JvdGF0ZWQgPSBmYWxzZQoKIyBEZWxldGUgb2xkIGJhY2t1cHMgYWZ0ZXIgWCBkYXlzLiAwIGZvciBkaXNhYmxlLgpNYXhEYXlzID0gMTAKCiMgRGVsZXRlIG9sZCBiYWNrdXBzIGlmIG9sZCBmaWxlIG51bWJlciBtb3JlIHRoZW4gWC4gMCBmb3IgZGlzYWJsZS4KTWF4Q291bnQgPSAxMAoKW1Byb3h5XQoKIyBEZWZhdWx0IHJ1bGUgb2Ygc2VsZWN0IGRlc3RpbmF0aW9uIGFkZHJlc3MuCiMgSXQgY2FuIGJlOiBJUCAod2l0aCBkZWZhdWx0IHBvcnQgODApLCA6UG9ydCAoZGVmYXVsdCAtIHNhbWUgSVAgYXMgcmVjZWl2ZSBjb25uZWN0aW9uKSwgSVB2NDpQb3J0IG9yIFtJUHY2XTpQb3J0CiMgTXVzdCBkZWZpbmUgcG9ydCBmb3JjZSBpZiBIVFRQU0JhY2tlbmQgaXMgdHJ1ZQpEZWZhdWx0VGFyZ2V0ID0gIjo4MCIKCiMgQWZ0ZXIgS2VlcEFsaXZlVGltZW91dFNlY29uZHMgb2YgaW5hY3RpdmUgaW5jb21pbmcgY29ubmVjdGlvbiB3aWxsIGNsb3NlLgpLZWVwQWxpdmVUaW1lb3V0U2Vjb25kcyA9IDkwMAoKIyBBcnJheSBvZiAnLScgc2VwYXJhdGVkIHBhaXJzIG9yIElQOlBvcnQuIEZvciBleGFtcGxlOgojIFsKIyAgICIxLjIuMy40OjQ0My0yLjIuMi4yOjEyMzQiLAojICAgIjMuMy4zLjM6MzMzLVs6OjFdOjk0IgojICJdCiMgTWVhbjogY29ubmVjdGlvbnMsIGFjY2VwdGVkIG9uIDEuMi4zLjQ6NDQzIHNlbmQgdG8gc2VydmVyIDIuMi4yLjI6MTIzNAojIGFuZCBjb25uZWN0aW9ucyBhY2NlcHRlZCBvbiAzLjMuMy4zOjMzMyBzZW5kIHRvIGlwdjYgOjoxIHBvcnQgOTQKVGFyZ2V0TWFwID0gW10KCiMgQXJyYXkgb2YgY29sb24gc2VwYXJhdGVkIEhlYWRlck5hbWU6SGVhZGVyVmFsdWUgZm9yIGFkZCB0byByZXF1ZXN0IGZvciBiYWNrZW5kLiB7e1ZhbHVlfX0gaXMgc3BlY2lhbCBmb3Jtcywgd2hpY2ggY2FuCiMgaW50ZXJuYWxseSBwYXJzaW5nLiBOb3cgaXQgc3VwcG9ydCBvbmx5IHNwZWNpYWwgdmFsdWVzOgojIHt7Q09OTkVDVElPTl9JRH19IC0gSWQgb2YgYWNjZXB0ZWQgY29ubmVjdGlvbiwgZ2VuZXJhdGVkIGJ5IGxldHMtcHJveHkKIyB7e0hUVFBfUFJPVE99fSAtIHNldCB0byBodHRwL2h0dHBzIGRlcGVuZGVuY2UgaW5jb21pbmcgY29ubmVjdGlvbnMgaGFuZGxlZAojIHt7U09VUkNFX0lQfX0gLSBSZW1vdGUgSVAgb2YgaW5jb21pbmcgY29ubmVjdGlvbgojIHtTT1VSQ0VfUE9SVH19IC0gUmVtb3RlIHBvcnQgb2YgaW5jb21pbmcgY29ubmVjdGlvbgojIHt7U09VUkNFX0lQfX06e3tTT1VSQ0VfUE9SVH19IC0gUmVtb3RlIElQOlBvcnQgb2YgaW5jb21pbmcgY29ubmVjdGlvbi4KIyBOb3cgaXQgYWNjZXB0ZWQgb25seSB0aGlzIHNwZWNpYWwgdmFsdWVzLCB3aGljaCBtdXN0IGJlIGV4YXhsdHkgZXF1YWwgdG8gZXhhbXBsZXMuIEFsbCBvdGhlciB2YWx1ZXMgc2VuZCBhcyBpcy4KIyBCdXQgaXQgY2FuIGNoYW5nZSBhbmQgZXh0ZW5kIGluIGZ1dHVyZS4gRG9lc24ndCB1c2Uge3suLi59fSBhcyBvd24gdmFsdWVzLgojIEV4YW1wbGU6CiMgWyJJUDp7e1NPVVJDRV9JUH19IiwgIlByb3h5OmxldHMtcHJveHkiLCAiUHJvdG9jb2w6e3tIVFRQX1BST1RPfX0iIF0KSGVhZGVycyA9IFtdCgojIFVzZSBodHRwcyByZXF1ZXN0cyB0byBiYWNrZW5kIGluc3RlYWQgb2YgaHR0cApIVFRQU0JhY2tlbmQgPSBmYWxzZQoKIyBJZ25vcmUgYmFja2VuZCBodHRwcyBjZXJ0aWZpY2F0ZSB2YWxpZGF0aW9ucyBpZiBIVFRQU0JhY2tlbmQgaXMgdHJ1ZQpIVFRQU0JhY2tlbmRJZ25vcmVDZXJ0ID0gdHJ1ZQoKW0NoZWNrRG9tYWluc10KCiMgQWxsb3cgZG9tYWluIGlmIGl0IHJlc29sdmVyIGZvciBvbmUgb2YgcHVibGljIElQcyBvZiB0aGlzIHNlcnZlci4KSVBTZWxmID0gdHJ1ZQoKIyBBbGxvdyBkb21haW4gaWYgaXQgcmVzb2x2ZXIgZm9yIG9uZSBvZiB0aGUgaXBzLgpJUFdoaXRlTGlzdCA9ICIiCgojIFJlZ2V4cCBpbiBnb2xhbmcgc3ludGF4IG9mIGJsYWNrbGlzdGVkIGRvbWFpbiBmb3IgaXNzdWUgY2VydGlmaWNhdGUuCiNUaGlzIGxpc3Qgb3ZlcnJpZGVkIGJ5IHdoaXRlbGlzdC4KQmxhY2tMaXN0ID0gIiIKCiMgUmVnZXhwIGluIGdvbGFuZyBzeW50YXggb2Ygd2hpdGVsaXN0IGRvbWFpbnMgZm9yIGlzc3VlIGNlcnRpZmljYXRlLgojV2hpdGVsaXN0IG5lZWQgZm9yIGFsbG93IHBhcnQgb2YgZG9tYWlucywgd2hpY2ggZXhjbHVkZWQgYnkgYmxhY2tsaXN0LgojCldoaXRlTGlzdCA9ICIiCgojIENvbW1hIHNlcGFyYXRlZCBkbnMgc2VydmVyLCB1c2VkIGZvciByZXNvbHZlIGlwOnBvcnQgYWRkcmVzcyBvZiBkb21haW5zIHdoaWxlIGNoZWNrIGl0LgojIGlmIGVtcHR5IC0gdXNlIHN5c3RlbSBkbnMgcmVzb2x2ZXIgKHVzdWFsbHkgaW5jbHVkZSBob3N0cyBmaWxlLCBjYWNoZSwgZXRjKQojIGlmIHNldCAtIHVzZSBkaXJlY3QgZG5zIHF1ZXJpZXMgZm9yIHNlcnZlcnMsIHdpdGhvdXQgc2VsZiBjYWNoZS4KIyBpZiBzZXQgbW9yZSwgdGhhbiBvbmUgZG5zIHNlcnZlciAtIHNlbmQgcXVlcmllcyBpbiBwYXJhbGxlbCB0byBhbGwgc2VydmVycy4KIyBlcnJvciByZXN1bHRzIGZyb20gcGFydCBvZiBzZXJ2ZXJzIC0gaWdub3JlLiBOZWVkIG1pbmltdW0gb25lIGFuc3dlci4KIyBpZiBkaWZmZXJlbnQgZG5zIHNlcnZlcnMgcmV0dXJuIGRpZmZlcmVudCBpcCBhZGRyZXNzZXMgLSBhbGwgb2YgdGhlbSB1c2UgZm9yIGNoZWNrCiMgRXhhbXBsZTogIjguOC44Ljg6NTMsMS4xLjEuMTo1Myw3Ny44OC44Ljg6NTMsWzJhMDI6NmI4OjpmZWVkOjBmZl06NTMsWzIwMDE6NDg2MDo0ODYwOjo4ODg4XTo1MyIKUmVzb2x2ZXIgPSAiIgoKCgpbTGlzdGVuXQoKIyBCaW5kIGFkZHJlc3NlcyBmb3IgVExTIGxpc3RlbmVycwpUTFNBZGRyZXNzZXMgPSBbIjo0NDMiXQoKIyBCaW5kIGFkZHJlc3NlcyB3aXRob3V0IFRMUyBzZWN1cmUgKGZvciBIVFRQIHJldmVyc2UgcHJveHkgYW5kIGh0dHAtMDEgdmFsaWRhdGlvbiB3aXRob3V0IHJlZGlyZWN0IHRvIGh0dHBzKQpUQ1BBZGRyZXNzZXMgPSBbXQoKW1Byb2ZpbGVyXQpFbmFibGUgPSBmYWxzZQoKIyBJUCBuZXR3b3JrcyBmb3IgYWxsb3cgdG8gdXNlIHByb2ZpbGVyLgojIERlZmF1bHQgLSBkZW55IGZyb20gYWxsLgojIEV4YW1wbGU6CiMgWyAiMS4yLjMuNC8zMiIsICIxOTIuMTY4LjAuMC8yNCIsICI6OjEvMTI4IiBdCkFsbG93ZWROZXR3b3JrcyA9IFtdCkJpbmRBZGRyZXNzID0gImxvY2FsaG9zdDozMTM0NCIK\"") } diff --git a/cmd/static/default-config.toml b/cmd/static/default-config.toml index bacfab9f..5759c994 100644 --- a/cmd/static/default-config.toml +++ b/cmd/static/default-config.toml @@ -59,7 +59,8 @@ MaxCount = 10 [Proxy] # Default rule of select destination address. -#It can be: IP (with default port 80), :Port (default - same IP as receive connection), IPv4:Port or [IPv6]:Port +# It can be: IP (with default port 80), :Port (default - same IP as receive connection), IPv4:Port or [IPv6]:Port +# Must define port force if HTTPSBackend is true DefaultTarget = ":80" # After KeepAliveTimeoutSeconds of inactive incoming connection will close. @@ -87,6 +88,12 @@ TargetMap = [] # ["IP:{{SOURCE_IP}}", "Proxy:lets-proxy", "Protocol:{{HTTP_PROTO}}" ] Headers = [] +# Use https requests to backend instead of http +HTTPSBackend = false + +# Ignore backend https certificate validations if HTTPSBackend is true +HTTPSBackendIgnoreCert = true + [CheckDomains] # Allow domain if it resolver for one of public IPs of this server. diff --git a/internal/proxy/config.go b/internal/proxy/config.go index 3a3c8559..6a7071fd 100644 --- a/internal/proxy/config.go +++ b/internal/proxy/config.go @@ -23,6 +23,8 @@ type Config struct { TargetMap []string Headers []string KeepAliveTimeoutSeconds int + HTTPSBackend bool + HTTPSBackendIgnoreCert bool } func (c *Config) Apply(ctx context.Context, p *HTTPProxy) error { @@ -42,6 +44,8 @@ func (c *Config) Apply(ctx context.Context, p *HTTPProxy) error { appendDirector(c.getDefaultTargetDirector) appendDirector(c.getMapDirector) appendDirector(c.getHeadersDirector) + appendDirector(c.getSchemaDirector) + p.httpReverseProxy.Transport = Transport{c.HTTPSBackendIgnoreCert} if resErr != nil { zc.L(ctx).Error("Can't parse proxy config", zap.Error(resErr)) @@ -130,6 +134,13 @@ func (c *Config) getMapDirector(ctx context.Context) (Director, error) { return NewDirectorDestMap(m), nil } +func (c *Config) getSchemaDirector(ctx context.Context) (Director, error) { + if c.HTTPSBackend { + return NewSetSchemeDirector(ProtocolHTTPS), nil + } + return NewSetSchemeDirector(ProtocolHTTP), nil +} + func parseTCPMapPair(line string) (from, to string, err error) { line = strings.TrimSpace(line) lineParts := strings.Split(line, "-") diff --git a/internal/proxy/config_test.go b/internal/proxy/config_test.go index 333aee45..268fb221 100644 --- a/internal/proxy/config_test.go +++ b/internal/proxy/config_test.go @@ -201,6 +201,30 @@ func TestConfig_getMapDirector(t *testing.T) { td.CmpNoError(err) } +func TestConfig_getSchemeDirector(t *testing.T) { + ctx, flush := th.TestContext() + defer flush() + + td := testdeep.NewT(t) + + var director Director + var err error + + c := &Config{ + HTTPSBackend: false, + } + director, err = c.getSchemaDirector(ctx) + td.CmpNoError(err) + td.CmpDeeply(director, NewSetSchemeDirector(ProtocolHTTP)) + + c = &Config{ + HTTPSBackend: true, + } + director, err = c.getSchemaDirector(ctx) + td.CmpNoError(err) + td.CmpDeeply(director, NewSetSchemeDirector(ProtocolHTTPS)) +} + func TestConfig_Apply(t *testing.T) { ctx, flush := th.TestContext() defer flush() @@ -228,9 +252,16 @@ func TestConfig_Apply(t *testing.T) { p = &HTTPProxy{} err = c.Apply(ctx, p) td.CmpNoError(err) - td.CmpDeeply(p.Director, NewDirectorChain(NewDirectorSameIP(94), NewDirectorSetHeaders(map[string]string{"aaa": "bbb"}))) + td.CmpDeeply(p.Director, + NewDirectorChain( + NewDirectorSameIP(94), + NewDirectorSetHeaders(map[string]string{"aaa": "bbb"}), + NewSetSchemeDirector(ProtocolHTTP), + ), + ) c = Config{ + HTTPSBackend: true, DefaultTarget: "1.2.3.4:94", TargetMap: []string{"1.2.3.4:33-4.5.6.7:88"}, Headers: []string{"aaa:bbb"}, @@ -242,5 +273,20 @@ func TestConfig_Apply(t *testing.T) { NewDirectorHost("1.2.3.4:94"), NewDirectorDestMap(map[string]string{"1.2.3.4:33": "4.5.6.7:88"}), NewDirectorSetHeaders(map[string]string{"aaa": "bbb"}), + NewSetSchemeDirector(ProtocolHTTPS), )) + + // Test backendSchemas + + c = Config{HTTPSBackendIgnoreCert: false} + p = &HTTPProxy{} + c.Apply(ctx, p) + transport := p.httpReverseProxy.Transport.(Transport) + transport.IgnoreHttpsCertificate = false + + c = Config{HTTPSBackendIgnoreCert: true} + p = &HTTPProxy{} + c.Apply(ctx, p) + transport = p.httpReverseProxy.Transport.(Transport) + transport.IgnoreHttpsCertificate = true } diff --git a/internal/proxy/directors.go b/internal/proxy/directors.go index c717785f..e96f7645 100644 --- a/internal/proxy/directors.go +++ b/internal/proxy/directors.go @@ -70,7 +70,6 @@ func (s DirectorSameIP) Director(request *http.Request) { if request.URL == nil { request.URL = &url.URL{} } - request.URL.Scheme = ProtocolHTTP request.URL.Host = localAddr.IP.String() + ":" + s.Port zc.L(request.Context()).Debug("Set target as same ip", zap.Stringer("local_addr", localAddr), zap.String("dest_host", request.Host)) @@ -169,3 +168,16 @@ func (h DirectorSetHeaders) Director(request *http.Request) { request.Header.Set(name, value) } } + +type DirectorSetScheme string + +func (d DirectorSetScheme) Director(req *http.Request) { + if req.URL == nil { + req.URL = &url.URL{} + } + req.URL.Scheme = string(d) +} + +func NewSetSchemeDirector(scheme string) DirectorSetScheme { + return DirectorSetScheme(scheme) +} diff --git a/internal/proxy/http-proxy.go b/internal/proxy/http-proxy.go index 04ca5728..441bb369 100644 --- a/internal/proxy/http-proxy.go +++ b/internal/proxy/http-proxy.go @@ -90,6 +90,5 @@ func (p *HTTPProxy) director(request *http.Request) { if request.URL == nil { request.URL = &url.URL{} } - request.URL.Scheme = ProtocolHTTP p.Director.Director(request) }