Compare commits
No commits in common. "main" and "dev" have entirely different histories.
30
.github/ISSUE_TEMPLATE/1feature-request.yaml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: 功能建议
|
||||
# Feature request
|
||||
description: 新功能或现有能力的优化建议
|
||||
title: "[建议] "
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
提示:创建前请搜索一下是否有重复问题。一个 issue 尽量只描述一个问题。简洁、准确的描述有助于集中大家的意见,推进问题尽快解决
|
||||
# Please check for duplicate issue first.
|
||||
# 尽量描述需求的背景、原始问题,避免出现 X-Y 问题,参考: https://coolshell.cn/articles/10804.html
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: 背景与遇到的问题
|
||||
# Background and the problem that frustrates you
|
||||
placeholder: |
|
||||
例如:我的业务有xxx特性,当我在使用xxx功能的时候,会遇到xxx情况...
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: 建议的解决方案
|
||||
# Describe the solution you'd like
|
||||
placeholder: |
|
||||
例如:建议增加xxx功能;将xxx改为xxx...
|
||||
validations:
|
||||
required: false
|
42
.github/ISSUE_TEMPLATE/2bug-report.yaml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: Bug
|
||||
description: 明确的软件故障或缺陷
|
||||
# Create a report to help us improve
|
||||
title: "[Bug] "
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
提示:提问前请先搜索一下是否存在重复问题
|
||||
# Please check for duplicate issue first.
|
||||
- type: textarea
|
||||
id: Description
|
||||
attributes:
|
||||
label: 问题描述
|
||||
# Describe the bug
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: 版本号
|
||||
placeholder: 3.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: Reproduce
|
||||
attributes:
|
||||
label: 复现方法
|
||||
# To Reproduce
|
||||
placeholder: |
|
||||
1. ...
|
||||
2. ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: Expected
|
||||
attributes:
|
||||
label: 期望的结果
|
||||
# Expected behavior. Descript what you expected to happen.
|
||||
validations:
|
||||
required: true
|
14
.github/ISSUE_TEMPLATE/3other.yaml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
name: 其他问题与反馈
|
||||
description: 文档、部署失败等其他问题。
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
提示:创建前请先搜索一下是否存在重复问题
|
||||
# Please check for duplicate issue first.
|
||||
# 尽量描述需求的背景、原始问题,避免出现 X-Y 问题,参考: https://coolshell.cn/articles/10804.html
|
||||
# 提問的智慧: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md
|
||||
- type: textarea
|
||||
id: content
|
||||
attributes:
|
||||
label: 反馈内容
|
45
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
|
@ -1,45 +0,0 @@
|
|||
name: Bug
|
||||
description: Report a bug
|
||||
# Create a report to help us improve
|
||||
title: "[Bug] "
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please search the [open issues](https://github.com/chaitin/SafeLine/issues) and [discussion](https://github.com/chaitin/SafeLine/discussions) for duplicate issue first.
|
||||
The more information you share, the faster we can identify and fix the bug.
|
||||
# Please check for duplicate issue first.
|
||||
- type: textarea
|
||||
id: Description
|
||||
attributes:
|
||||
label: What happened?
|
||||
# Describe the bug
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: Reproduce
|
||||
attributes:
|
||||
label: How we reproduce?
|
||||
description: |
|
||||
Reports cannot be reproduced will Most likely be closed.
|
||||
# To Reproduce
|
||||
value: |
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
- type: textarea
|
||||
id: Expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
# placeholder: |
|
||||
# Descript what you expected to happen.
|
||||
# Expected behavior. Descript what you expected to happen.
|
||||
- type: textarea
|
||||
id: Errorlog
|
||||
attributes:
|
||||
label: Error log
|
||||
placeholder: |
|
||||
Paste the error logs if any.
|
||||
# Expected behavior. Descript what you expected to happen.
|
||||
|
10
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,11 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
blank_issues_enabled: Ture
|
||||
contact_links:
|
||||
- name: Discord
|
||||
url: https://discord.gg/wyshSVuvxC
|
||||
about: Ask questions and discuss with other SafeLine users in real time.
|
||||
- name: Home page 官网
|
||||
url: https://waf.chaitin.com/
|
||||
about: Get feature descriptions, technical documentation and more information. 获取功能描述、技术文档和更多信息。
|
||||
- name: 绕过反馈
|
||||
url: https://stack.chaitin.com/security-challenge/safeline/index
|
||||
about: Waf 绕过可在 CT Stack 安全挑战赛提交细节
|
||||
about: Waf 绕过可在 CT Stack 安全挑战赛提交细节
|
||||
|
|
28
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
|
@ -1,28 +0,0 @@
|
|||
name: Suggestion
|
||||
# Feature request
|
||||
description: New feature or improvements.
|
||||
title: "[Suggestion] "
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please search the [open issues](https://github.com/chaitin/SafeLine/issues) and [discussion](https://github.com/chaitin/SafeLine/discussions) for duplicate issue first.
|
||||
Please rise only one suggestion in an issue.
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: What would you like to be added or improved?
|
||||
# Describe the solution you'd like
|
||||
# placeholder: |
|
||||
#
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Why is it needed?
|
||||
# Background and the specific problem that frustrates you
|
||||
placeholder: |
|
||||
Background and the problem that frustrates you
|
||||
|
||||
validations:
|
||||
required: true
|
12
.github/ISSUE_TEMPLATE/other.yaml
vendored
|
@ -1,12 +0,0 @@
|
|||
name: Other
|
||||
description: Other issues such as Doc
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please search the [open issues](https://github.com/chaitin/SafeLine/issues) and [discussion](https://github.com/chaitin/SafeLine/discussions) for duplicate issue first.
|
||||
Please rise only one suggestion in an issue.
|
||||
- type: textarea
|
||||
id: content
|
||||
attributes:
|
||||
label: Content
|
209
README.md
|
@ -1,34 +1,35 @@
|
|||
<p align="center">
|
||||
<img src="/images/banner.png" width="400" />
|
||||
|
||||
# SafeLine, make your webserver secure
|
||||
|
||||
<img src="/images/403.svg" align="right" width="200" />
|
||||
|
||||
SafeLine is a web security gateway to protect your websites from attacks and exploits.
|
||||
|
||||
It defenses for all of web attacks, such as sql injection, code injection, os command injection, CRLF injection, ldap injection, xpath injection, rce, xss, xxe, ssrf, path traversal, backdoor, bruteforce, http-flood, bot abused and so on.
|
||||
|
||||
<p align="left">
|
||||
<a target="_blank" href="https://waf.chaitin.com/">🏠Home</a> |
|
||||
<a target="_blank" href="https://docs.waf.chaitin.com/">📖Documentation</a> |
|
||||
<a target="_blank" href="https://demo.waf.chaitin.com:9443/dashboard">🔍Live Demo</a> |
|
||||
<a target="_blank" href="https://waf-ce.chaitin.cn/">中文版</a>
|
||||
</p>
|
||||
|
||||
<h4 align="center">
|
||||
SafeLine - Make your web apps secure
|
||||
</h4>
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://waf.chaitin.com/">🏠 Website</a> |
|
||||
<a target="_blank" href="https://docs.waf.chaitin.com/">📖 Docs</a> |
|
||||
<a target="_blank" href="https://demo.waf.chaitin.com:9443/">🔍 Live Demo</a> |
|
||||
<a target="_blank" href="https://discord.gg/SVnZGzHFvn">🙋♂️ Discord</a> |
|
||||
<a target="_blank" href="/README_CN.md">中文版</a>
|
||||
<p align="left">
|
||||
<a target="_blank" href="https://discord.gg/wyshSVuvxC"><img src="https://img.shields.io/badge/Discord-5865F2?style=flat&logo=discord&logoColor=white"></a>
|
||||
<a target="_blank" href="https://x.com/safeline_waf"><img src="https://img.shields.io/badge/X-000000?style=flat&logo=x&logoColor=white"></a>
|
||||
<a target="_blank" href="https://t.me/safeline_waf"><img src="https://img.shields.io/badge/Telegram-2CA5E0?style=flat&logo=telegram&logoColor=white"></a>
|
||||
<a target="_blank" href="/images/wechat-230825.png"><img src="https://img.shields.io/badge/WeChat-07C160?style=flat&logo=wechat&logoColor=white"></a>
|
||||
</p>
|
||||
|
||||
## 👋 INTRODUCTION
|
||||
# Screenshots
|
||||
|
||||
SafeLine is a self-hosted **`WAF(Web Application Firewall)`** to protect your web apps from attacks and exploits.
|
||||
<img src="./images/safeline_en.png" width=600 />
|
||||
|
||||
A web application firewall helps protect web apps by filtering and monitoring HTTP traffic between a web application and the Internet. It typically protects web apps from attacks such as `SQL injection`, `XSS`, `code injection`, `os command injection`, `CRLF injection`, `ldap injection`, `xpath injection`, `RCE`, `XXE`, `SSRF`, `path traversal`, `backdoor`, `bruteforce`, `http-flood`, `bot abused`, among others.
|
||||
# How It Works
|
||||
|
||||
#### 💡 How It Works
|
||||
<img src="/images/safeline-as-proxy.png" align="right" width=400 />
|
||||
|
||||
<img src="/images/how-it-works.png" width="800" />
|
||||
|
||||
By deploying a WAF in front of a web application, a shield is placed between the web application and the Internet. While a proxy server protects a client machine’s identity by using an intermediary, a WAF is a type of reverse-proxy, protecting the server from exposure by having clients pass through the WAF before reaching the server.
|
||||
|
||||
A WAF protects your web apps by filtering, monitoring, and blocking any malicious HTTP/S traffic traveling to the web application, and prevents any unauthorized data from leaving the app. It does this by adhering to a set of policies that help determine what traffic is malicious and what traffic is safe. Just as a proxy server acts as an intermediary to protect the identity of a client, a WAF operates in similar fashion but acting as an reverse proxy intermediary that protects the web app server from a potentially malicious client.
|
||||
|
||||
its core capabilities include:
|
||||
SafeLine is developed based on nginx, it serves as a reverse proxy middleware to detect and cleans web attacks, its core capabilities include:
|
||||
|
||||
- Defenses for web attacks
|
||||
- Proactive bot abused defense
|
||||
|
@ -36,93 +37,107 @@ its core capabilities include:
|
|||
- IP-based rate limiting
|
||||
- Web Access Control List
|
||||
|
||||
#### ⚡️ Screenshots
|
||||
# Installation
|
||||
|
||||
| <img src="./images/screenshot-1.png" width=370 /> | <img src="./images/screenshot-2.png" width=370 /> |
|
||||
| ------------------------------------------------- | ------------------------------------------------- |
|
||||
| <img src="./images/screenshot-3.png" width=370 /> | <img src="./images/screenshot-4.png" width=370 /> |
|
||||
**中国大陆用户安装国际版可能会导致无法连接云服务,请查看** [中文版安装文档](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)
|
||||
|
||||
Get [Live Demo](https://demo.waf.chaitin.com:9443/)
|
||||
## Automatic Deploy
|
||||
|
||||
## 🔥 FEATURES
|
||||
> 👍Recommended
|
||||
|
||||
List of the main features as follows:
|
||||
Use the following command to start the automated installation of SafeLine. (This process requires root privileges)
|
||||
|
||||
- **`Block Web Attacks`**
|
||||
- It defenses for all of web attacks, such as `SQL injection`, `XSS`, `code injection`, `os command injection`, `CRLF injection`, `XXE`, `SSRF`, `path traversal` and so on.
|
||||
- **`Rate Limiting`**
|
||||
- Defend your web apps against `DoS attacks`, `bruteforce attempts`, `traffic surges`, and other types of abuse by throttling traffic that exceeds defined limits.
|
||||
- **`Anti-Bot Challenge`**
|
||||
- Anti-Bot challenges to protect your website from `bot attacks`, humen users will be allowed, crawlers and bots will be blocked.
|
||||
- **`Authentication Challenge`**
|
||||
- When authentication challenge turned on, visitors need to enter the password, otherwise they will be blocked.
|
||||
- **`Dynamic Protection`**
|
||||
- When dynamic protection turned on, html and js codes in your web server will be dynamically encrypted by each time you visit.
|
||||
```bash
|
||||
bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/setup.sh)"
|
||||
```
|
||||
|
||||
#### 🧩 Showcases
|
||||
|
||||
| | Legitimate User | Malicious User |
|
||||
| ----------------------------- | --------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| **`Block Web Attacks`** | <img src="./images/skeleton.png" width=270 /> | <img src="./images/blocked-for-attack-detected.png" width=270 /> |
|
||||
| **`Rate Limiting`** | <img src="./images/skeleton.png" width=270 /> | <img src="./images/blocked-for-access-too-fast.png" width=270 /> |
|
||||
| **`Anti-Bot Challenge`** | <img src="./images/captcha-1.gif" width=270 /> | <img src="./images/captcha-2.gif" width=270 /> |
|
||||
| **`Auth Challenge`** | <img src="./images/auth-1.gif" width=270 /> | <img src="./images/auth-2.gif" width=270 /> |
|
||||
| **`HTML Dynamic Protection`** | <img src="./images/dynamic-html-1.png" width=270 /> | <img src="./images/dynamic-html-2.png" width=270 /> |
|
||||
| **`JS Dynamic Protection`** | <img src="./images/dynamic-js-1.png" width=270 /> | <img src="./images/dynamic-js-2.png" width=270 /> |
|
||||
|
||||
## 🚀 Quickstart
|
||||
|
||||
> [!WARNING]
|
||||
> 中国大陆用户安装国际版可能会导致无法连接云服务,请查看 [中文版安装文档](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)
|
||||
|
||||
#### 📦 Installing
|
||||
|
||||
Information on how to install SafeLine can be found in the [Install Guide](https://docs.waf.chaitin.com/en/tutorials/install)
|
||||
|
||||
#### ⚙️ Protecting Web Apps
|
||||
|
||||
to see [Configuration](https://docs.waf.chaitin.com/en/tutorials/Configuration)
|
||||
|
||||
## 📋 More Informations
|
||||
|
||||
#### Effect Evaluation
|
||||
|
||||
| Metric | ModSecurity, Level 1 | CloudFlare, Free | SafeLine, Balance | SafeLine, Strict |
|
||||
| ----------------- | -------------------- | -------------------- | ---------------------- | --------------------- |
|
||||
| Total Samples | 33669 | 33669 | 33669 | 33669 |
|
||||
| **Detection** | 69.74% | 10.70% | 71.65% | **76.17%** |
|
||||
| **False Positive**| 17.58% | 0.07% | **0.07%** | 0.22% |
|
||||
| **Accuracy** | 82.20% | 98.40% | **99.45%** | 99.38% |
|
||||
After the command is executed, it means the installation is successfully. Please go to "Use Web UI" directly.
|
||||
|
||||
|
||||
#### Is SafeLine Production-Ready?
|
||||
## Mannually Deploy
|
||||
|
||||
Yes, SafeLine is production-ready.
|
||||
to see [Documentation](https://docs.waf.chaitin.com/en/tutorials/install)
|
||||
|
||||
- Over 180,000 installations worldwide
|
||||
- Protecting over 1,000,000 Websites
|
||||
- Handling over 30,000,000,000 HTTP Requests Daily
|
||||
# Usage
|
||||
|
||||
#### 🙋♂️ Community
|
||||
## Login
|
||||
|
||||
Join our [Discord](https://discord.gg/SVnZGzHFvn) to get community support, the core team members are identified by the STAFF role in Discord.
|
||||
Open the web console page `https://<safeline-ip>:9443/` in the browser, then you will see below.
|
||||
|
||||
- channel [#feedback](https://discord.com/channels/1243085666485534830/1243120292822253598): for new features discussion.
|
||||
- channel [#FAQ](https://discord.com/channels/1243085666485534830/1263761679619981413): for FAQ.
|
||||
- channel [#general](https://discord.com/channels/1243085666485534830/1243115843919806486): for any other questions.
|
||||
<img width="400" src="/images/login.png">
|
||||
|
||||
Several contact options exist for our community, the primary one being Discord. These are in addition to GitHub issues for creating a new issue.
|
||||
Execute the following command to get administrator account
|
||||
|
||||
<p align="left">
|
||||
<a target="_blank" href="https://discord.gg/SVnZGzHFvn"><img src="https://img.shields.io/badge/Discord-5865F2?style=flat&logo=discord&logoColor=white"></a>
|
||||
<a target="_blank" href="https://x.com/safeline_waf"><img src="https://img.shields.io/badge/X.com-000000?style=flat&logo=x&logoColor=white"></a>
|
||||
<a target="_blank" href="/images/wechat.png"><img src="https://img.shields.io/badge/WeChat-07C160?style=flat&logo=wechat&logoColor=white"></a>
|
||||
```bash
|
||||
docker exec safeline-mgt /app/mgt-cli reset-admin --once
|
||||
```
|
||||
|
||||
After the command is successfully executed, you will see the following content
|
||||
|
||||
> Please must remember this content
|
||||
|
||||
```text
|
||||
[SafeLine] Initial username:admin
|
||||
[SafeLine] Initial password:**********
|
||||
[SafeLine] Done
|
||||
```
|
||||
|
||||
Enter the password in the previous step and you will successfully logged into SafeLine.
|
||||
|
||||
## Protecting a website
|
||||
|
||||
Log into the SafeLine Web Admin Console, go to the "Site" -> "Website" page and click the "Add Site" button in the upper right corner.
|
||||
|
||||
<img src="/images/add-site-1.png" width=800>
|
||||
|
||||
In the next dialog box, enter the information to the original website.
|
||||
|
||||
- **Domain**: domain name of your original website, or hostname, or ip address, for example: `www.chaitin.com`
|
||||
- **Port**: port that SafeLine will listen, such as 80 or 443. (for `https` websites, please check the `SSL` option)
|
||||
- **Upstream**: real address of your original website, through which SafeLine will forward traffic to it
|
||||
|
||||
After completing the above settings, please resolve the domain name you just entered to the IP address of the server where SafeLine is located.
|
||||
|
||||
<img src="/images/add-site-2.png" width=400>
|
||||
|
||||
Then you can access the website protected by the SafeLine through the domain name like this.
|
||||
|
||||
<img src="/images/safeline-as-proxy-2.png" width=400>
|
||||
|
||||
## Try to attack your website
|
||||
|
||||
Now, your website is protected by SafeLine, let’s try tp attack it and see what happens.
|
||||
|
||||
If https://chaitin.com is a website protected by SafeLine, here are some test cases for common attacks:
|
||||
|
||||
- SQL Injection: `https://chaitin.com/?id=1+and+1=2+union+select+1`
|
||||
- XSS: `https://chaitin.com/?id=<img+src=x+onerror=alert()>`
|
||||
- Path Traversal: `https://chaitin.com/?id=../../../../etc/passwd`
|
||||
- Code Injection: `https://chaitin.com/?id=phpinfo();system('id')`
|
||||
- XXE: `https://chaitin.com/?id=<?xml+version="1.0"?><!DOCTYPE+foo+SYSTEM+"">`
|
||||
|
||||
Replace `chaitin.com` in the above cases with your website domain name and try to access it.
|
||||
|
||||
<img src="/images/blocked.png" width=400>
|
||||
|
||||
Check the web console of SafeLine to see the attack list
|
||||
|
||||
<img src="/images/log-list.png" width=800>
|
||||
|
||||
To view the specific details of the attack, click "detail"
|
||||
|
||||
<img src="/images/log-detail.png" width=600>
|
||||
|
||||
## Star History
|
||||
|
||||
<a href="https://github.com/chaitin/safeline/stargazers">
|
||||
<img width="500" alt="Star History Chart" src="https://api.star-history.com/svg?repos=chaitin/safeline&type=Date">
|
||||
</a>
|
||||
|
||||
## Related Repo
|
||||
<p >
|
||||
<a href="https://github.com/chaitin/yanshi">Automaton Generator</a> |
|
||||
<a href="https://github.com/chaitin/safeline-open-platform">Lua Plugin</a> |
|
||||
<a href="https://github.com/chaitin/lua-resty-t1k">T1K Protocol</a> |
|
||||
<a href="https://github.com/chaitin/blazehttp">WAF Test Tool</a>
|
||||
</p>
|
||||
|
||||
#### 💪 PRO Edition
|
||||
|
||||
Coming soon!
|
||||
|
||||
#### 📝 License
|
||||
|
||||
See [LICENSE](/LICENSE.md) for details.
|
||||
|
|
115
README_CN.md
|
@ -1,115 +0,0 @@
|
|||
<p align="center">
|
||||
<img src="/images/banner.png" width="400" />
|
||||
</p>
|
||||
|
||||
<h4 align="center">
|
||||
SafeLine - 雷池 - 不让黑客越过半步
|
||||
</h4>
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://waf-ce.chaitin.cn/">🏠 官网</a> |
|
||||
<a target="_blank" href="https://docs.waf-ce.chaitin.cn/">📖 文档</a> |
|
||||
<a target="_blank" href="https://demo.waf-ce.chaitin.cn:9443/">🔍 演示环境</a> |
|
||||
<a target="_blank" href="/images/wechat.png">🙋♂️ 社区微信群</a> |
|
||||
<a target="_blank" href="https://github.com/chaitin/SafeLine">国际版</a>
|
||||
</p>
|
||||
|
||||
## 👋 项目介绍
|
||||
|
||||
SafeLine,中文名 "雷池",是一款简单好用, 效果突出的 **`Web 应用防火墙(WAF)`**,可以保护 Web 服务不受黑客攻击。
|
||||
|
||||
雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 `SQL 注入`、`XSS`、 `代码注入`、`命令注入`、`CRLF 注入`、`ldap 注入`、`xpath 注入`、`RCE`、`XXE`、`SSRF`、`路径遍历`、`后门`、`暴力破解`、`CC`、`爬虫` 等攻击。
|
||||
|
||||
#### 💡 工作原理
|
||||
|
||||
<img src="/images/how-it-works.png" width="800" />
|
||||
|
||||
雷池通过阻断流向 Web 服务的恶意 HTTP 流量来保护 Web 服务。雷池作为反向代理接入网络,通过在 Web 服务前部署雷池,可在 Web 服务和互联网之间设置一道屏障。
|
||||
|
||||
雷池的核心功能如下:
|
||||
|
||||
- 防护 Web 攻击
|
||||
- 防爬虫, 防扫描
|
||||
- 前端代码动态加密
|
||||
- 基于源 IP 的访问速率限制
|
||||
- HTTP 访问控制
|
||||
|
||||
#### ⚡️ 项目截图
|
||||
|
||||
| <img src="./images/screenshot-1.png" width=370 /> | <img src="./images/screenshot-2.png" width=370 /> |
|
||||
| ------------------------------------------------- | ------------------------------------------------- |
|
||||
| <img src="./images/screenshot-3.png" width=370 /> | <img src="./images/screenshot-4.png" width=370 /> |
|
||||
|
||||
查看 [演示环境](https://demo.waf-ce.chaitin.cn:9443/)
|
||||
|
||||
## 🔥 核心能力
|
||||
|
||||
对于你的网站而言, 雷池可以实现如下效果:
|
||||
|
||||
- **`阻断 Web 攻击`**
|
||||
- 可以防御所有的 Web 攻击,例如 `SQL 注入`、`XSS`、`代码注入`、`操作系统命令注入`、`CRLF 注入`、`XXE`、`SSRF`、`路径遍历` 等等。
|
||||
- **`限制访问频率`**
|
||||
- 限制用户的访问速率,让 Web 服务免遭 `CC 攻击`、`暴力破解`、`流量激增` 和其他类型的滥用。
|
||||
- **`人机验证`**
|
||||
- 互联网上有来自真人用户的流量,但更多的是由爬虫, 漏洞扫描器, 蠕虫病毒, 漏洞利用程序等自动化程序发起的流量,开启雷池的人机验证功能后真人用户会被放行,恶意爬虫将会被阻断。
|
||||
- **`身份认证`**
|
||||
- 雷池的 "身份认证" 功能可以很好的解决 "未授权访问" 漏洞,当用户访问您的网站时,需要输入您配置的用户名和密码信息,不持有认证信息的用户将被拒之门外。
|
||||
- **`动态防护`**
|
||||
- 在用户浏览到的网页内容不变的情况下,将网页赋予动态特性,对 HTML 和 JavaScript 代码进行动态加密,确保每次访问时这些代码都以随机且独特的形态呈现。
|
||||
|
||||
#### 🧩 核心能力展示
|
||||
|
||||
| | Legitimate User | Malicious User |
|
||||
| ----------------------------- | --------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| **`阻断 Web 攻击`** | <img src="./images/skeleton.png" width=270 /> | <img src="./images/blocked-for-attack-detected.png" width=270 /> |
|
||||
| **`限制访问频率`** | <img src="./images/skeleton.png" width=270 /> | <img src="./images/blocked-for-access-too-fast.png" width=270 /> |
|
||||
| **`人机验证`** | <img src="./images/captcha-1.gif" width=270 /> | <img src="./images/captcha-2.gif" width=270 /> |
|
||||
| **`身份认证`** | <img src="./images/auth-1.gif" width=270 /> | <img src="./images/auth-2.gif" width=270 /> |
|
||||
| **`HTML 动态防护`** | <img src="./images/dynamic-html-1.png" width=270 /> | <img src="./images/dynamic-html-2.png" width=270 /> |
|
||||
| **`JS 动态防护`** | <img src="./images/dynamic-js-1.png" width=270 /> | <img src="./images/dynamic-js-2.png" width=270 /> |
|
||||
|
||||
## 🚀 上手指南
|
||||
|
||||
#### 📦 安装
|
||||
|
||||
查看 [安装雷池](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)
|
||||
|
||||
#### ⚙️ 配置防护站点
|
||||
|
||||
查看 [快速配置](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE)
|
||||
|
||||
## 📋 更多信息
|
||||
|
||||
#### 防护效果测试
|
||||
|
||||
| Metric | ModSecurity, Level 1 | CloudFlare | 雷池, 平衡 | 雷池, 严格 |
|
||||
| ----------------- | -------------------- | -------------------- | ---------------------- | --------------------- |
|
||||
| 样本数量 | 33669 | 33669 | 33669 | 33669 |
|
||||
| **检出率** | 69.74% | 10.70% | 71.65% | **76.17%** |
|
||||
| **误报率** | 17.58% | 0.07% | **0.07%** | 0.22% |
|
||||
| **准确率** | 82.20% | 98.40% | **99.45%** | 99.38% |
|
||||
|
||||
|
||||
#### 雷池可以投入生产使用吗
|
||||
|
||||
是的,已经有不少用户将雷池投入生产使用,截至目前
|
||||
|
||||
- 全球累计装机量已超过 18 万台
|
||||
- 防护的网站数量超过 100 万个
|
||||
- 每天清洗 HTTP 请求超过 300 亿次
|
||||
|
||||
#### 🙋♂️ 用户社区
|
||||
|
||||
欢迎加入雷池 [社区微信群](/images/wechat.png) 进行技术交流。
|
||||
|
||||
也可以加入雷池 [Discord](https://discord.gg/SVnZGzHFvn) 来获取更多社区支持。
|
||||
|
||||
<p align="left">
|
||||
<a target="_blank" href="/images/wechat.png"><img src="https://img.shields.io/badge/WeChat-07C160?style=flat&logo=wechat&logoColor=white"></a>
|
||||
<a target="_blank" href="https://discord.gg/SVnZGzHFvn"><img src="https://img.shields.io/badge/Discord-5865F2?style=flat&logo=discord&logoColor=white"></a>
|
||||
<a target="_blank" href="https://x.com/safeline_waf"><img src="https://img.shields.io/badge/X.com-000000?style=flat&logo=x&logoColor=white"></a>
|
||||
</p>
|
||||
|
||||
#### 💪 专业版
|
||||
|
||||
查看 [社区版 vs 专业版](https://waf-ce.chaitin.cn/version)
|
69
compose.yaml
|
@ -14,7 +14,7 @@ services:
|
|||
postgres:
|
||||
container_name: safeline-pg
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-postgres${ARCH_SUFFIX}:15.2
|
||||
image: ${IMAGE_PREFIX}/safeline-postgres:15.2
|
||||
volumes:
|
||||
- ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
@ -30,18 +30,18 @@ services:
|
|||
mgt:
|
||||
container_name: safeline-mgt
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-mgt${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG:?image tag required}
|
||||
image: ${IMAGE_PREFIX}/safeline-mgt-g:${IMAGE_TAG:?image tag required}
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ${SAFELINE_DIR}/resources/mgt:/app/data
|
||||
- ${SAFELINE_DIR}/logs/nginx:/app/log/nginx:z
|
||||
- ${SAFELINE_DIR}/resources/sock:/app/sock
|
||||
- /var/run:/app/run
|
||||
ports:
|
||||
- ${MGT_PORT:-9443}:1443
|
||||
healthcheck:
|
||||
test: curl -k -f https://localhost:1443/api/open/health
|
||||
environment:
|
||||
- MGT_READ_ONLY=true
|
||||
- MGT_NO_AUTH=true
|
||||
- MGT_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
|
||||
depends_on:
|
||||
- postgres
|
||||
|
@ -56,7 +56,7 @@ services:
|
|||
detect:
|
||||
container_name: safeline-detector
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-detector${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG}
|
||||
image: ${IMAGE_PREFIX}/safeline-detector-g:${IMAGE_TAG}
|
||||
volumes:
|
||||
- ${SAFELINE_DIR}/resources/detector:/resources/detector
|
||||
- ${SAFELINE_DIR}/logs/detector:/logs/detector
|
||||
|
@ -66,35 +66,50 @@ services:
|
|||
networks:
|
||||
safeline-ce:
|
||||
ipv4_address: ${SUBNET_PREFIX}.5
|
||||
mario:
|
||||
container_name: safeline-mario
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-mario-g:${IMAGE_TAG}
|
||||
volumes:
|
||||
- ${SAFELINE_DIR}/resources/mario:/resources/mario
|
||||
- ${SAFELINE_DIR}/logs/mario:/logs/mario
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
environment:
|
||||
- LOG_DIR=/logs/mario
|
||||
- GOGC=100
|
||||
- DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce
|
||||
logging:
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "5"
|
||||
networks:
|
||||
safeline-ce:
|
||||
ipv4_address: ${SUBNET_PREFIX}.6
|
||||
tengine:
|
||||
container_name: safeline-tengine
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-tengine${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG}
|
||||
image: ${IMAGE_PREFIX}/safeline-tengine-g:${IMAGE_TAG}
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/resolv.conf:/etc/resolv.conf:ro
|
||||
- ${SAFELINE_DIR}/resources/nginx:/etc/nginx
|
||||
- ${SAFELINE_DIR}/resources/detector:/resources/detector
|
||||
- ${SAFELINE_DIR}/resources/chaos:/resources/chaos
|
||||
- ${SAFELINE_DIR}/logs/nginx:/var/log/nginx:z
|
||||
- ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache
|
||||
- ${SAFELINE_DIR}/resources/sock:/app/sock
|
||||
environment:
|
||||
- TCD_MGT_API=https://${SUBNET_PREFIX}.4:1443/api/open/publish/server
|
||||
- TCD_SNSERVER=${SUBNET_PREFIX}.5:8000
|
||||
# deprecated
|
||||
- SNSERVER_ADDR=${SUBNET_PREFIX}.5:8000
|
||||
- CHAOS_ADDR=${SUBNET_PREFIX}.10
|
||||
ulimits:
|
||||
nofile: 131072
|
||||
network_mode: host
|
||||
luigi:
|
||||
container_name: safeline-luigi
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-luigi${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG}
|
||||
image: ${IMAGE_PREFIX}/safeline-luigi-g:${IMAGE_TAG}
|
||||
environment:
|
||||
- MGT_IP=${SUBNET_PREFIX}.4
|
||||
- LUIGI_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ${SAFELINE_DIR}/resources/luigi:/app/data
|
||||
|
@ -111,7 +126,7 @@ services:
|
|||
fvm:
|
||||
container_name: safeline-fvm
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-fvm${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG}
|
||||
image: ${IMAGE_PREFIX}/safeline-fvm-g:${IMAGE_TAG}
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
logging:
|
||||
|
@ -121,19 +136,39 @@ services:
|
|||
networks:
|
||||
safeline-ce:
|
||||
ipv4_address: ${SUBNET_PREFIX}.8
|
||||
bridge:
|
||||
container_name: safeline-bridge
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-bridge-g:${IMAGE_TAG}
|
||||
command:
|
||||
- /app/bridge
|
||||
- serve
|
||||
- -n
|
||||
- unix
|
||||
- -a
|
||||
- /app/run/safeline.sock
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run:/app/run
|
||||
logging:
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "5"
|
||||
networks:
|
||||
safeline-ce:
|
||||
ipv4_address: ${SUBNET_PREFIX}.9
|
||||
depends_on:
|
||||
- mgt
|
||||
chaos:
|
||||
container_name: safeline-chaos
|
||||
restart: always
|
||||
image: ${IMAGE_PREFIX}/safeline-chaos${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG}
|
||||
image: ${IMAGE_PREFIX}/safeline-chaos-g:${IMAGE_TAG}
|
||||
logging:
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "10"
|
||||
environment:
|
||||
- DB_ADDR=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
|
||||
volumes:
|
||||
- ${SAFELINE_DIR}/resources/sock:/app/sock
|
||||
- ${SAFELINE_DIR}/resources/chaos:/app/chaos
|
||||
networks:
|
||||
safeline-ce:
|
||||
ipv4_address: ${SUBNET_PREFIX}.10
|
||||
ipv4_address: ${SUBNET_PREFIX}.10
|
||||
|
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
BIN
images/add-site-1.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
images/add-site-2.png
Normal file
After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 821 KiB |
Before Width: | Height: | Size: 806 KiB |
Before Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 276 KiB |
Before Width: | Height: | Size: 501 KiB |
BIN
images/log-detail.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
images/log-list.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
images/login.png
Normal file
After Width: | Height: | Size: 123 KiB |
BIN
images/safeline-as-proxy-2.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
images/safeline-as-proxy.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
images/safeline_en.png
Normal file
After Width: | Height: | Size: 557 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 343 KiB |
Before Width: | Height: | Size: 353 KiB |
Before Width: | Height: | Size: 243 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
@ -1,20 +1,24 @@
|
|||
module chaitin.cn/patronus/safeline-2/management/tcontrollerd
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.3
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
chaitin.cn/dev/go/errors v0.0.0-20210324055134-dc5247602af6
|
||||
chaitin.cn/dev/go/log v0.0.0-20221220104336-05125760b10c
|
||||
chaitin.cn/dev/go/settings v0.0.0-20221220104336-05125760b10c
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
google.golang.org/grpc v1.65.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
google.golang.org/grpc v1.39.0-dev
|
||||
google.golang.org/protobuf v1.28.1
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.7 // indirect
|
||||
)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
chaitin.cn/dev/go/errors v0.0.0-20200717101723-df6132d53dc8/go.mod h1:u+ZD0shdyUt0UG9XfCgD1R5mSqXpTVoO5rwQXQeo3Eo=
|
||||
chaitin.cn/dev/go/errors v0.0.0-20210324055134-dc5247602af6 h1:1Qa9ABk907/9ZrOLbbRcS8Fqq9VhjAF/mLjbSP1qAJY=
|
||||
chaitin.cn/dev/go/errors v0.0.0-20210324055134-dc5247602af6/go.mod h1:u+ZD0shdyUt0UG9XfCgD1R5mSqXpTVoO5rwQXQeo3Eo=
|
||||
|
@ -5,7 +6,6 @@ chaitin.cn/dev/go/log v0.0.0-20221220104336-05125760b10c h1:Xn9IYkxmnpDcEpV+7JIR
|
|||
chaitin.cn/dev/go/log v0.0.0-20221220104336-05125760b10c/go.mod h1:xJIYwUoA2TX5mNg/RBrEPyE251BPwj+70/mM7UIhoxg=
|
||||
chaitin.cn/dev/go/settings v0.0.0-20221220104336-05125760b10c h1:tXsraF7o9iUsQY6IwpDJusc6OFhB7iv/bBTfgR3MPUU=
|
||||
chaitin.cn/dev/go/settings v0.0.0-20221220104336-05125760b10c/go.mod h1:fUvtmpG8Z8Zf5aciadL9a/vn5SB3knG7pdNJixDplPg=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
|
@ -31,7 +31,6 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
@ -49,14 +48,12 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
|||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -68,7 +65,6 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
|||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -76,14 +72,11 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
@ -102,7 +95,6 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
|||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.39.0-dev h1:K4VkkiYp4LCvQiW6OiGglzm5nO4Zyryf7pHhzP15cmI=
|
||||
google.golang.org/grpc v1.39.0-dev/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -116,12 +108,10 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -1,59 +1,61 @@
|
|||
module chaitin.cn/patronus/safeline-2/management/webserver
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.3
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
chaitin.cn/dev/go/errors v0.0.0-20210324055134-dc5247602af6
|
||||
chaitin.cn/dev/go/log v0.0.0-20221220104336-05125760b10c
|
||||
chaitin.cn/dev/go/settings v0.0.0-20221220104336-05125760b10c
|
||||
github.com/gin-contrib/sessions v0.0.5
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/gin-gonic/gin v1.9.0
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rogpeppe/go-internal v1.10.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/grpc v1.54.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gorm.io/datatypes v1.1.1
|
||||
gorm.io/driver/postgres v1.5.9
|
||||
gorm.io/gorm v1.25.10
|
||||
gorm.io/driver/postgres v1.5.0
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic v1.8.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/gorilla/sessions v1.2.1 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||
github.com/jackc/pgx/v5 v5.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.4.7 // indirect
|
||||
)
|
||||
|
|
|
@ -10,13 +10,9 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
|
|||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
|
||||
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -27,7 +23,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
|
||||
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
|
@ -35,18 +30,15 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
||||
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -62,7 +54,6 @@ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/
|
|||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA=
|
||||
github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
|
@ -73,8 +64,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
|
@ -88,20 +77,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
|
@ -117,7 +102,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
@ -127,23 +111,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
|
||||
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
@ -151,7 +130,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -165,8 +143,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -176,8 +152,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
|
@ -189,7 +163,6 @@ google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY7
|
|||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
|
@ -212,12 +185,9 @@ gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y=
|
|||
gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
1261
scripts/manage.py
|
@ -1,20 +0,0 @@
|
|||
package = "ingress-nginx-safeline"
|
||||
version = "1.0.3-1"
|
||||
source = {
|
||||
url = "git://github.com/xbingW/ingress-nginx-safeline.git"
|
||||
}
|
||||
description = {
|
||||
summary = "Ingress-Nginx plugin for Chaitin SafeLine Web Application Firewall",
|
||||
homepage = "https://github.com/xbingW/ingress-nginx-safeline",
|
||||
license = "Apache License 2.0",
|
||||
maintainer = "Xiaobing Wang <xiaobing.wang@chaitin.com>"
|
||||
}
|
||||
dependencies = {
|
||||
"lua-resty-t1k >= 1.1.5"
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["safeline.main"] = "lib/safeline/main.lua"
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package = "kong-safeline"
|
||||
version = "1.0.2-1"
|
||||
source = {
|
||||
url = "git://github.com/xbingW/kong-safeline.git"
|
||||
}
|
||||
description = {
|
||||
summary = "Kong plugin for Chaitin SafeLine Web Application Firewall",
|
||||
homepage = "https://github.com/xbingW/kong-safeline",
|
||||
license = "Apache License 2.0",
|
||||
maintainer = "Xiaobing Wang <xiaobing.wang@chaitin.com>"
|
||||
}
|
||||
dependencies = {
|
||||
"lua-resty-t1k >= 1.1.5"
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["kong.plugins.safeline.handler"] = "kong/plugins/safeline/handler.lua",
|
||||
["kong.plugins.safeline.schema"] = "kong/plugins/safeline/schema.lua"
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ local byte = string.byte
|
|||
local char = string.char
|
||||
local fmt = string.format
|
||||
local sub = string.sub
|
||||
local concat = table.concat
|
||||
|
||||
local ngx = ngx
|
||||
local nlog = ngx.log
|
||||
|
@ -89,13 +88,6 @@ local function get_remote_addr(remote_addr_var, remote_addr_idx)
|
|||
return addr or ngx_var.remote_addr
|
||||
end
|
||||
|
||||
local function parse_v(v)
|
||||
if type(v) == "table" then
|
||||
return concat(v, ", ")
|
||||
end
|
||||
return tostring(v)
|
||||
end
|
||||
|
||||
local function build_header()
|
||||
local http_version = ngx_req.http_version()
|
||||
if http_version < 2.0 then
|
||||
|
@ -109,10 +101,13 @@ local function build_header()
|
|||
end
|
||||
|
||||
local buf = buffer:new()
|
||||
buf:add(fmt("%s %s HTTP/%.1f\r\n", ngx_req.get_method(), ngx_var.request_uri, http_version))
|
||||
buf:add(ngx_req.get_method())
|
||||
buf:add(" ")
|
||||
buf:add(ngx_var.request_uri)
|
||||
buf:add(fmt(" HTTP/%.1f\r\n", http_version))
|
||||
|
||||
for k, v in pairs(headers) do
|
||||
buf:add(fmt("%s: %s\r\n", k, parse_v(v)))
|
||||
buf:add(k .. ": " .. v .. "\r\n")
|
||||
end
|
||||
buf:add("\r\n")
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package = "lua-resty-t1k"
|
||||
version = "1.1.5-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.5"
|
||||
}
|
||||
|
||||
description = {
|
||||
summary = "Lua implementation of the T1K protocol for Chaitin SafeLine Web Application Firewall",
|
||||
detailed = [[
|
||||
Check https://waf-ce.chaitin.cn/ for more information about Chaitin SafeLine Web Application Firewall.
|
||||
]],
|
||||
homepage = "https://github.com/chaitin/lua-resty-t1k",
|
||||
license = "Apache License 2.0",
|
||||
maintainer = "Xudong Wang <xudong.wang@chaitin.com>"
|
||||
}
|
||||
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["resty.t1k"] = "lib/resty/t1k.lua",
|
||||
["resty.t1k.buffer"] = "lib/resty/t1k/buffer.lua",
|
||||
["resty.t1k.constants"] = "lib/resty/t1k/constants.lua",
|
||||
["resty.t1k.file"] = "lib/resty/t1k/file.lua",
|
||||
["resty.t1k.filter"] = "lib/resty/t1k/filter.lua",
|
||||
["resty.t1k.handler"] = "lib/resty/t1k/handler.lua",
|
||||
["resty.t1k.log"] = "lib/resty/t1k/log.lua",
|
||||
["resty.t1k.request"] = "lib/resty/t1k/request.lua",
|
||||
["resty.t1k.utils"] = "lib/resty/t1k/utils.lua",
|
||||
["resty.t1k.uuid"] = "lib/resty/t1k/uuid.lua",
|
||||
},
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
displayName: Chaitin Safeline WAF
|
||||
type: middleware
|
||||
|
||||
import: github.com/chaitin/traefik-safeline
|
||||
import: github.com/xbingW/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.'
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ The following declaration (given here in YAML) defines a plugin:
|
|||
experimental:
|
||||
plugins:
|
||||
safeline:
|
||||
moduleName: github.com/chaitin/traefik-safeline
|
||||
moduleName: github.com/xbingW/traefik-safeline
|
||||
version: v1.0.0
|
||||
```
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
module github.com/chaitin/traefik-safeline
|
||||
module github.com/xbingW/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
|
||||
require github.com/xbingW/t1k v1.2.1
|
||||
|
|
|
@ -2,13 +2,12 @@ package traefik_safeline
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
t1k "github.com/chaitin/t1k-go"
|
||||
"github.com/xbingW/t1k"
|
||||
)
|
||||
|
||||
// Package example a example plugin.
|
||||
|
@ -16,84 +15,61 @@ import (
|
|||
// Config the plugin configuration.
|
||||
type Config struct {
|
||||
// Addr is the address for the detector
|
||||
Addr string `yaml:"addr"`
|
||||
PoolSize int `yaml:"pool_size"`
|
||||
Addr string `yaml:"addr"`
|
||||
// Get ip from header, if not set, get ip from remote addr
|
||||
IpHeader string `yaml:"ipHeader"`
|
||||
// When ip_header has multiple ip, use this to get the ip
|
||||
//
|
||||
//for example, X-Forwarded-For: ip1, ip2, ip3
|
||||
// when ip_last_index is 0, the client ip is ip3
|
||||
// when ip_last_index is 1, the client ip is ip2
|
||||
// when ip_last_index is 2, the client ip is ip1
|
||||
IPRightIndex uint `yaml:"ipRightIndex"`
|
||||
}
|
||||
|
||||
// CreateConfig creates the default plugin configuration.
|
||||
func CreateConfig() *Config {
|
||||
return &Config{
|
||||
Addr: "",
|
||||
PoolSize: 100,
|
||||
Addr: "",
|
||||
IpHeader: "",
|
||||
IPRightIndex: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
logger: log.New(os.Stdout, "safeline", log.LstdFlags),
|
||||
}, 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)
|
||||
d := t1k.NewDetector(t1k.Config{
|
||||
Addr: s.config.Addr,
|
||||
IpHeader: s.config.IpHeader,
|
||||
IPRightIndex: s.config.IPRightIndex,
|
||||
})
|
||||
resp, err := d.DetectorRequest(req)
|
||||
if err != nil {
|
||||
s.logger.Printf("error in detection: \n%+v\n", err)
|
||||
s.next.ServeHTTP(rw, req)
|
||||
return
|
||||
s.logger.Printf("Failed to detect request: %v", err)
|
||||
}
|
||||
if result.Blocked() {
|
||||
rw.WriteHeader(result.StatusCode())
|
||||
msg := fmt.Sprintf(`{"code": %d, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "%s"}`,
|
||||
result.StatusCode(),
|
||||
result.EventID(),
|
||||
)
|
||||
_, _ = rw.Write([]byte(msg))
|
||||
if resp != nil && !resp.Allowed() {
|
||||
rw.WriteHeader(resp.StatusCode())
|
||||
if err := json.NewEncoder(rw).Encode(resp.BlockMessage()); err != nil {
|
||||
s.logger.Printf("Failed to encode block message: %v", err)
|
||||
}
|
||||
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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
}
|
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
|
@ -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
|
@ -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
|
@ -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 +0,0 @@
|
|||
issuerepo: golang/go
|
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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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()
|
14
sdk/traefik/vendor/modules.txt
vendored
|
@ -1,10 +1,6 @@
|
|||
# github.com/chaitin/t1k-go v1.5.0
|
||||
# github.com/xbingW/t1k v1.2.1
|
||||
## 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
|
||||
github.com/xbingW/t1k
|
||||
github.com/xbingW/t1k/pkg/datetime
|
||||
github.com/xbingW/t1k/pkg/rand
|
||||
github.com/xbingW/t1k/pkg/t1k
|
||||
|
|