mirror of
https://github.com/chaitin/SafeLine.git
synced 2025-11-25 19:37:42 +08:00
feat: update traefik sdk
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
displayName: Chaitin Safeline WAF
|
displayName: Chaitin Safeline WAF
|
||||||
type: middleware
|
type: middleware
|
||||||
|
|
||||||
import: github.com/xbingW/traefik-safeline
|
import: github.com/chaitin/traefik-safeline
|
||||||
|
|
||||||
summary: 'Traefik plugin to proxy requests to safeline waf.t serves as a reverse proxy access to protect your website from network attacks that including OWASP attacks, zero-day attacks, web crawlers, vulnerability scanning, vulnerability exploit, http flood and so on.'
|
summary: 'Traefik plugin to proxy requests to safeline waf.t serves as a reverse proxy access to protect your website from network attacks that including OWASP attacks, zero-day attacks, web crawlers, vulnerability scanning, vulnerability exploit, http flood and so on.'
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ The following declaration (given here in YAML) defines a plugin:
|
|||||||
experimental:
|
experimental:
|
||||||
plugins:
|
plugins:
|
||||||
safeline:
|
safeline:
|
||||||
moduleName: github.com/xbingW/traefik-safeline
|
moduleName: github.com/chaitin/traefik-safeline
|
||||||
version: v1.0.0
|
version: v1.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module github.com/xbingW/traefik-safeline
|
module github.com/chaitin/traefik-safeline
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require github.com/xbingW/t1k v1.2.1
|
require golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||||
|
|
||||||
|
require github.com/chaitin/t1k-go v1.5.0
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package traefik_safeline
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/xbingW/t1k"
|
t1k "github.com/chaitin/t1k-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Package example a example plugin.
|
// Package example a example plugin.
|
||||||
@@ -15,61 +16,84 @@ import (
|
|||||||
// Config the plugin configuration.
|
// Config the plugin configuration.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Addr is the address for the detector
|
// Addr is the address for the detector
|
||||||
Addr string `yaml:"addr"`
|
Addr string `yaml:"addr"`
|
||||||
// Get ip from header, if not set, get ip from remote addr
|
PoolSize int `yaml:"pool_size"`
|
||||||
IpHeader string `yaml:"ipHeader"`
|
|
||||||
// When ip_header has multiple ip, use this to get the ip
|
|
||||||
//
|
|
||||||
//for example, X-Forwarded-For: ip1, ip2, ip3
|
|
||||||
// when ip_last_index is 0, the client ip is ip3
|
|
||||||
// when ip_last_index is 1, the client ip is ip2
|
|
||||||
// when ip_last_index is 2, the client ip is ip1
|
|
||||||
IPRightIndex uint `yaml:"ipRightIndex"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateConfig creates the default plugin configuration.
|
// CreateConfig creates the default plugin configuration.
|
||||||
func CreateConfig() *Config {
|
func CreateConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Addr: "",
|
Addr: "",
|
||||||
IpHeader: "",
|
PoolSize: 100,
|
||||||
IPRightIndex: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safeline a plugin.
|
// Safeline a plugin.
|
||||||
type Safeline struct {
|
type Safeline struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
|
server *t1k.Server
|
||||||
name string
|
name string
|
||||||
config *Config
|
config *Config
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New created a new plugin.
|
// New created a new plugin.
|
||||||
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
|
||||||
|
logger := log.New(os.Stdout, "safeline", log.LstdFlags)
|
||||||
|
logger.Printf("config: %+v", config)
|
||||||
return &Safeline{
|
return &Safeline{
|
||||||
next: next,
|
next: next,
|
||||||
name: name,
|
name: name,
|
||||||
config: config,
|
config: config,
|
||||||
logger: log.New(os.Stdout, "safeline", log.LstdFlags),
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Safeline) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (s *Safeline) initServer() error {
|
||||||
d := t1k.NewDetector(t1k.Config{
|
if s.server != nil {
|
||||||
Addr: s.config.Addr,
|
return nil
|
||||||
IpHeader: s.config.IpHeader,
|
|
||||||
IPRightIndex: s.config.IPRightIndex,
|
|
||||||
})
|
|
||||||
resp, err := d.DetectorRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Printf("Failed to detect request: %v", err)
|
|
||||||
}
|
}
|
||||||
if resp != nil && !resp.Allowed() {
|
s.mu.Lock()
|
||||||
rw.WriteHeader(resp.StatusCode())
|
defer s.mu.Unlock()
|
||||||
if err := json.NewEncoder(rw).Encode(resp.BlockMessage()); err != nil {
|
if s.server == nil {
|
||||||
s.logger.Printf("Failed to encode block message: %v", err)
|
server, err := t1k.NewWithPoolSize(s.config.Addr, s.config.PoolSize)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
s.server = server
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Safeline) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
s.logger.Printf("panic: %s", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err := s.initServer(); err != nil {
|
||||||
|
s.logger.Printf("error in initServer: %s", err)
|
||||||
|
s.next.ServeHTTP(rw, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rw.Header().Set("X-Chaitin-waf", "safeline")
|
||||||
|
result, err := s.server.DetectHttpRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("error in detection: \n%+v\n", err)
|
||||||
|
s.next.ServeHTTP(rw, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.Blocked() {
|
||||||
|
rw.WriteHeader(result.StatusCode())
|
||||||
|
msg := fmt.Sprintf(`{"code": %d, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "%s"}`,
|
||||||
|
result.StatusCode(),
|
||||||
|
result.EventID(),
|
||||||
|
)
|
||||||
|
_, _ = rw.Write([]byte(msg))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.next.ServeHTTP(rw, req)
|
s.next.ServeHTTP(rw, req)
|
||||||
|
//rw.WriteHeader(http.StatusForbidden)
|
||||||
|
//_, _ = rw.Write([]byte("Inject by safeline\n"))
|
||||||
}
|
}
|
||||||
|
|||||||
201
sdk/traefik/vendor/github.com/chaitin/t1k-go/License
generated
vendored
Normal file
201
sdk/traefik/vendor/github.com/chaitin/t1k-go/License
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor 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, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2023 Beijing Chaitin Technology Co., Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
5
sdk/traefik/vendor/github.com/chaitin/t1k-go/README.md
generated
vendored
Normal file
5
sdk/traefik/vendor/github.com/chaitin/t1k-go/README.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# t1k-go
|
||||||
|
|
||||||
|
Go implementation of the T1K protocol for [Chaitin/SafeLine](https://github.com/chaitin/safeline) Web Application Firewall.
|
||||||
|
|
||||||
|
|
||||||
101
sdk/traefik/vendor/github.com/chaitin/t1k-go/conn.go
generated
vendored
Normal file
101
sdk/traefik/vendor/github.com/chaitin/t1k-go/conn.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/detection"
|
||||||
|
"github.com/chaitin/t1k-go/t1k"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type conn struct {
|
||||||
|
socket net.Conn
|
||||||
|
server *Server
|
||||||
|
failing bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeConn(socket net.Conn, server *Server) *conn {
|
||||||
|
return &conn{
|
||||||
|
socket: socket,
|
||||||
|
server: server,
|
||||||
|
failing: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) onErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
// re-open socket to recover from possible error state
|
||||||
|
c.socket.Close()
|
||||||
|
sock, errConnect := c.server.socketFactory()
|
||||||
|
if errConnect != nil {
|
||||||
|
c.failing = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.socket = sock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Close() {
|
||||||
|
if c.socket == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.socket.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) DetectRequestInCtx(dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
ret, err := DetectRequestInCtx(c.socket, dc)
|
||||||
|
c.onErr(err)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) DetectResponseInCtx(dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
ret, err := DetectResponseInCtx(c.socket, dc)
|
||||||
|
c.onErr(err)
|
||||||
|
return ret, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Detect(dc *detection.DetectionContext) (*detection.Result, *detection.Result, error) {
|
||||||
|
retReq, retRsp, err := Detect(c.socket, dc)
|
||||||
|
c.onErr(err)
|
||||||
|
return retReq, retRsp, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) DetectHttpRequest(req *http.Request) (*detection.Result, error) {
|
||||||
|
ret, err := DetectHttpRequest(c.socket, req)
|
||||||
|
c.onErr(err)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) DetectRequest(req detection.Request) (*detection.Result, error) {
|
||||||
|
ret, err := DetectRequest(c.socket, req)
|
||||||
|
c.onErr(err)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Heartbeat() {
|
||||||
|
err := DoHeartbeat(c.socket)
|
||||||
|
c.onErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) WriteSection(sec t1k.Section) error {
|
||||||
|
err := t1k.WriteSection(sec, c.socket)
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) ReadSection() (t1k.Section, error) {
|
||||||
|
sec, err := t1k.ReadSection(c.socket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
return sec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) ReadFullSection() (t1k.Section, error) {
|
||||||
|
sec, err := t1k.ReadFullSection(c.socket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
return sec, nil
|
||||||
|
}
|
||||||
253
sdk/traefik/vendor/github.com/chaitin/t1k-go/detect.go
generated
vendored
Normal file
253
sdk/traefik/vendor/github.com/chaitin/t1k-go/detect.go
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/detection"
|
||||||
|
"github.com/chaitin/t1k-go/t1k"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeDetectionRequest(w io.Writer, req detection.Request) error {
|
||||||
|
{
|
||||||
|
data, err := req.Header()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_HEADER|t1k.MASK_FIRST, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bodySize, bodyReadCloser, err := req.Body()
|
||||||
|
if err == nil {
|
||||||
|
defer bodyReadCloser.Close()
|
||||||
|
sec := t1k.MakeReaderSection(t1k.TAG_BODY, bodySize, bodyReadCloser)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data, err := req.Extra()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_EXTRA, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_VERSION|t1k.MASK_LAST, []byte("Proto:2\n"))
|
||||||
|
err := t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeDetectionResponse(w io.Writer, rsp detection.Response) error {
|
||||||
|
{
|
||||||
|
data, err := rsp.RequestHeader()
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_HEADER|t1k.MASK_FIRST, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data, err := rsp.Header()
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_RSP_HEADER, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bodySize, bodyReadCloser, err := rsp.Body()
|
||||||
|
if err == nil {
|
||||||
|
defer bodyReadCloser.Close()
|
||||||
|
sec := t1k.MakeReaderSection(t1k.TAG_RSP_BODY, bodySize, bodyReadCloser)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data, err := rsp.Extra()
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_RSP_EXTRA, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_VERSION, []byte("Proto:2\n"))
|
||||||
|
err := t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data, err := rsp.T1KContext()
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
sec := t1k.MakeSimpleSection(t1k.TAG_CONTEXT|t1k.MASK_LAST, data)
|
||||||
|
err = t1k.WriteSection(sec, w)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readDetectionResult(r io.Reader) (*detection.Result, error) {
|
||||||
|
var ret detection.Result
|
||||||
|
parseSection := func(sec t1k.Section) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := sec.WriteBody(&buf)
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
tag := sec.Header().Tag.Strip()
|
||||||
|
switch tag {
|
||||||
|
case t1k.TAG_HEADER:
|
||||||
|
if len(buf.Bytes()) != 1 {
|
||||||
|
return fmt.Errorf("len(T1K_HEADER) != 1")
|
||||||
|
}
|
||||||
|
ret.Head = buf.Bytes()[0]
|
||||||
|
case t1k.TAG_BODY:
|
||||||
|
ret.Body = buf.Bytes()
|
||||||
|
case t1k.TAG_ALOG:
|
||||||
|
ret.Alog = buf.Bytes()
|
||||||
|
case t1k.TAG_EXTRA_HEADER:
|
||||||
|
ret.ExtraHeader = buf.Bytes()
|
||||||
|
case t1k.TAG_EXTRA_BODY:
|
||||||
|
ret.ExtraBody = buf.Bytes()
|
||||||
|
case t1k.TAG_CONTEXT:
|
||||||
|
ret.T1KContext = buf.Bytes()
|
||||||
|
case t1k.TAG_COOKIE:
|
||||||
|
ret.Cookie = buf.Bytes()
|
||||||
|
case t1k.TAG_WEB_LOG:
|
||||||
|
ret.WebLog = buf.Bytes()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sec, err := t1k.ReadFullSection(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
if !sec.Header().Tag.IsFirst() {
|
||||||
|
return nil, fmt.Errorf("first section IsFirst != true, middle of another msg or corrupt stream, with <%x>", sec.Header().Tag)
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
err = parseSection(sec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
if sec.Header().Tag.IsLast() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sec, err = t1k.ReadSection(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doDetectRequest(s io.ReadWriter, req detection.Request) (*detection.Result, error) {
|
||||||
|
err := writeDetectionRequest(s, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
ret, err := readDetectionResult(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
ret.Objective = detection.RO_REQUEST
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doDetectResponse(s io.ReadWriter, rsp detection.Response) (*detection.Result, error) {
|
||||||
|
err := writeDetectionResponse(s, rsp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
ret, err := readDetectionResult(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
ret.Objective = detection.RO_RESPONSE
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectRequestInCtx(s io.ReadWriter, dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
ret, err := doDetectRequest(s, dc.Request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dc.ProcessResult(ret)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectResponseInCtx(s io.ReadWriter, dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
ret, err := doDetectResponse(s, dc.Response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
dc.ProcessResult(ret)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Detect(s io.ReadWriter, dc *detection.DetectionContext) (*detection.Result, *detection.Result, error) {
|
||||||
|
var reqResult *detection.Result
|
||||||
|
var rspResult *detection.Result
|
||||||
|
if dc.Request != nil {
|
||||||
|
ret, err := doDetectRequest(s, dc.Request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
reqResult = ret
|
||||||
|
dc.ProcessResult(reqResult)
|
||||||
|
}
|
||||||
|
if dc.Response != nil {
|
||||||
|
ret, err := doDetectResponse(s, dc.Response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
rspResult = ret
|
||||||
|
dc.ProcessResult(rspResult)
|
||||||
|
}
|
||||||
|
return reqResult, rspResult, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectHttpRequest(s io.ReadWriter, req *http.Request) (*detection.Result, error) {
|
||||||
|
dc, _ := detection.MakeContextWithRequest(req)
|
||||||
|
return doDetectRequest(s, detection.MakeHttpRequestInCtx(req, dc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectRequest(s io.ReadWriter, req detection.Request) (*detection.Result, error) {
|
||||||
|
return doDetectRequest(s, req)
|
||||||
|
}
|
||||||
88
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/context.go
generated
vendored
Normal file
88
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/context.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package detection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DetectionContext struct {
|
||||||
|
UUID string
|
||||||
|
Scheme string
|
||||||
|
ProxyName string
|
||||||
|
RemoteAddr string
|
||||||
|
Protocol string
|
||||||
|
RemotePort uint16
|
||||||
|
LocalAddr string
|
||||||
|
LocalPort uint16
|
||||||
|
ReqBeginTime int64
|
||||||
|
RspBeginTime int64
|
||||||
|
|
||||||
|
T1KContext []byte
|
||||||
|
|
||||||
|
Request Request
|
||||||
|
Response Response
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *DetectionContext {
|
||||||
|
return &DetectionContext{
|
||||||
|
UUID: misc.GenUUID(),
|
||||||
|
Scheme: "http",
|
||||||
|
ProxyName: "go-sdk",
|
||||||
|
RemoteAddr: "127.0.0.1",
|
||||||
|
RemotePort: 30001,
|
||||||
|
LocalAddr: "127.0.0.1",
|
||||||
|
LocalPort: 80,
|
||||||
|
Protocol: "HTTP/1.1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeContextWithRequest(req *http.Request) (*DetectionContext, error) {
|
||||||
|
if req == nil {
|
||||||
|
return nil, errors.New("nil http.request or response")
|
||||||
|
}
|
||||||
|
wrapReq := &HttpRequest{
|
||||||
|
req: req,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore GetRemoteIP error,not sure request record remote ip
|
||||||
|
remoteIP, _ := wrapReq.GetRemoteIP()
|
||||||
|
remotePort, _ := wrapReq.GetRemotePort()
|
||||||
|
|
||||||
|
localAddr, err := wrapReq.GetUpstreamAddress()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
localPort, err := wrapReq.GetUpstreamPort()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
scheme := "http"
|
||||||
|
if req.TLS != nil {
|
||||||
|
scheme = "https"
|
||||||
|
}
|
||||||
|
|
||||||
|
context := &DetectionContext{
|
||||||
|
UUID: misc.GenUUID(),
|
||||||
|
Scheme: scheme,
|
||||||
|
ProxyName: "go-sdk",
|
||||||
|
RemoteAddr: remoteIP,
|
||||||
|
RemotePort: remotePort,
|
||||||
|
LocalAddr: localAddr,
|
||||||
|
LocalPort: localPort,
|
||||||
|
ReqBeginTime: misc.Now(),
|
||||||
|
Request: wrapReq,
|
||||||
|
Protocol: req.Proto,
|
||||||
|
}
|
||||||
|
wrapReq.dc = context
|
||||||
|
return context, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *DetectionContext) ProcessResult(r *Result) {
|
||||||
|
if r.Objective == RO_REQUEST {
|
||||||
|
dc.T1KContext = r.T1KContext
|
||||||
|
}
|
||||||
|
}
|
||||||
93
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/extra.go
generated
vendored
Normal file
93
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/extra.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package detection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeRequestExtra(
|
||||||
|
scheme string,
|
||||||
|
proxyName string,
|
||||||
|
remoteAddr string,
|
||||||
|
remotePort uint16,
|
||||||
|
localAddr string,
|
||||||
|
localPort uint16,
|
||||||
|
uuid string,
|
||||||
|
hasRspIfOK string,
|
||||||
|
hasRspIfBlock string,
|
||||||
|
reqBeginTime int64,
|
||||||
|
) []byte {
|
||||||
|
format := "Scheme:%s\n" +
|
||||||
|
"ProxyName:%s\n" +
|
||||||
|
"RemoteAddr:%s\n" +
|
||||||
|
"RemotePort:%d\n" +
|
||||||
|
"LocalAddr:%s\n" +
|
||||||
|
"LocalPort:%d\n" +
|
||||||
|
"UUID:%s\n" +
|
||||||
|
"HasRspIfOK:%s\n" +
|
||||||
|
"HasRspIfBlock:%s\n" +
|
||||||
|
"ReqBeginTime:%d\n"
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf(
|
||||||
|
format,
|
||||||
|
scheme,
|
||||||
|
proxyName,
|
||||||
|
remoteAddr,
|
||||||
|
remotePort,
|
||||||
|
localAddr,
|
||||||
|
localPort,
|
||||||
|
uuid,
|
||||||
|
hasRspIfOK,
|
||||||
|
hasRspIfBlock,
|
||||||
|
reqBeginTime,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeResponseExtra(
|
||||||
|
scheme string,
|
||||||
|
proxyName string,
|
||||||
|
remoteAddr string,
|
||||||
|
remotePort uint16,
|
||||||
|
localAddr string,
|
||||||
|
localPort uint16,
|
||||||
|
uuid string,
|
||||||
|
rspBeginTime int64,
|
||||||
|
) []byte {
|
||||||
|
format := "Scheme:%s\n" +
|
||||||
|
"ProxyName:%s\n" +
|
||||||
|
"RemoteAddr:%s\n" +
|
||||||
|
"RemotePort:%d\n" +
|
||||||
|
"LocalAddr:%s\n" +
|
||||||
|
"LocalPort:%d\n" +
|
||||||
|
"UUID:%s\n" +
|
||||||
|
"RspBeginTime:%d\n"
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf(
|
||||||
|
format,
|
||||||
|
scheme,
|
||||||
|
proxyName,
|
||||||
|
remoteAddr,
|
||||||
|
remotePort,
|
||||||
|
localAddr,
|
||||||
|
localPort,
|
||||||
|
uuid,
|
||||||
|
rspBeginTime,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func PlaceholderRequestExtra(uuid string) []byte {
|
||||||
|
return MakeRequestExtra("http", "go-sdk", "127.0.0.1", 30001, "127.0.0.1", 80, uuid, "n", "n", misc.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenRequestExtra(dc *DetectionContext) []byte {
|
||||||
|
hasRsp := "u"
|
||||||
|
if dc.Response != nil {
|
||||||
|
hasRsp = "y"
|
||||||
|
}
|
||||||
|
return MakeRequestExtra(dc.Scheme, dc.ProxyName, dc.RemoteAddr, dc.RemotePort, dc.LocalAddr, dc.LocalPort, dc.UUID, hasRsp, hasRsp, dc.ReqBeginTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenResponseExtra(dc *DetectionContext) []byte {
|
||||||
|
return MakeResponseExtra(dc.Scheme, dc.ProxyName, dc.RemoteAddr, dc.RemotePort, dc.LocalAddr, dc.LocalPort, dc.UUID, dc.RspBeginTime)
|
||||||
|
}
|
||||||
132
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/request.go
generated
vendored
Normal file
132
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/request.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package detection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Request interface {
|
||||||
|
Header() ([]byte, error)
|
||||||
|
Body() (uint32, io.ReadCloser, error)
|
||||||
|
Extra() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpRequest struct {
|
||||||
|
req *http.Request
|
||||||
|
dc *DetectionContext // this is optional
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeHttpRequest(req *http.Request) *HttpRequest {
|
||||||
|
return &HttpRequest{
|
||||||
|
req: req,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeHttpRequestInCtx(req *http.Request, dc *DetectionContext) *HttpRequest {
|
||||||
|
ret := &HttpRequest{
|
||||||
|
req: req,
|
||||||
|
dc: dc,
|
||||||
|
}
|
||||||
|
dc.Request = ret
|
||||||
|
|
||||||
|
if dc.ReqBeginTime == 0 {
|
||||||
|
dc.ReqBeginTime = misc.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) GetUpstreamAddress() (string, error) {
|
||||||
|
if r.req.Host == "" {
|
||||||
|
return "", errors.New("empty Host in request")
|
||||||
|
}
|
||||||
|
host, _, err := net.SplitHostPort(r.req.Host)
|
||||||
|
if err != nil {
|
||||||
|
return r.req.Host, nil // OK; there probably was no port
|
||||||
|
}
|
||||||
|
return host, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) GetUpstreamPort() (uint16, error) {
|
||||||
|
_, port, err := net.SplitHostPort(r.req.Host)
|
||||||
|
if err != nil {
|
||||||
|
if r.req.TLS != nil {
|
||||||
|
return 443, nil
|
||||||
|
} else {
|
||||||
|
return 80, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if portNum, err := strconv.Atoi(port); err == nil {
|
||||||
|
return uint16(portNum), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("wrong value of port")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) GetRemoteIP() (string, error) {
|
||||||
|
host, _, err := net.SplitHostPort(r.req.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
return r.req.RemoteAddr, nil
|
||||||
|
}
|
||||||
|
return host, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) GetRemotePort() (uint16, error) {
|
||||||
|
_, port, _ := net.SplitHostPort(r.req.RemoteAddr)
|
||||||
|
if portNum, err := strconv.Atoi(port); err == nil {
|
||||||
|
return uint16(portNum), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("wrong value of port")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) Header() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
proto := r.req.Proto
|
||||||
|
if r.dc != nil {
|
||||||
|
if r.dc.Protocol != "" {
|
||||||
|
proto = r.dc.Protocol
|
||||||
|
} else {
|
||||||
|
r.dc.Protocol = proto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startLine := fmt.Sprintf("%s %s %s\r\n", r.req.Method, r.req.URL.RequestURI(), proto)
|
||||||
|
_, err := buf.Write([]byte(startLine))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = buf.Write([]byte(fmt.Sprintf("Host: %s\r\n", r.req.Host)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = r.req.Header.Write(&buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = buf.Write([]byte("\r\n"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) Body() (uint32, io.ReadCloser, error) {
|
||||||
|
bodyBytes, err := io.ReadAll(r.req.Body)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
r.req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
|
||||||
|
return uint32(len(bodyBytes)), io.NopCloser(bytes.NewReader(bodyBytes)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpRequest) Extra() ([]byte, error) {
|
||||||
|
if r.dc == nil {
|
||||||
|
return PlaceholderRequestExtra(misc.GenUUID()), nil
|
||||||
|
}
|
||||||
|
return GenRequestExtra(r.dc), nil
|
||||||
|
}
|
||||||
72
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/response.go
generated
vendored
Normal file
72
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/response.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package detection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Response interface {
|
||||||
|
RequestHeader() ([]byte, error)
|
||||||
|
Header() ([]byte, error)
|
||||||
|
Body() (uint32, io.ReadCloser, error)
|
||||||
|
Extra() ([]byte, error)
|
||||||
|
T1KContext() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpResponse struct {
|
||||||
|
rsp *http.Response
|
||||||
|
dc *DetectionContext // this is a must-have
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeHttpResponseInCtx(rsp *http.Response, dc *DetectionContext) *HttpResponse {
|
||||||
|
ret := &HttpResponse{
|
||||||
|
rsp: rsp,
|
||||||
|
dc: dc,
|
||||||
|
}
|
||||||
|
dc.Response = ret
|
||||||
|
dc.RspBeginTime = misc.Now()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpResponse) RequestHeader() ([]byte, error) {
|
||||||
|
return r.dc.Request.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpResponse) Header() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
statusLine := fmt.Sprintf("HTTP/1.1 %s\n", r.rsp.Status)
|
||||||
|
_, err := buf.Write([]byte(statusLine))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = r.rsp.Header.Write(&buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = buf.Write([]byte("\r\n"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpResponse) Body() (uint32, io.ReadCloser, error) {
|
||||||
|
bodyBytes, err := io.ReadAll(r.rsp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, misc.ErrorWrapf(err, "get body size %d", len(bodyBytes))
|
||||||
|
}
|
||||||
|
r.rsp.Body = io.NopCloser(bytes.NewReader(bodyBytes))
|
||||||
|
return uint32(len(bodyBytes)), io.NopCloser(bytes.NewReader(bodyBytes)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpResponse) Extra() ([]byte, error) {
|
||||||
|
return GenResponseExtra(r.dc), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HttpResponse) T1KContext() ([]byte, error) {
|
||||||
|
return r.dc.T1KContext, nil
|
||||||
|
}
|
||||||
76
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/result.go
generated
vendored
Normal file
76
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/result.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package detection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResultObjective int
|
||||||
|
|
||||||
|
const (
|
||||||
|
RO_REQUEST ResultObjective = 0
|
||||||
|
RO_RESPONSE ResultObjective = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
Objective ResultObjective
|
||||||
|
Head byte
|
||||||
|
Body []byte
|
||||||
|
Alog []byte
|
||||||
|
ExtraHeader []byte
|
||||||
|
ExtraBody []byte
|
||||||
|
T1KContext []byte
|
||||||
|
Cookie []byte
|
||||||
|
WebLog []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Result) Passed() bool {
|
||||||
|
return r.Head == '.'
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Result) Blocked() bool {
|
||||||
|
return !r.Passed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Result) StatusCode() int {
|
||||||
|
str := string(r.Body)
|
||||||
|
if str == "" {
|
||||||
|
return http.StatusForbidden
|
||||||
|
}
|
||||||
|
code, err := strconv.Atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("t1k convert status code failed: %v", err)
|
||||||
|
return http.StatusForbidden
|
||||||
|
}
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Result) BlockMessage() map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"status": r.StatusCode(),
|
||||||
|
"success": false,
|
||||||
|
"message": "blocked by Chaitin SafeLine Web Application Firewall",
|
||||||
|
"event_id": r.EventID(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Result) EventID() string {
|
||||||
|
extra := string(r.ExtraBody)
|
||||||
|
if extra == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// <!-- event_id: e1impksyjq0gl92le6odi0fnobi270cj -->
|
||||||
|
re, err := regexp.Compile(`<\!--\s*event_id:\s*([a-zA-Z0-9]+)\s*-->\s*`)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("t1k compile regexp failed: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
matches := re.FindStringSubmatch(extra)
|
||||||
|
if len(matches) < 2 {
|
||||||
|
log.Printf("t1k regexp not match event id: %s", extra)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return matches[1]
|
||||||
|
}
|
||||||
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/heartbeat.go
generated
vendored
Normal file
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/heartbeat.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/t1k"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DoHeartbeat(s io.ReadWriter) error {
|
||||||
|
h := t1k.MakeHeader(t1k.MASK_FIRST|t1k.MASK_LAST, 0)
|
||||||
|
_, err := s.Write(h.Serialize())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = readDetectionResult(s)
|
||||||
|
return err
|
||||||
|
}
|
||||||
81
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/dump_hex.go
generated
vendored
Normal file
81
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/dump_hex.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package misc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var asciiPrintableMap map[byte]bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
asciiPrintableMap = make(map[byte]bool)
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
asciiPrintableMap[byte(i)] = false
|
||||||
|
}
|
||||||
|
s := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "
|
||||||
|
for _, ch := range []byte(s) {
|
||||||
|
asciiPrintableMap[ch] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAsciiPrintable(b byte) bool {
|
||||||
|
return asciiPrintableMap[b]
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpHex(w io.Writer, b []byte) error {
|
||||||
|
lines := len(b) / 16
|
||||||
|
for i := 0; i < lines; i += 1 {
|
||||||
|
srep := ""
|
||||||
|
for j := 0; j < 16; j += 1 {
|
||||||
|
it := b[16*i+j]
|
||||||
|
_, err := w.Write([]byte(fmt.Sprintf("%02x ", it)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isAsciiPrintable(it) {
|
||||||
|
srep += string([]byte{it})
|
||||||
|
} else {
|
||||||
|
srep += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := w.Write([]byte("| " + srep + "\n"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remain := len(b) - 16*lines
|
||||||
|
srep := ""
|
||||||
|
j := 0
|
||||||
|
for ; j < remain; j += 1 {
|
||||||
|
it := b[16*lines+j]
|
||||||
|
_, err := w.Write([]byte(fmt.Sprintf("%02x ", it)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isAsciiPrintable(it) {
|
||||||
|
srep += string([]byte{it})
|
||||||
|
} else {
|
||||||
|
srep += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ; j < 16; j++ {
|
||||||
|
_, err := w.Write([]byte(" "))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srep += " "
|
||||||
|
}
|
||||||
|
_, err := w.Write([]byte("| " + srep + "\n"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintHex(b []byte) {
|
||||||
|
err := DumpHex(os.Stdout, b)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error in PrintHex() : %s\n", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
58
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/errors.go
generated
vendored
Normal file
58
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/errors.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package misc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type wrapError struct {
|
||||||
|
message string
|
||||||
|
next error
|
||||||
|
frame xerrors.Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *wrapError) Unwrap() error {
|
||||||
|
return e.next
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *wrapError) Error() string {
|
||||||
|
if e.next == nil {
|
||||||
|
return e.message
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s: %v", e.message, e.next)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *wrapError) Format(f fmt.State, c rune) {
|
||||||
|
xerrors.FormatError(e, f, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *wrapError) FormatError(p xerrors.Printer) error {
|
||||||
|
p.Print(e.message)
|
||||||
|
if p.Detail() {
|
||||||
|
e.frame.Format(p)
|
||||||
|
}
|
||||||
|
return e.next
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrap(err error, message string, skip int) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &wrapError{
|
||||||
|
message: message,
|
||||||
|
next: err,
|
||||||
|
frame: xerrors.Caller(skip),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap returns a error annotating `err` with `message` and the caller's frame.
|
||||||
|
// Wrap returns nil if `err` is nil.
|
||||||
|
func ErrorWrap(err error, message string) error {
|
||||||
|
return wrap(err, message, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf returns a error annotating `err` with `message` formatted and the caller's frame.
|
||||||
|
func ErrorWrapf(err error, message string, args ...interface{}) error {
|
||||||
|
return wrap(err, fmt.Sprintf(message, args...), 2)
|
||||||
|
}
|
||||||
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/gen_uuid.go
generated
vendored
Normal file
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/gen_uuid.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package misc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rng *MT19937 = NewMT19937()
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenUUID() string {
|
||||||
|
u := make([]byte, 16)
|
||||||
|
rng.RandBytes(u)
|
||||||
|
u[6] = (u[6] | 0x40) & 0x4F
|
||||||
|
u[8] = (u[8] | 0x80) & 0xBF
|
||||||
|
return hex.EncodeToString(u)
|
||||||
|
}
|
||||||
102
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/mt19937.go
generated
vendored
Normal file
102
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/mt19937.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package misc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
n = 312
|
||||||
|
m = 156
|
||||||
|
seedMask = 170298
|
||||||
|
hiMask uint64 = 0xffffffff80000000
|
||||||
|
loMask uint64 = 0x000000007fffffff
|
||||||
|
matrixA uint64 = 0xB5026F5AA96619E9
|
||||||
|
)
|
||||||
|
|
||||||
|
type MT19937 struct {
|
||||||
|
state []uint64
|
||||||
|
index int
|
||||||
|
mut sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMT19937WithSeed(seed int64) *MT19937 {
|
||||||
|
mt := &MT19937{
|
||||||
|
state: make([]uint64, n),
|
||||||
|
index: n,
|
||||||
|
}
|
||||||
|
|
||||||
|
mt.mut.Lock()
|
||||||
|
defer mt.mut.Unlock()
|
||||||
|
|
||||||
|
mt.state[0] = uint64(seed)
|
||||||
|
for i := uint64(1); i < n; i++ {
|
||||||
|
mt.state[i] = 6364136223846793005*(mt.state[i-1]^(mt.state[i-1]>>62)) + i
|
||||||
|
}
|
||||||
|
|
||||||
|
return mt
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMT19937() *MT19937 {
|
||||||
|
var seed int64
|
||||||
|
|
||||||
|
b := make([]byte, 8)
|
||||||
|
if _, err := rand.Read(b); err == nil {
|
||||||
|
seed = int64(binary.LittleEndian.Uint64(b[:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
seed = seed ^ time.Now().UnixNano() ^ seedMask
|
||||||
|
|
||||||
|
return NewMT19937WithSeed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mt *MT19937) Uint64() uint64 {
|
||||||
|
mt.mut.Lock()
|
||||||
|
defer mt.mut.Unlock()
|
||||||
|
|
||||||
|
x := mt.state
|
||||||
|
if mt.index >= n {
|
||||||
|
for i := 0; i < n-m; i++ {
|
||||||
|
y := (x[i] & hiMask) | (x[i+1] & loMask)
|
||||||
|
x[i] = x[i+m] ^ (y >> 1) ^ ((y & 1) * matrixA)
|
||||||
|
}
|
||||||
|
for i := n - m; i < n-1; i++ {
|
||||||
|
y := (x[i] & hiMask) | (x[i+1] & loMask)
|
||||||
|
x[i] = x[i+(m-n)] ^ (y >> 1) ^ ((y & 1) * matrixA)
|
||||||
|
}
|
||||||
|
y := (x[n-1] & hiMask) | (x[0] & loMask)
|
||||||
|
x[n-1] = x[m-1] ^ (y >> 1) ^ ((y & 1) * matrixA)
|
||||||
|
mt.index = 0
|
||||||
|
}
|
||||||
|
y := x[mt.index]
|
||||||
|
y ^= (y >> 29) & 0x5555555555555555
|
||||||
|
y ^= (y << 17) & 0x71D67FFFEDA60000
|
||||||
|
y ^= (y << 37) & 0xFFF7EEE000000000
|
||||||
|
y ^= (y >> 43)
|
||||||
|
mt.index++
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mt *MT19937) RandBytes(p []byte) {
|
||||||
|
for len(p) >= 8 {
|
||||||
|
val := mt.Uint64()
|
||||||
|
p[0] = byte(val)
|
||||||
|
p[1] = byte(val >> 8)
|
||||||
|
p[2] = byte(val >> 16)
|
||||||
|
p[3] = byte(val >> 24)
|
||||||
|
p[4] = byte(val >> 32)
|
||||||
|
p[5] = byte(val >> 40)
|
||||||
|
p[6] = byte(val >> 48)
|
||||||
|
p[7] = byte(val >> 56)
|
||||||
|
p = p[8:]
|
||||||
|
}
|
||||||
|
if len(p) > 0 {
|
||||||
|
val := mt.Uint64()
|
||||||
|
for i := 0; i < len(p); i++ {
|
||||||
|
p[i] = byte(val)
|
||||||
|
val >>= 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/now.go
generated
vendored
Normal file
9
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/now.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package misc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Now() int64 {
|
||||||
|
return time.Now().UnixNano() / 1e3
|
||||||
|
}
|
||||||
184
sdk/traefik/vendor/github.com/chaitin/t1k-go/server.go
generated
vendored
Normal file
184
sdk/traefik/vendor/github.com/chaitin/t1k-go/server.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/detection"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEFAULT_POOL_SIZE = 8
|
||||||
|
HEARTBEAT_INTERVAL = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
socketFactory func() (net.Conn, error)
|
||||||
|
poolCh chan *conn
|
||||||
|
poolSize int
|
||||||
|
count int
|
||||||
|
closeCh chan struct{}
|
||||||
|
logger *log.Logger
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) newConn() error {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
sock, err := s.socketFactory()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.count += 1
|
||||||
|
s.poolCh <- makeConn(sock, s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetConn() (*conn, error) {
|
||||||
|
if s.count < s.poolSize {
|
||||||
|
for i := 0; i < (s.poolSize - s.count); i++ {
|
||||||
|
err := s.newConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := <-s.poolCh
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) PutConn(c *conn) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
if c.failing {
|
||||||
|
s.count -= 1
|
||||||
|
c.Close()
|
||||||
|
} else {
|
||||||
|
s.poolCh <- c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) broadcastHeartbeat() {
|
||||||
|
l := len(s.poolCh)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
select {
|
||||||
|
case c := <-s.poolCh:
|
||||||
|
c.Heartbeat()
|
||||||
|
s.PutConn(c)
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) runHeartbeatCo() {
|
||||||
|
for {
|
||||||
|
timer := time.NewTimer(HEARTBEAT_INTERVAL * time.Second)
|
||||||
|
select {
|
||||||
|
case <-s.closeCh:
|
||||||
|
return
|
||||||
|
case <-timer.C:
|
||||||
|
}
|
||||||
|
s.broadcastHeartbeat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFromSocketFactoryWithPoolSize(socketFactory func() (net.Conn, error), poolSize int) (*Server, error) {
|
||||||
|
ret := &Server{
|
||||||
|
socketFactory: socketFactory,
|
||||||
|
poolCh: make(chan *conn, poolSize),
|
||||||
|
poolSize: poolSize,
|
||||||
|
closeCh: make(chan struct{}),
|
||||||
|
logger: log.New(os.Stdout, "snserver", log.LstdFlags),
|
||||||
|
mu: sync.Mutex{},
|
||||||
|
}
|
||||||
|
for i := 0; i < poolSize; i++ {
|
||||||
|
err := ret.newConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go ret.runHeartbeatCo()
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFromSocketFactory(socketFactory func() (net.Conn, error)) (*Server, error) {
|
||||||
|
return NewFromSocketFactoryWithPoolSize(socketFactory, DEFAULT_POOL_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWithPoolSize(addr string, poolSize int) (*Server, error) {
|
||||||
|
return NewFromSocketFactoryWithPoolSize(func() (net.Conn, error) {
|
||||||
|
return net.Dial("tcp", addr)
|
||||||
|
}, poolSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(addr string) (*Server, error) {
|
||||||
|
return NewWithPoolSize(addr, DEFAULT_POOL_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) DetectRequestInCtx(dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.PutConn(c)
|
||||||
|
return c.DetectRequestInCtx(dc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) DetectResponseInCtx(dc *detection.DetectionContext) (*detection.Result, error) {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
defer s.PutConn(c)
|
||||||
|
return c.DetectResponseInCtx(dc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Detect(dc *detection.DetectionContext) (*detection.Result, *detection.Result, error) {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
reqResult, rspResult, err := c.Detect(dc)
|
||||||
|
if err == nil {
|
||||||
|
s.PutConn(c)
|
||||||
|
}
|
||||||
|
return reqResult, rspResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) DetectHttpRequest(req *http.Request) (*detection.Result, error) {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.PutConn(c)
|
||||||
|
return c.DetectHttpRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) DetectRequest(req detection.Request) (*detection.Result, error) {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.PutConn(c)
|
||||||
|
return c.DetectRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// blocks until all pending detection is completed
|
||||||
|
func (s *Server) Close() {
|
||||||
|
close(s.closeCh)
|
||||||
|
for i := 0; i < s.count; i++ {
|
||||||
|
c, err := s.GetConn()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
35
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/header.go
generated
vendored
Normal file
35
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/header.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
T1K_HEADER_SIZE uint64 = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
type Header struct {
|
||||||
|
Tag Tag
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeHeader(tag Tag, size uint32) Header {
|
||||||
|
return Header{
|
||||||
|
Tag: tag,
|
||||||
|
Size: size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Header) Serialize() []byte {
|
||||||
|
b := make([]byte, 5)
|
||||||
|
b[0] = byte(uint8(h.Tag))
|
||||||
|
binary.LittleEndian.PutUint32(b[1:], h.Size)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeserializeHeader(b []byte) Header {
|
||||||
|
return MakeHeader(
|
||||||
|
Tag(uint8(b[0])),
|
||||||
|
binary.LittleEndian.Uint32(b[1:]),
|
||||||
|
)
|
||||||
|
}
|
||||||
95
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/section.go
generated
vendored
Normal file
95
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/section.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/chaitin/t1k-go/misc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Section interface {
|
||||||
|
Header() Header
|
||||||
|
WriteBody(io.Writer) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type SimpleSection struct {
|
||||||
|
tag Tag
|
||||||
|
body []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeSimpleSection(tag Tag, body []byte) *SimpleSection {
|
||||||
|
return &SimpleSection{
|
||||||
|
tag: tag,
|
||||||
|
body: body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *SimpleSection) Header() Header {
|
||||||
|
return MakeHeader(msg.tag, uint32(len(msg.body)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *SimpleSection) WriteBody(w io.Writer) error {
|
||||||
|
_, err := w.Write(msg.body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReaderSection struct {
|
||||||
|
tag Tag
|
||||||
|
size uint32
|
||||||
|
reader io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeReaderSection(tag Tag, size uint32, reader io.Reader) *ReaderSection {
|
||||||
|
return &ReaderSection{
|
||||||
|
tag: tag,
|
||||||
|
size: size,
|
||||||
|
reader: reader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ReaderSection) Header() Header {
|
||||||
|
return MakeHeader(msg.tag, msg.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ReaderSection) WriteBody(w io.Writer) error {
|
||||||
|
_, err := io.CopyN(w, msg.reader, int64(msg.size))
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteSection(s Section, w io.Writer) error {
|
||||||
|
h := s.Header()
|
||||||
|
_, err := w.Write(h.Serialize())
|
||||||
|
if err != nil {
|
||||||
|
return misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
return s.WriteBody(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a *ReaderSection, must call its WriteBody
|
||||||
|
// before next call to r
|
||||||
|
func ReadSection(r io.Reader) (Section, error) {
|
||||||
|
bHeader := make([]byte, T1K_HEADER_SIZE)
|
||||||
|
_, err := io.ReadFull(r, bHeader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h := DeserializeHeader(bHeader)
|
||||||
|
bodyReader := io.LimitReader(r, int64(h.Size))
|
||||||
|
return MakeReaderSection(h.Tag, h.Size, bodyReader), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a *SimpleSection
|
||||||
|
func ReadFullSection(r io.Reader) (Section, error) {
|
||||||
|
bHeader := make([]byte, T1K_HEADER_SIZE)
|
||||||
|
_, err := io.ReadFull(r, bHeader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
h := DeserializeHeader(bHeader)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
_, err = io.CopyN(&buf, r, int64(h.Size))
|
||||||
|
if err != nil {
|
||||||
|
return nil, misc.ErrorWrap(err, "")
|
||||||
|
}
|
||||||
|
return MakeSimpleSection(h.Tag, buf.Bytes()), nil
|
||||||
|
}
|
||||||
39
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/tag.go
generated
vendored
Normal file
39
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/tag.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package t1k
|
||||||
|
|
||||||
|
type Tag uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
TAG_HEADER Tag = 0x01
|
||||||
|
TAG_BODY Tag = 0x02
|
||||||
|
TAG_EXTRA Tag = 0x03
|
||||||
|
TAG_RSP_HEADER Tag = 0x11
|
||||||
|
TAG_RSP_BODY Tag = 0x12
|
||||||
|
TAG_RSP_EXTRA Tag = 0x13
|
||||||
|
TAG_VERSION Tag = 0x20
|
||||||
|
TAG_ALOG Tag = 0x21
|
||||||
|
TAG_STAT Tag = 0x22
|
||||||
|
TAG_EXTRA_HEADER Tag = 0x23
|
||||||
|
TAG_EXTRA_BODY Tag = 0x24
|
||||||
|
TAG_CONTEXT Tag = 0x25
|
||||||
|
TAG_COOKIE Tag = 0x26
|
||||||
|
TAG_WEB_LOG Tag = 0x27
|
||||||
|
TAG_USER_DATA Tag = 0x28
|
||||||
|
TAG_BOT_QUERY Tag = 0x29
|
||||||
|
TAG_BOT_BODY Tag = 0x30
|
||||||
|
|
||||||
|
MASK_TAG Tag = 0x3f
|
||||||
|
MASK_FIRST Tag = 0x40
|
||||||
|
MASK_LAST Tag = 0x80
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t Tag) IsFirst() bool {
|
||||||
|
return !(0 == (t & MASK_FIRST))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tag) IsLast() bool {
|
||||||
|
return !(0 == (t & MASK_LAST))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tag) Strip() Tag {
|
||||||
|
return t & MASK_TAG
|
||||||
|
}
|
||||||
27
sdk/traefik/vendor/golang.org/x/xerrors/LICENSE
generated
vendored
Normal file
27
sdk/traefik/vendor/golang.org/x/xerrors/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
22
sdk/traefik/vendor/golang.org/x/xerrors/PATENTS
generated
vendored
Normal file
22
sdk/traefik/vendor/golang.org/x/xerrors/PATENTS
generated
vendored
Normal file
@@ -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.
|
||||||
2
sdk/traefik/vendor/golang.org/x/xerrors/README
generated
vendored
Normal file
2
sdk/traefik/vendor/golang.org/x/xerrors/README
generated
vendored
Normal file
@@ -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.
|
||||||
193
sdk/traefik/vendor/golang.org/x/xerrors/adaptor.go
generated
vendored
Normal file
193
sdk/traefik/vendor/golang.org/x/xerrors/adaptor.go
generated
vendored
Normal file
@@ -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("<nil>")
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
1
sdk/traefik/vendor/golang.org/x/xerrors/codereview.cfg
generated
vendored
Normal file
1
sdk/traefik/vendor/golang.org/x/xerrors/codereview.cfg
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
issuerepo: golang/go
|
||||||
23
sdk/traefik/vendor/golang.org/x/xerrors/doc.go
generated
vendored
Normal file
23
sdk/traefik/vendor/golang.org/x/xerrors/doc.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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"
|
||||||
33
sdk/traefik/vendor/golang.org/x/xerrors/errors.go
generated
vendored
Normal file
33
sdk/traefik/vendor/golang.org/x/xerrors/errors.go
generated
vendored
Normal file
@@ -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
|
||||||
|
}
|
||||||
190
sdk/traefik/vendor/golang.org/x/xerrors/fmt.go
generated
vendored
Normal file
190
sdk/traefik/vendor/golang.org/x/xerrors/fmt.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Note that as of Go 1.13, the fmt.Errorf function will do error formatting,
|
||||||
|
// but it will not capture a stack backtrace.
|
||||||
|
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
|
||||||
|
}
|
||||||
34
sdk/traefik/vendor/golang.org/x/xerrors/format.go
generated
vendored
Normal file
34
sdk/traefik/vendor/golang.org/x/xerrors/format.go
generated
vendored
Normal file
@@ -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
|
||||||
|
}
|
||||||
56
sdk/traefik/vendor/golang.org/x/xerrors/frame.go
generated
vendored
Normal file
56
sdk/traefik/vendor/golang.org/x/xerrors/frame.go
generated
vendored
Normal file
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
sdk/traefik/vendor/golang.org/x/xerrors/internal/internal.go
generated
vendored
Normal file
8
sdk/traefik/vendor/golang.org/x/xerrors/internal/internal.go
generated
vendored
Normal file
@@ -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
|
||||||
112
sdk/traefik/vendor/golang.org/x/xerrors/wrap.go
generated
vendored
Normal file
112
sdk/traefik/vendor/golang.org/x/xerrors/wrap.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Deprecated: As of Go 1.13, use errors.Unwrap instead.
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
// Deprecated: As of Go 1.13, use errors.Is instead.
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
// Deprecated: As of Go 1.13, use errors.As instead.
|
||||||
|
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()
|
||||||
14
sdk/traefik/vendor/modules.txt
vendored
14
sdk/traefik/vendor/modules.txt
vendored
@@ -1,6 +1,10 @@
|
|||||||
# github.com/xbingW/t1k v1.2.1
|
# github.com/chaitin/t1k-go v1.5.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/xbingW/t1k
|
github.com/chaitin/t1k-go
|
||||||
github.com/xbingW/t1k/pkg/datetime
|
github.com/chaitin/t1k-go/detection
|
||||||
github.com/xbingW/t1k/pkg/rand
|
github.com/chaitin/t1k-go/misc
|
||||||
github.com/xbingW/t1k/pkg/t1k
|
github.com/chaitin/t1k-go/t1k
|
||||||
|
# golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
|
||||||
|
## explicit; go 1.18
|
||||||
|
golang.org/x/xerrors
|
||||||
|
golang.org/x/xerrors/internal
|
||||||
|
|||||||
Reference in New Issue
Block a user