mirror of
https://github.com/chaitin/SafeLine.git
synced 2025-11-25 03:15:15 +08:00
feat: add sdk
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,7 +1,5 @@
|
||||
[submodule "blazehttp"]
|
||||
path = blazehttp
|
||||
url = https://github.com/chaitin/blazehttp
|
||||
[submodule "lua-resty-t1k"]
|
||||
path = lua-resty-t1k
|
||||
url = https://github.com/chaitin/lua-resty-t1k
|
||||
|
||||
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
9
.idea/Safeline.iml
generated
Normal file
9
.idea/Safeline.iml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
13
.idea/material_theme_project_new.xml
generated
Normal file
13
.idea/material_theme_project_new.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MaterialThemeProjectNewConfig">
|
||||
<option name="metadata">
|
||||
<MTProjectMetadataState>
|
||||
<option name="migrated" value="true" />
|
||||
<option name="pristineConfig" value="false" />
|
||||
<option name="userId" value="61f9103c:183e5ad9d68:-8000" />
|
||||
<option name="version" value="8.12.6" />
|
||||
</MTProjectMetadataState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Safeline.iml" filepath="$PROJECT_DIR$/.idea/Safeline.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
9
.idea/vcs.xml
generated
Normal file
9
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/blazehttp" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lua-resty-t1k" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/plugins" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Submodule blazehttp updated: 23e8b59cd2...afc88a94d0
Submodule lua-resty-t1k deleted from 6446166301
46
sdk/lua-resty-t1k/.github/workflows/release.yml
vendored
Normal file
46
sdk/lua-resty-t1k/.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Lua
|
||||
uses: leafo/gh-actions-lua@v10
|
||||
|
||||
- name: Install Luarocks
|
||||
uses: leafo/gh-actions-luarocks@v4
|
||||
|
||||
- name: Extract release tag
|
||||
id: release_tag
|
||||
run: |
|
||||
# Extract the tag name from the ref
|
||||
tag="${GITHUB_REF#refs/tags/}"
|
||||
version_without_v="${tag#v}"
|
||||
echo "version=${tag}" >> $GITHUB_ENV
|
||||
echo "version_without_v=${version_without_v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Create Release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.version }}
|
||||
release_name: ${{ env.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: Upload to luarocks
|
||||
env:
|
||||
LUAROCKS_TOKEN: ${{ secrets.LUAROCKS_TOKEN }}
|
||||
run: |
|
||||
luarocks install dkjson
|
||||
luarocks upload rockspec/lua-resty-t1k-${{ env.version_without_v }}-0.rockspec --api-key=${{ secrets.LUAROCKS_API_KEY }}
|
||||
63
sdk/lua-resty-t1k/.github/workflows/test.yml
vendored
Normal file
63
sdk/lua-resty-t1k/.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Test
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
luacheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: leafo/gh-actions-lua@v10
|
||||
with:
|
||||
luaVersion: "luajit-openresty"
|
||||
- uses: leafo/gh-actions-luarocks@v4
|
||||
- run: luarocks install luacheck
|
||||
- run: luacheck lib
|
||||
|
||||
run_tests:
|
||||
strategy:
|
||||
matrix:
|
||||
openresty_version:
|
||||
- 1.17.8.2
|
||||
- 1.19.9.1
|
||||
- 1.21.4.3
|
||||
- 1.25.3.1
|
||||
|
||||
services:
|
||||
detector:
|
||||
image: chaitin/safeline-detector:t1k-ci-1.6.0
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: openresty/openresty:${{ matrix.openresty_version }}-alpine-fat
|
||||
# --init runs tinit as PID 1 and prevents the 'WARNING: killing the child process' spam from the test suite
|
||||
options: --init
|
||||
|
||||
steps:
|
||||
- name: Install deps
|
||||
run: |
|
||||
apk add --no-cache bash bind-tools curl git git-lfs libarchive-tools perl perl-dev wget
|
||||
ln -s /usr/bin/bsdtar /usr/bin/tar
|
||||
|
||||
- name: Install CPAN
|
||||
run: curl -s -L http://xrl.us/cpanm > /bin/cpanm && chmod +x /bin/cpanm
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cpan
|
||||
~/.cache
|
||||
key: ${{ runner.os }}-${{ matrix.openresty_version }}-cache
|
||||
|
||||
- name: Install Test::Nginx
|
||||
run: cpanm -q -n Test::Nginx
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
curl -fs -X POST -H "Content-Type: application/octet-stream" --data-binary "@ci/bytecode" "http://detector:8001/update/policy"
|
||||
env DETECTOR_IP=$(dig detector +short) prove -r t/
|
||||
25
sdk/lua-resty-t1k/.gitignore
vendored
Normal file
25
sdk/lua-resty-t1k/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# IntelliJ project files
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
gen
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
# Test::Nginx files
|
||||
t/servroot
|
||||
|
||||
# luarocks build files
|
||||
*.src.rock
|
||||
6
sdk/lua-resty-t1k/.luacheckrc
Normal file
6
sdk/lua-resty-t1k/.luacheckrc
Normal file
@@ -0,0 +1,6 @@
|
||||
std = "ngx_lua"
|
||||
redefined = false
|
||||
max_line_length = 130
|
||||
max_code_line_length = 130
|
||||
max_string_line_length = 130
|
||||
max_comment_line_length = 130
|
||||
201
sdk/lua-resty-t1k/LICENSE
Normal file
201
sdk/lua-resty-t1k/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2023 Beijing Chaitin Technology Co., Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
76
sdk/lua-resty-t1k/README.md
Normal file
76
sdk/lua-resty-t1k/README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# lua-resty-t1k
|
||||
|
||||
[](https://luarocks.org/modules/blaisewang/lua-resty-t1k)
|
||||
[](https://github.com/chaitin/lua-resty-t1k/releases)
|
||||
[](https://github.com/chaitin/lua-resty-t1k/blob/main/LICENSE)
|
||||
|
||||
## Name
|
||||
|
||||
Lua implementation of the T1K protocol for [Chaitin/SafeLine](https://github.com/chaitin/safeline) Web Application Firewall.
|
||||
|
||||
## Status
|
||||
|
||||
Production ready.
|
||||
|
||||
[](https://github.com/chaitin/lua-resty-t1k/actions)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
luarocks install lua-resty-t1k
|
||||
```
|
||||
|
||||
If you are in Mainland China
|
||||
|
||||
```bash
|
||||
luarocks install lua-resty-t1k --server https://luarocks.cn
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
```lua
|
||||
location / {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local t = {
|
||||
mode = "block", -- block or monitor or off, default off
|
||||
host = "unix:/workdir/snserver.sock", -- required, SafeLine WAF detection service host, unix domain socket, IP, or domain is supported, string
|
||||
port = 8000, -- required when the host is an IP or domain, SafeLine WAF detection service port, integer
|
||||
connect_timeout = 1000, -- connect timeout, in milliseconds, integer, default 1s (1000ms)
|
||||
send_timeout = 1000, -- send timeout, in milliseconds, integer, default 1s (1000ms)
|
||||
read_timeout = 1000, -- read timeout, in milliseconds, integer, default 1s (1000ms)
|
||||
req_body_size = 1024, -- request body size, in KB, integer, default 1MB (1024KB)
|
||||
keepalive_size = 256, -- maximum concurrent idle connections to the SafeLine WAF detection service, integer, default 256
|
||||
keepalive_timeout = 60000, -- idle connection timeout, in milliseconds, integer, default 60s (60000ms)
|
||||
remote_addr = "http_x_forwarded_for: 1", -- remote address from ngx.var.VARIABLE, string, default from ngx.var.remote_addr
|
||||
}
|
||||
|
||||
local ok, err, _ = t1k.do_access(t, true)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
|
||||
header_filter_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
t1k.do_header_filter()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Lua Resty T1K vs. C T1K
|
||||
|
||||
[C T1K](https://t1k.chaitin.com/), as part of SafeLine's enterprise edition, is a deployment mode crafted in C language for enhanced performance.
|
||||
It is compatible with all versions of Nginx and does not require deployment via OpenResty (lua_nginx_module).
|
||||
|
||||
| | Lua Resty T1K | C T1K |
|
||||
|-----------------------|---------------|-------|
|
||||
| Request Detection | ✅ | ✅ |
|
||||
| Response Detection | ❌ | ✅ |
|
||||
| Health Checks* | ❌ | ✅ |
|
||||
| Cookie Protection | ❌ | ✅ |
|
||||
| Bot Protection | ❌ | ✅ |
|
||||
| Proxy-side Statistics | ❌ | ✅ |
|
||||
|
||||
* APISIX implements health check functionality for the `chaitin-waf` plugin. For more information, please see the [chaitin-waf documentation](https://apisix.apache.org/docs/apisix/next/plugins/chaitin-waf/).
|
||||
1
sdk/lua-resty-t1k/ci/.dockerignore
Normal file
1
sdk/lua-resty-t1k/ci/.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
/bytecode
|
||||
6
sdk/lua-resty-t1k/ci/Dockerfile
Normal file
6
sdk/lua-resty-t1k/ci/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
||||
# Usage:
|
||||
# docker build -t chaitin/safeline-detector:t1k-ci-1.6.0 .
|
||||
# docker push chaitin/safeline-detector:t1k-ci-1.6.0
|
||||
FROM chaitin/safeline-detector:1.6.0
|
||||
|
||||
RUN sed -i "s/^# bind_addr/bind_addr/; s/^# listen_port/listen_port/; s/^bind_addr: unix/# bind_addr: unix/;" /detector/snserver.yml
|
||||
BIN
sdk/lua-resty-t1k/ci/bytecode
Normal file
BIN
sdk/lua-resty-t1k/ci/bytecode
Normal file
Binary file not shown.
97
sdk/lua-resty-t1k/lib/resty/t1k.lua
Normal file
97
sdk/lua-resty-t1k/lib/resty/t1k.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
local consts = require "resty.t1k.constants"
|
||||
local filter = require "resty.t1k.filter"
|
||||
local handler = require "resty.t1k.handler"
|
||||
local log = require "resty.t1k.log"
|
||||
local request = require "resty.t1k.request"
|
||||
local utils = require "resty.t1k.utils"
|
||||
|
||||
local lower = string.lower
|
||||
|
||||
local ngx = ngx
|
||||
local nlog = ngx.log
|
||||
|
||||
local log_fmt = log.fmt
|
||||
local debug_fmt = log.debug_fmt
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local DEFAULT_T1K_CONNECT_TIMEOUT = 1000 -- 1s
|
||||
local DEFAULT_T1K_SEND_TIMEOUT = 1000 -- 1s
|
||||
local DEFAULT_T1K_READ_TIMEOUT = 1000 -- 1s
|
||||
local DEFAULT_T1K_REQ_BODY_SIZE = 1024 -- 1024 KB
|
||||
local DEFAULT_T1K_KEEPALIVE_SIZE = 256
|
||||
local DEFAULT_T1K_KEEPALIVE_TIMEOUT = 60 * 1000 -- 60s
|
||||
|
||||
function _M.do_access(t, handle)
|
||||
local ok, err, result
|
||||
local opts = {}
|
||||
t = t or {}
|
||||
|
||||
if not t.mode then
|
||||
return true, nil, nil
|
||||
end
|
||||
|
||||
opts.mode = lower(t.mode)
|
||||
if opts.mode == consts.MODE_OFF then
|
||||
nlog(debug_fmt("t1k is not enabled"))
|
||||
return true, nil, nil
|
||||
end
|
||||
|
||||
if opts.mode ~= consts.MODE_OFF and opts.mode ~= consts.MODE_BLOCK and opts.mode ~= consts.MODE_MONITOR then
|
||||
err = log_fmt("invalid t1k mode: %s", t.mode)
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
if not t.host then
|
||||
err = log_fmt("invalid t1k host: %s", t.host)
|
||||
return nil, err, nil
|
||||
end
|
||||
opts.host = t.host
|
||||
|
||||
if utils.starts_with(opts.host, consts.UNIX_SOCK_PREFIX) then
|
||||
opts.uds = true
|
||||
else
|
||||
if not tonumber(t.port) then
|
||||
err = log_fmt("invalid t1k port: %s", t.port)
|
||||
return nil, err, nil
|
||||
end
|
||||
opts.port = tonumber(t.port)
|
||||
end
|
||||
|
||||
opts.connect_timeout = t.connect_timeout or DEFAULT_T1K_CONNECT_TIMEOUT
|
||||
opts.send_timeout = t.send_timeout or DEFAULT_T1K_SEND_TIMEOUT
|
||||
opts.read_timeout = t.read_timeout or DEFAULT_T1K_READ_TIMEOUT
|
||||
opts.req_body_size = t.req_body_size or DEFAULT_T1K_REQ_BODY_SIZE
|
||||
opts.keepalive_size = t.keepalive_size or DEFAULT_T1K_KEEPALIVE_SIZE
|
||||
opts.keepalive_timeout = t.keepalive_timeout or DEFAULT_T1K_KEEPALIVE_TIMEOUT
|
||||
|
||||
if t.remote_addr then
|
||||
local var, idx = utils.to_var_idx(t.remote_addr)
|
||||
opts.remote_addr_var = var
|
||||
opts.remote_addr_idx = idx
|
||||
end
|
||||
|
||||
ok, err, result = request.do_request(opts)
|
||||
if not ok then
|
||||
return ok, err, result
|
||||
end
|
||||
|
||||
if handle and opts.mode == consts.MODE_BLOCK then
|
||||
ok, err = _M.do_handle(result)
|
||||
end
|
||||
|
||||
return ok, err, result
|
||||
end
|
||||
|
||||
function _M.do_handle(t)
|
||||
local ok, err = handler.handle(t)
|
||||
return ok, err
|
||||
end
|
||||
|
||||
function _M.do_header_filter()
|
||||
filter.do_header_filter()
|
||||
end
|
||||
|
||||
return _M
|
||||
24
sdk/lua-resty-t1k/lib/resty/t1k/buffer.lua
Normal file
24
sdk/lua-resty-t1k/lib/resty/t1k/buffer.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
local _M = {
|
||||
_VERSION = '1.0.0',
|
||||
}
|
||||
|
||||
function _M:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function _M:add(v)
|
||||
self[#self + 1] = v
|
||||
end
|
||||
|
||||
function _M:len()
|
||||
local len = 0
|
||||
for _, v in ipairs(self) do
|
||||
len = len + #v
|
||||
end
|
||||
return len
|
||||
end
|
||||
|
||||
return _M
|
||||
30
sdk/lua-resty-t1k/lib/resty/t1k/constants.lua
Normal file
30
sdk/lua-resty-t1k/lib/resty/t1k/constants.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local t = {}
|
||||
|
||||
t.ACTION_PASSED = "."
|
||||
t.ACTION_BLOCKED = "?"
|
||||
|
||||
t.MODE_OFF = "off"
|
||||
t.MODE_BLOCK = "block"
|
||||
t.MODE_MONITOR = "monitor"
|
||||
|
||||
t.T1K_HEADER_SIZE = 5
|
||||
|
||||
t.TAG_HEAD = 0x01
|
||||
t.TAG_BODY = 0x02
|
||||
t.TAG_EXTRA = 0x03
|
||||
t.TAG_VERSION = 0x20
|
||||
t.TAG_EXTRA_HEADER = 0x23
|
||||
t.TAG_EXTRA_BODY = 0x24
|
||||
|
||||
t.MASK_FIRST = 0x40
|
||||
t.MASK_LAST = 0x80
|
||||
|
||||
t.NGX_HTTP_HEADER_PREFIX = "http_"
|
||||
|
||||
t.BLOCK_CONTENT_TYPE = "application/json"
|
||||
t.BLOCK_CONTENT_FORMAT = [[
|
||||
{"code": %s, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "%s"}]]
|
||||
|
||||
t.UNIX_SOCK_PREFIX = "unix:"
|
||||
|
||||
return t
|
||||
34
sdk/lua-resty-t1k/lib/resty/t1k/file.lua
Normal file
34
sdk/lua-resty-t1k/lib/resty/t1k/file.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
local buffer = require "resty.t1k.buffer"
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local buffer_size = 2 ^ 13
|
||||
|
||||
function _M.read(p, size)
|
||||
size = (not size or size < 0) and 0 or size
|
||||
|
||||
local f, err = io.open(p, "rb")
|
||||
if not f or err then
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
local left = size
|
||||
local buf = buffer:new()
|
||||
|
||||
while left ~= 0 do
|
||||
local block_size = math.min(left, buffer_size)
|
||||
local block = f:read(block_size)
|
||||
if not block then
|
||||
break
|
||||
end
|
||||
buf:add(block)
|
||||
left = math.max(left - block_size, 0)
|
||||
end
|
||||
f:close()
|
||||
|
||||
return true, nil, buf
|
||||
end
|
||||
|
||||
return _M
|
||||
50
sdk/lua-resty-t1k/lib/resty/t1k/filter.lua
Normal file
50
sdk/lua-resty-t1k/lib/resty/t1k/filter.lua
Normal file
@@ -0,0 +1,50 @@
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local find = string.find
|
||||
local sub = string.sub
|
||||
|
||||
local ngx = ngx
|
||||
|
||||
local function parse_extra_header(extra_header)
|
||||
local t = {}
|
||||
local idx = 1
|
||||
|
||||
while (idx <= #extra_header) do
|
||||
local key, val
|
||||
local _, to = find(extra_header, ":", idx)
|
||||
if to == 0 then
|
||||
break
|
||||
else
|
||||
key = sub(extra_header, idx, to - 1)
|
||||
end
|
||||
|
||||
idx = to + 1
|
||||
_, to = find(extra_header, "\n", idx)
|
||||
if to == 0 then
|
||||
break
|
||||
else
|
||||
val = sub(extra_header, idx, to - 1)
|
||||
end
|
||||
|
||||
t[key] = val
|
||||
idx = to + 1
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
function _M.do_header_filter()
|
||||
local extra_header = ngx.ctx.t1k_extra_header
|
||||
if extra_header ~= nil then
|
||||
local header_table = parse_extra_header(extra_header)
|
||||
for k, v in pairs(header_table) do
|
||||
if k ~= nil and v ~= nil then
|
||||
ngx.header[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return _M
|
||||
36
sdk/lua-resty-t1k/lib/resty/t1k/handler.lua
Normal file
36
sdk/lua-resty-t1k/lib/resty/t1k/handler.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
local consts = require "resty.t1k.constants"
|
||||
local log = require "resty.t1k.log"
|
||||
|
||||
local fmt = string.format
|
||||
|
||||
local ngx = ngx
|
||||
|
||||
local log_fmt = log.fmt
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
function _M.handle(t)
|
||||
local t_type = type(t)
|
||||
if t_type ~= "table" then
|
||||
local err = log_fmt("invalid result type: %s", t_type)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local action = t["action"]
|
||||
if action == consts.ACTION_PASSED then
|
||||
return true, nil
|
||||
elseif action == consts.ACTION_BLOCKED then
|
||||
ngx.status = t["status"] or ngx.HTTP_FORBIDDEN
|
||||
ngx.header.content_type = consts.BLOCK_CONTENT_TYPE
|
||||
ngx.say(fmt(consts.BLOCK_CONTENT_FORMAT, ngx.status, t["event_id"]))
|
||||
|
||||
return ngx.exit(ngx.status)
|
||||
else
|
||||
local err = log_fmt("unknown action from t1k server: %s", action)
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
return _M
|
||||
27
sdk/lua-resty-t1k/lib/resty/t1k/log.lua
Normal file
27
sdk/lua-resty-t1k/lib/resty/t1k/log.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local fmt = string.format
|
||||
|
||||
local ERR = ngx.ERR
|
||||
local WARN = ngx.WARN
|
||||
local DEBUG = ngx.DEBUG
|
||||
|
||||
function _M.fmt(formatstring, ...)
|
||||
return fmt("lua-resty-t1k: " .. formatstring, ...)
|
||||
end
|
||||
|
||||
function _M.err_fmt(formatstring, ...)
|
||||
return ERR, _M.fmt(formatstring, ...)
|
||||
end
|
||||
|
||||
function _M.warn_fmt(formatstring, ...)
|
||||
return WARN, _M.fmt(formatstring, ...)
|
||||
end
|
||||
|
||||
function _M.debug_fmt(formatstring, ...)
|
||||
return DEBUG, _M.fmt(formatstring, ...)
|
||||
end
|
||||
|
||||
return _M
|
||||
360
sdk/lua-resty-t1k/lib/resty/t1k/request.lua
Normal file
360
sdk/lua-resty-t1k/lib/resty/t1k/request.lua
Normal file
@@ -0,0 +1,360 @@
|
||||
local bit = require "bit"
|
||||
|
||||
local buffer = require "resty.t1k.buffer"
|
||||
local consts = require "resty.t1k.constants"
|
||||
local file = require "resty.t1k.file"
|
||||
local log = require "resty.t1k.log"
|
||||
local utils = require "resty.t1k.utils"
|
||||
local uuid = require "resty.t1k.uuid"
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0',
|
||||
}
|
||||
|
||||
local bor = bit.bor
|
||||
local byte = string.byte
|
||||
local char = string.char
|
||||
local fmt = string.format
|
||||
local sub = string.sub
|
||||
|
||||
local ngx = ngx
|
||||
local nlog = ngx.log
|
||||
local ngx_req = ngx.req
|
||||
local ngx_socket = ngx.socket
|
||||
local ngx_var = ngx.var
|
||||
|
||||
local warn_fmt = log.warn_fmt
|
||||
local debug_fmt = log.debug_fmt
|
||||
|
||||
local KEY_EXTRA_UUID = "UUID"
|
||||
local KEY_EXTRA_LOCAL_ADDR = "LocalAddr"
|
||||
local KEY_EXTRA_LOCAL_PORT = "LocalPort"
|
||||
local KEY_EXTRA_REMOTE_ADDR = "RemoteAddr"
|
||||
local KEY_EXTRA_REMOTE_PORT = "RemotePort"
|
||||
local KEY_EXTRA_SCHEME = "Scheme"
|
||||
local KEY_EXTRA_SERVER_NAME = "ServerName"
|
||||
local KEY_EXTRA_PROXY_NAME = "ProxyName"
|
||||
local KEY_EXTRA_REQ_BEGIN_TIME = "ReqBeginTime"
|
||||
local KEY_EXTRA_HAS_RSP_IF_OK = "HasRspIfOK"
|
||||
local KEY_EXTRA_HAS_RSP_IF_BLOCK = "HasRspIfBlock"
|
||||
|
||||
local TAG_HEAD_WITH_MASK_FIRST = bor(consts.TAG_HEAD, consts.MASK_FIRST)
|
||||
local TAG_EXTRA_WITH_MASK_LAST = bor(consts.TAG_EXTRA, consts.MASK_LAST)
|
||||
|
||||
local T1K_PROTO = "Proto:2\n"
|
||||
local T1K_PROTO_DATA = fmt("%s%s%s", char(consts.TAG_VERSION), utils.int_to_char_length(#T1K_PROTO), T1K_PROTO)
|
||||
|
||||
local function read_request_body(opt_req_body_size)
|
||||
local ok, err
|
||||
local req_body, req_body_size
|
||||
|
||||
local content_length = tonumber(ngx_var.http_content_length) or 0
|
||||
local transfer_encoding = ngx_var.http_transfer_encoding
|
||||
if content_length == 0 and not transfer_encoding then
|
||||
return true, nil, nil
|
||||
end
|
||||
|
||||
ngx_req.read_body()
|
||||
req_body = ngx_req.get_body_data()
|
||||
if req_body then
|
||||
req_body_size = #req_body
|
||||
if req_body_size > opt_req_body_size then
|
||||
nlog(debug_fmt("request body is too long: %d bytes, cut to %d bytes", req_body_size, opt_req_body_size))
|
||||
req_body = sub(req_body, 1, opt_req_body_size)
|
||||
end
|
||||
|
||||
return true, nil, req_body
|
||||
end
|
||||
|
||||
local path = ngx_req.get_body_file()
|
||||
if not path then
|
||||
return true, nil, nil
|
||||
end
|
||||
|
||||
ok, err, req_body = file.read(path, opt_req_body_size)
|
||||
if not ok then
|
||||
err = fmt("failed to read temporary file %s: %s", path, err)
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
return true, nil, req_body
|
||||
end
|
||||
|
||||
local function get_remote_addr(remote_addr_var, remote_addr_idx)
|
||||
local addr
|
||||
if remote_addr_var then
|
||||
addr = utils.get_indexed_element(ngx_var[remote_addr_var], remote_addr_idx)
|
||||
end
|
||||
return addr or ngx_var.remote_addr
|
||||
end
|
||||
|
||||
local function build_header()
|
||||
local http_version = ngx_req.http_version()
|
||||
if http_version < 2.0 then
|
||||
return true, nil, ngx_req.raw_header()
|
||||
end
|
||||
|
||||
local headers, err = ngx_req.get_headers(0, true)
|
||||
if err then
|
||||
err = fmt("failed to call ngx_req.get_headers: %s", err)
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
local buf = buffer:new()
|
||||
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(k .. ": " .. v .. "\r\n")
|
||||
end
|
||||
buf:add("\r\n")
|
||||
|
||||
return true, nil, buf
|
||||
end
|
||||
|
||||
local function build_body(opts)
|
||||
local ok, err
|
||||
local body
|
||||
|
||||
local req_body_size = opts.req_body_size * 1024
|
||||
ok, err, body = read_request_body(req_body_size)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
return true, nil, body
|
||||
end
|
||||
|
||||
local function build_extra(opts)
|
||||
local err
|
||||
|
||||
local src_ip = get_remote_addr(opts.remote_addr_var, opts.remote_addr_idx)
|
||||
if not src_ip then
|
||||
err = fmt("failed to get remote_addr, var: %s, idx %d", opts.remote_addr_var, opts.remote_addr_idx)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local src_port = ngx_var.remote_port
|
||||
if not src_port then
|
||||
err = "failed to get ngx_var.remote_port"
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
local local_ip = ngx_var.server_addr
|
||||
if not local_ip then
|
||||
err = "failed to get ngx_var.server_addr"
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
local local_port = ngx_var.server_port
|
||||
if not local_port then
|
||||
err = "failed to get ngx_var.server_port"
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
local extra = buffer:new({
|
||||
KEY_EXTRA_UUID, ":", uuid.generate_v4(), "\n",
|
||||
KEY_EXTRA_REMOTE_ADDR, ":", src_ip, "\n",
|
||||
KEY_EXTRA_REMOTE_PORT, ":", src_port, "\n",
|
||||
KEY_EXTRA_LOCAL_ADDR, ":", local_ip, "\n",
|
||||
KEY_EXTRA_LOCAL_PORT, ":", local_port, "\n",
|
||||
KEY_EXTRA_SCHEME, ":", ngx_var.scheme, "\n",
|
||||
KEY_EXTRA_SERVER_NAME, ":", ngx_var.server_name, "\n",
|
||||
KEY_EXTRA_PROXY_NAME, ":", ngx_var.hostname, "\n",
|
||||
KEY_EXTRA_REQ_BEGIN_TIME, ":", fmt("%.0f", ngx_req.start_time() * 1000000), "\n",
|
||||
KEY_EXTRA_HAS_RSP_IF_OK, ":n\n",
|
||||
KEY_EXTRA_HAS_RSP_IF_BLOCK, ":n\n"
|
||||
})
|
||||
|
||||
return true, nil, extra
|
||||
end
|
||||
|
||||
local function do_send(sock, data)
|
||||
local ok, err = sock:send(data)
|
||||
if not ok then
|
||||
return ok, err
|
||||
end
|
||||
return true, nil
|
||||
end
|
||||
|
||||
local function receive_data(s, srv)
|
||||
local t = {}
|
||||
local ft = true
|
||||
local finished
|
||||
|
||||
repeat
|
||||
local err
|
||||
local tag, length, packet, rsp_body
|
||||
|
||||
packet, err = s:receive(consts.T1K_HEADER_SIZE)
|
||||
if err then
|
||||
err = fmt("failed to receive info packet from t1k server %s: %s", srv, err)
|
||||
return nil, err, nil
|
||||
end
|
||||
if not packet then
|
||||
err = fmt("empty packet from t1k server %s", srv)
|
||||
return nil, err, nil
|
||||
end
|
||||
|
||||
if ft then
|
||||
if not utils.is_mask_first(byte(packet, 1, 1)) then
|
||||
err = fmt("first packet is not MASK_FIRST from t1k server %s", srv)
|
||||
return nil, err, nil
|
||||
end
|
||||
ft = false
|
||||
end
|
||||
|
||||
finished, tag, length = utils.packet_parser(packet)
|
||||
if length > 0 then
|
||||
rsp_body, err = s:receive(length)
|
||||
if not rsp_body or #rsp_body ~= length then
|
||||
err = fmt("failed to receive payload from t1k server %s: %s", srv, err)
|
||||
return nil, err, nil
|
||||
end
|
||||
t[tag] = rsp_body
|
||||
end
|
||||
|
||||
until (finished)
|
||||
|
||||
return true, nil, t
|
||||
end
|
||||
|
||||
local function get_socket(opts)
|
||||
local ok, err
|
||||
local count, sock, server
|
||||
|
||||
sock, err = ngx_socket.tcp()
|
||||
if not sock then
|
||||
err = fmt("failed to create socket: %s", err)
|
||||
return nil, err, nil, nil
|
||||
end
|
||||
|
||||
sock:settimeouts(opts.connect_timeout, opts.send_timeout, opts.read_timeout)
|
||||
|
||||
if opts.uds then
|
||||
server = opts.host
|
||||
ok, err = sock:connect(opts.host)
|
||||
else
|
||||
server = fmt("%s:%d", opts.host, opts.port)
|
||||
ok, err = sock:connect(opts.host, opts.port)
|
||||
end
|
||||
if not ok then
|
||||
sock:close()
|
||||
err = fmt("failed to connect to t1k server %s: %s", server, err)
|
||||
return ok, err, nil, nil
|
||||
end
|
||||
nlog(debug_fmt("successfully connected to t1k server %s", server))
|
||||
|
||||
count, err = sock:getreusedtimes()
|
||||
if not count then
|
||||
nlog(warn_fmt("failed to get reused times from t1k server %s: %s", server, err))
|
||||
end
|
||||
|
||||
if count == 0 then
|
||||
ok, err = sock:setoption("keepalive", true)
|
||||
if not ok then
|
||||
nlog(warn_fmt("failed to set keepalive for t1k server %s: %s", server, err))
|
||||
end
|
||||
ok, err = sock:setoption("reuseaddr", true)
|
||||
if not ok then
|
||||
nlog(warn_fmt("failed to set reuseaddr for t1k server %s: %s", server, err))
|
||||
end
|
||||
ok, err = sock:setoption("tcp-nodelay", true)
|
||||
if not ok then
|
||||
nlog(warn_fmt("failed to set tcp-nodelay for t1k server %s: %s", server, err))
|
||||
end
|
||||
end
|
||||
|
||||
return true, nil, sock, server
|
||||
end
|
||||
|
||||
local function do_socket(opts, header, body, extra)
|
||||
local ok, err
|
||||
local t, sock, server
|
||||
|
||||
ok, err, sock, server = get_socket(opts)
|
||||
if not ok then
|
||||
err = fmt("failed to get socket: %s", err)
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err = do_send(sock, { char(TAG_HEAD_WITH_MASK_FIRST), utils.int_to_char_length(header:len()), header })
|
||||
if not ok then
|
||||
sock:close()
|
||||
err = fmt("failed to send header data to t1k server %s: %s", server, err)
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
if body ~= nil then
|
||||
ok, err = do_send(sock, { char(consts.TAG_BODY), utils.int_to_char_length(body:len()), body })
|
||||
if not ok then
|
||||
sock:close()
|
||||
err = fmt("failed to send body data to t1k server %s: %s", server, err)
|
||||
return ok, err, nil
|
||||
end
|
||||
end
|
||||
|
||||
ok, err = do_send(sock, { T1K_PROTO_DATA, char(TAG_EXTRA_WITH_MASK_LAST), utils.int_to_char_length(extra:len()), extra })
|
||||
if not ok then
|
||||
sock:close()
|
||||
err = fmt("failed to send extra data to t1k server %s: %s", server, err)
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err, t = receive_data(sock, server)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err = sock:setkeepalive(opts.keepalive_timeout, opts.keepalive_size)
|
||||
if not ok then
|
||||
nlog(warn_fmt("failed to set keepalive: %s", err))
|
||||
sock:close()
|
||||
end
|
||||
|
||||
return true, nil, t
|
||||
end
|
||||
|
||||
function _M.do_request(opts)
|
||||
local ok, err
|
||||
local header, body, extra, t
|
||||
|
||||
ok, err, header = build_header(opts)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err, body = build_body(opts)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err, extra = build_extra(opts)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
ok, err, t = do_socket(opts, header, body, extra)
|
||||
if not ok then
|
||||
return ok, err, nil
|
||||
end
|
||||
|
||||
if opts.mode == consts.MODE_BLOCK then
|
||||
local extra_header = t[consts.TAG_EXTRA_HEADER]
|
||||
if extra_header then
|
||||
ngx.ctx.t1k_extra_header = extra_header
|
||||
end
|
||||
end
|
||||
|
||||
local result = {
|
||||
action = t[consts.TAG_HEAD],
|
||||
status = t[consts.TAG_BODY],
|
||||
event_id = utils.get_event_id(t[consts.TAG_EXTRA_BODY]),
|
||||
}
|
||||
|
||||
return true, nil, result
|
||||
end
|
||||
|
||||
return _M
|
||||
123
sdk/lua-resty-t1k/lib/resty/t1k/utils.lua
Normal file
123
sdk/lua-resty-t1k/lib/resty/t1k/utils.lua
Normal file
@@ -0,0 +1,123 @@
|
||||
local consts = require "resty.t1k.constants"
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local band = bit.band
|
||||
local bnot = bit.bnot
|
||||
local lshift = bit.lshift
|
||||
local rshift = bit.rshift
|
||||
|
||||
local abs = math.abs
|
||||
local char = string.char
|
||||
|
||||
local ngx = ngx
|
||||
local ngx_re = ngx.re
|
||||
local re_match = ngx_re.match
|
||||
local re_gmatch = ngx_re.gmatch
|
||||
local re_gsub = ngx_re.gsub
|
||||
|
||||
local NOT_MASK_FIRST = bnot(consts.MASK_FIRST)
|
||||
local NOT_MASK_LAST = bnot(consts.MASK_LAST)
|
||||
|
||||
function _M.int_to_char_length(x)
|
||||
return char(band(x, 0xff)) .. char(band(rshift(x, 8), 0xff)) ..
|
||||
char(band(rshift(x, 16), 0xff)) .. char(band(rshift(x, 24), 0xff))
|
||||
end
|
||||
|
||||
function _M.char_to_int_length(l)
|
||||
return l:byte(1, 1) + lshift(l:byte(2, 2), 8) + lshift(l:byte(3, 3), 16) + lshift(l:byte(4, 4), 24)
|
||||
end
|
||||
|
||||
function _M.is_mask_first(b)
|
||||
return band(b, consts.MASK_FIRST) == consts.MASK_FIRST
|
||||
end
|
||||
|
||||
function _M.is_mask_last(b)
|
||||
return band(b, consts.MASK_LAST) == consts.MASK_LAST
|
||||
end
|
||||
|
||||
local function tag_parser(tag)
|
||||
return band(band(tag, NOT_MASK_FIRST), NOT_MASK_LAST)
|
||||
end
|
||||
|
||||
function _M.packet_parser(header)
|
||||
if #header ~= consts.T1K_HEADER_SIZE then
|
||||
return true, nil, 0
|
||||
end
|
||||
|
||||
local fb = header:byte(1, 1)
|
||||
local finished = _M.is_mask_last(fb)
|
||||
local tag = tag_parser(fb)
|
||||
local length = _M.char_to_int_length(header:sub(2, 5))
|
||||
|
||||
return finished, tag, length
|
||||
end
|
||||
|
||||
function _M.starts_with(str, start)
|
||||
return str:sub(1, #start) == start
|
||||
end
|
||||
|
||||
function _M.to_var_idx(o)
|
||||
local var = o
|
||||
local idx
|
||||
|
||||
local _, p = o:find(":")
|
||||
if p then
|
||||
var = o:sub(1, p - 1)
|
||||
idx = tonumber(o:sub(p + 1))
|
||||
end
|
||||
|
||||
var = re_gsub(var:lower(), "-", "_")
|
||||
if not _M.starts_with(var, consts.NGX_HTTP_HEADER_PREFIX) then
|
||||
var = consts.NGX_HTTP_HEADER_PREFIX .. var
|
||||
end
|
||||
|
||||
return var, idx
|
||||
end
|
||||
|
||||
function _M.get_indexed_element(str, idx)
|
||||
if not str or not idx or idx == 0 then
|
||||
return str
|
||||
end
|
||||
|
||||
local it, err = re_gmatch(str, [[([^,\s]+)]], "jo")
|
||||
if err then
|
||||
return nil
|
||||
end
|
||||
|
||||
local t = {}
|
||||
for m, e in it do
|
||||
if e then
|
||||
return nil
|
||||
end
|
||||
table.insert(t, m[1])
|
||||
end
|
||||
|
||||
local len = #t
|
||||
if len < abs(idx) then
|
||||
return nil
|
||||
end
|
||||
|
||||
return t[idx > 0 and idx or (len + idx + 1)]
|
||||
end
|
||||
|
||||
function _M.get_event_id(str)
|
||||
if not str then
|
||||
return nil
|
||||
end
|
||||
|
||||
local m, err = re_match(str, [[<!-- event_id: ([A-Za-z0-9]+)(?: TYPE: [a-zA-Z])? -->]], "jo")
|
||||
if err then
|
||||
return nil
|
||||
end
|
||||
|
||||
if m then
|
||||
return m[1]
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
return _M
|
||||
100
sdk/lua-resty-t1k/lib/resty/t1k/uuid.lua
Normal file
100
sdk/lua-resty-t1k/lib/resty/t1k/uuid.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
local bit = require "bit"
|
||||
local ffi = require "ffi"
|
||||
|
||||
local log = require "resty.t1k.log"
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.0'
|
||||
}
|
||||
|
||||
local C = ffi.C
|
||||
local N_BYTES = 32
|
||||
local random = math.random
|
||||
|
||||
local nlog = ngx.log
|
||||
|
||||
local warn_fmt = log.warn_fmt
|
||||
|
||||
ffi.cdef [[
|
||||
int RAND_bytes(unsigned char *buf, int num);
|
||||
]]
|
||||
|
||||
local function _rand_bytes(buf, len)
|
||||
return C.RAND_bytes(buf, len)
|
||||
end
|
||||
|
||||
local function rand_bytes(len)
|
||||
local buf = ffi.new("char[?]", len)
|
||||
local ok, ret = pcall(_rand_bytes, buf, len)
|
||||
|
||||
if not ok or ret ~= 1 then
|
||||
nlog(warn_fmt("call RAND_bytes failed: %s", ret))
|
||||
return nil
|
||||
end
|
||||
|
||||
return ffi.string(buf, len)
|
||||
end
|
||||
|
||||
do
|
||||
local band = bit.band
|
||||
local bor = bit.bor
|
||||
local tohex = bit.tohex
|
||||
|
||||
local fmt = string.format
|
||||
local byte = string.byte
|
||||
|
||||
function _M.generate_v4()
|
||||
local bytes = rand_bytes(N_BYTES)
|
||||
|
||||
-- fallback to math.random based method
|
||||
if not bytes then
|
||||
return (fmt('%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
|
||||
tohex(bor(band(random(0, 255), 0x0F), 0x40), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
|
||||
tohex(bor(band(random(0, 255), 0x3F), 0x80), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2),
|
||||
tohex(random(0, 255), 2)))
|
||||
end
|
||||
|
||||
return fmt('%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
|
||||
tohex(byte(bytes, 1, 2), 2),
|
||||
tohex(byte(bytes, 3, 4), 2),
|
||||
tohex(byte(bytes, 5, 6), 2),
|
||||
tohex(byte(bytes, 7, 8), 2),
|
||||
|
||||
tohex(byte(bytes, 9, 10), 2),
|
||||
tohex(byte(bytes, 11, 12), 2),
|
||||
|
||||
tohex(bor(band(byte(bytes, 13, 14), 0x0F), 0x40), 2),
|
||||
tohex(byte(bytes, 15, 16), 2),
|
||||
|
||||
tohex(bor(band(byte(bytes, 17, 18), 0x3F), 0x80), 2),
|
||||
tohex(byte(bytes, 19, 20), 2),
|
||||
|
||||
tohex(byte(bytes, 21, 22), 2),
|
||||
tohex(byte(bytes, 23, 24), 2),
|
||||
tohex(byte(bytes, 25, 26), 2),
|
||||
tohex(byte(bytes, 27, 28), 2),
|
||||
tohex(byte(bytes, 29, 30), 2),
|
||||
tohex(byte(bytes, 31, 32), 2))
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(_M, {
|
||||
__call = _M.generate_v4
|
||||
})
|
||||
32
sdk/lua-resty-t1k/mainspec/lua-resty-t1k-main-0-0.rockspec
Normal file
32
sdk/lua-resty-t1k/mainspec/lua-resty-t1k-main-0-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k-main"
|
||||
version = "0-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
branch = "main",
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.0-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.0-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.0.0-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.0.0"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.1-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.1-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.0.1-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.0.1"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.2-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.2-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.0.2-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.0.2"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.3-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.0.3-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.0.3-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.0.3"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.0-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.0-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.1.0-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.0"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.1-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.1-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.1.1-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.1"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.2-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.2-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.1.2-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.2"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.3-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.3-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.1.3-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.3"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.4-0.rockspec
Normal file
32
sdk/lua-resty-t1k/rockspec/lua-resty-t1k-1.1.4-0.rockspec
Normal file
@@ -0,0 +1,32 @@
|
||||
package = "lua-resty-t1k"
|
||||
version = "1.1.4-0"
|
||||
source = {
|
||||
url = "git://github.com/chaitin/lua-resty-t1k",
|
||||
tag = "v1.1.4"
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
36
sdk/lua-resty-t1k/t/buffer.t
Normal file
36
sdk/lua-resty-t1k/t/buffer.t
Normal file
@@ -0,0 +1,36 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: buffer add
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local buffer = require "resty.t1k.buffer"
|
||||
local b = buffer:new()
|
||||
b:add("hello")
|
||||
b:add(" ")
|
||||
b:add("world")
|
||||
b:add("!")
|
||||
ngx.say(b[1], b[2], b[3], b[4])
|
||||
ngx.say(b:len())
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
hello world!
|
||||
12
|
||||
--- no_error_log
|
||||
[error]
|
||||
136
sdk/lua-resty-t1k/t/file.t
Normal file
136
sdk/lua-resty-t1k/t/file.t
Normal file
@@ -0,0 +1,136 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: read full file
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local file = require "resty.t1k.file"
|
||||
local path = ngx.var.document_root .. "/foo.bar"
|
||||
local ok, err, content = file.read(path, 2 ^ 15)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.print(table.concat(content))
|
||||
}
|
||||
}
|
||||
--- user_files eval
|
||||
[
|
||||
["foo.bar" => "a" x (2 ** 14) ],
|
||||
]
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body eval
|
||||
"a" x (2 ** 14)
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: read partial file
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local file = require "resty.t1k.file"
|
||||
local path = ngx.var.document_root .. "/foo.bar"
|
||||
local ok, err, content = file.read(path, 2 ^ 13)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.print(table.concat(content))
|
||||
}
|
||||
}
|
||||
--- user_files eval
|
||||
[
|
||||
["foo.bar" => "a" x (2 ** 14) ],
|
||||
]
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body eval
|
||||
"a" x (2 ** 13)
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: read negative bytes
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local file = require "resty.t1k.file"
|
||||
local path = ngx.var.document_root .. "/foo.bar"
|
||||
local ok, err, content = file.read(path, -1)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.print(table.concat(content))
|
||||
}
|
||||
}
|
||||
--- user_files
|
||||
>>> foo.bar
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body eval
|
||||
""
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: read empty file
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local file = require "resty.t1k.file"
|
||||
local path = ngx.var.document_root .. "/foo.bar"
|
||||
local ok, err, content = file.read(path, 1)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
ngx.print(table.concat(content))
|
||||
}
|
||||
}
|
||||
--- user_files
|
||||
>>> foo.bar
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body eval
|
||||
""
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: read non-existent file
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local file = require "resty.t1k.file"
|
||||
local ok, err, buffer = file.read("/opt/non_existent_file", 0)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
/opt/non_existent_file: No such file or directory
|
||||
--- no_error_log
|
||||
[error]
|
||||
39
sdk/lua-resty-t1k/t/filter.t
Normal file
39
sdk/lua-resty-t1k/t/filter.t
Normal file
@@ -0,0 +1,39 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 5);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: do_header_filter
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
ngx.ctx.t1k_extra_header = "k1:v1\nk2:v2\nk3:v3\n"
|
||||
}
|
||||
|
||||
header_filter_by_lua_block {
|
||||
local filter = require "resty.t1k.filter"
|
||||
filter.do_header_filter()
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("hi")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_headers
|
||||
k1: v1
|
||||
k2: v2
|
||||
k3: v3
|
||||
--- no_error_log
|
||||
[error]
|
||||
138
sdk/lua-resty-t1k/t/handler.t
Normal file
138
sdk/lua-resty-t1k/t/handler.t
Normal file
@@ -0,0 +1,138 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: handle passed action
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local handler = require "resty.t1k.handler"
|
||||
|
||||
local t = {
|
||||
action = ".",
|
||||
}
|
||||
|
||||
local ok, err = handler.handle(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
passed
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: handle blocked action
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local handler = require "resty.t1k.handler"
|
||||
|
||||
local t = {
|
||||
action = "?",
|
||||
status = 405,
|
||||
event_id = "c0c039a7c348486eaffd9e2f9846b66b",
|
||||
}
|
||||
|
||||
local ok, err = handler.handle(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
|
||||
header_filter_by_lua_block {
|
||||
local filter = require "resty.t1k.filter"
|
||||
filter.do_header_filter()
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
{"code": 405, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "c0c039a7c348486eaffd9e2f9846b66b"}
|
||||
--- error_code eval
|
||||
"405"
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: handle unknown action
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local handler = require "resty.t1k.handler"
|
||||
|
||||
local t = {
|
||||
action = "~"
|
||||
}
|
||||
|
||||
local ok, err = handler.handle(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
passed
|
||||
--- error_log
|
||||
lua-resty-t1k: unknown action from t1k server: ~
|
||||
|
||||
|
||||
|
||||
=== TEST 4: handle nil result
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local handler = require "resty.t1k.handler"
|
||||
|
||||
local ok, err = handler.handle(nil)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
passed
|
||||
--- error_log
|
||||
lua-resty-t1k: invalid result type: nil
|
||||
1142
sdk/lua-resty-t1k/t/integration.t
Normal file
1142
sdk/lua-resty-t1k/t/integration.t
Normal file
File diff suppressed because it is too large
Load Diff
67
sdk/lua-resty-t1k/t/log.t
Normal file
67
sdk/lua-resty-t1k/t/log.t
Normal file
@@ -0,0 +1,67 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 2 + 2);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: err_fmt
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local log = require "resty.t1k.log"
|
||||
ngx.log(log.err_fmt("%s - %04d - %.4f", "test", 1, 1))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: test - 0001 - 1.0000
|
||||
--- log_level: error
|
||||
|
||||
|
||||
|
||||
=== TEST 2: warn_fmt
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local log = require "resty.t1k.log"
|
||||
ngx.log(log.warn_fmt("%s - %04d - %.4f", "test", 1, 1))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: test - 0001 - 1.0000
|
||||
--- log_level: warn
|
||||
|
||||
|
||||
|
||||
=== TEST 3: debug_fmt
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local log = require "resty.t1k.log"
|
||||
ngx.log(log.debug_fmt("%s - %04d - %.4f", "test", 1, 1))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: test - 0001 - 1.0000
|
||||
--- log_level: debug
|
||||
169
sdk/lua-resty-t1k/t/option.t
Normal file
169
sdk/lua-resty-t1k/t/option.t
Normal file
@@ -0,0 +1,169 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3 + 1);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: do_access nil option
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local ok, err, _ = t1k.do_access(nil)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
passed
|
||||
--- no_error_log
|
||||
[debug]
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 2: do_access disabled
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local t = {
|
||||
mode = "off",
|
||||
}
|
||||
|
||||
local ok, err, _ = t1k.do_access(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
passed
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: t1k is not enabled
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 3: do_access invalid mode
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local t = {
|
||||
mode = "invalid",
|
||||
}
|
||||
|
||||
local ok, err, _ = t1k.do_access(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
passed
|
||||
--- error_log
|
||||
lua-resty-t1k: invalid t1k mode: invalid
|
||||
|
||||
|
||||
|
||||
=== TEST 4: do_access invalid host
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local t = {
|
||||
mode = "block"
|
||||
}
|
||||
|
||||
local ok, err, _ = t1k.do_access(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
passed
|
||||
--- error_log
|
||||
lua-resty-t1k: invalid t1k host: nil
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 5: do_access invalid port
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local t1k = require "resty.t1k"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
|
||||
local ok, err, _ = t1k.do_access(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
}
|
||||
|
||||
content_by_lua_block {
|
||||
ngx.say("passed")
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
passed
|
||||
--- error_log
|
||||
lua-resty-t1k: invalid t1k port: nil
|
||||
--- log_level: debug
|
||||
640
sdk/lua-resty-t1k/t/request.t
Normal file
640
sdk/lua-resty-t1k/t/request.t
Normal file
@@ -0,0 +1,640 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3 + 14);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: do_request blocked
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
ngx.say(result["status"])
|
||||
ngx.say(result["event_id"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
?
|
||||
405
|
||||
c0c039a7c348486eaffd9e2f9846b66b
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 2: do_request blocked with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
ngx.say(result["status"])
|
||||
ngx.say(result["event_id"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
?
|
||||
405
|
||||
c0c039a7c348486eaffd9e2f9846b66b
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 3: do_request passed
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00."
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
.
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 4: do_request passed with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00."
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
.
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 5: do_request trim request body
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00."
|
||||
--- request
|
||||
GET /t
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
--- response_body
|
||||
.
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: request body is too long: 123 bytes, cut to 64 bytes
|
||||
lua-resty-t1k: successfully connected to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 6: do_request trim request body with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00."
|
||||
--- request
|
||||
GET /t
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
--- response_body
|
||||
.
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: request body is too long: 123 bytes, cut to 64 bytes
|
||||
lua-resty-t1k: successfully connected to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 7: do_request refuse connection
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("result: ", result)
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
result: nil
|
||||
--- error_log
|
||||
failed to connect to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 8: do_request refuse connection with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("result: ", result)
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
result: nil
|
||||
--- error_log
|
||||
failed to connect to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 9: do_request timeout
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 100,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("result: ", result)
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply_delay: 200ms
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
result: nil
|
||||
--- error_log
|
||||
failed to receive info packet from t1k server 127.0.0.1:18000: timeout
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 10: do_request timeout with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 100,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("result: ", result)
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply_delay: 200ms
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- response_body
|
||||
result: nil
|
||||
--- error_log
|
||||
failed to receive info packet from t1k server unix:t1k.sock: timeout
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 11: do_request invalid action
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("action: ", result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00~"
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
action: ~
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
successfully connected to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 12: do_request invalid action with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 0.0625,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say("action: ", result["action"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply eval
|
||||
"\xc1\x01\x00\x00\x00~"
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
action: ~
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
successfully connected to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 13: do_request remote address
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
access_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("ngx.var.http_x_real_ip or ngx.var.remote_addr is ", utils.get_indexed_element(ngx.var.http_x_real_ip) or ngx.var.remote_addr)
|
||||
ngx.say("ngx.var.http_x_forwarded_for: 2 or ngx.var.remote_addr is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 2) or ngx.var.remote_addr)
|
||||
ngx.say("ngx.var.http_x_forwarded_for: -2 or ngx.var.remote_addr is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -2) or ngx.var.remote_addr)
|
||||
ngx.say("ngx.var.http_non_existent_header or ngx.var.remote_addr is ", utils.get_indexed_element(ngx.var.http_non_existent_header) or ngx.var.remote_addr)
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- more_headers
|
||||
X-Forwarded-For: 1.1.1.1, 2.2.2.2, 2001:db8:3333:4444:5555:6666:7777:8888, 3.3.3.3
|
||||
X-Real-IP: 100.100.100.100
|
||||
--- response_body
|
||||
ngx.var.http_x_real_ip or ngx.var.remote_addr is 100.100.100.100
|
||||
ngx.var.http_x_forwarded_for: 2 or ngx.var.remote_addr is 2.2.2.2
|
||||
ngx.var.http_x_forwarded_for: -2 or ngx.var.remote_addr is 2001:db8:3333:4444:5555:6666:7777:8888
|
||||
ngx.var.http_non_existent_header or ngx.var.remote_addr is 127.0.0.1
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 14: do_request http2
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "127.0.0.1",
|
||||
port = 18000,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
ngx.say(result["status"])
|
||||
ngx.say(result["event_id"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: 18000
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- http2
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- tcp_query eval
|
||||
qr/.*HTTP\/2.0.*/
|
||||
--- response_body
|
||||
?
|
||||
405
|
||||
c0c039a7c348486eaffd9e2f9846b66b
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server 127.0.0.1:18000
|
||||
--- log_level: debug
|
||||
|
||||
|
||||
|
||||
=== TEST 15: do_request http2 with unix domain socket
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local request = require "resty.t1k.request"
|
||||
|
||||
local t = {
|
||||
mode = "block",
|
||||
host = "unix:t1k.sock",
|
||||
uds = true,
|
||||
connect_timeout = 1000,
|
||||
send_timeout = 1000,
|
||||
read_timeout = 1000,
|
||||
req_body_size = 1024,
|
||||
keepalive_size = 16,
|
||||
keepalive_timeout = 10000,
|
||||
}
|
||||
|
||||
local ok, err, result = request.do_request(t)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(result["action"])
|
||||
ngx.say(result["status"])
|
||||
ngx.say(result["event_id"])
|
||||
}
|
||||
}
|
||||
--- tcp_listen: t1k.sock
|
||||
--- tcp_reply eval
|
||||
"\x41\x01\x00\x00\x00?\x02\x03\x00\x00\x00405\xa4\x33\x00\x00\x00<!-- event_id: c0c039a7c348486eaffd9e2f9846b66b -->"
|
||||
--- http2
|
||||
--- request
|
||||
GET /t/shell.php
|
||||
--- tcp_query eval
|
||||
qr/.*HTTP\/2.0.*/
|
||||
--- response_body
|
||||
?
|
||||
405
|
||||
c0c039a7c348486eaffd9e2f9846b66b
|
||||
--- no_error_log
|
||||
[error]
|
||||
--- error_log
|
||||
lua-resty-t1k: successfully connected to t1k server unix:t1k.sock
|
||||
--- log_level: debug
|
||||
264
sdk/lua-resty-t1k/t/utils.t
Normal file
264
sdk/lua-resty-t1k/t/utils.t
Normal file
@@ -0,0 +1,264 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: int_to_char_length
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("255 to char length: ", utils.int_to_char_length(255))
|
||||
ngx.print("16777216 to char length: ", utils.int_to_char_length(16777216))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body eval
|
||||
"255 to char length: \x{ff}\x{00}\x{00}\x{00}
|
||||
16777216 to char length: \x{00}\x{00}\x{00}\x{01}"
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: int_to_char_length
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("0xff 0x00 0x00 0x00 to int length: ", utils.char_to_int_length("\xff\x00\x00\x00"))
|
||||
ngx.say("0x00 0x00 0x00 0x01 to int length: ", utils.char_to_int_length("\x00\x00\x00\x01"))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0xff 0x00 0x00 0x00 to int length: 255
|
||||
0x00 0x00 0x00 0x01 to int length: 16777216
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: is_mask_first
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("0x30 is MASK FIRST: ", utils.is_mask_first(0x30))
|
||||
ngx.say("0x41 is MASK FIRST: ", utils.is_mask_first(0x41))
|
||||
ngx.say("0xc0 is MASK FIRST: ", utils.is_mask_first(0xc0))
|
||||
ngx.say("0xc1 is MASK FIRST: ", utils.is_mask_first(0xc1))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0x30 is MASK FIRST: false
|
||||
0x41 is MASK FIRST: true
|
||||
0xc0 is MASK FIRST: true
|
||||
0xc1 is MASK FIRST: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: is_mask_last
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("0x41 is MASK LAST: ", utils.is_mask_last(65))
|
||||
ngx.say("0x80 is MASK LAST: ", utils.is_mask_last(128))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0x41 is MASK LAST: false
|
||||
0x80 is MASK LAST: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: packet_parser unfinished
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
local finished, tag, length = utils.packet_parser("\x41\x59\x00\x00\x00")
|
||||
ngx.say("finished: ", finished)
|
||||
ngx.say("tag == TAG_HEAD: ", tag == 1)
|
||||
ngx.say("length: ", 89)
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
finished: false
|
||||
tag == TAG_HEAD: true
|
||||
length: 89
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: packet_parser finished
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
local finished, tag, length = utils.packet_parser("\xa0\x08\x00\x00\x00")
|
||||
ngx.say("finished: ", finished)
|
||||
ngx.say("tag == TAG_VERSION: ", tag == 32)
|
||||
ngx.say("length: ", 8)
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
finished: true
|
||||
tag == TAG_VERSION: true
|
||||
length: 8
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: starts_with
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("http://www.baidu.com starts with \"http\": ", utils.starts_with("http://www.baidu.com", "http"))
|
||||
ngx.say("http://www.baidu.com starts with \"https\": ", utils.starts_with("http://www.baidu.com", "https"))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
http://www.baidu.com starts with "http": true
|
||||
http://www.baidu.com starts with "https": false
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: to_var_idx
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
local fmt = string.format
|
||||
ngx.say(fmt("http_x_real_ip is %s and %s", utils.to_var_idx("http_x_real_ip")))
|
||||
ngx.say(fmt("X_REAL_IP is %s and %s", utils.to_var_idx("X_REAL_IP")))
|
||||
ngx.say(fmt("X-Forwarded-For: 1 is %s and %d", utils.to_var_idx("X-Forwarded-For: 1")))
|
||||
ngx.say(fmt("X-Forwarded-For: -1 is %s and %d", utils.to_var_idx("X-Forwarded-For: -1")))
|
||||
ngx.say(fmt("X-FORWARDED-FOR:100 is %s and %d", utils.to_var_idx("X-FORWARDED-FOR:-100")))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
http_x_real_ip is http_x_real_ip and nil
|
||||
X_REAL_IP is http_x_real_ip and nil
|
||||
X-Forwarded-For: 1 is http_x_forwarded_for and 1
|
||||
X-Forwarded-For: -1 is http_x_forwarded_for and -1
|
||||
X-FORWARDED-FOR:100 is http_x_forwarded_for and -100
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: get_indexed_element
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say("X-Forwarded-For: 1 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 1))
|
||||
ngx.say("X-Forwarded-For: 2 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 2))
|
||||
ngx.say("X-Forwarded-For: 3 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 3))
|
||||
ngx.say("X-Forwarded-For: 4 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 4))
|
||||
ngx.say("X-Forwarded-For: 5 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 5))
|
||||
ngx.say("X-Forwarded-For: -1 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -1))
|
||||
ngx.say("X-Forwarded-For: -2 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -2))
|
||||
ngx.say("X-Forwarded-For: -3 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -3))
|
||||
ngx.say("X-Forwarded-For: -4 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -4))
|
||||
ngx.say("X-Forwarded-For: -5 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, -5))
|
||||
ngx.say("X-Forwarded-For: 0 is ", utils.get_indexed_element(ngx.var.http_x_forwarded_for, 0))
|
||||
ngx.say("X-Non-Existent-Header is ", utils.get_indexed_element(ngx.var.http_non_existent_header))
|
||||
ngx.say("X-Real-IP is ", utils.get_indexed_element(ngx.var.http_x_real_ip))
|
||||
ngx.say("X-Real-IP: 1 is ", utils.get_indexed_element(ngx.var.http_x_real_ip, 1))
|
||||
ngx.say("X-Real-IP: 2 is ", utils.get_indexed_element(ngx.var.http_x_real_ip, 2))
|
||||
ngx.say("X-Real-IP: -1 is ", utils.get_indexed_element(ngx.var.http_x_real_ip, -1))
|
||||
ngx.say("X-Real-IP: -2 is ", utils.get_indexed_element(ngx.var.http_x_real_ip, -2))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- more_headers
|
||||
X-Forwarded-For: 1.1.1.1, 2.2.2.2
|
||||
X-Forwarded-For: 3.3.3.3, 4.4.4.4
|
||||
X-Real-IP: 10.10.10.10
|
||||
--- response_body
|
||||
X-Forwarded-For: 1 is 1.1.1.1
|
||||
X-Forwarded-For: 2 is 2.2.2.2
|
||||
X-Forwarded-For: 3 is 3.3.3.3
|
||||
X-Forwarded-For: 4 is 4.4.4.4
|
||||
X-Forwarded-For: 5 is nil
|
||||
X-Forwarded-For: -1 is 4.4.4.4
|
||||
X-Forwarded-For: -2 is 3.3.3.3
|
||||
X-Forwarded-For: -3 is 2.2.2.2
|
||||
X-Forwarded-For: -4 is 1.1.1.1
|
||||
X-Forwarded-For: -5 is nil
|
||||
X-Forwarded-For: 0 is 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4
|
||||
X-Non-Existent-Header is nil
|
||||
X-Real-IP is 10.10.10.10
|
||||
X-Real-IP: 1 is 10.10.10.10
|
||||
X-Real-IP: 2 is nil
|
||||
X-Real-IP: -1 is 10.10.10.10
|
||||
X-Real-IP: -2 is nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: get_event_id
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local utils = require "resty.t1k.utils"
|
||||
ngx.say(utils.get_event_id("<!-- event_id: 0988987de04844c7a3ce6d27865c9513 -->"))
|
||||
ngx.say(utils.get_event_id("<!-- event_id: 8bae6adf33864c7f8bf715a9b7a65b2c TYPE: A -->"))
|
||||
ngx.say(utils.get_event_id("<!-- TYPE B -->"))
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0988987de04844c7a3ce6d27865c9513
|
||||
8bae6adf33864c7f8bf715a9b7a65b2c
|
||||
nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
29
sdk/lua-resty-t1k/t/uuid.t
Normal file
29
sdk/lua-resty-t1k/t/uuid.t
Normal file
@@ -0,0 +1,29 @@
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
our $HttpConfig = <<'_EOC_';
|
||||
lua_package_path "lib/?.lua;/usr/local/share/lua/5.1/?.lua;;";
|
||||
_EOC_
|
||||
|
||||
repeat_each(3);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 3);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: generate_v4
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local uuid = require "resty.t1k.uuid"
|
||||
ngx.say(uuid.generate_v4())
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body_like
|
||||
^[0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}$
|
||||
--- no_error_log
|
||||
[error]
|
||||
Reference in New Issue
Block a user