Explorar el Código

feat: update traefik sdk

xiaobing.wang hace 10 meses
padre
commit
4e033ed5f3
Se han modificado 36 ficheros con 2426 adiciones y 37 borrados
  1. 1 1
      sdk/traefik/.traefik.yml
  2. 1 1
      sdk/traefik/README.md
  3. 4 2
      sdk/traefik/go.mod
  4. 52 28
      sdk/traefik/safeline.go
  5. 201 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/License
  6. 5 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/README.md
  7. 101 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/conn.go
  8. 253 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detect.go
  9. 88 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/context.go
  10. 93 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/extra.go
  11. 132 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/request.go
  12. 72 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/response.go
  13. 76 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/result.go
  14. 17 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/heartbeat.go
  15. 81 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/dump_hex.go
  16. 58 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/errors.go
  17. 17 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/gen_uuid.go
  18. 102 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/mt19937.go
  19. 9 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/now.go
  20. 184 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/server.go
  21. 35 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/header.go
  22. 95 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/section.go
  23. 39 0
      sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/tag.go
  24. 27 0
      sdk/traefik/vendor/golang.org/x/xerrors/LICENSE
  25. 22 0
      sdk/traefik/vendor/golang.org/x/xerrors/PATENTS
  26. 2 0
      sdk/traefik/vendor/golang.org/x/xerrors/README
  27. 193 0
      sdk/traefik/vendor/golang.org/x/xerrors/adaptor.go
  28. 1 0
      sdk/traefik/vendor/golang.org/x/xerrors/codereview.cfg
  29. 23 0
      sdk/traefik/vendor/golang.org/x/xerrors/doc.go
  30. 33 0
      sdk/traefik/vendor/golang.org/x/xerrors/errors.go
  31. 190 0
      sdk/traefik/vendor/golang.org/x/xerrors/fmt.go
  32. 34 0
      sdk/traefik/vendor/golang.org/x/xerrors/format.go
  33. 56 0
      sdk/traefik/vendor/golang.org/x/xerrors/frame.go
  34. 8 0
      sdk/traefik/vendor/golang.org/x/xerrors/internal/internal.go
  35. 112 0
      sdk/traefik/vendor/golang.org/x/xerrors/wrap.go
  36. 9 5
      sdk/traefik/vendor/modules.txt

+ 1 - 1
sdk/traefik/.traefik.yml

@@ -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.'
 
 

+ 1 - 1
sdk/traefik/README.md

@@ -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
 ```
 ```
 
 

+ 4 - 2
sdk/traefik/go.mod

@@ -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

+ 52 - 28
sdk/traefik/safeline.go

@@ -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"`
-	// Get ip from header, if not set, get ip from remote addr
-	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"`
+	Addr     string `yaml:"addr"`
+	PoolSize int    `yaml:"pool_size"`
 }
 }
 
 
 // CreateConfig creates the default plugin configuration.
 // CreateConfig creates the default plugin configuration.
 func CreateConfig() *Config {
 func CreateConfig() *Config {
 	return &Config{
 	return &Config{
-		Addr:         "",
-		IpHeader:     "",
-		IPRightIndex: 0,
+		Addr:     "",
+		PoolSize: 100,
 	}
 	}
 }
 }
 
 
 // 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) initServer() error {
+	if s.server != nil {
+		return nil
+	}
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	if s.server == nil {
+		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) {
 func (s *Safeline) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
-	d := t1k.NewDetector(t1k.Config{
-		Addr:         s.config.Addr,
-		IpHeader:     s.config.IpHeader,
-		IPRightIndex: s.config.IPRightIndex,
-	})
-	resp, err := d.DetectorRequest(req)
+	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 {
 	if err != nil {
-		s.logger.Printf("Failed to detect request: %v", err)
+		s.logger.Printf("error in detection: \n%+v\n", err)
+		s.next.ServeHTTP(rw, req)
+		return
 	}
 	}
-	if resp != nil && !resp.Allowed() {
-		rw.WriteHeader(resp.StatusCode())
-		if err := json.NewEncoder(rw).Encode(resp.BlockMessage()); err != nil {
-			s.logger.Printf("Failed to encode block message: %v", err)
-		}
+	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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/License

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/README.md

@@ -0,0 +1,5 @@
+# t1k-go
+
+Go implementation of the T1K protocol for [Chaitin/SafeLine](https://github.com/chaitin/safeline) Web Application Firewall.
+
+

+ 101 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/conn.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detect.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/context.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/extra.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/request.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/response.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/result.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/heartbeat.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/dump_hex.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/errors.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/gen_uuid.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/mt19937.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/now.go

@@ -0,0 +1,9 @@
+package misc
+
+import (
+	"time"
+)
+
+func Now() int64 {
+	return time.Now().UnixNano() / 1e3
+}

+ 184 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/server.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/header.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/section.go

@@ -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 - 0
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/tag.go

@@ -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 - 0
sdk/traefik/vendor/golang.org/x/xerrors/LICENSE

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

+ 22 - 0
sdk/traefik/vendor/golang.org/x/xerrors/PATENTS

@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.

+ 2 - 0
sdk/traefik/vendor/golang.org/x/xerrors/README

@@ -0,0 +1,2 @@
+This repository holds the transition packages for the new Go 1.13 error values.
+See golang.org/design/29934-error-values.

+ 193 - 0
sdk/traefik/vendor/golang.org/x/xerrors/adaptor.go

@@ -0,0 +1,193 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+)
+
+// FormatError calls the FormatError method of f with an errors.Printer
+// configured according to s and verb, and writes the result to s.
+func FormatError(f Formatter, s fmt.State, verb rune) {
+	// Assuming this function is only called from the Format method, and given
+	// that FormatError takes precedence over Format, it cannot be called from
+	// any package that supports errors.Formatter. It is therefore safe to
+	// disregard that State may be a specific printer implementation and use one
+	// of our choice instead.
+
+	// limitations: does not support printing error as Go struct.
+
+	var (
+		sep    = " " // separator before next error
+		p      = &state{State: s}
+		direct = true
+	)
+
+	var err error = f
+
+	switch verb {
+	// Note that this switch must match the preference order
+	// for ordinary string printing (%#v before %+v, and so on).
+
+	case 'v':
+		if s.Flag('#') {
+			if stringer, ok := err.(fmt.GoStringer); ok {
+				io.WriteString(&p.buf, stringer.GoString())
+				goto exit
+			}
+			// proceed as if it were %v
+		} else if s.Flag('+') {
+			p.printDetail = true
+			sep = "\n  - "
+		}
+	case 's':
+	case 'q', 'x', 'X':
+		// Use an intermediate buffer in the rare cases that precision,
+		// truncation, or one of the alternative verbs (q, x, and X) are
+		// specified.
+		direct = false
+
+	default:
+		p.buf.WriteString("%!")
+		p.buf.WriteRune(verb)
+		p.buf.WriteByte('(')
+		switch {
+		case err != nil:
+			p.buf.WriteString(reflect.TypeOf(f).String())
+		default:
+			p.buf.WriteString("<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 - 0
sdk/traefik/vendor/golang.org/x/xerrors/codereview.cfg

@@ -0,0 +1 @@
+issuerepo: golang/go

+ 23 - 0
sdk/traefik/vendor/golang.org/x/xerrors/doc.go

@@ -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 - 0
sdk/traefik/vendor/golang.org/x/xerrors/errors.go

@@ -0,0 +1,33 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import "fmt"
+
+// errorString is a trivial implementation of error.
+type errorString struct {
+	s     string
+	frame Frame
+}
+
+// New returns an error that formats as the given text.
+//
+// The returned error contains a Frame set to the caller's location and
+// implements Formatter to show this information when printed with details.
+func New(text string) error {
+	return &errorString{text, Caller(1)}
+}
+
+func (e *errorString) Error() string {
+	return e.s
+}
+
+func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) }
+
+func (e *errorString) FormatError(p Printer) (next error) {
+	p.Print(e.s)
+	e.frame.Format(p)
+	return nil
+}

+ 190 - 0
sdk/traefik/vendor/golang.org/x/xerrors/fmt.go

@@ -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 - 0
sdk/traefik/vendor/golang.org/x/xerrors/format.go

@@ -0,0 +1,34 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+// A Formatter formats error messages.
+type Formatter interface {
+	error
+
+	// FormatError prints the receiver's first error and returns the next error in
+	// the error chain, if any.
+	FormatError(p Printer) (next error)
+}
+
+// A Printer formats error messages.
+//
+// The most common implementation of Printer is the one provided by package fmt
+// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message
+// typically provide their own implementations.
+type Printer interface {
+	// Print appends args to the message output.
+	Print(args ...interface{})
+
+	// Printf writes a formatted string.
+	Printf(format string, args ...interface{})
+
+	// Detail reports whether error detail is requested.
+	// After the first call to Detail, all text written to the Printer
+	// is formatted as additional detail, or ignored when
+	// detail has not been requested.
+	// If Detail returns false, the caller can avoid printing the detail at all.
+	Detail() bool
+}

+ 56 - 0
sdk/traefik/vendor/golang.org/x/xerrors/frame.go

@@ -0,0 +1,56 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors
+
+import (
+	"runtime"
+)
+
+// A Frame contains part of a call stack.
+type Frame struct {
+	// Make room for three PCs: the one we were asked for, what it called,
+	// and possibly a PC for skipPleaseUseCallersFrames. See:
+	// https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169
+	frames [3]uintptr
+}
+
+// Caller returns a Frame that describes a frame on the caller's stack.
+// The argument skip is the number of frames to skip over.
+// Caller(0) returns the frame for the caller of Caller.
+func Caller(skip int) Frame {
+	var s Frame
+	runtime.Callers(skip+1, s.frames[:])
+	return s
+}
+
+// location reports the file, line, and function of a frame.
+//
+// The returned function may be "" even if file and line are not.
+func (f Frame) location() (function, file string, line int) {
+	frames := runtime.CallersFrames(f.frames[:])
+	if _, ok := frames.Next(); !ok {
+		return "", "", 0
+	}
+	fr, ok := frames.Next()
+	if !ok {
+		return "", "", 0
+	}
+	return fr.Function, fr.File, fr.Line
+}
+
+// Format prints the stack as error detail.
+// It should be called from an error's Format implementation
+// after printing any other error detail.
+func (f Frame) Format(p Printer) {
+	if p.Detail() {
+		function, file, line := f.location()
+		if function != "" {
+			p.Printf("%s\n    ", function)
+		}
+		if file != "" {
+			p.Printf("%s:%d\n", file, line)
+		}
+	}
+}

+ 8 - 0
sdk/traefik/vendor/golang.org/x/xerrors/internal/internal.go

@@ -0,0 +1,8 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+// EnableTrace indicates whether stack information should be recorded in errors.
+var EnableTrace = true

+ 112 - 0
sdk/traefik/vendor/golang.org/x/xerrors/wrap.go

@@ -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()

+ 9 - 5
sdk/traefik/vendor/modules.txt

@@ -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/xbingW/t1k/pkg/datetime
-github.com/xbingW/t1k/pkg/rand
-github.com/xbingW/t1k/pkg/t1k
+github.com/chaitin/t1k-go
+github.com/chaitin/t1k-go/detection
+github.com/chaitin/t1k-go/misc
+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