mirror of
https://github.com/chaitin/SafeLine.git
synced 2025-11-25 03:15:15 +08:00
feat: use submodule
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -3,3 +3,6 @@
|
||||
url = https://github.com/chaitin/blazehttp
|
||||
|
||||
|
||||
[submodule "sdk/traefik-safeline"]
|
||||
path = sdk/traefik-safeline
|
||||
url = https://github.com/chaitin/traefik-safeline
|
||||
|
||||
1
sdk/traefik-safeline
Submodule
1
sdk/traefik-safeline
Submodule
Submodule sdk/traefik-safeline added at bc2258ccc3
@@ -1,9 +0,0 @@
|
||||
displayName: Chaitin Safeline WAF
|
||||
type: middleware
|
||||
|
||||
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.'
|
||||
|
||||
testData:
|
||||
addr: safeline-detector:8000
|
||||
@@ -1,62 +0,0 @@
|
||||
# Traefik Plugin Safeline
|
||||
|
||||
This plugin is a middleware for Traefik that can be used to detect and block malicious requests which base on the [Safeline](https://waf.chaitin.com/) engine.
|
||||
|
||||
## Usage
|
||||
|
||||
For a plugin to be active for a given Traefik instance, it must be declared in the static configuration.
|
||||
|
||||
Plugins are parsed and loaded exclusively during startup, which allows Traefik to check the integrity of the code and catch errors early on.
|
||||
If an error occurs during loading, the plugin is disabled.
|
||||
|
||||
For security reasons, it is not possible to start a new plugin or modify an existing one while Traefik is running.
|
||||
|
||||
Once loaded, middleware plugins behave exactly like statically compiled middlewares.
|
||||
Their instantiation and behavior are driven by the dynamic configuration.
|
||||
|
||||
Plugin dependencies must be [vendored](https://golang.org/ref/mod#vendoring) for each plugin.
|
||||
Vendored packages should be included in the plugin's GitHub repository. ([Go modules](https://blog.golang.org/using-go-modules) are not supported.)
|
||||
|
||||
### Configuration
|
||||
|
||||
For each plugin, the Traefik static configuration must define the module name (as is usual for Go packages).
|
||||
|
||||
The following declaration (given here in YAML) defines a plugin:
|
||||
|
||||
```yaml
|
||||
# Static configuration
|
||||
|
||||
experimental:
|
||||
plugins:
|
||||
safeline:
|
||||
moduleName: github.com/chaitin/traefik-safeline
|
||||
version: v1.0.0
|
||||
```
|
||||
|
||||
Here is an example of a file provider dynamic configuration (given here in YAML), where the interesting part is the `http.middlewares` section:
|
||||
|
||||
```yaml
|
||||
# Dynamic configuration
|
||||
|
||||
http:
|
||||
routers:
|
||||
my-router:
|
||||
rule: host(`demo.localhost`)
|
||||
service: service-foo
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- chaitin
|
||||
|
||||
services:
|
||||
service-foo:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://127.0.0.1:5000
|
||||
|
||||
middlewares:
|
||||
chaitin:
|
||||
plugin:
|
||||
safeline:
|
||||
addr: safeline-detector.safeline:8000
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
module github.com/chaitin/traefik-safeline
|
||||
|
||||
go 1.17
|
||||
|
||||
require golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
|
||||
require github.com/chaitin/t1k-go v1.5.0
|
||||
@@ -1,99 +0,0 @@
|
||||
package traefik_safeline
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
t1k "github.com/chaitin/t1k-go"
|
||||
)
|
||||
|
||||
// Package example a example plugin.
|
||||
|
||||
// Config the plugin configuration.
|
||||
type Config struct {
|
||||
// Addr is the address for the detector
|
||||
Addr string `yaml:"addr"`
|
||||
PoolSize int `yaml:"pool_size"`
|
||||
}
|
||||
|
||||
// CreateConfig creates the default plugin configuration.
|
||||
func CreateConfig() *Config {
|
||||
return &Config{
|
||||
Addr: "",
|
||||
PoolSize: 100,
|
||||
}
|
||||
}
|
||||
|
||||
// Safeline a plugin.
|
||||
type Safeline struct {
|
||||
next http.Handler
|
||||
server *t1k.Server
|
||||
name string
|
||||
config *Config
|
||||
logger *log.Logger
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// New created a new plugin.
|
||||
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{
|
||||
next: next,
|
||||
name: name,
|
||||
config: config,
|
||||
logger: logger,
|
||||
}, 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) {
|
||||
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
|
||||
}
|
||||
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
201
sdk/traefik/vendor/github.com/chaitin/t1k-go/License
generated
vendored
@@ -1,201 +0,0 @@
|
||||
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
5
sdk/traefik/vendor/github.com/chaitin/t1k-go/README.md
generated
vendored
@@ -1,5 +0,0 @@
|
||||
# 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
101
sdk/traefik/vendor/github.com/chaitin/t1k-go/conn.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
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
253
sdk/traefik/vendor/github.com/chaitin/t1k-go/detect.go
generated
vendored
@@ -1,253 +0,0 @@
|
||||
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
88
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/context.go
generated
vendored
@@ -1,88 +0,0 @@
|
||||
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
93
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/extra.go
generated
vendored
@@ -1,93 +0,0 @@
|
||||
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
132
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/request.go
generated
vendored
@@ -1,132 +0,0 @@
|
||||
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
72
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/response.go
generated
vendored
@@ -1,72 +0,0 @@
|
||||
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
76
sdk/traefik/vendor/github.com/chaitin/t1k-go/detection/result.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
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
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/heartbeat.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
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
81
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/dump_hex.go
generated
vendored
@@ -1,81 +0,0 @@
|
||||
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
58
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/errors.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
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
17
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/gen_uuid.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
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
102
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/mt19937.go
generated
vendored
@@ -1,102 +0,0 @@
|
||||
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
9
sdk/traefik/vendor/github.com/chaitin/t1k-go/misc/now.go
generated
vendored
@@ -1,9 +0,0 @@
|
||||
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
184
sdk/traefik/vendor/github.com/chaitin/t1k-go/server.go
generated
vendored
@@ -1,184 +0,0 @@
|
||||
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
35
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/header.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
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
95
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/section.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
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
39
sdk/traefik/vendor/github.com/chaitin/t1k-go/t1k/tag.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
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
|
||||
}
|
||||
4
sdk/traefik/vendor/github.com/xbingW/t1k/README.md
generated
vendored
4
sdk/traefik/vendor/github.com/xbingW/t1k/README.md
generated
vendored
@@ -1,4 +0,0 @@
|
||||
# t1k-go
|
||||
|
||||
## Getting started
|
||||
|
||||
173
sdk/traefik/vendor/github.com/xbingW/t1k/detector.go
generated
vendored
173
sdk/traefik/vendor/github.com/xbingW/t1k/detector.go
generated
vendored
@@ -1,173 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/xbingW/t1k/pkg/datetime"
|
||||
"github.com/xbingW/t1k/pkg/rand"
|
||||
"github.com/xbingW/t1k/pkg/t1k"
|
||||
)
|
||||
|
||||
type Detector struct {
|
||||
cfg Config
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Addr string `json:"addr"`
|
||||
// Get ip from header, if not set, get ip from remote addr
|
||||
IpHeader string `json:"ip_header"`
|
||||
// When ip_header has multiple ip, use this to get ip from right
|
||||
//
|
||||
//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 `json:"ip_right_index"`
|
||||
}
|
||||
|
||||
func NewDetector(cfg Config) *Detector {
|
||||
return &Detector{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Detector) GetConn() (net.Conn, error) {
|
||||
_, _, err := net.SplitHostPort(d.cfg.Addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("detector add %s is invalid because %v", d.cfg.Addr, err)
|
||||
}
|
||||
return net.Dial("tcp", d.cfg.Addr)
|
||||
}
|
||||
|
||||
func (d *Detector) DetectorRequestStr(req string) (*t1k.DetectorResponse, error) {
|
||||
httpReq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(req)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read request failed: %v", err)
|
||||
}
|
||||
return d.DetectorRequest(httpReq)
|
||||
}
|
||||
|
||||
func (d *Detector) DetectorRequest(req *http.Request) (*t1k.DetectorResponse, error) {
|
||||
extra, err := d.GenerateExtra(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate extra failed: %v", err)
|
||||
}
|
||||
dc := t1k.NewHttpDetector(req, extra)
|
||||
conn, err := d.GetConn()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get conn failed: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
return dc.DetectRequest(conn)
|
||||
}
|
||||
|
||||
func (d *Detector) DetectorResponseStr(req string, resp string) (*t1k.DetectorResponse, error) {
|
||||
httpReq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(req)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read request failed: %v", err)
|
||||
}
|
||||
httpResp, err := http.ReadResponse(bufio.NewReader(strings.NewReader(resp)), httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read response failed: %v", err)
|
||||
}
|
||||
extra, err := d.GenerateExtra(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate extra failed: %v", err)
|
||||
}
|
||||
conn, err := d.GetConn()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get conn failed: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
return t1k.NewHttpDetector(httpReq, extra).SetResponse(httpResp).DetectResponse(conn)
|
||||
}
|
||||
|
||||
func (d *Detector) DetectorResponse(req *http.Request, resp *http.Response) (*t1k.DetectorResponse, error) {
|
||||
extra, err := d.GenerateExtra(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate extra failed: %v", err)
|
||||
}
|
||||
conn, err := d.GetConn()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get conn failed: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
return t1k.NewHttpDetector(req, extra).SetResponse(resp).DetectResponse(conn)
|
||||
}
|
||||
|
||||
func (d *Detector) GenerateExtra(req *http.Request) (*t1k.HttpExtra, error) {
|
||||
clientHost, err := d.getClientIP(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverHost, serverPort := req.Host, "80"
|
||||
if hasPort(req.Host) {
|
||||
serverHost, serverPort, err = net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &t1k.HttpExtra{
|
||||
UpstreamAddr: "",
|
||||
RemoteAddr: clientHost,
|
||||
RemotePort: d.getClientPort(req),
|
||||
LocalAddr: serverHost,
|
||||
LocalPort: serverPort,
|
||||
ServerName: "",
|
||||
Schema: req.URL.Scheme,
|
||||
ProxyName: "",
|
||||
UUID: rand.String(32),
|
||||
HasRspIfOK: "y",
|
||||
HasRspIfBlock: "n",
|
||||
ReqBeginTime: strconv.FormatInt(datetime.Now(), 10),
|
||||
ReqEndTime: "",
|
||||
RspBeginTime: strconv.FormatInt(datetime.Now(), 10),
|
||||
RepEndTime: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Detector) getClientIP(req *http.Request) (string, error) {
|
||||
if d.cfg.IpHeader != "" {
|
||||
ips := req.Header.Get(d.cfg.IpHeader)
|
||||
if ips != "" {
|
||||
ipList := reverseStrSlice(strings.Split(ips, ","))
|
||||
if len(ipList) > int(d.cfg.IPRightIndex) {
|
||||
return strings.TrimSpace(ipList[d.cfg.IPRightIndex]), nil
|
||||
}
|
||||
return ipList[0], nil
|
||||
}
|
||||
}
|
||||
if !hasPort(req.RemoteAddr) {
|
||||
return req.RemoteAddr, nil
|
||||
}
|
||||
clientHost, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return clientHost, nil
|
||||
}
|
||||
|
||||
func (d *Detector) getClientPort(req *http.Request) string {
|
||||
_, clientPort, err := net.SplitHostPort(req.RemoteAddr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return clientPort
|
||||
}
|
||||
|
||||
// has port check if host has port
|
||||
func hasPort(host string) bool {
|
||||
return strings.LastIndex(host, ":") > strings.LastIndex(host, "]")
|
||||
}
|
||||
|
||||
func reverseStrSlice(arr []string) []string {
|
||||
if len(arr) == 0 {
|
||||
return arr
|
||||
}
|
||||
return append(reverseStrSlice(arr[1:]), arr[0])
|
||||
}
|
||||
7
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/datetime/datetime.go
generated
vendored
7
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/datetime/datetime.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
package datetime
|
||||
|
||||
import "time"
|
||||
|
||||
func Now() int64 {
|
||||
return time.Now().UnixNano() / 1e3
|
||||
}
|
||||
15
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/rand/str.go
generated
vendored
15
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/rand/str.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package rand
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
func String(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
163
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/detector.go
generated
vendored
163
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/detector.go
generated
vendored
@@ -1,163 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ResultFlag string
|
||||
|
||||
const (
|
||||
ResultFlagAllowed ResultFlag = "."
|
||||
ResultFlagBlocked ResultFlag = "?"
|
||||
)
|
||||
|
||||
func (d ResultFlag) Byte() byte {
|
||||
return d[0]
|
||||
}
|
||||
|
||||
type DetectorResponse struct {
|
||||
Head byte
|
||||
Body []byte
|
||||
Delay []byte
|
||||
ExtraHeader []byte
|
||||
ExtraBody []byte
|
||||
Context []byte
|
||||
Cookie []byte
|
||||
WebLog []byte
|
||||
BotQuery []byte
|
||||
BotBody []byte
|
||||
Forward []byte
|
||||
}
|
||||
|
||||
func (r *DetectorResponse) Allowed() bool {
|
||||
return r.Head == ResultFlagAllowed.Byte()
|
||||
}
|
||||
|
||||
func (r *DetectorResponse) 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 *DetectorResponse) 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 *DetectorResponse) 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]
|
||||
}
|
||||
|
||||
type HttpDetector struct {
|
||||
extra *HttpExtra
|
||||
req Request
|
||||
resp Response
|
||||
}
|
||||
|
||||
func NewHttpDetector(req *http.Request, extra *HttpExtra) *HttpDetector {
|
||||
return &HttpDetector{
|
||||
req: NewHttpRequest(req, extra),
|
||||
extra: extra,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *HttpDetector) SetResponse(resp *http.Response) *HttpDetector {
|
||||
d.resp = NewHttpResponse(d.req, resp, d.extra)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *HttpDetector) DetectRequest(socket io.ReadWriter) (*DetectorResponse, error) {
|
||||
raw, err := d.req.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = socket.Write(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.ReadResponse(socket)
|
||||
}
|
||||
|
||||
func (d *HttpDetector) DetectResponse(socket io.ReadWriter) (*DetectorResponse, error) {
|
||||
raw, err := d.resp.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = socket.Write(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.ReadResponse(socket)
|
||||
}
|
||||
|
||||
func (d *HttpDetector) ReadResponse(r io.Reader) (*DetectorResponse, error) {
|
||||
res := &DetectorResponse{}
|
||||
for {
|
||||
p, err := ReadPacket(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch p.Tag().Strip() {
|
||||
case TAG_HEADER:
|
||||
if len(p.PayLoad()) != 1 {
|
||||
return nil, errors.New("len(T1K_HEADER) != 1")
|
||||
}
|
||||
res.Head = p.PayLoad()[0]
|
||||
case TAG_DELAY:
|
||||
res.Delay = p.PayLoad()
|
||||
case TAG_BODY:
|
||||
res.Body = p.PayLoad()
|
||||
case TAG_EXTRA_HEADER:
|
||||
res.ExtraHeader = p.PayLoad()
|
||||
case TAG_EXTRA_BODY:
|
||||
res.ExtraBody = p.PayLoad()
|
||||
case TAG_CONTEXT:
|
||||
res.Context = p.PayLoad()
|
||||
case TAG_COOKIE:
|
||||
res.Cookie = p.PayLoad()
|
||||
case TAG_WEB_LOG:
|
||||
res.WebLog = p.PayLoad()
|
||||
case TAG_BOT_QUERY:
|
||||
res.BotQuery = p.PayLoad()
|
||||
case TAG_BOT_BODY:
|
||||
res.BotBody = p.PayLoad()
|
||||
case TAG_FORWARD:
|
||||
res.Forward = p.PayLoad()
|
||||
}
|
||||
if p.Last() {
|
||||
break
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
75
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/extra.go
generated
vendored
75
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/extra.go
generated
vendored
@@ -1,75 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import "fmt"
|
||||
|
||||
type HttpExtra struct {
|
||||
UpstreamAddr string
|
||||
RemoteAddr string
|
||||
RemotePort string
|
||||
LocalAddr string
|
||||
LocalPort string
|
||||
ServerName string
|
||||
Schema string
|
||||
ProxyName string
|
||||
UUID string
|
||||
HasRspIfOK string
|
||||
HasRspIfBlock string
|
||||
ReqBeginTime string
|
||||
ReqEndTime string
|
||||
RspBeginTime string
|
||||
RepEndTime string
|
||||
}
|
||||
|
||||
func (h *HttpExtra) ReqSerialize() ([]byte, error) {
|
||||
format := "UpstreamAddr:%s\n" +
|
||||
"RemotePort:%s\n" +
|
||||
"LocalPort:%s\n" +
|
||||
"RemoteAddr:%s\n" +
|
||||
"LocalAddr:%s\n" +
|
||||
"ServerName:%s\n" +
|
||||
"Schema:%s\n" +
|
||||
"ProxyName:%s\n" +
|
||||
"UUID:%s\n" +
|
||||
"HasRspIfOK:%s\n" +
|
||||
"HasRspIfBlock:%s\n" +
|
||||
"ReqBeginTime:%s\n" +
|
||||
"ReqEndTime:%s\n"
|
||||
return []byte(fmt.Sprintf(
|
||||
format,
|
||||
h.UpstreamAddr,
|
||||
h.RemotePort,
|
||||
h.LocalPort,
|
||||
h.RemoteAddr,
|
||||
h.LocalAddr,
|
||||
h.ServerName,
|
||||
h.Schema,
|
||||
h.ProxyName,
|
||||
h.UUID,
|
||||
h.HasRspIfOK,
|
||||
h.HasRspIfBlock,
|
||||
h.ReqBeginTime,
|
||||
h.ReqEndTime,
|
||||
)), nil
|
||||
}
|
||||
|
||||
func (h *HttpExtra) RspSerialize() ([]byte, error) {
|
||||
format := "Scheme:%s\n" +
|
||||
"ProxyName:%s\n" +
|
||||
"RemoteAddr:%s\n" +
|
||||
"RemotePort:%s\n" +
|
||||
"LocalAddr:%s\n" +
|
||||
"LocalPort:%s\n" +
|
||||
"UUID:%s\n" +
|
||||
"RspBeginTime:%s\n"
|
||||
return []byte(fmt.Sprintf(
|
||||
format,
|
||||
h.Schema,
|
||||
h.ProxyName,
|
||||
h.RemoteAddr,
|
||||
h.RemotePort,
|
||||
h.LocalAddr,
|
||||
h.LocalPort,
|
||||
h.UUID,
|
||||
h.RspBeginTime,
|
||||
)), nil
|
||||
}
|
||||
69
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/packet.go
generated
vendored
69
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/packet.go
generated
vendored
@@ -1,69 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Packet interface {
|
||||
Serialize() []byte
|
||||
Last() bool
|
||||
Tag() Tag
|
||||
PayLoad() []byte
|
||||
}
|
||||
|
||||
type HttpPacket struct {
|
||||
tag Tag
|
||||
payload []byte
|
||||
}
|
||||
|
||||
func (p *HttpPacket) Last() bool {
|
||||
return p.tag.Last()
|
||||
}
|
||||
|
||||
func (p *HttpPacket) Tag() Tag {
|
||||
return p.tag
|
||||
}
|
||||
|
||||
func (p *HttpPacket) PayLoad() []byte {
|
||||
return p.payload
|
||||
}
|
||||
|
||||
func NewHttpPacket(tag Tag, payload []byte) Packet {
|
||||
return &HttpPacket{
|
||||
tag: tag,
|
||||
payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *HttpPacket) SizeBytes() []byte {
|
||||
sizeBytes := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(sizeBytes, uint32(len(p.payload)))
|
||||
return sizeBytes
|
||||
}
|
||||
|
||||
func (p *HttpPacket) Serialize() []byte {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte(byte(p.tag))
|
||||
buf.Write(p.SizeBytes())
|
||||
buf.Write(p.payload)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func ReadPacket(r io.Reader) (Packet, error) {
|
||||
tag := make([]byte, 1)
|
||||
if _, err := io.ReadFull(r, tag); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sizeBytes := make([]byte, 4)
|
||||
if _, err := io.ReadFull(r, sizeBytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size := binary.LittleEndian.Uint32(sizeBytes)
|
||||
payload := make([]byte, size)
|
||||
if _, err := io.ReadFull(r, payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewHttpPacket(Tag(tag[0]), payload), nil
|
||||
}
|
||||
122
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/req.go
generated
vendored
122
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/req.go
generated
vendored
@@ -1,122 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Request interface {
|
||||
Header() ([]byte, error)
|
||||
Body() ([]byte, error)
|
||||
Extra() ([]byte, error)
|
||||
Serialize() ([]byte, error)
|
||||
}
|
||||
|
||||
type HttpRequest struct {
|
||||
extra *HttpExtra
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
func NewHttpRequest(req *http.Request, extra *HttpExtra) *HttpRequest {
|
||||
return &HttpRequest{
|
||||
req: req,
|
||||
extra: extra,
|
||||
}
|
||||
}
|
||||
|
||||
func NewHttpRequestRead(req string) *HttpRequest {
|
||||
httpReq, _ := http.ReadRequest(bufio.NewReader(strings.NewReader(req)))
|
||||
return &HttpRequest{
|
||||
req: httpReq,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *HttpRequest) Header() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
proto := r.req.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() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.ReadFrom(r.req.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.req.Body = io.NopCloser(bytes.NewReader(buf.Bytes()))
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (r *HttpRequest) Extra() ([]byte, error) {
|
||||
return r.extra.ReqSerialize()
|
||||
}
|
||||
|
||||
func (r *HttpRequest) Version() []byte {
|
||||
return []byte("Proto:3\n")
|
||||
}
|
||||
|
||||
func (r *HttpRequest) Serialize() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
{
|
||||
raw, err := r.Header()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_HEADER|MASK_FIRST, raw)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
raw, err := r.Body()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_BODY, raw)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
raw, err := r.Extra()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_EXTRA, raw)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
packet := NewHttpPacket(TAG_VERSION|MASK_LAST, r.Version())
|
||||
_, err := buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
127
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/res.go
generated
vendored
127
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/res.go
generated
vendored
@@ -1,127 +0,0 @@
|
||||
package t1k
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Response interface {
|
||||
RequestHeader() ([]byte, error)
|
||||
RspHeader() ([]byte, error)
|
||||
Body() ([]byte, error)
|
||||
Extra() ([]byte, error)
|
||||
Serialize() ([]byte, error)
|
||||
}
|
||||
|
||||
type HttpResponse struct {
|
||||
req Request
|
||||
extra *HttpExtra
|
||||
rsp *http.Response
|
||||
}
|
||||
|
||||
func NewHttpResponse(req Request, rsp *http.Response, extra *HttpExtra) *HttpResponse {
|
||||
return &HttpResponse{
|
||||
req: req,
|
||||
rsp: rsp,
|
||||
extra: extra,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *HttpResponse) RequestHeader() ([]byte, error) {
|
||||
return r.req.Header()
|
||||
}
|
||||
|
||||
func (r *HttpResponse) RspHeader() ([]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() ([]byte, error) {
|
||||
data, err := io.ReadAll(r.rsp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.rsp.Body = io.NopCloser(bytes.NewReader(data))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Extra() ([]byte, error) {
|
||||
return r.extra.RspSerialize()
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Version() []byte {
|
||||
return []byte("Proto:3\n")
|
||||
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Serialize() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
{
|
||||
header, err := r.RequestHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_HEADER|MASK_FIRST, header)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
header, err := r.RspHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_RSP_HEADER, header)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
body, err := r.Body()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_RSP_BODY, body)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
extra, err := r.Extra()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet := NewHttpPacket(TAG_RSP_EXTRA, extra)
|
||||
_, err = buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{
|
||||
version := r.Version()
|
||||
packet := NewHttpPacket(TAG_VERSION|MASK_LAST, version)
|
||||
_, err := buf.Write(packet.Serialize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
45
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/tag.go
generated
vendored
45
sdk/traefik/vendor/github.com/xbingW/t1k/pkg/t1k/tag.go
generated
vendored
@@ -1,45 +0,0 @@
|
||||
package t1k
|
||||
|
||||
type Tag byte
|
||||
|
||||
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_DELAY Tag = 0x2b
|
||||
TAG_FORWARD Tag = 0x2c
|
||||
TAG_BOT_BODY Tag = 0x30
|
||||
|
||||
MASK_TAG Tag = 0x3f
|
||||
MASK_FIRST Tag = 0x40
|
||||
MASK_LAST Tag = 0x80
|
||||
)
|
||||
|
||||
func (t Tag) Last() bool {
|
||||
return t&MASK_LAST != 0
|
||||
}
|
||||
|
||||
func (t Tag) First() bool {
|
||||
return t&MASK_FIRST != 0
|
||||
}
|
||||
|
||||
func (t Tag) Strip() Tag {
|
||||
return t & MASK_TAG
|
||||
}
|
||||
|
||||
func (t Tag) Byte() byte {
|
||||
return byte(t)
|
||||
}
|
||||
27
sdk/traefik/vendor/golang.org/x/xerrors/LICENSE
generated
vendored
27
sdk/traefik/vendor/golang.org/x/xerrors/LICENSE
generated
vendored
@@ -1,27 +0,0 @@
|
||||
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
22
sdk/traefik/vendor/golang.org/x/xerrors/PATENTS
generated
vendored
@@ -1,22 +0,0 @@
|
||||
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
2
sdk/traefik/vendor/golang.org/x/xerrors/README
generated
vendored
@@ -1,2 +0,0 @@
|
||||
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
193
sdk/traefik/vendor/golang.org/x/xerrors/adaptor.go
generated
vendored
@@ -1,193 +0,0 @@
|
||||
// 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
1
sdk/traefik/vendor/golang.org/x/xerrors/codereview.cfg
generated
vendored
@@ -1 +0,0 @@
|
||||
issuerepo: golang/go
|
||||
23
sdk/traefik/vendor/golang.org/x/xerrors/doc.go
generated
vendored
23
sdk/traefik/vendor/golang.org/x/xerrors/doc.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
// 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
33
sdk/traefik/vendor/golang.org/x/xerrors/errors.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// 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
190
sdk/traefik/vendor/golang.org/x/xerrors/fmt.go
generated
vendored
@@ -1,190 +0,0 @@
|
||||
// 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
34
sdk/traefik/vendor/golang.org/x/xerrors/format.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
// 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
56
sdk/traefik/vendor/golang.org/x/xerrors/frame.go
generated
vendored
@@ -1,56 +0,0 @@
|
||||
// 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
8
sdk/traefik/vendor/golang.org/x/xerrors/internal/internal.go
generated
vendored
@@ -1,8 +0,0 @@
|
||||
// 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
112
sdk/traefik/vendor/golang.org/x/xerrors/wrap.go
generated
vendored
@@ -1,112 +0,0 @@
|
||||
// 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()
|
||||
10
sdk/traefik/vendor/modules.txt
vendored
10
sdk/traefik/vendor/modules.txt
vendored
@@ -1,10 +0,0 @@
|
||||
# github.com/chaitin/t1k-go v1.5.0
|
||||
## explicit; go 1.17
|
||||
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
|
||||
Reference in New Issue
Block a user