Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b212e124c2 | ||
|
|
ee2781fe65 | ||
|
|
89c1edc9ee | ||
|
|
773f3e1a7e | ||
|
|
e6f6f4dcc2 | ||
|
|
174946aa4d | ||
|
|
93c594a785 | ||
|
|
2aea527dff | ||
|
|
fa30015ca5 | ||
|
|
d06c8cebf5 | ||
|
|
e4ef2e8253 | ||
|
|
665aa06cc7 | ||
|
|
88dfda82d6 | ||
|
|
243463df83 | ||
|
|
2dc1bfcb55 | ||
|
|
e6f7cafe7e | ||
|
|
26fe3558f4 | ||
|
|
ea09ef3d91 | ||
|
|
c4ca2521ee | ||
|
|
db5cdd2957 | ||
|
|
0f483b98ec | ||
|
|
0fe51abeb1 | ||
|
|
db6b7f57bb | ||
|
|
663ead19e4 | ||
|
|
bc8adb663a | ||
|
|
08b5dd7531 | ||
|
|
8177f3d7e4 | ||
|
|
bb5252caf6 | ||
|
|
bd4a47d2a1 | ||
|
|
300be4e936 | ||
|
|
c9dbfb79a7 | ||
|
|
589ae124f1 | ||
|
|
d72b440406 | ||
|
|
63e4e7cf9f | ||
|
|
ad416dddec | ||
|
|
4e18129c6c | ||
|
|
c03d9f1880 | ||
|
|
fe448e6556 | ||
|
|
adcb33fce4 | ||
|
|
e58c3774b6 | ||
|
|
cd7e01c2f0 | ||
|
|
d884777a55 | ||
|
|
c48aba1c99 | ||
|
|
8cc0faf1d7 | ||
|
|
9851b1a146 | ||
|
|
36162c603d | ||
|
|
cc2782584e | ||
|
|
1c1e82ee38 | ||
|
|
4b3a9cedfa | ||
|
|
e9497ee65d | ||
|
|
29fae55dc6 | ||
|
|
54fdf3b762 | ||
|
|
f609008984 | ||
|
|
f9b6838dc6 | ||
|
|
6d2ecb9af3 | ||
|
|
7c4a01137b | ||
|
|
418c15f79f | ||
|
|
d13176b8a5 | ||
|
|
b2752ddd5a | ||
|
|
7aea2fd48c | ||
|
|
803f11659c | ||
|
|
073926ff67 | ||
|
|
65b4832c94 | ||
|
|
5f793f1f76 | ||
|
|
0ce1df25bc | ||
|
|
06ad9cc63b | ||
|
|
57247d0f5b | ||
|
|
813267c50f | ||
|
|
b8078e73b2 | ||
|
|
f958c57984 | ||
|
|
30bfbdc01e | ||
|
|
314362c24d | ||
|
|
8582715be7 | ||
|
|
74e585263c | ||
|
|
35cb10fffe | ||
|
|
7c84794ac4 | ||
|
|
5859f5df91 | ||
|
|
e370944233 | ||
|
|
a23a2ed826 | ||
|
|
3f9c250dff | ||
|
|
06c9c9403b | ||
|
|
0e580a0890 | ||
|
|
7aba622403 | ||
|
|
72cc8389e6 | ||
|
|
39cf470b0c | ||
|
|
6e71dda713 | ||
|
|
10909e28c8 | ||
|
|
6bd6e350b9 | ||
|
|
d2ae7834ae | ||
|
|
c1ffd25c8b | ||
|
|
931e55162b | ||
|
|
fa2bac6d1d | ||
|
|
2f7b7240dd | ||
|
|
da67e726a2 | ||
|
|
6cb5529c3f | ||
|
|
473d0d9439 | ||
|
|
bf0db231fc | ||
|
|
5644906b77 | ||
|
|
3e32fe8e10 | ||
|
|
8459f106e9 | ||
|
|
b768bbce5d | ||
|
|
9e7beb39c0 | ||
|
|
94287f5857 | ||
|
|
60690dfd01 | ||
|
|
fb00a7931e | ||
|
|
42a6494bde | ||
|
|
85a46a9827 | ||
|
|
088636553c | ||
|
|
95de3b12e2 | ||
|
|
b66b8d198a | ||
|
|
e968a79886 | ||
|
|
4fc5d5b549 | ||
|
|
77606709b3 | ||
|
|
3529ceefcd | ||
|
|
7e851f07b1 | ||
|
|
a62711e520 | ||
|
|
ffce574b39 | ||
|
|
4b1a9f9a45 | ||
|
|
7a86ecb44b | ||
|
|
89a113431a | ||
|
|
ce62d0769b | ||
|
|
a72dc2e011 | ||
|
|
91ca2d6b6b | ||
|
|
0de6fa5ce8 | ||
|
|
84e2628769 | ||
|
|
fc28798c9f | ||
|
|
24c21c5513 | ||
|
|
8445e811a5 | ||
|
|
d54621d500 | ||
|
|
ef045e90f2 | ||
|
|
5205136809 | ||
|
|
179a7760fa | ||
|
|
640e69524c | ||
|
|
3620ab3dc6 |
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"log"
|
||||
"os"
|
||||
@@ -83,6 +84,45 @@ func main() {
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("debug", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "debug"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var isDebug = maps.NewMap(reply.Params).GetBool("debug")
|
||||
if isDebug {
|
||||
fmt.Println("debug on")
|
||||
} else {
|
||||
fmt.Println("debug off")
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("db.stmt.prepare", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.prepare"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var isOn = maps.NewMap(reply.Params).GetBool("isOn")
|
||||
if isOn {
|
||||
fmt.Println("show statements: on")
|
||||
} else {
|
||||
fmt.Println("show statements: off")
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("db.stmt.count", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.count"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var count = maps.NewMap(reply.Params).GetInt("count")
|
||||
fmt.Println("prepared statements count: " + types.String(count))
|
||||
}
|
||||
})
|
||||
|
||||
app.Run(func() {
|
||||
nodes.NewAPINode().Start()
|
||||
})
|
||||
|
||||
21
go.mod
21
go.mod
@@ -1,31 +1,26 @@
|
||||
module github.com/TeaOSLab/EdgeAPI
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183
|
||||
github.com/andybalholm/brotli v1.0.4
|
||||
github.com/cespare/xxhash/v2 v2.1.1
|
||||
github.com/go-acme/lego/v4 v4.5.2
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible
|
||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
|
||||
google.golang.org/grpc v1.38.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
|
||||
google.golang.org/grpc v1.45.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
99
go.sum
99
go.sum
@@ -43,8 +43,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -52,6 +50,7 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 h1:dkj8/dxOQ4L1XpwCzRLqukvUBbx
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@@ -78,6 +77,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -101,7 +104,8 @@ github.com/dnsimple/dnsimple-go v0.70.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MO
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -122,8 +126,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
||||
@@ -132,8 +136,6 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -161,6 +163,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@@ -173,8 +176,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
@@ -201,6 +206,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
@@ -231,11 +237,11 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13 h1:HuEJ5xJfujW1Q6rNDhOu5LQXEBB2qLPah3jYslT8Gz4=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24 h1:1cGulkD2SNJJRok5OKwyhP/Ddm+PgSWKOupn0cR36/A=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d h1:e8fkTKras/RXQWECApM9fKlFWujjYjEClpshkmZmtYg=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c h1:ugjYZ74FJGWlfDKKraNgMyDTeS4vbXHe89JGUVQIJMo=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
@@ -250,8 +256,6 @@ github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@@ -277,12 +281,12 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/linode/linodego v0.31.1/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM=
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible h1:1qp9iks+69h7IGLazAplzS9Ca14HAxuD5c0rbFdPGy4=
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
||||
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -322,7 +326,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
@@ -371,6 +374,8 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
@@ -390,14 +395,15 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc=
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
@@ -436,10 +442,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
||||
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
||||
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
|
||||
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
@@ -456,13 +462,15 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@@ -482,8 +490,9 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -507,7 +516,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -516,7 +524,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -551,8 +558,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -588,6 +597,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -611,19 +621,23 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -631,8 +645,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -674,7 +689,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -714,9 +728,10 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -726,9 +741,10 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -739,8 +755,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
)
|
||||
|
||||
type BaseStorage struct {
|
||||
isOk bool
|
||||
version int
|
||||
isOk bool
|
||||
version int
|
||||
firewallOnly bool
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetVersion(version int) {
|
||||
@@ -32,6 +33,10 @@ func (this *BaseStorage) SetOk(isOk bool) {
|
||||
this.isOk = isOk
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetFirewallOnly(firewallOnly bool) {
|
||||
this.firewallOnly = firewallOnly
|
||||
}
|
||||
|
||||
// Marshal 对日志进行编码
|
||||
func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
|
||||
return json.Marshal(accessLog)
|
||||
|
||||
@@ -61,6 +61,10 @@ func (this *CommandStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
return err
|
||||
}
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -59,6 +59,10 @@ func (this *ESStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
indexName := this.FormatVariables(this.config.Index)
|
||||
typeName := this.FormatVariables(this.config.MappingType)
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(accessLog.RequestId) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ func (this *FileStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -12,6 +12,9 @@ type StorageInterface interface {
|
||||
// SetVersion 设置版本
|
||||
SetVersion(version int)
|
||||
|
||||
// SetFirewallOnly 设置是否只处理防火墙相关的访问日志
|
||||
SetFirewallOnly(firewallOnly bool)
|
||||
|
||||
IsOk() bool
|
||||
|
||||
SetOk(ok bool)
|
||||
|
||||
@@ -58,7 +58,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
var policyIds = []int64{}
|
||||
for _, policy := range policies {
|
||||
if policy.IsOn == 1 {
|
||||
if policy.IsOn {
|
||||
policyIds = append(policyIds, int64(policy.Id))
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
|
||||
if len(policy.Options) > 0 {
|
||||
err = json.Unmarshal([]byte(policy.Options), storage.Config())
|
||||
err = json.Unmarshal(policy.Options, storage.Config())
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "unmarshal policy '"+types.String(policyId)+"' config failed: "+err.Error())
|
||||
storage.SetOk(false)
|
||||
@@ -101,6 +101,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
|
||||
storage.SetVersion(types.Int(policy.Version))
|
||||
storage.SetFirewallOnly(policy.FirewallOnly == 1)
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
@@ -110,12 +111,13 @@ func (this *StorageManager) Loop() error {
|
||||
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "restart policy '"+types.String(policyId)+"'")
|
||||
}
|
||||
} else {
|
||||
storage, err := this.createStorage(policy.Type, []byte(policy.Options))
|
||||
storage, err := this.createStorage(policy.Type, policy.Options)
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "create policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
storage.SetVersion(types.Int(policy.Version))
|
||||
storage.SetFirewallOnly(policy.FirewallOnly == 1)
|
||||
this.storageMap[policyId] = storage
|
||||
err = storage.Start()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package accesslogs
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
}
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -60,6 +60,9 @@ func (this *TCPStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -1,51 +1,108 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/utils/time"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LogWriter struct {
|
||||
fileAppender *files.Appender
|
||||
fp *os.File
|
||||
c chan string
|
||||
}
|
||||
|
||||
func (this *LogWriter) Init() {
|
||||
// 创建目录
|
||||
dir := files.NewFile(Tea.LogDir())
|
||||
var dir = files.NewFile(Tea.LogDir())
|
||||
if !dir.Exists() {
|
||||
err := dir.Mkdir()
|
||||
if err != nil {
|
||||
log.Println("[error]" + err.Error())
|
||||
log.Println("[LOG]create log dir failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
logFile := files.NewFile(Tea.LogFile("run.log"))
|
||||
|
||||
// 打开要写入的日志文件
|
||||
appender, err := logFile.Appender()
|
||||
var logPath = Tea.LogFile("run.log")
|
||||
fp, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
log.Println("[LOG]open log file failed: " + err.Error())
|
||||
} else {
|
||||
this.fileAppender = appender
|
||||
this.fp = fp
|
||||
}
|
||||
|
||||
this.c = make(chan string, 1024)
|
||||
|
||||
// 异步写入文件
|
||||
var maxFileSize = 2 * sizes.G // 文件最大尺寸,超出此尺寸则清空
|
||||
if fp != nil {
|
||||
goman.New(func() {
|
||||
var totalSize int64 = 0
|
||||
stat, err := fp.Stat()
|
||||
if err == nil {
|
||||
totalSize = stat.Size()
|
||||
}
|
||||
|
||||
for message := range this.c {
|
||||
totalSize += int64(len(message))
|
||||
_, err := fp.WriteString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
|
||||
if err != nil {
|
||||
log.Println("[LOG]write log failed: " + err.Error())
|
||||
} else {
|
||||
// 如果太大则Truncate
|
||||
if totalSize > maxFileSize {
|
||||
_ = fp.Truncate(0)
|
||||
totalSize = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (this *LogWriter) Write(message string) {
|
||||
log.Println(message)
|
||||
backgroundEnv, _ := os.LookupEnv("EdgeBackground")
|
||||
if backgroundEnv != "on" {
|
||||
// 文件和行号
|
||||
var file string
|
||||
var line int
|
||||
if Tea.IsTesting() {
|
||||
var callDepth = 3
|
||||
var ok bool
|
||||
_, file, line, ok = runtime.Caller(callDepth)
|
||||
if ok {
|
||||
file = this.packagePath(file)
|
||||
}
|
||||
}
|
||||
|
||||
if this.fileAppender != nil {
|
||||
_, err := this.fileAppender.AppendString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
|
||||
if err != nil {
|
||||
log.Println("[error]" + err.Error())
|
||||
if len(file) > 0 {
|
||||
log.Println(message + " (" + file + ":" + strconv.Itoa(line) + ")")
|
||||
} else {
|
||||
log.Println(message)
|
||||
}
|
||||
}
|
||||
|
||||
this.c <- message
|
||||
}
|
||||
|
||||
func (this *LogWriter) Close() {
|
||||
if this.fileAppender != nil {
|
||||
_ = this.fileAppender.Close()
|
||||
if this.fp != nil {
|
||||
_ = this.fp.Close()
|
||||
}
|
||||
|
||||
close(this.c)
|
||||
}
|
||||
|
||||
func (this *LogWriter) packagePath(path string) string {
|
||||
var pieces = strings.Split(path, "/")
|
||||
if len(pieces) >= 2 {
|
||||
return strings.Join(pieces[len(pieces)-2:], "/")
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package configs
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/go-yaml/yaml"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package teaconst
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.4.0"
|
||||
Version = "0.4.7"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,10 +18,13 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.4.0"
|
||||
UserNodeVersion = "0.3.0"
|
||||
NodeVersion = "0.4.7"
|
||||
UserNodeVersion = "0.3.3"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.1"
|
||||
DNSNodeVersion = "0.2.2"
|
||||
ReportNodeVersion = "0.1.0"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "8"
|
||||
)
|
||||
|
||||
@@ -6,4 +6,5 @@ var (
|
||||
IsPlus = false
|
||||
MaxNodes int32 = 0
|
||||
NodeId int64 = 0
|
||||
Debug = false
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
@@ -42,3 +43,13 @@ func TestDB_Instance(t *testing.T) {
|
||||
}
|
||||
time.Sleep(100 * time.Second)
|
||||
}
|
||||
|
||||
func TestDB_Reuse(t *testing.T) {
|
||||
var dao = models.NewVersionDAO()
|
||||
for i := 0; i < 20_000; i++ {
|
||||
_, _, err := dao.Query(nil).Attr("version", i).Reuse(true).FindOne()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -79,7 +80,7 @@ func (this *UserAccountLogDAO) CountAccountLogs(tx *dbs.Tx, userId int64, accoun
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
|
||||
query.Param("keyword", "%"+keyword+"%")
|
||||
query.Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
@@ -98,7 +99,7 @@ func (this *UserAccountLogDAO) ListAccountLogs(tx *dbs.Tx, userId int64, account
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
|
||||
query.Param("keyword", "%"+keyword+"%")
|
||||
query.Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package accounts
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// UserAccountLog 用户账户日志
|
||||
type UserAccountLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
AccountId uint64 `field:"accountId"` // 账户ID
|
||||
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
|
||||
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
|
||||
Total float64 `field:"total"` // 操作后余额
|
||||
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
|
||||
EventType string `field:"eventType"` // 类型
|
||||
Description string `field:"description"` // 描述文字
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
CreatedAt uint64 `field:"createdAt"` // 时间
|
||||
Params string `field:"params"` // 参数
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
AccountId uint64 `field:"accountId"` // 账户ID
|
||||
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
|
||||
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
|
||||
Total float64 `field:"total"` // 操作后余额
|
||||
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
|
||||
EventType string `field:"eventType"` // 类型
|
||||
Description string `field:"description"` // 描述文字
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
CreatedAt uint64 `field:"createdAt"` // 时间
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
}
|
||||
|
||||
type UserAccountLogOperator struct {
|
||||
|
||||
@@ -3,7 +3,7 @@ package acme
|
||||
// ACMEProviderAccount ACME提供商
|
||||
type ACMEProviderAccount struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
ProviderCode string `field:"providerCode"` // 代号
|
||||
Error string `field:"error"` // 最后一条错误信息
|
||||
|
||||
@@ -125,11 +125,11 @@ func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, adminId int64, use
|
||||
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(domains LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("domains LIKE :keyword").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
|
||||
return query.State(ACMETaskStateEnabled).
|
||||
@@ -155,7 +155,7 @@ func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, adminId int64, userId
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(domains LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
State(ACMETaskStateEnabled).
|
||||
@@ -271,7 +271,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
errMsg = "找不到要执行的任务"
|
||||
return
|
||||
}
|
||||
if task.IsOn != 1 {
|
||||
if !task.IsOn {
|
||||
errMsg = "任务没有启用"
|
||||
return
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
})
|
||||
|
||||
if len(user.Registration) > 0 {
|
||||
err = remoteUser.SetRegistration([]byte(user.Registration))
|
||||
err = remoteUser.SetRegistration(user.Registration)
|
||||
if err != nil {
|
||||
errMsg = "设置注册信息时出错:" + err.Error()
|
||||
return
|
||||
@@ -453,7 +453,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
return
|
||||
}
|
||||
|
||||
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn == 1, cert.Name, cert.Description, cert.ServerName, cert.IsCA == 1, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
|
||||
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn, cert.Name, cert.Description, cert.ServerName, cert.IsCA, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
|
||||
if err != nil {
|
||||
errMsg = "证书生成成功,但是修改数据库中的证书信息时出错:" + err.Error()
|
||||
return
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package acme
|
||||
|
||||
// ACME任务运行日志
|
||||
// ACMETaskLog ACME任务运行日志
|
||||
type ACMETaskLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
TaskId uint64 `field:"taskId"` // 任务ID
|
||||
IsOk uint8 `field:"isOk"` // 是否成功
|
||||
IsOk bool `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
CreatedAt uint64 `field:"createdAt"` // 运行时间
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
package acme
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ACMETask ACME任务
|
||||
type ACMETask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
|
||||
DnsDomain string `field:"dnsDomain"` // DNS主域名
|
||||
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
|
||||
Domains string `field:"domains"` // 证书域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
CertId uint64 `field:"certId"` // 生成的证书ID
|
||||
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
||||
AuthType string `field:"authType"` // 认证类型
|
||||
AuthURL string `field:"authURL"` // 认证URL
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
|
||||
DnsDomain string `field:"dnsDomain"` // DNS主域名
|
||||
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
|
||||
Domains dbs.JSON `field:"domains"` // 证书域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
CertId uint64 `field:"certId"` // 生成的证书ID
|
||||
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
||||
AuthType string `field:"authType"` // 认证类型
|
||||
AuthURL string `field:"authURL"` // 认证URL
|
||||
}
|
||||
|
||||
type ACMETaskOperator struct {
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
// 将域名解析成字符串数组
|
||||
// DecodeDomains 将域名解析成字符串数组
|
||||
func (this *ACMETask) DecodeDomains() []string {
|
||||
if len(this.Domains) == 0 || this.Domains == "null" {
|
||||
if len(this.Domains) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := []string{}
|
||||
err := json.Unmarshal([]byte(this.Domains), &result)
|
||||
err := json.Unmarshal(this.Domains, &result)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return nil
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package acme
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ACMEUser ACME用户
|
||||
type ACMEUser struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
PrivateKey string `field:"privateKey"` // 私钥
|
||||
Email string `field:"email"` // E-mail
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 备注介绍
|
||||
Registration string `field:"registration"` // 注册信息
|
||||
ProviderCode string `field:"providerCode"` // 服务商代号
|
||||
AccountId uint64 `field:"accountId"` // 提供商ID
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
PrivateKey string `field:"privateKey"` // 私钥
|
||||
Email string `field:"email"` // E-mail
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 备注介绍
|
||||
Registration dbs.JSON `field:"registration"` // 注册信息
|
||||
ProviderCode string `field:"providerCode"` // 服务商代号
|
||||
AccountId uint64 `field:"accountId"` // 提供商ID
|
||||
}
|
||||
|
||||
type ACMEUserOperator struct {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// Admin 管理员
|
||||
type Admin struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 全名
|
||||
IsSuper uint8 `field:"isSuper"` // 是否为超级管理员
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Modules string `field:"modules"` // 允许的模块
|
||||
CanLogin uint8 `field:"canLogin"` // 是否可以登录
|
||||
Theme string `field:"theme"` // 模板设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 全名
|
||||
IsSuper bool `field:"isSuper"` // 是否为超级管理员
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Modules dbs.JSON `field:"modules"` // 允许的模块
|
||||
CanLogin uint8 `field:"canLogin"` // 是否可以登录
|
||||
Theme string `field:"theme"` // 模板设置
|
||||
}
|
||||
|
||||
type AdminOperator struct {
|
||||
|
||||
76
internal/db/models/api_method_stat_dao.go
Normal file
76
internal/db/models/api_method_stat_dao.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type APIMethodStatDAO dbs.DAO
|
||||
|
||||
func NewAPIMethodStatDAO() *APIMethodStatDAO {
|
||||
return dbs.NewDAO(&APIMethodStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeAPIMethodStats",
|
||||
Model: new(APIMethodStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*APIMethodStatDAO)
|
||||
}
|
||||
|
||||
var SharedAPIMethodStatDAO *APIMethodStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedAPIMethodStatDAO = NewAPIMethodStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateStat 记录统计数据
|
||||
func (this *APIMethodStatDAO) CreateStat(tx *dbs.Tx, method string, tag string, costMs float64) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
return this.Query(tx).
|
||||
Param("costMs", costMs).
|
||||
InsertOrUpdateQuickly(map[string]interface{}{
|
||||
"apiNodeId": teaconst.NodeId,
|
||||
"method": method,
|
||||
"tag": tag,
|
||||
"costMs": costMs,
|
||||
"peekMs": costMs,
|
||||
"countCalls": 1,
|
||||
"day": day,
|
||||
}, map[string]interface{}{
|
||||
"costMs": dbs.SQL("(costMs*countCalls+:costMs)/(countCalls+1)"),
|
||||
"peekMs": dbs.SQL("IF(peekMs>:costMs, peekMs, :costMs)"),
|
||||
"countCalls": dbs.SQL("countCalls+1"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindAllStatsWithDay 查询当前统计
|
||||
func (this *APIMethodStatDAO) FindAllStatsWithDay(tx *dbs.Tx, day string) (result []*APIMethodStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("day", day).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllStatsWithDay 统计当天数量
|
||||
func (this *APIMethodStatDAO) CountAllStatsWithDay(tx *dbs.Tx, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("day", day).
|
||||
Count()
|
||||
}
|
||||
|
||||
// Clean 清理数据
|
||||
func (this *APIMethodStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
_, err := this.Query(tx).
|
||||
Param("day", day).
|
||||
Where("day<:day").
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
19
internal/db/models/api_method_stat_dao_test.go
Normal file
19
internal/db/models/api_method_stat_dao_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAPIMethodStatDAO_CreateStat(t *testing.T) {
|
||||
var dao = NewAPIMethodStatDAO()
|
||||
var tx *dbs.Tx
|
||||
|
||||
err := dao.CreateStat(tx, "/pb.Hello/World", "tag", 1.123)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
28
internal/db/models/api_method_stat_model.go
Normal file
28
internal/db/models/api_method_stat_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
// APIMethodStat API方法统计
|
||||
type APIMethodStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ApiNodeId uint32 `field:"apiNodeId"` // API节点ID
|
||||
Method string `field:"method"` // 方法
|
||||
Tag string `field:"tag"` // 标签方法
|
||||
CostMs float64 `field:"costMs"` // 耗时Ms
|
||||
PeekMs float64 `field:"peekMs"` // 峰值耗时
|
||||
CountCalls uint64 `field:"countCalls"` // 调用次数
|
||||
Day string `field:"day"` // 日期
|
||||
}
|
||||
|
||||
type APIMethodStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ApiNodeId interface{} // API节点ID
|
||||
Method interface{} // 方法
|
||||
Tag interface{} // 标签方法
|
||||
CostMs interface{} // 耗时Ms
|
||||
PeekMs interface{} // 峰值耗时
|
||||
CountCalls interface{} // 调用次数
|
||||
Day interface{} // 日期
|
||||
}
|
||||
|
||||
func NewAPIMethodStatOperator() *APIMethodStatOperator {
|
||||
return &APIMethodStatOperator{}
|
||||
}
|
||||
1
internal/db/models/api_method_stat_model_ext.go
Normal file
1
internal/db/models/api_method_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -3,6 +3,8 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -49,7 +51,10 @@ func (this *APINodeDAO) EnableAPINode(tx *dbs.Tx, id int64) error {
|
||||
Pk(id).
|
||||
Set("state", APINodeStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
}
|
||||
|
||||
// DisableAPINode 禁用条目
|
||||
@@ -58,11 +63,22 @@ func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
Pk(id).
|
||||
Set("state", APINodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, error) {
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64, cacheMap *utils.CacheMap) (*APINode, error) {
|
||||
var cacheKey = this.Table + ":FindEnabledAPINode:" + types.String(id)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*APINode), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", APINodeStateEnabled).
|
||||
@@ -70,6 +86,11 @@ func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, erro
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*APINode), err
|
||||
}
|
||||
|
||||
@@ -136,16 +157,33 @@ func (this *APINodeDAO) CreateAPINode(tx *dbs.Tx, name string, description strin
|
||||
return
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, types.Int64(op.Id))
|
||||
if err != nil {
|
||||
remotelogs.Error("API_NODE_DAO", err.Error())
|
||||
}
|
||||
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// UpdateAPINode 修改API节点
|
||||
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool) error {
|
||||
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool, isPrimary bool) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
|
||||
op := NewAPINodeOperator()
|
||||
// 取消别的Primary
|
||||
if isPrimary {
|
||||
err := this.Query(tx).
|
||||
Neq("id", nodeId).
|
||||
Attr("isPrimary", true).
|
||||
Set("isPrimary", false).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var op = NewAPINodeOperator()
|
||||
op.Id = nodeId
|
||||
op.Name = name
|
||||
op.Description = description
|
||||
@@ -178,8 +216,13 @@ func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, des
|
||||
op.AccessAddrs = "[]"
|
||||
}
|
||||
|
||||
op.IsPrimary = isPrimary
|
||||
|
||||
err := this.Save(tx, op)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, nodeId)
|
||||
}
|
||||
|
||||
// FindAllEnabledAPINodes 列出所有可用API节点
|
||||
@@ -281,23 +324,6 @@ func (this *APINodeDAO) UpdateAPINodeStatus(tx *dbs.Tx, apiNodeId int64, statusJ
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
|
||||
for {
|
||||
uniqueId := rands.HexString(32)
|
||||
ok, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
return uniqueId, nil
|
||||
}
|
||||
}
|
||||
|
||||
// CountAllLowerVersionNodes 计算所有节点中低于某个版本的节点数量
|
||||
func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
@@ -371,3 +397,114 @@ func (this *APINodeDAO) FindAllEnabledAPIAccessIPs(tx *dbs.Tx, cacheMap *utils.C
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CheckAPINodeIsPrimary 检查当前节点是否为Primary节点
|
||||
func (this *APINodeDAO) CheckAPINodeIsPrimary(tx *dbs.Tx) (bool, error) {
|
||||
config, err := configs.SharedAPIConfig()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
isPrimary, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("uniqueId", config.NodeId).
|
||||
Attr("isPrimary", true).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isPrimary {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 检查是否有别的Primary节点
|
||||
count, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("isPrimary", true).
|
||||
Count()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
err = this.ResetPrimaryAPINode(tx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// CheckAPINodeIsPrimaryWithoutErr 检查当前节点是否为Primary节点,并忽略错误
|
||||
func (this *APINodeDAO) CheckAPINodeIsPrimaryWithoutErr() bool {
|
||||
b, err := this.CheckAPINodeIsPrimary(nil)
|
||||
return b && err == nil
|
||||
}
|
||||
|
||||
// ResetPrimaryAPINode 重置Primary节点
|
||||
func (this *APINodeDAO) ResetPrimaryAPINode(tx *dbs.Tx) error {
|
||||
// 当前是否有Primary节点
|
||||
apiNode, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("isPrimary", true).
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apiNode == nil {
|
||||
// 选择一个作为Primary
|
||||
// TODO 将来需要考虑API节点离线的情况
|
||||
apiNodeId, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apiNodeId > 0 {
|
||||
err = this.Query(tx).
|
||||
Pk(apiNodeId).
|
||||
Set("isPrimary", true).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知变更
|
||||
func (this *APINodeDAO) NotifyUpdate(tx *dbs.Tx, apiNodeId int64) error {
|
||||
// suppress IDE warning
|
||||
_ = apiNodeId
|
||||
|
||||
err := this.ResetPrimaryAPINode(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
|
||||
for {
|
||||
uniqueId := rands.HexString(32)
|
||||
ok, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
return uniqueId, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,16 @@ func TestAPINodeDAO_FindAllEnabledAPIAccessIPs(t *testing.T) {
|
||||
t.Log(NewAPINodeDAO().FindAllEnabledAPIAccessIPs(nil, cacheMap))
|
||||
}
|
||||
|
||||
func TestAPINodeDAO_CheckAPINodeIsPrimary(t *testing.T) {
|
||||
var dao = NewAPINodeDAO()
|
||||
t.Log(dao.CheckAPINodeIsPrimary(nil))
|
||||
}
|
||||
|
||||
func TestAPINodeDAO_ResetPrimaryAPINode(t *testing.T) {
|
||||
var dao = NewAPINodeDAO()
|
||||
t.Log(dao.ResetPrimaryAPINode(nil))
|
||||
}
|
||||
|
||||
func BenchmarkAPINodeDAO_New(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
package models
|
||||
|
||||
// API节点
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// APINode API节点
|
||||
type APINode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
ClusterId uint32 `field:"clusterId"` // 专用集群ID
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Http string `field:"http"` // 监听的HTTP配置
|
||||
Https string `field:"https"` // 监听的HTTPS配置
|
||||
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
|
||||
RestHTTP string `field:"restHTTP"` // REST HTTP配置
|
||||
RestHTTPS string `field:"restHTTPS"` // REST HTTPS配置
|
||||
AccessAddrs string `field:"accessAddrs"` // 外部访问地址
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status string `field:"status"` // 运行状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
ClusterId uint32 `field:"clusterId"` // 专用集群ID
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Http dbs.JSON `field:"http"` // 监听的HTTP配置
|
||||
Https dbs.JSON `field:"https"` // 监听的HTTPS配置
|
||||
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
|
||||
RestHTTP dbs.JSON `field:"restHTTP"` // REST HTTP配置
|
||||
RestHTTPS dbs.JSON `field:"restHTTPS"` // REST HTTPS配置
|
||||
AccessAddrs dbs.JSON `field:"accessAddrs"` // 外部访问地址
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status dbs.JSON `field:"status"` // 运行状态
|
||||
IsPrimary bool `field:"isPrimary"` // 是否为主API节点
|
||||
}
|
||||
|
||||
type APINodeOperator struct {
|
||||
@@ -43,6 +46,7 @@ type APINodeOperator struct {
|
||||
AdminId interface{} // 管理员ID
|
||||
Weight interface{} // 权重
|
||||
Status interface{} // 运行状态
|
||||
IsPrimary interface{} // 是否为主API节点
|
||||
}
|
||||
|
||||
func NewAPINodeOperator() *APINodeOperator {
|
||||
|
||||
@@ -13,7 +13,7 @@ func (this *APINode) DecodeHTTP() (*serverconfigs.HTTPProtocolConfig, error) {
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.Http), config)
|
||||
err := json.Unmarshal(this.Http, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverc
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.Https), config)
|
||||
err := json.Unmarshal(this.Https, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (this *APINode) DecodeAccessAddrs() ([]*serverconfigs.NetworkAddressConfig,
|
||||
}
|
||||
|
||||
addrConfigs := []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal([]byte(this.AccessAddrs), &addrConfigs)
|
||||
err := json.Unmarshal(this.AccessAddrs, &addrConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func (this *APINode) DecodeRestHTTP() (*serverconfigs.HTTPProtocolConfig, error)
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.RestHTTP), config)
|
||||
err := json.Unmarshal(this.RestHTTP, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*ser
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.RestHTTPS), config)
|
||||
err := json.Unmarshal(this.RestHTTPS, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package authority
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package authority
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// AuthorityKey 企业版认证信息
|
||||
type AuthorityKey struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Value string `field:"value"` // Key值
|
||||
DayFrom string `field:"dayFrom"` // 开始日期
|
||||
DayTo string `field:"dayTo"` // 结束日期
|
||||
Hostname string `field:"hostname"` // Hostname
|
||||
MacAddresses string `field:"macAddresses"` // MAC地址
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
|
||||
Company string `field:"company"` // 公司组织
|
||||
Id uint32 `field:"id"` // ID
|
||||
Value string `field:"value"` // Key值
|
||||
DayFrom string `field:"dayFrom"` // 开始日期
|
||||
DayTo string `field:"dayTo"` // 结束日期
|
||||
Hostname string `field:"hostname"` // Hostname
|
||||
MacAddresses dbs.JSON `field:"macAddresses"` // MAC地址
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
|
||||
Company string `field:"company"` // 公司组织
|
||||
}
|
||||
|
||||
type AuthorityKeyOperator struct {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package authority
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// AuthorityNode 监控节点
|
||||
type AuthorityNode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status string `field:"status"` // 运行状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status dbs.JSON `field:"status"` // 运行状态
|
||||
}
|
||||
|
||||
type AuthorityNodeOperator struct {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package models
|
||||
|
||||
// 终端浏览器信息
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ClientBrowser 终端浏览器信息
|
||||
type ClientBrowser struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 浏览器名称
|
||||
Codes string `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 浏览器名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type ClientBrowserOperator struct {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package models
|
||||
|
||||
// 终端操作系统信息
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ClientSystem 终端操作系统信息
|
||||
type ClientSystem struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 系统名称
|
||||
Codes string `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` //
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 系统名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` //
|
||||
}
|
||||
|
||||
type ClientSystemOperator struct {
|
||||
|
||||
@@ -29,8 +29,7 @@ type httpAccessLogDefinition struct {
|
||||
}
|
||||
|
||||
// HTTP服务访问
|
||||
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
var httpAccessLogTableMapping = map[string]*httpAccessLogDefinition{} // tableName_crc(dsn) => true
|
||||
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
|
||||
// DNS服务访问
|
||||
var nsAccessLogDAOMapping = map[int64]*NSAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
@@ -57,6 +56,25 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func AllAccessLogDBs() []*dbs.DB {
|
||||
accessLogLocker.Lock()
|
||||
defer accessLogLocker.Unlock()
|
||||
|
||||
var result = []*dbs.DB{}
|
||||
for _, db := range accessLogDBMapping {
|
||||
result = append(result, db)
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
db, _ := dbs.Default()
|
||||
if db != nil {
|
||||
result = append(result, db)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 获取获取DAO
|
||||
func randomHTTPAccessLogDAO() (dao *HTTPAccessLogDAOWrapper) {
|
||||
accessLogLocker.RLock()
|
||||
@@ -86,36 +104,6 @@ func randomNSAccessLogDAO() (dao *NSAccessLogDAOWrapper) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查表格是否存在
|
||||
func findHTTPAccessLogTableName(db *dbs.DB, day string) (tableName string, hasRemoteAddr bool, hasDomain bool, ok bool, err error) {
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
||||
return
|
||||
}
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return "", false, false, false, err
|
||||
}
|
||||
|
||||
tableName = "edgeHTTPAccessLogs_" + day
|
||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
||||
|
||||
accessLogLocker.RLock()
|
||||
def, ok := httpAccessLogTableMapping[cacheKey]
|
||||
accessLogLocker.RUnlock()
|
||||
if ok {
|
||||
return tableName, def.HasRemoteAddr, def.HasDomain, true, nil
|
||||
}
|
||||
|
||||
def, err = findHTTPAccessLogTable(db, day, false)
|
||||
if err != nil {
|
||||
return tableName, false, false, false, err
|
||||
}
|
||||
|
||||
return tableName, def.HasRemoteAddr, def.HasDomain, def.Exists, nil
|
||||
}
|
||||
|
||||
func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool, err error) {
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
||||
@@ -145,75 +133,6 @@ func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool
|
||||
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
|
||||
}
|
||||
|
||||
// 根据日期获取表名
|
||||
func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tableName := "edgeHTTPAccessLogs_" + day
|
||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
||||
|
||||
if !force {
|
||||
accessLogLocker.RLock()
|
||||
definition, ok := httpAccessLogTableMapping[cacheKey]
|
||||
accessLogLocker.RUnlock()
|
||||
if ok {
|
||||
return definition, nil
|
||||
}
|
||||
}
|
||||
|
||||
tableNames, err := db.TableNames()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if utils.ContainsStringInsensitive(tableNames, tableName) {
|
||||
table, err := db.FindTable(tableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessLogLocker.Lock()
|
||||
var definition = &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: table.FindFieldWithName("remoteAddr") != nil,
|
||||
HasDomain: table.FindFieldWithName("domain") != nil,
|
||||
Exists: true,
|
||||
}
|
||||
httpAccessLogTableMapping[cacheKey] = definition
|
||||
accessLogLocker.Unlock()
|
||||
return definition, nil
|
||||
}
|
||||
|
||||
if !force {
|
||||
return &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 创建表格
|
||||
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessLogLocker.Lock()
|
||||
var definition = &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
Exists: true,
|
||||
}
|
||||
httpAccessLogTableMapping[cacheKey] = definition
|
||||
accessLogLocker.Unlock()
|
||||
|
||||
return definition, nil
|
||||
}
|
||||
|
||||
func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
@@ -337,7 +256,7 @@ func (this *DBNodeInitializer) loop() error {
|
||||
}
|
||||
|
||||
if db == nil {
|
||||
config := &dbs.DBConfig{
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: dsn,
|
||||
Prefix: "edge",
|
||||
@@ -351,22 +270,17 @@ func (this *DBNodeInitializer) loop() error {
|
||||
// 检查表是否存在
|
||||
// httpAccessLog
|
||||
{
|
||||
tableDef, err := findHTTPAccessLogTable(db, timeutil.Format("Ymd"), true)
|
||||
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(db, timeutil.Format("Ymd"), true)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "1050") { // 非表格已存在错误
|
||||
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
||||
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
||||
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
|
||||
if createLogErr != nil {
|
||||
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
err = nil
|
||||
continue
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
|
||||
if createLogErr != nil {
|
||||
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
daoObject := dbs.DAOObject{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDBNodeInitializer_loop(t *testing.T) {
|
||||
@@ -14,32 +12,3 @@ func TestDBNodeInitializer_loop(t *testing.T) {
|
||||
}
|
||||
t.Log(len(accessLogDBMapping), len(httpAccessLogDAOMapping))
|
||||
}
|
||||
|
||||
func TestFindAccessLogTable(t *testing.T) {
|
||||
before := time.Now()
|
||||
db := SharedHTTPAccessLogDAO.Instance
|
||||
tableName, err := findHTTPAccessLogTable(db, "20201010", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(tableName)
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
|
||||
before = time.Now()
|
||||
tableName, err = findHTTPAccessLogTable(db, "20201010", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(tableName)
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
|
||||
func BenchmarkFindAccessLogTable(b *testing.B) {
|
||||
db := SharedHTTPAccessLogDAO.Instance
|
||||
|
||||
runtime.GOMAXPROCS(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = findHTTPAccessLogTable(db, "20201010", false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package models
|
||||
|
||||
// 数据库节点
|
||||
// DBNode 数据库节点
|
||||
type DBNode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Role string `field:"role"` // 数据库角色
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package dns
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// DNSDomain 管理的域名
|
||||
type DNSDomain struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ProviderId uint32 `field:"providerId"` // 服务商ID
|
||||
IsOn uint8 `field:"isOn"` // 是否可用
|
||||
Name string `field:"name"` // 域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
|
||||
DataError string `field:"dataError"` // 数据更新错误
|
||||
Data string `field:"data"` // 原始数据信息
|
||||
Records string `field:"records"` // 所有解析记录
|
||||
Routes string `field:"routes"` // 线路数据
|
||||
IsUp uint8 `field:"isUp"` // 是否在线
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsDeleted uint8 `field:"isDeleted"` // 是否已删除
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ProviderId uint32 `field:"providerId"` // 服务商ID
|
||||
IsOn bool `field:"isOn"` // 是否可用
|
||||
Name string `field:"name"` // 域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
|
||||
DataError string `field:"dataError"` // 数据更新错误
|
||||
Data string `field:"data"` // 原始数据信息
|
||||
Records dbs.JSON `field:"records"` // 所有解析记录
|
||||
Routes dbs.JSON `field:"routes"` // 线路数据
|
||||
IsUp bool `field:"isUp"` // 是否在线
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsDeleted bool `field:"isDeleted"` // 是否已删除
|
||||
}
|
||||
|
||||
type DNSDomainOperator struct {
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
|
||||
// DecodeRoutes 获取所有的线路
|
||||
func (this *DNSDomain) DecodeRoutes() ([]*dnstypes.Route, error) {
|
||||
if len(this.Routes) == 0 || this.Routes == "null" {
|
||||
if len(this.Routes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
result := []*dnstypes.Route{}
|
||||
err := json.Unmarshal([]byte(this.Routes), &result)
|
||||
err := json.Unmarshal(this.Routes, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,11 +35,11 @@ func (this *DNSDomain) ContainsRouteCode(route string) (bool, error) {
|
||||
// DecodeRecords 获取所有的记录
|
||||
func (this *DNSDomain) DecodeRecords() ([]*dnstypes.Record, error) {
|
||||
records := this.Records
|
||||
if len(records) == 0 || records == "null" {
|
||||
if len(records) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
result := []*dnstypes.Record{}
|
||||
err := json.Unmarshal([]byte(records), &result)
|
||||
err := json.Unmarshal(records, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -107,22 +107,32 @@ func (this *DNSProviderDAO) UpdateDNSProvider(tx *dbs.Tx, dnsProviderId int64, n
|
||||
}
|
||||
|
||||
// CountAllEnabledDNSProviders 计算服务商数量
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string) (int64, error) {
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string) (int64, error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
|
||||
if len(domain) > 0 {
|
||||
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
|
||||
return query.State(DNSProviderStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledDNSProviders 列出单页服务商
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(domain) > 0 {
|
||||
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
_, err = query.
|
||||
State(DNSProviderStateEnabled).
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package dns
|
||||
|
||||
// DNS服务商
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// DNSProvider DNS服务商
|
||||
type DNSProvider struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 名称
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 供应商类型
|
||||
ApiParams string `field:"apiParams"` // API参数
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 名称
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 供应商类型
|
||||
ApiParams dbs.JSON `field:"apiParams"` // API参数
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
|
||||
}
|
||||
|
||||
type DNSProviderOperator struct {
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 获取API参数
|
||||
// DecodeAPIParams 获取API参数
|
||||
func (this *DNSProvider) DecodeAPIParams() (maps.Map, error) {
|
||||
if len(this.ApiParams) == 0 || this.ApiParams == "null" {
|
||||
if len(this.ApiParams) == 0 {
|
||||
return maps.Map{}, nil
|
||||
}
|
||||
result := maps.Map{}
|
||||
err := json.Unmarshal([]byte(this.ApiParams), &result)
|
||||
err := json.Unmarshal(this.ApiParams, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
type DNSTaskType = string
|
||||
|
||||
const (
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
|
||||
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
|
||||
DNSTaskTypeServerChange DNSTaskType = "serverChange"
|
||||
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
|
||||
DNSTaskTypeClusterRemoveDomain DNSTaskType = "clusterRemoveDomain" // 从集群中移除域名
|
||||
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
|
||||
DNSTaskTypeServerChange DNSTaskType = "serverChange"
|
||||
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
|
||||
)
|
||||
|
||||
type DNSTaskDAO dbs.DAO
|
||||
@@ -40,20 +41,21 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateDNSTask 生成任务
|
||||
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, taskType string) error {
|
||||
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, recordName string, taskType string) error {
|
||||
if clusterId <= 0 && serverId <= 0 && nodeId <= 0 && domainId <= 0 {
|
||||
return nil
|
||||
}
|
||||
err := this.Query(tx).InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
"serverId": serverId,
|
||||
"nodeId": nodeId,
|
||||
"domainId": domainId,
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"type": taskType,
|
||||
"isDone": false,
|
||||
"isOk": false,
|
||||
"error": "",
|
||||
"clusterId": clusterId,
|
||||
"serverId": serverId,
|
||||
"nodeId": nodeId,
|
||||
"domainId": domainId,
|
||||
"recordName": recordName,
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"type": taskType,
|
||||
"isDone": false,
|
||||
"isOk": false,
|
||||
"error": "",
|
||||
}, maps.Map{
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"isDone": false,
|
||||
@@ -63,24 +65,29 @@ func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int6
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateClusterTask 生成集群任务
|
||||
// CreateClusterTask 生成集群变更任务
|
||||
func (this *DNSTaskDAO) CreateClusterTask(tx *dbs.Tx, clusterId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, taskType)
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateClusterRemoveTask 生成集群删除域名任务
|
||||
func (this *DNSTaskDAO) CreateClusterRemoveTask(tx *dbs.Tx, clusterId int64, domainId int64, recordName string) error {
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, domainId, recordName, DNSTaskTypeClusterRemoveDomain)
|
||||
}
|
||||
|
||||
// CreateNodeTask 生成节点任务
|
||||
func (this *DNSTaskDAO) CreateNodeTask(tx *dbs.Tx, nodeId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, taskType)
|
||||
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateServerTask 生成服务任务
|
||||
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, serverId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, serverId, 0, 0, taskType)
|
||||
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, clusterId int64, serverId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, clusterId, serverId, 0, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateDomainTask 生成域名更新任务
|
||||
func (this *DNSTaskDAO) CreateDomainTask(tx *dbs.Tx, domainId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, 0, 0, domainId, taskType)
|
||||
return this.CreateDNSTask(tx, 0, 0, 0, domainId, "", taskType)
|
||||
}
|
||||
|
||||
// FindAllDoingTasks 查找所有正在执行的任务
|
||||
@@ -101,6 +108,7 @@ func (this *DNSTaskDAO) FindAllDoingOrErrorTasks(tx *dbs.Tx, nodeClusterId int64
|
||||
}
|
||||
_, err = query.
|
||||
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
|
||||
Asc("updatedAt").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
package dns
|
||||
|
||||
// DNS更新任务
|
||||
// DNSTask DNS更新任务
|
||||
type DNSTask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
DomainId uint32 `field:"domainId"` // 域名ID
|
||||
Type string `field:"type"` // 任务类型
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
|
||||
IsDone uint8 `field:"isDone"` // 是否已完成
|
||||
IsOk uint8 `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
DomainId uint32 `field:"domainId"` // 域名ID
|
||||
RecordName string `field:"recordName"` // 记录名
|
||||
Type string `field:"type"` // 任务类型
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
IsOk bool `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
}
|
||||
|
||||
type DNSTaskOperator struct {
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
ServerId interface{} // 服务ID
|
||||
NodeId interface{} // 节点ID
|
||||
DomainId interface{} // 域名ID
|
||||
Type interface{} // 任务类型
|
||||
UpdatedAt interface{} // 更新时间
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否成功
|
||||
Error interface{} // 错误信息
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
ServerId interface{} // 服务ID
|
||||
NodeId interface{} // 节点ID
|
||||
DomainId interface{} // 域名ID
|
||||
RecordName interface{} // 记录名
|
||||
Type interface{} // 任务类型
|
||||
UpdatedAt interface{} // 更新时间
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否成功
|
||||
Error interface{} // 错误信息
|
||||
}
|
||||
|
||||
func NewDNSTaskOperator() *DNSTaskOperator {
|
||||
|
||||
@@ -153,7 +153,7 @@ func CheckClusterDNS(tx *dbs.Tx, cluster *models.NodeCluster) (issues []*pb.DNSI
|
||||
}
|
||||
|
||||
// 检查IP地址
|
||||
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, nodeconfigs.NodeRoleNode)
|
||||
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, true, nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package models
|
||||
type FileChunk struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
FileId uint32 `field:"fileId"` // 文件ID
|
||||
Data string `field:"data"` // 分块内容
|
||||
Data []byte `field:"data"` // 分块内容
|
||||
}
|
||||
|
||||
type FileChunkOperator struct {
|
||||
|
||||
@@ -12,8 +12,8 @@ type File struct {
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Type string `field:"type"` // 类型
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsFinished uint8 `field:"isFinished"` // 是否已完成上传
|
||||
IsPublic uint8 `field:"isPublic"` // 是否可以公开访问
|
||||
IsFinished bool `field:"isFinished"` // 是否已完成上传
|
||||
IsPublic bool `field:"isPublic"` // 是否可以公开访问
|
||||
}
|
||||
|
||||
type FileOperator struct {
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -34,13 +36,25 @@ type HTTPAccessLogDAO dbs.DAO
|
||||
var SharedHTTPAccessLogDAO *HTTPAccessLogDAO
|
||||
|
||||
// 队列
|
||||
var oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
||||
var accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
||||
var accessLogQueueMaxLength = 100_000
|
||||
var accessLogQueuePercent = 100 // 0-100
|
||||
var accessLogCountPerSecond = 10_000 // 0 表示不限制
|
||||
var accessLogConfigJSON = []byte{}
|
||||
var accessLogQueueChanged = make(chan zero.Zero, 1)
|
||||
var (
|
||||
oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
||||
accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
||||
accessLogQueueMaxLength = 100_000
|
||||
accessLogQueuePercent = 100 // 0-100
|
||||
accessLogCountPerSecond = 10_000 // 0 表示不限制
|
||||
accessLogConfigJSON = []byte{}
|
||||
accessLogQueueChanged = make(chan zero.Zero, 1)
|
||||
|
||||
accessLogEnableAutoPartial = true // 是否启用自动分表
|
||||
accessLogRowsPerTable int64 = 500_000 // 自动分表的单表最大值
|
||||
)
|
||||
|
||||
type accessLogTableQuery struct {
|
||||
daoWrapper *HTTPAccessLogDAOWrapper
|
||||
name string
|
||||
hasRemoteAddrField bool
|
||||
hasDomainField bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
@@ -120,7 +134,7 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.
|
||||
|
||||
// DumpAccessLogsFromQueue 从队列导入访问日志
|
||||
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
|
||||
dao := randomHTTPAccessLogDAO()
|
||||
var dao = randomHTTPAccessLogDAO()
|
||||
if dao == nil {
|
||||
dao = &HTTPAccessLogDAOWrapper{
|
||||
DAO: SharedHTTPAccessLogDAO,
|
||||
@@ -168,8 +182,8 @@ Loop:
|
||||
|
||||
// CreateHTTPAccessLog 写入单条访问日志
|
||||
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
|
||||
day := timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
|
||||
tableDef, err := findHTTPAccessLogTable(dao.Instance, day, false)
|
||||
var day = timeutil.FormatTime("Ymd", accessLog.Timestamp)
|
||||
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(dao.Instance, day, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -203,36 +217,46 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
|
||||
}
|
||||
fields["content"] = content
|
||||
|
||||
_, err = dao.Query(tx).
|
||||
var lastId int64
|
||||
lastId, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
// 是否为 Error 1146: Table 'xxx.xxx' doesn't exist 如果是,则创建表之后重试
|
||||
if strings.Contains(err.Error(), "1146") {
|
||||
tableDef, err = findHTTPAccessLogTable(dao.Instance, day, true)
|
||||
// 错误重试
|
||||
if CheckSQLErrCode(err, 1146) { // Error 1146: Table 'xxx' doesn't exist
|
||||
err = SharedHTTPAccessLogManager.CreateTable(dao.Instance, tableDef.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dao.Query(tx).
|
||||
|
||||
// 重新尝试
|
||||
lastId, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG", err.Error())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId >= accessLogRowsPerTable {
|
||||
SharedHTTPAccessLogManager.ResetTable(dao.Instance, day)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListAccessLogs 读取往前的 单页访问日志
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx,
|
||||
partition int32,
|
||||
lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
hourFrom string,
|
||||
hourTo string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
@@ -255,23 +279,42 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size = 1000
|
||||
}
|
||||
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, partition, lastRequestId, size, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
if err != nil || int64(len(result)) < size {
|
||||
return
|
||||
}
|
||||
|
||||
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
moreResult, _, _ := this.listAccessLogs(tx, partition, nextLastRequestId, 1, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
hasMore = len(moreResult) > 0
|
||||
return
|
||||
}
|
||||
|
||||
// 读取往前的单页访问日志
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, size int64, day string, clusterId int64, nodeId int64, serverId int64, reverse bool, hasError bool, firewallPolicyId int64, firewallRuleGroupId int64, firewallRuleSetId int64, hasFirewallPolicy bool, userId int64, keyword string, ip string, domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
partition int32,
|
||||
lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
hourFrom string,
|
||||
hourTo string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
reverse bool,
|
||||
hasError bool,
|
||||
firewallPolicyId int64,
|
||||
firewallRuleGroupId int64,
|
||||
firewallRuleSetId int64,
|
||||
hasFirewallPolicy bool,
|
||||
userId int64,
|
||||
keyword string,
|
||||
ip string,
|
||||
domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
if size <= 0 {
|
||||
return nil, lastRequestId, nil
|
||||
}
|
||||
|
||||
serverIds := []int64{}
|
||||
var serverIds = []int64{}
|
||||
if userId > 0 {
|
||||
serverIds, err = SharedServerDAO.FindAllEnabledServerIdsWithUserId(tx, userId)
|
||||
if err != nil {
|
||||
@@ -283,7 +326,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
|
||||
accessLogLocker.RLock()
|
||||
daoList := []*HTTPAccessLogDAOWrapper{}
|
||||
var daoList = []*HTTPAccessLogDAOWrapper{}
|
||||
for _, daoWrapper := range httpAccessLogDAOMapping {
|
||||
daoList = append(daoList, daoWrapper)
|
||||
}
|
||||
@@ -296,42 +339,81 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}}
|
||||
}
|
||||
|
||||
locker := sync.Mutex{}
|
||||
// 查询某个集群下的节点
|
||||
var nodeIds = []int64{}
|
||||
if clusterId > 0 {
|
||||
nodeIds, err = SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
remotelogs.Error("DB_NODE", err.Error())
|
||||
return
|
||||
}
|
||||
sort.Slice(nodeIds, func(i, j int) bool {
|
||||
return nodeIds[i] < nodeIds[j]
|
||||
})
|
||||
}
|
||||
|
||||
count := len(daoList)
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
// 准备查询
|
||||
var tableQueries = []*accessLogTableQuery{}
|
||||
var maxTableName = ""
|
||||
for _, daoWrapper := range daoList {
|
||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
||||
var instance = daoWrapper.DAO.Instance
|
||||
def, err := SharedHTTPAccessLogManager.FindPartitionTable(instance, day, partition)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if !def.Exists {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(maxTableName) == 0 || def.Name > maxTableName {
|
||||
maxTableName = def.Name
|
||||
}
|
||||
|
||||
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||
daoWrapper: daoWrapper,
|
||||
name: def.Name,
|
||||
hasRemoteAddrField: def.HasRemoteAddr,
|
||||
hasDomainField: def.HasDomain,
|
||||
})
|
||||
}
|
||||
|
||||
// 检查各个分表是否一致
|
||||
if partition < 0 {
|
||||
var newTableQueries = []*accessLogTableQuery{}
|
||||
for _, tableQuery := range tableQueries {
|
||||
if tableQuery.name != maxTableName {
|
||||
continue
|
||||
}
|
||||
newTableQueries = append(newTableQueries, tableQuery)
|
||||
}
|
||||
tableQueries = newTableQueries
|
||||
}
|
||||
|
||||
if len(tableQueries) == 0 {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
|
||||
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
|
||||
var urlReg = regexp.MustCompile(`^(http|https)://`)
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
for _, tableQuery := range tableQueries {
|
||||
go func(tableQuery *accessLogTableQuery, keyword string) {
|
||||
defer wg.Done()
|
||||
|
||||
dao := daoWrapper.DAO
|
||||
|
||||
tableName, hasRemoteAddrField, hasDomainField, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
// 表格不存在则跳过
|
||||
return
|
||||
}
|
||||
|
||||
query := dao.Query(tx)
|
||||
var dao = tableQuery.daoWrapper.DAO
|
||||
var query = dao.Query(tx)
|
||||
|
||||
// 条件
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else if clusterId > 0 {
|
||||
nodeIds, err := SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
remotelogs.Error("DBNODE", err.Error())
|
||||
return
|
||||
}
|
||||
if len(nodeIds) > 0 {
|
||||
sort.Slice(nodeIds, func(i, j int) bool {
|
||||
return nodeIds[i] < nodeIds[j]
|
||||
})
|
||||
var nodeIdStrings = []string{}
|
||||
for _, subNodeId := range nodeIds {
|
||||
nodeIdStrings = append(nodeIdStrings, types.String(subNodeId))
|
||||
@@ -370,7 +452,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
// keyword
|
||||
if len(ip) > 0 {
|
||||
// TODO 支持IP范围
|
||||
if hasRemoteAddrField {
|
||||
if tableQuery.hasRemoteAddrField {
|
||||
// IP格式
|
||||
if strings.Contains(ip, ",") || strings.Contains(ip, "-") {
|
||||
rangeConfig, err := shared.ParseIPRange(ip)
|
||||
@@ -380,6 +462,9 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 去掉IPv6的[]
|
||||
ip = strings.Trim(ip, "[]")
|
||||
|
||||
query.Attr("remoteAddr", ip)
|
||||
query.UseIndex("remoteAddr")
|
||||
}
|
||||
@@ -389,7 +474,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
}
|
||||
if len(domain) > 0 {
|
||||
if hasDomainField {
|
||||
if tableQuery.hasDomainField {
|
||||
if strings.Contains(domain, "*") {
|
||||
domain = strings.ReplaceAll(domain, "*", "%")
|
||||
domain = regexp.MustCompile(`[^a-zA-Z0-9-.%]`).ReplaceAllString(domain, "")
|
||||
@@ -404,24 +489,48 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
Param("host1", domain)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keyword) > 0 {
|
||||
// remoteAddr
|
||||
if hasRemoteAddrField && net.ParseIP(keyword) != nil {
|
||||
var isSpecialKeyword = false
|
||||
|
||||
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil { // ip
|
||||
isSpecialKeyword = true
|
||||
query.Attr("remoteAddr", keyword)
|
||||
} else if hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) { // ip:x.x.x.x
|
||||
isSpecialKeyword = true
|
||||
keyword = keyword[3:]
|
||||
pieces := strings.SplitN(keyword, ",", 2)
|
||||
if len(pieces) == 1 || len(pieces[1]) == 0 {
|
||||
if len(pieces) == 1 || len(pieces[1]) == 0 || pieces[0] == pieces[1] {
|
||||
query.Attr("remoteAddr", pieces[0])
|
||||
} else {
|
||||
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
|
||||
}
|
||||
} else {
|
||||
} else if statusRangeReg.MatchString(keyword) { // status:200-400
|
||||
isSpecialKeyword = true
|
||||
var matches = statusRangeReg.FindStringSubmatch(keyword)
|
||||
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
|
||||
|
||||
// TODO 处理剩余的关键词
|
||||
} else if statusPrefixReg.MatchString(keyword) { // status:200
|
||||
isSpecialKeyword = true
|
||||
var matches = statusPrefixReg.FindStringSubmatch(keyword)
|
||||
query.Attr("status", matches[1])
|
||||
// TODO 处理剩余的关键词
|
||||
} else if urlReg.MatchString(keyword) { // https://xxx/yyy
|
||||
u, err := url.Parse(keyword)
|
||||
if err == nil {
|
||||
isSpecialKeyword = true
|
||||
query.Attr("domain", u.Host)
|
||||
query.Where("JSON_EXTRACT(content, '$.requestURI') LIKE :keyword").
|
||||
Param("keyword", dbutils.QuoteLikePrefix("\""+u.RequestURI()))
|
||||
}
|
||||
}
|
||||
if !isSpecialKeyword {
|
||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
keyword = keyword[3:]
|
||||
}
|
||||
|
||||
useOriginKeyword := false
|
||||
var useOriginKeyword = false
|
||||
|
||||
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword OR JSON_EXTRACT(content, '$.userAgent') LIKE :keyword"
|
||||
|
||||
@@ -447,13 +556,13 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
|
||||
// 响应状态码
|
||||
if regexp.MustCompile(`^\d{3}$`).MatchString(keyword) {
|
||||
where += " OR JSON_EXTRACT(content, '$.status')=:intKeyword"
|
||||
where += " OR status=:intKeyword"
|
||||
query.Param("intKeyword", types.Int(keyword))
|
||||
}
|
||||
|
||||
if regexp.MustCompile(`^\d{3}-\d{3}$`).MatchString(keyword) {
|
||||
pieces := strings.Split(keyword, "-")
|
||||
where += " OR JSON_EXTRACT(content, '$.status') BETWEEN :intKeyword1 AND :intKeyword2"
|
||||
where += " OR status BETWEEN :intKeyword1 AND :intKeyword2"
|
||||
query.Param("intKeyword1", types.Int(pieces[0]))
|
||||
query.Param("intKeyword2", types.Int(pieces[1]))
|
||||
}
|
||||
@@ -464,13 +573,27 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
|
||||
query.Where("("+where+")").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
if useOriginKeyword {
|
||||
query.Param("originKeyword", keyword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hourFrom - hourTo
|
||||
if len(hourFrom) > 0 && len(hourTo) > 0 {
|
||||
var hourFromInt = types.Int(hourFrom)
|
||||
var hourToInt = types.Int(hourTo)
|
||||
if hourFromInt >= 0 && hourFromInt <= 23 && hourToInt >= hourFromInt && hourToInt <= 23 {
|
||||
var y = types.Int(day[:4])
|
||||
var m = types.Int(day[4:6])
|
||||
var d = types.Int(day[6:])
|
||||
var timeFrom = time.Date(y, time.Month(m), d, hourFromInt, 0, 0, 0, time.Local)
|
||||
var timeTo = time.Date(y, time.Month(m), d, hourToInt, 59, 59, 0, time.Local)
|
||||
query.Between("createdAt", timeFrom.Unix(), timeTo.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
// offset
|
||||
if len(lastRequestId) > 0 {
|
||||
if !reverse {
|
||||
@@ -490,20 +613,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
|
||||
// 开始查询
|
||||
ones, err := query.
|
||||
Table(tableName).
|
||||
Table(tableQuery.name).
|
||||
Limit(size).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
remotelogs.Println("DB_NODE", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
locker.Lock()
|
||||
for _, one := range ones {
|
||||
accessLog := one.(*HTTPAccessLog)
|
||||
var accessLog = one.(*HTTPAccessLog)
|
||||
result = append(result, accessLog)
|
||||
}
|
||||
locker.Unlock()
|
||||
}(daoWrapper)
|
||||
}(tableQuery, keyword)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@@ -524,7 +648,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
result = result[:size]
|
||||
}
|
||||
|
||||
requestId := result[len(result)-1].RequestId
|
||||
var requestId = result[len(result)-1].RequestId
|
||||
if reverse {
|
||||
lists.Reverse(result)
|
||||
}
|
||||
@@ -556,28 +680,36 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
||||
}}
|
||||
}
|
||||
|
||||
count := len(daoList)
|
||||
wg := &sync.WaitGroup{}
|
||||
// 准备查询
|
||||
var day = timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
||||
var tableQueries = []*accessLogTableQuery{}
|
||||
for _, daoWrapper := range daoList {
|
||||
var instance = daoWrapper.DAO.Instance
|
||||
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, def := range tableDefs {
|
||||
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||
daoWrapper: daoWrapper,
|
||||
name: def.Name,
|
||||
hasRemoteAddrField: def.HasRemoteAddr,
|
||||
hasDomainField: def.HasDomain,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
var result *HTTPAccessLog = nil
|
||||
day := timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
||||
for _, daoWrapper := range daoList {
|
||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
||||
for _, tableQuery := range tableQueries {
|
||||
go func(tableQuery *accessLogTableQuery) {
|
||||
defer wg.Done()
|
||||
|
||||
dao := daoWrapper.DAO
|
||||
|
||||
tableName, _, _, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
|
||||
var dao = tableQuery.daoWrapper.DAO
|
||||
one, err := dao.Query(tx).
|
||||
Table(tableName).
|
||||
Table(tableQuery.name).
|
||||
Attr("requestId", requestId).
|
||||
Find()
|
||||
if err != nil {
|
||||
@@ -587,7 +719,7 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
||||
if one != nil {
|
||||
result = one.(*HTTPAccessLog)
|
||||
}
|
||||
}(daoWrapper)
|
||||
}(tableQuery)
|
||||
}
|
||||
wg.Wait()
|
||||
return result, nil
|
||||
@@ -623,11 +755,18 @@ func (this *HTTPAccessLogDAO) SetupQueue() {
|
||||
config.MaxLength = 100_000
|
||||
}
|
||||
|
||||
accessLogEnableAutoPartial = config.EnableAutoPartial
|
||||
if config.RowsPerTable > 0 {
|
||||
accessLogRowsPerTable = config.RowsPerTable
|
||||
}
|
||||
|
||||
if accessLogQueueMaxLength != config.MaxLength {
|
||||
accessLogQueueMaxLength = config.MaxLength
|
||||
oldAccessLogQueue = accessLogQueue
|
||||
accessLogQueue = make(chan *pb.HTTPAccessLog, config.MaxLength)
|
||||
}
|
||||
|
||||
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue max length: "+types.String(config.MaxLength)+", percent: "+types.String(config.Percent)+", countPerSecond: "+types.String(config.CountPerSecond))
|
||||
if Tea.IsTesting() {
|
||||
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue "+string(configJSON))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
@@ -53,7 +54,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "", 10, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -111,7 +112,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -136,7 +137,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -157,3 +158,13 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHTTPAccessLogDAO_JSONEncode(b *testing.B) {
|
||||
var accessLog = &pb.HTTPAccessLog{
|
||||
RequestPath: "/hello/world",
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = json.Marshal(accessLog)
|
||||
}
|
||||
}
|
||||
|
||||
439
internal/db/models/http_access_log_manager.go
Normal file
439
internal/db/models/http_access_log_manager.go
Normal file
@@ -0,0 +1,439 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 访问日志的两个表格形式
|
||||
// 括号位置需要固定,会用来读取日期和分区
|
||||
var accessLogTableMainReg = regexp.MustCompile(`_(\d{8})$`)
|
||||
var accessLogTablePartialReg = regexp.MustCompile(`_(\d{8})_(\d{4})$`)
|
||||
|
||||
var SharedHTTPAccessLogManager = NewHTTPAccessLogManager()
|
||||
|
||||
type HTTPAccessLogManager struct {
|
||||
currentTableMapping map[string]*httpAccessLogDefinition // dsn => def
|
||||
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogManager() *HTTPAccessLogManager {
|
||||
return &HTTPAccessLogManager{
|
||||
currentTableMapping: map[string]*httpAccessLogDefinition{},
|
||||
}
|
||||
}
|
||||
|
||||
// FindTableNames 读取数据库中某日所有日志表名称
|
||||
func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]string, error) {
|
||||
var results = []string{}
|
||||
|
||||
// 需要防止用户设置了表名自动小写
|
||||
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||
if err != nil {
|
||||
return nil, errors.New("query table names error: " + err.Error())
|
||||
}
|
||||
|
||||
var columnName = columnNames[0]
|
||||
|
||||
for _, one := range ones {
|
||||
var tableName = one[columnName].(string)
|
||||
|
||||
if lists.ContainsString(results, tableName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if accessLogTableMainReg.MatchString(tableName) || accessLogTablePartialReg.MatchString(tableName) {
|
||||
results = append(results, tableName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 排序
|
||||
// 这里不能直接使用sort.Strings(),因为表名里面可能大小写混合
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
var name1 = results[i]
|
||||
var name2 = results[j]
|
||||
if len(name1) < len(name2) {
|
||||
return true
|
||||
}
|
||||
return strings.ToLower(name1) < strings.ToLower(name2)
|
||||
})
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// FindTables 读取数据库中某日所有日志表
|
||||
func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAccessLogDefinition, error) {
|
||||
var results = []*httpAccessLogDefinition{}
|
||||
var tableNames = []string{}
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cachePrefix = config.Dsn
|
||||
|
||||
// 需要防止用户设置了表名自动小写
|
||||
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||
if err != nil {
|
||||
return nil, errors.New("query table names error: " + err.Error())
|
||||
}
|
||||
|
||||
var columnName = columnNames[0]
|
||||
|
||||
for _, one := range ones {
|
||||
var tableName = one[columnName].(string)
|
||||
|
||||
if lists.ContainsString(tableNames, tableName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if accessLogTableMainReg.MatchString(tableName) {
|
||||
tableNames = append(tableNames, tableName)
|
||||
|
||||
// 查找已有的表格信息,避免SHOW FIELDS
|
||||
var tableDay = tableName[strings.LastIndex(tableName, "_")+1:]
|
||||
var cacheKey = this.composeTableCacheKey(cachePrefix, tableDay)
|
||||
this.locker.Lock()
|
||||
currentTableDef, ok := this.currentTableMapping[cacheKey]
|
||||
this.locker.Unlock()
|
||||
if ok {
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: currentTableDef.HasRemoteAddr,
|
||||
HasDomain: currentTableDef.HasDomain,
|
||||
Exists: true,
|
||||
})
|
||||
} else {
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
})
|
||||
}
|
||||
} else if accessLogTablePartialReg.MatchString(tableName) {
|
||||
tableNames = append(tableNames, tableName)
|
||||
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 排序
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (this *HTTPAccessLogManager) FindPartitionTable(db *dbs.DB, day string, partition int32) (*httpAccessLogDefinition, error) {
|
||||
var tableNames []string
|
||||
if partition < 0 {
|
||||
tableList, err := this.FindTables(db, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(tableList) > 0 {
|
||||
return tableList[len(tableList)-1], nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: "",
|
||||
HasRemoteAddr: false,
|
||||
HasDomain: false,
|
||||
Exists: false,
|
||||
}, nil
|
||||
} else if partition == 0 {
|
||||
tableNames = []string{"edgeHTTPAccessLogs_" + day, "edgehttpaccesslogs_" + day}
|
||||
} else {
|
||||
tableNames = []string{"edgeHTTPAccessLogs_" + day + "_" + fmt.Sprintf("%04d", partition), "edgehttpaccesslogs_" + day + "_" + fmt.Sprintf("%04d", partition)}
|
||||
}
|
||||
for _, tableName := range tableNames {
|
||||
hasRemoteField, hasDomainField, err := this.checkTableFields(db, tableName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: hasRemoteField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: "",
|
||||
HasRemoteAddr: false,
|
||||
HasDomain: false,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindLastTable 根据日期获取上一个可以使用的表名
|
||||
// 表名组成
|
||||
// - PREFIX_DAY
|
||||
// - PREFIX_DAY_0001
|
||||
func (this *HTTPAccessLogManager) FindLastTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cachePrefix = config.Dsn
|
||||
var cacheKey = this.composeTableCacheKey(cachePrefix, day)
|
||||
def, ok := this.currentTableMapping[cacheKey]
|
||||
if ok {
|
||||
return def, nil
|
||||
}
|
||||
|
||||
def, err = this.findTableWithoutCache(db, day, force)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 只有存在的表格才缓存
|
||||
if def != nil && def.Exists {
|
||||
this.currentTableMapping[cacheKey] = def
|
||||
|
||||
// 清除过时缓存
|
||||
for oldCacheKey := range this.currentTableMapping {
|
||||
var dayIndex = strings.LastIndex(oldCacheKey, "_")
|
||||
if dayIndex > 0 {
|
||||
var oldPrefix = oldCacheKey[:dayIndex]
|
||||
var oldDay = oldCacheKey[dayIndex+1:]
|
||||
if oldPrefix == cachePrefix && oldDay < day {
|
||||
delete(this.currentTableMapping, oldCacheKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return def, nil
|
||||
}
|
||||
|
||||
// CreateTable 创建访问日志表格
|
||||
func (this *HTTPAccessLogManager) CreateTable(db *dbs.DB, tableName string) error {
|
||||
_, err := db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
if err != nil {
|
||||
if CheckSQLErrCode(err, 1050) { // Error 1050: Table 'xxx' already exists
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetTable 清除某个数据库表名缓存
|
||||
func (this *HTTPAccessLogManager) ResetTable(db *dbs.DB, day string) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
delete(this.currentTableMapping, this.composeTableCacheKey(config.Dsn, day))
|
||||
}
|
||||
|
||||
// TablePartition 从表名中获取分区
|
||||
func (this *HTTPAccessLogManager) TablePartition(tableName string) (partition int32) {
|
||||
if accessLogTablePartialReg.MatchString(tableName) {
|
||||
return types.Int32(accessLogTablePartialReg.FindStringSubmatch(tableName)[2])
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// FindLatestPartition 读取最后一个分区
|
||||
func (this *HTTPAccessLogManager) FindLatestPartition(day string) (int32, error) {
|
||||
var dbList = AllAccessLogDBs()
|
||||
if len(dbList) == 0 {
|
||||
return 0, errors.New("no valid database")
|
||||
}
|
||||
|
||||
var partitions = []int32{}
|
||||
var locker sync.Mutex
|
||||
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(dbList))
|
||||
|
||||
var lastErr error
|
||||
for _, db := range dbList {
|
||||
go func(db *dbs.DB) {
|
||||
defer wg.Done()
|
||||
|
||||
names, err := this.FindTableNames(db, day)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
for _, name := range names {
|
||||
var partition = this.TablePartition(name)
|
||||
locker.Lock()
|
||||
if !lists.Contains(partitions, partition) {
|
||||
partitions = append(partitions, partition)
|
||||
}
|
||||
locker.Unlock()
|
||||
}
|
||||
}(db)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if lastErr != nil {
|
||||
return 0, lastErr
|
||||
}
|
||||
|
||||
if len(partitions) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return partitions[len(partitions)-1], nil
|
||||
}
|
||||
|
||||
// 查找某个表格
|
||||
func (this *HTTPAccessLogManager) findTableWithoutCache(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
tableNames, err := this.FindTableNames(db, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var prefix = "edgeHTTPAccessLogs_" + day
|
||||
|
||||
if len(tableNames) == 0 {
|
||||
if force {
|
||||
err := this.CreateTable(db, prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: prefix,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: prefix,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var lastTableName = tableNames[len(tableNames)-1]
|
||||
if !force || !accessLogEnableAutoPartial || accessLogRowsPerTable <= 0 {
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: lastTableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 检查是否生成下个分表
|
||||
lastId, err := db.FindCol(0, "SELECT id FROM "+lastTableName+" ORDER BY id DESC LIMIT 1")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if lastId != nil {
|
||||
var lastInt64Id = types.Int64(lastId)
|
||||
if accessLogRowsPerTable > 0 && lastInt64Id >= accessLogRowsPerTable {
|
||||
// create next partial table
|
||||
var nextTableName = ""
|
||||
if accessLogTableMainReg.MatchString(lastTableName) {
|
||||
nextTableName = prefix + "_0001"
|
||||
} else if accessLogTablePartialReg.MatchString(lastTableName) {
|
||||
var matches = accessLogTablePartialReg.FindStringSubmatch(lastTableName)
|
||||
if len(matches) < 3 {
|
||||
return nil, errors.New("fatal error: invalid 'accessLogTablePartialReg'")
|
||||
}
|
||||
var lastPartial = matches[2]
|
||||
nextTableName = prefix + "_" + fmt.Sprintf("%04d", types.Int(lastPartial)+1)
|
||||
} else {
|
||||
nextTableName = prefix + "_0001"
|
||||
}
|
||||
|
||||
err = this.CreateTable(db, nextTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: nextTableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 检查字段
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: lastTableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO 考虑缓存检查结果
|
||||
func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string) (hasRemoteAddrField bool, hasDomainField bool, err error) {
|
||||
fields, _, err := db.FindPreparedOnes("SHOW FIELDS FROM " + tableName)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
for _, field := range fields {
|
||||
var fieldName = field.GetString("Field")
|
||||
if strings.ToLower(fieldName) == strings.ToLower("remoteAddr") {
|
||||
hasRemoteAddrField = true
|
||||
}
|
||||
if strings.ToLower(fieldName) == "domain" {
|
||||
hasDomainField = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 组合表格的缓存Key
|
||||
func (this *HTTPAccessLogManager) composeTableCacheKey(dsn string, day string) string {
|
||||
// 注意:格式一定要固定,下面清除缓存的时候需要用到
|
||||
return dsn + "_" + day
|
||||
}
|
||||
189
internal/db/models/http_access_log_manager_test.go
Normal file
189
internal/db/models/http_access_log_manager_test.go
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewHTTPAccessLogManager(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
var manager = models.SharedHTTPAccessLogManager
|
||||
err = manager.CreateTable(db, "accessLog_1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tables)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindTables(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tables)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindLastTable(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tableDef, err := models.SharedHTTPAccessLogManager.FindLastTable(db, "20220306", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tableDef)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindPartitionTable(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), -1))
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 0))
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 1))
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAccessLog 访问日志
|
||||
type HTTPAccessLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Status uint32 `field:"status"` // 状态码
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Content string `field:"content"` // 日志内容
|
||||
RequestId string `field:"requestId"` // 请求ID
|
||||
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
|
||||
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
|
||||
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
|
||||
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
|
||||
RemoteAddr string `field:"remoteAddr"` // IP地址
|
||||
Domain string `field:"domain"` // 域名
|
||||
RequestBody string `field:"requestBody"` // 请求内容
|
||||
ResponseBody string `field:"responseBody"` // 响应内容
|
||||
Id uint64 `field:"id"` // ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Status uint32 `field:"status"` // 状态码
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Content dbs.JSON `field:"content"` // 日志内容
|
||||
RequestId string `field:"requestId"` // 请求ID
|
||||
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
|
||||
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
|
||||
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
|
||||
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
|
||||
RemoteAddr string `field:"remoteAddr"` // IP地址
|
||||
Domain string `field:"domain"` // 域名
|
||||
RequestBody []byte `field:"requestBody"` // 请求内容
|
||||
ResponseBody []byte `field:"responseBody"` // 响应内容
|
||||
}
|
||||
|
||||
type HTTPAccessLogOperator struct {
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
// ToPB 转换成PB对象
|
||||
func (this *HTTPAccessLog) ToPB() (*pb.HTTPAccessLog, error) {
|
||||
p := &pb.HTTPAccessLog{}
|
||||
err := json.Unmarshal([]byte(this.Content), p)
|
||||
err := json.Unmarshal(this.Content, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.RequestId = this.RequestId
|
||||
p.RequestBody = []byte(this.RequestBody)
|
||||
p.RequestBody = this.RequestBody
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -109,7 +106,7 @@ func (this *HTTPAccessLogPolicyDAO) FindAllEnabledAndOnPolicies(tx *dbs.Tx) (res
|
||||
}
|
||||
|
||||
// CreatePolicy 创建策略
|
||||
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool) (policyId int64, err error) {
|
||||
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool) (policyId int64, err error) {
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Name = name
|
||||
op.Type = policyType
|
||||
@@ -121,12 +118,13 @@ func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policy
|
||||
}
|
||||
op.IsPublic = isPublic
|
||||
op.IsOn = true
|
||||
op.FirewallOnly = firewallOnly
|
||||
op.State = HTTPAccessLogPolicyStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdatePolicy 修改策略
|
||||
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, isOn bool) error {
|
||||
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool, isOn bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -140,7 +138,6 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
|
||||
if oldOne == nil {
|
||||
return nil
|
||||
}
|
||||
var oldPolicy = oldOne.(*HTTPAccessLogPolicy)
|
||||
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Id = policyId
|
||||
@@ -156,22 +153,11 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
|
||||
op.Conds = "{}"
|
||||
}
|
||||
|
||||
// 版本号
|
||||
if len(oldPolicy.Options) == 0 || len(optionsJSON) == 0 {
|
||||
op.Version = dbs.SQL("version+1")
|
||||
} else {
|
||||
var m1 = maps.Map{}
|
||||
_ = json.Unmarshal([]byte(oldPolicy.Options), &m1)
|
||||
|
||||
var m2 = maps.Map{}
|
||||
_ = json.Unmarshal(optionsJSON, &m2)
|
||||
|
||||
if bytes.Compare(m1.AsJSON(), m2.AsJSON()) != 0 {
|
||||
op.Version = dbs.SQL("version+1")
|
||||
}
|
||||
}
|
||||
// 版本号总是加1
|
||||
op.Version = dbs.SQL("version+1")
|
||||
|
||||
op.IsPublic = isPublic
|
||||
op.FirewallOnly = firewallOnly
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAccessLogPolicy 访问日志策略
|
||||
type HTTPAccessLogPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Name string `field:"name"` // 名称
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options string `field:"options"` // 存储选项
|
||||
Conds string `field:"conds"` // 请求条件
|
||||
IsPublic uint8 `field:"isPublic"` // 是否为公用
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Name string `field:"name"` // 名称
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options dbs.JSON `field:"options"` // 存储选项
|
||||
Conds dbs.JSON `field:"conds"` // 请求条件
|
||||
IsPublic bool `field:"isPublic"` // 是否为公用
|
||||
FirewallOnly uint8 `field:"firewallOnly"` // 是否只记录防火墙相关
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
}
|
||||
|
||||
type HTTPAccessLogPolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Name interface{} // 名称
|
||||
IsOn interface{} // 是否启用
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
Conds interface{} // 请求条件
|
||||
IsPublic interface{} // 是否为公用
|
||||
Version interface{} // 版本号
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Name interface{} // 名称
|
||||
IsOn interface{} // 是否启用
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
Conds interface{} // 请求条件
|
||||
IsPublic interface{} // 是否为公用
|
||||
FirewallOnly interface{} // 是否只记录防火墙相关
|
||||
Version interface{} // 版本号
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogPolicyOperator() *HTTPAccessLogPolicyOperator {
|
||||
|
||||
@@ -116,13 +116,13 @@ func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, c
|
||||
var config = &serverconfigs.HTTPAuthPolicy{
|
||||
Id: int64(policy.Id),
|
||||
Name: policy.Name,
|
||||
IsOn: policy.IsOn == 1,
|
||||
IsOn: policy.IsOn,
|
||||
Type: policy.Type,
|
||||
}
|
||||
|
||||
var params map[string]interface{}
|
||||
if IsNotNull(policy.Params) {
|
||||
err = json.Unmarshal([]byte(policy.Params), ¶ms)
|
||||
err = json.Unmarshal(policy.Params, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAuthPolicy HTTP认证策略
|
||||
type HTTPAuthPolicy struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Type string `field:"type"` // 类型
|
||||
Params string `field:"params"` // 参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Type string `field:"type"` // 类型
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type HTTPAuthPolicyOperator struct {
|
||||
|
||||
@@ -80,10 +80,10 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
|
||||
config := &serverconfigs.HTTPBrotliCompressionConfig{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
if IsNotNull(policy.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(policy.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
}
|
||||
if IsNotNull(policy.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
|
||||
if IsNotNull(policy.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
|
||||
err = json.Unmarshal(policy.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPBrotliPolicy Gzip配置
|
||||
type HTTPBrotliPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPBrotliPolicyOperator struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
@@ -95,7 +96,7 @@ func (this *HTTPCachePolicyDAO) FindAllEnabledCachePolicies(tx *dbs.Tx) (result
|
||||
}
|
||||
|
||||
// CreateCachePolicy 创建缓存策略
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
|
||||
op := NewHTTPCachePolicyOperator()
|
||||
op.State = HTTPCachePolicyStateEnabled
|
||||
op.IsOn = isOn
|
||||
@@ -112,6 +113,7 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
|
||||
if len(storageOptionsJSON) > 0 {
|
||||
op.Options = storageOptionsJSON
|
||||
}
|
||||
op.SyncCompressionCache = syncCompressionCache
|
||||
|
||||
// 默认的缓存条件
|
||||
cacheRef := &serverconfigs.HTTPCacheRef{
|
||||
@@ -182,13 +184,19 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
|
||||
var storageOptions = &serverconfigs.HTTPFileCacheStorage{
|
||||
Dir: "/opt/cache",
|
||||
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
|
||||
Capacity: &shared.SizeCapacity{
|
||||
Count: 1,
|
||||
Unit: shared.SizeCapacityUnitGB,
|
||||
},
|
||||
},
|
||||
}
|
||||
storageOptionsJSON, err := json.Marshal(storageOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON)
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -196,7 +204,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
}
|
||||
|
||||
// UpdateCachePolicy 修改缓存策略
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) error {
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -217,6 +225,7 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
|
||||
if len(storageOptionsJSON) > 0 {
|
||||
op.Options = storageOptionsJSON
|
||||
}
|
||||
op.SyncCompressionCache = syncCompressionCache
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -244,14 +253,15 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
config := &serverconfigs.HTTPCachePolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.SyncCompressionCache = policy.SyncCompressionCache == 1
|
||||
|
||||
// capacity
|
||||
if IsNotNull(policy.Capacity) {
|
||||
capacityConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.Capacity), capacityConfig)
|
||||
err = json.Unmarshal(policy.Capacity, capacityConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,7 +273,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// max size
|
||||
if IsNotNull(policy.MaxSize) {
|
||||
maxSizeConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxSize), maxSizeConfig)
|
||||
err = json.Unmarshal(policy.MaxSize, maxSizeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -275,7 +285,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// options
|
||||
if IsNotNull(policy.Options) {
|
||||
m := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(policy.Options), &m)
|
||||
err = json.Unmarshal(policy.Options, &m)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
@@ -285,7 +295,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// refs
|
||||
if IsNotNull(policy.Refs) {
|
||||
refs := []*serverconfigs.HTTPCacheRef{}
|
||||
err = json.Unmarshal([]byte(policy.Refs), &refs)
|
||||
err = json.Unmarshal(policy.Refs, &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -300,7 +310,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
|
||||
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -309,13 +319,16 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clu
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(storageType) > 0 {
|
||||
query.Attr("type", storageType)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -324,7 +337,10 @@ func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, cluster
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(storageType) > 0 {
|
||||
query.Attr("type", storageType)
|
||||
}
|
||||
ones, err := query.
|
||||
ResultPk().
|
||||
|
||||
@@ -1,40 +1,44 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPCachePolicy HTTP缓存策略
|
||||
type HTTPCachePolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Capacity string `field:"capacity"` // 容量数据
|
||||
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
||||
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options string `field:"options"` // 存储选项
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 描述
|
||||
Refs string `field:"refs"` // 默认的缓存设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Capacity dbs.JSON `field:"capacity"` // 容量数据
|
||||
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
||||
MaxSize dbs.JSON `field:"maxSize"` // 最大缓存内容尺寸
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options dbs.JSON `field:"options"` // 存储选项
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 描述
|
||||
Refs dbs.JSON `field:"refs"` // 默认的缓存设置
|
||||
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
|
||||
}
|
||||
|
||||
type HTTPCachePolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Capacity interface{} // 容量数据
|
||||
MaxKeys interface{} // 最多Key值
|
||||
MaxSize interface{} // 最大缓存内容尺寸
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
Description interface{} // 描述
|
||||
Refs interface{} // 默认的缓存设置
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Capacity interface{} // 容量数据
|
||||
MaxKeys interface{} // 最多Key值
|
||||
MaxSize interface{} // 最大缓存内容尺寸
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
Description interface{} // 描述
|
||||
Refs interface{} // 默认的缓存设置
|
||||
SyncCompressionCache interface{} // 是否同步写入压缩缓存
|
||||
}
|
||||
|
||||
func NewHTTPCachePolicyOperator() *HTTPCachePolicyOperator {
|
||||
|
||||
@@ -80,10 +80,10 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
|
||||
config := &serverconfigs.HTTPDeflateCompressionConfig{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
if IsNotNull(policy.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(policy.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
}
|
||||
if IsNotNull(policy.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
|
||||
if IsNotNull(policy.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
|
||||
err = json.Unmarshal(policy.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPDeflatePolicy Gzip配置
|
||||
type HTTPDeflatePolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPDeflatePolicyOperator struct {
|
||||
|
||||
@@ -81,12 +81,12 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
}
|
||||
config := &serverconfigs.HTTPFastcgiConfig{}
|
||||
config.Id = int64(fastcgi.Id)
|
||||
config.IsOn = fastcgi.IsOn == 1
|
||||
config.IsOn = fastcgi.IsOn
|
||||
config.Address = fastcgi.Address
|
||||
|
||||
if IsNotNull(fastcgi.Params) {
|
||||
params := []*serverconfigs.HTTPFastcgiParam{}
|
||||
err = json.Unmarshal([]byte(fastcgi.Params), ¶ms)
|
||||
err = json.Unmarshal(fastcgi.Params, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
|
||||
if IsNotNull(fastcgi.ReadTimeout) {
|
||||
duration := &shared.TimeDuration{}
|
||||
err = json.Unmarshal([]byte(fastcgi.ReadTimeout), duration)
|
||||
err = json.Unmarshal(fastcgi.ReadTimeout, duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
|
||||
if IsNotNull(fastcgi.ConnTimeout) {
|
||||
duration := &shared.TimeDuration{}
|
||||
err = json.Unmarshal([]byte(fastcgi.ConnTimeout), duration)
|
||||
err = json.Unmarshal(fastcgi.ConnTimeout, duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFastcgi Fastcgi设置
|
||||
type HTTPFastcgi struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Address string `field:"address"` // 地址
|
||||
Params string `field:"params"` // 参数
|
||||
ReadTimeout string `field:"readTimeout"` // 读取超时
|
||||
ConnTimeout string `field:"connTimeout"` // 连接超时
|
||||
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
|
||||
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Address string `field:"address"` // 地址
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时
|
||||
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
|
||||
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type HTTPFastcgiOperator struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
@@ -259,7 +260,18 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
||||
}
|
||||
|
||||
// UpdateFirewallPolicy 修改策略
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte, blockOptionsJSON []byte, mode firewallconfigs.FirewallMode, useLocalFirewall bool, synFloodConfig *firewallconfigs.SYNFloodConfig) error {
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
policyId int64,
|
||||
isOn bool,
|
||||
name string,
|
||||
description string,
|
||||
inboundJSON []byte,
|
||||
outboundJSON []byte,
|
||||
blockOptionsJSON []byte,
|
||||
mode firewallconfigs.FirewallMode,
|
||||
useLocalFirewall bool,
|
||||
synFloodConfig *firewallconfigs.SYNFloodConfig,
|
||||
logConfig *firewallconfigs.HTTPFirewallPolicyLogConfig) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -293,6 +305,16 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
op.SynFlood = "null"
|
||||
}
|
||||
|
||||
if logConfig != nil {
|
||||
logJSON, err := json.Marshal(logConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Log = logJSON
|
||||
} else {
|
||||
op.Log = "null"
|
||||
}
|
||||
|
||||
op.UseLocalFirewall = useLocalFirewall
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -311,7 +333,7 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, c
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
return query.
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
@@ -330,7 +352,7 @@ func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, clust
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
@@ -364,9 +386,9 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &firewallconfigs.HTTPFirewallPolicy{}
|
||||
var config = &firewallconfigs.HTTPFirewallPolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.UseLocalFirewall = policy.UseLocalFirewall == 1
|
||||
@@ -379,7 +401,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
// Inbound
|
||||
inbound := &firewallconfigs.HTTPFirewallInboundConfig{}
|
||||
if IsNotNull(policy.Inbound) {
|
||||
err = json.Unmarshal([]byte(policy.Inbound), inbound)
|
||||
err = json.Unmarshal(policy.Inbound, inbound)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -407,7 +429,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
// Outbound
|
||||
outbound := &firewallconfigs.HTTPFirewallOutboundConfig{}
|
||||
if IsNotNull(policy.Outbound) {
|
||||
err = json.Unmarshal([]byte(policy.Outbound), outbound)
|
||||
err = json.Unmarshal(policy.Outbound, outbound)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -435,7 +457,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
// Block动作配置
|
||||
if IsNotNull(policy.BlockOptions) {
|
||||
blockAction := &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
err = json.Unmarshal([]byte(policy.BlockOptions), blockAction)
|
||||
err = json.Unmarshal(policy.BlockOptions, blockAction)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
@@ -443,15 +465,27 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
}
|
||||
|
||||
// syn flood
|
||||
if len(policy.SynFlood) > 0 {
|
||||
if IsNotNull(policy.SynFlood) {
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
|
||||
err = json.Unmarshal(policy.SynFlood, synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SYNFlood = synFloodConfig
|
||||
}
|
||||
|
||||
// log
|
||||
if IsNotNull(policy.Log) {
|
||||
var logConfig = &firewallconfigs.HTTPFirewallPolicyLogConfig{}
|
||||
err = json.Unmarshal(policy.Log, logConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Log = logConfig
|
||||
} else {
|
||||
config.Log = firewallconfigs.DefaultHTTPFirewallPolicyLogConfig
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallPolicy HTTP防火墙
|
||||
type HTTPFirewallPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound string `field:"inbound"` // 入站规则
|
||||
Outbound string `field:"outbound"` // 出站规则
|
||||
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood string `field:"synFlood"` // SynFlood防御设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound dbs.JSON `field:"inbound"` // 入站规则
|
||||
Outbound dbs.JSON `field:"outbound"` // 出站规则
|
||||
BlockOptions dbs.JSON `field:"blockOptions"` // BLOCK选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood dbs.JSON `field:"synFlood"` // SynFlood防御设置
|
||||
Log dbs.JSON `field:"log"` // 日志配置
|
||||
}
|
||||
|
||||
type HTTPFirewallPolicyOperator struct {
|
||||
@@ -39,6 +42,7 @@ type HTTPFirewallPolicyOperator struct {
|
||||
Mode interface{} // 模式
|
||||
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||
SynFlood interface{} // SynFlood防御设置
|
||||
Log interface{} // 日志配置
|
||||
}
|
||||
|
||||
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
||||
|
||||
@@ -35,12 +35,12 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
// Init 初始化
|
||||
func (this *HTTPFirewallRuleDAO) Init() {
|
||||
_ = this.DAOObject.Init()
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableHTTPFirewallRule 启用条目
|
||||
func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -49,7 +49,7 @@ func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) er
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableHTTPFirewallRule 禁用条目
|
||||
func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(ruleId).
|
||||
@@ -61,7 +61,7 @@ func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int6
|
||||
return this.NotifyUpdate(tx, ruleId)
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledHTTPFirewallRule 查找启用中的条目
|
||||
func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int64) (*HTTPFirewallRule, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -73,7 +73,7 @@ func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int6
|
||||
return result.(*HTTPFirewallRule), err
|
||||
}
|
||||
|
||||
// 组合配置
|
||||
// ComposeFirewallRule 组合配置
|
||||
func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (*firewallconfigs.HTTPFirewallRule, error) {
|
||||
rule, err := this.FindEnabledHTTPFirewallRule(tx, ruleId)
|
||||
if err != nil {
|
||||
@@ -84,12 +84,12 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRule{}
|
||||
config.Id = int64(rule.Id)
|
||||
config.IsOn = rule.IsOn == 1
|
||||
config.IsOn = rule.IsOn
|
||||
config.Param = rule.Param
|
||||
|
||||
paramFilters := []*firewallconfigs.ParamFilter{}
|
||||
if IsNotNull(rule.ParamFilters) {
|
||||
err = json.Unmarshal([]byte(rule.ParamFilters), ¶mFilters)
|
||||
err = json.Unmarshal(rule.ParamFilters, ¶mFilters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,11 +98,11 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
|
||||
config.Operator = rule.Operator
|
||||
config.Value = rule.Value
|
||||
config.IsCaseInsensitive = rule.IsCaseInsensitive == 1
|
||||
config.IsCaseInsensitive = rule.IsCaseInsensitive
|
||||
|
||||
if IsNotNull(rule.CheckpointOptions) {
|
||||
checkpointOptions := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(rule.CheckpointOptions), &checkpointOptions)
|
||||
err = json.Unmarshal(rule.CheckpointOptions, &checkpointOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 从配置中配置规则
|
||||
// CreateOrUpdateRuleFromConfig 从配置中配置规则
|
||||
func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleConfig *firewallconfigs.HTTPFirewallRule) (int64, error) {
|
||||
op := NewHTTPFirewallRuleOperator()
|
||||
op.Id = ruleConfig.Id
|
||||
@@ -160,7 +160,7 @@ func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleCo
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPFirewallRuleDAO) NotifyUpdate(tx *dbs.Tx, ruleId int64) error {
|
||||
setId, err := SharedHTTPFirewallRuleSetDAO.FindEnabledRuleSetIdWithRuleId(tx, ruleId)
|
||||
if err != nil {
|
||||
|
||||
@@ -91,15 +91,15 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRuleGroup{}
|
||||
config.Id = int64(group.Id)
|
||||
config.IsOn = group.IsOn == 1
|
||||
config.IsOn = group.IsOn
|
||||
config.Name = group.Name
|
||||
config.Description = group.Description
|
||||
config.Code = group.Code
|
||||
config.IsTemplate = group.IsTemplate == 1
|
||||
config.IsTemplate = group.IsTemplate
|
||||
|
||||
if IsNotNull(group.Sets) {
|
||||
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||
err = json.Unmarshal([]byte(group.Sets), &setRefs)
|
||||
err = json.Unmarshal(group.Sets, &setRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRuleGroup 防火墙规则分组
|
||||
type HTTPFirewallRuleGroup struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Code string `field:"code"` // 代号
|
||||
IsTemplate uint8 `field:"isTemplate"` // 是否为预置模板
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
Sets string `field:"sets"` // 规则集列表
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Code string `field:"code"` // 代号
|
||||
IsTemplate bool `field:"isTemplate"` // 是否为预置模板
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
Sets dbs.JSON `field:"sets"` // 规则集列表
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleGroupOperator struct {
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
package models
|
||||
|
||||
// 防火墙规则
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRule 防火墙规则
|
||||
type HTTPFirewallRule struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Description string `field:"description"` // 说明
|
||||
Param string `field:"param"` // 参数
|
||||
ParamFilters string `field:"paramFilters"` // 处理器
|
||||
Operator string `field:"operator"` // 操作符
|
||||
Value string `field:"value"` // 对比值
|
||||
IsCaseInsensitive uint8 `field:"isCaseInsensitive"` // 是否大小写不敏感
|
||||
CheckpointOptions string `field:"checkpointOptions"` // 检查点参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Description string `field:"description"` // 说明
|
||||
Param string `field:"param"` // 参数
|
||||
ParamFilters dbs.JSON `field:"paramFilters"` // 处理器
|
||||
Operator string `field:"operator"` // 操作符
|
||||
Value string `field:"value"` // 对比值
|
||||
IsCaseInsensitive bool `field:"isCaseInsensitive"` // 是否大小写不敏感
|
||||
CheckpointOptions dbs.JSON `field:"checkpointOptions"` // 检查点参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleOperator struct {
|
||||
|
||||
@@ -94,7 +94,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRuleSet{}
|
||||
config.Id = int64(set.Id)
|
||||
config.IsOn = set.IsOn == 1
|
||||
config.IsOn = set.IsOn
|
||||
config.Name = set.Name
|
||||
config.Description = set.Description
|
||||
config.Code = set.Code
|
||||
@@ -103,7 +103,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
|
||||
if IsNotNull(set.Rules) {
|
||||
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
|
||||
err = json.Unmarshal([]byte(set.Rules), &ruleRefs)
|
||||
err = json.Unmarshal(set.Rules, &ruleRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
|
||||
var actionConfigs = []*firewallconfigs.HTTPFirewallActionConfig{}
|
||||
if len(set.Actions) > 0 {
|
||||
err = json.Unmarshal([]byte(set.Actions), &actionConfigs)
|
||||
err = json.Unmarshal(set.Actions, &actionConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRuleSet 防火墙规则集
|
||||
type HTTPFirewallRuleSet struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Code string `field:"code"` // 代号
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Rules string `field:"rules"` // 规则列表
|
||||
Connector string `field:"connector"` // 规则之间的关系
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Action string `field:"action"` // 执行的动作(过期)
|
||||
ActionOptions string `field:"actionOptions"` // 动作的选项(过期)
|
||||
Actions string `field:"actions"` // 一组动作
|
||||
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Code string `field:"code"` // 代号
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Rules dbs.JSON `field:"rules"` // 规则列表
|
||||
Connector string `field:"connector"` // 规则之间的关系
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Action string `field:"action"` // 执行的动作(过期)
|
||||
ActionOptions dbs.JSON `field:"actionOptions"` // 动作的选项(过期)
|
||||
Actions dbs.JSON `field:"actions"` // 一组动作
|
||||
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleSetOperator struct {
|
||||
|
||||
@@ -88,10 +88,10 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
|
||||
config := &serverconfigs.HTTPGzipCompressionConfig{}
|
||||
config.Id = int64(gzip.Id)
|
||||
config.IsOn = gzip.IsOn == 1
|
||||
config.IsOn = gzip.IsOn
|
||||
if IsNotNull(gzip.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(gzip.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(gzip.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
}
|
||||
if IsNotNull(gzip.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(gzip.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(gzip.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
|
||||
if IsNotNull(gzip.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(gzip.Conds), condsConfig)
|
||||
err = json.Unmarshal(gzip.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
// Gzip配置
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPGzip Gzip配置
|
||||
type HTTPGzip struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPGzipOperator struct {
|
||||
|
||||
@@ -5,22 +5,22 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
)
|
||||
|
||||
// 解析最小长度
|
||||
// DecodeMinLength 解析最小长度
|
||||
func (this *HTTPGzip) DecodeMinLength() (*shared.SizeCapacity, error) {
|
||||
if len(this.MinLength) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
capacity := &shared.SizeCapacity{}
|
||||
err := json.Unmarshal([]byte(this.MinLength), capacity)
|
||||
err := json.Unmarshal(this.MinLength, capacity)
|
||||
return capacity, err
|
||||
}
|
||||
|
||||
// 解析最大长度
|
||||
// DecodeMaxLength 解析最大长度
|
||||
func (this *HTTPGzip) DecodeMaxLength() (*shared.SizeCapacity, error) {
|
||||
if len(this.MaxLength) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
capacity := &shared.SizeCapacity{}
|
||||
err := json.Unmarshal([]byte(this.MaxLength), capacity)
|
||||
err := json.Unmarshal(this.MaxLength, capacity)
|
||||
return capacity, err
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
|
||||
config := &shared.HTTPHeaderConfig{}
|
||||
config.Id = int64(header.Id)
|
||||
config.IsOn = header.IsOn == 1
|
||||
config.IsOn = header.IsOn
|
||||
config.Name = header.Name
|
||||
config.Value = header.Value
|
||||
config.DisableRedirect = header.DisableRedirect == 1
|
||||
@@ -244,9 +244,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
|
||||
// replace
|
||||
config.ShouldReplace = header.ShouldReplace == 1
|
||||
if len(header.ReplaceValues) > 0 {
|
||||
if IsNotNull(header.ReplaceValues) {
|
||||
var values = []*shared.HTTPHeaderReplaceValue{}
|
||||
err = json.Unmarshal([]byte(header.ReplaceValues), &values)
|
||||
err = json.Unmarshal(header.ReplaceValues, &values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -254,9 +254,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
}
|
||||
|
||||
// status
|
||||
if len(header.Status) > 0 {
|
||||
if IsNotNull(header.Status) {
|
||||
status := &shared.HTTPStatusConfig{}
|
||||
err = json.Unmarshal([]byte(header.Status), status)
|
||||
err = json.Unmarshal(header.Status, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -264,9 +264,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
}
|
||||
|
||||
// methods
|
||||
if len(header.Methods) > 0 {
|
||||
if IsNotNull(header.Methods) {
|
||||
var methods = []string{}
|
||||
err = json.Unmarshal([]byte(header.Methods), &methods)
|
||||
err = json.Unmarshal(header.Methods, &methods)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -274,9 +274,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
}
|
||||
|
||||
// domains
|
||||
if len(header.Domains) > 0 {
|
||||
if IsNotNull(header.Domains) {
|
||||
var domains = []string{}
|
||||
err = json.Unmarshal([]byte(header.Domains), &domains)
|
||||
err = json.Unmarshal(header.Domains, &domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPHeader HTTP Header
|
||||
type HTTPHeader struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Value string `field:"value"` // 值
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Status string `field:"status"` // 状态码设置
|
||||
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
|
||||
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
|
||||
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
|
||||
ReplaceValues string `field:"replaceValues"` // 替换的值
|
||||
Methods string `field:"methods"` // 支持的方法
|
||||
Domains string `field:"domains"` // 支持的域名
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Value string `field:"value"` // 值
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Status dbs.JSON `field:"status"` // 状态码设置
|
||||
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
|
||||
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
|
||||
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
|
||||
ReplaceValues dbs.JSON `field:"replaceValues"` // 替换的值
|
||||
Methods dbs.JSON `field:"methods"` // 支持的方法
|
||||
Domains dbs.JSON `field:"domains"` // 支持的域名
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type HTTPHeaderOperator struct {
|
||||
|
||||
@@ -184,12 +184,12 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
|
||||
|
||||
config := &shared.HTTPHeaderPolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
|
||||
// SetHeaders
|
||||
if len(policy.SetHeaders) > 0 {
|
||||
if IsNotNull(policy.SetHeaders) {
|
||||
refs := []*shared.HTTPHeaderRef{}
|
||||
err = json.Unmarshal([]byte(policy.SetHeaders), &refs)
|
||||
err = json.Unmarshal(policy.SetHeaders, &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -211,9 +211,9 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
|
||||
}
|
||||
|
||||
// Delete Headers
|
||||
if len(policy.DeleteHeaders) > 0 {
|
||||
if IsNotNull(policy.DeleteHeaders) {
|
||||
headers := []string{}
|
||||
err = json.Unmarshal([]byte(policy.DeleteHeaders), &headers)
|
||||
err = json.Unmarshal(policy.DeleteHeaders, &headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
//
|
||||
type HTTPHeaderPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AddHeaders string `field:"addHeaders"` // 添加的Header
|
||||
AddTrailers string `field:"addTrailers"` // 添加的Trailers
|
||||
SetHeaders string `field:"setHeaders"` // 设置Header
|
||||
ReplaceHeaders string `field:"replaceHeaders"` // 替换Header内容
|
||||
Expires string `field:"expires"` // Expires单独设置
|
||||
DeleteHeaders string `field:"deleteHeaders"` // 删除的Headers
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AddHeaders dbs.JSON `field:"addHeaders"` // 添加的Header
|
||||
AddTrailers dbs.JSON `field:"addTrailers"` // 添加的Trailers
|
||||
SetHeaders dbs.JSON `field:"setHeaders"` // 设置Header
|
||||
ReplaceHeaders dbs.JSON `field:"replaceHeaders"` // 替换Header内容
|
||||
Expires dbs.JSON `field:"expires"` // Expires单独设置
|
||||
DeleteHeaders dbs.JSON `field:"deleteHeaders"` // 删除的Headers
|
||||
}
|
||||
|
||||
type HTTPHeaderPolicyOperator struct {
|
||||
|
||||
@@ -170,12 +170,12 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
|
||||
|
||||
config := &serverconfigs.HTTPLocationConfig{}
|
||||
config.Id = int64(location.Id)
|
||||
config.IsOn = location.IsOn == 1
|
||||
config.IsOn = location.IsOn
|
||||
config.Description = location.Description
|
||||
config.Name = location.Name
|
||||
config.Pattern = location.Pattern
|
||||
config.URLPrefix = location.UrlPrefix
|
||||
config.IsBreak = location.IsBreak == 1
|
||||
config.IsBreak = location.IsBreak
|
||||
|
||||
// web
|
||||
if location.WebId > 0 {
|
||||
@@ -189,7 +189,7 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
|
||||
// reverse proxy
|
||||
if IsNotNull(location.ReverseProxy) {
|
||||
ref := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(location.ReverseProxy), ref)
|
||||
err = json.Unmarshal(location.ReverseProxy, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -204,9 +204,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
|
||||
}
|
||||
|
||||
// conds
|
||||
if len(location.Conds) > 0 {
|
||||
if IsNotNull(location.Conds) {
|
||||
conds := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(location.Conds), conds)
|
||||
err = json.Unmarshal(location.Conds, conds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -214,9 +214,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
|
||||
}
|
||||
|
||||
// domains
|
||||
if len(location.Domains) > 0 {
|
||||
if IsNotNull(location.Domains) {
|
||||
var domains = []string{}
|
||||
err = json.Unmarshal([]byte(location.Domains), &domains)
|
||||
err = json.Unmarshal(location.Domains, &domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -241,7 +241,7 @@ func (this *HTTPLocationDAO) FindLocationReverseProxy(tx *dbs.Tx, locationId int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if IsNotNull(refString) {
|
||||
if IsNotNull([]byte(refString)) {
|
||||
ref := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(refString), ref)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPLocation 路由规则配置
|
||||
type HTTPLocation struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ParentId uint32 `field:"parentId"` // 父级ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Pattern string `field:"pattern"` // 匹配规则
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
WebId uint32 `field:"webId"` // Web配置ID
|
||||
ReverseProxy string `field:"reverseProxy"` // 反向代理
|
||||
UrlPrefix string `field:"urlPrefix"` // URL前缀
|
||||
IsBreak uint8 `field:"isBreak"` // 是否终止匹配
|
||||
Conds string `field:"conds"` // 匹配条件
|
||||
Domains string `field:"domains"` // 专属域名
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ParentId uint32 `field:"parentId"` // 父级ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Pattern string `field:"pattern"` // 匹配规则
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
WebId uint32 `field:"webId"` // Web配置ID
|
||||
ReverseProxy dbs.JSON `field:"reverseProxy"` // 反向代理
|
||||
UrlPrefix string `field:"urlPrefix"` // URL前缀
|
||||
IsBreak bool `field:"isBreak"` // 是否终止匹配
|
||||
Conds dbs.JSON `field:"conds"` // 匹配条件
|
||||
Domains dbs.JSON `field:"domains"` // 专属域名
|
||||
}
|
||||
|
||||
type HTTPLocationOperator struct {
|
||||
|
||||
@@ -77,8 +77,9 @@ func (this *HTTPPageDAO) FindEnabledHTTPPage(tx *dbs.Tx, id int64) (*HTTPPage, e
|
||||
}
|
||||
|
||||
// CreatePage 创建Page
|
||||
func (this *HTTPPageDAO) CreatePage(tx *dbs.Tx, statusList []string, bodyType shared.BodyType, url string, body string, newStatus int) (pageId int64, err error) {
|
||||
func (this *HTTPPageDAO) CreatePage(tx *dbs.Tx, userId int64, statusList []string, bodyType shared.BodyType, url string, body string, newStatus int) (pageId int64, err error) {
|
||||
op := NewHTTPPageOperator()
|
||||
op.UserId = userId
|
||||
op.IsOn = true
|
||||
op.State = HTTPPageStateEnabled
|
||||
|
||||
@@ -154,7 +155,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
|
||||
|
||||
config := &serverconfigs.HTTPPageConfig{}
|
||||
config.Id = int64(page.Id)
|
||||
config.IsOn = page.IsOn == 1
|
||||
config.IsOn = page.IsOn
|
||||
config.NewStatus = int(page.NewStatus)
|
||||
config.URL = page.Url
|
||||
config.Body = page.Body
|
||||
@@ -166,7 +167,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
|
||||
|
||||
if len(page.StatusList) > 0 {
|
||||
statusList := []string{}
|
||||
err = json.Unmarshal([]byte(page.StatusList), &statusList)
|
||||
err = json.Unmarshal(page.StatusList, &statusList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -182,6 +183,26 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// CheckUserPage 检查用户页面
|
||||
func (this *HTTPPageDAO) CheckUserPage(tx *dbs.Tx, userId int64, pageId int64) error {
|
||||
if userId <= 0 || pageId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
b, err := this.Query(tx).
|
||||
Pk(pageId).
|
||||
Attr("userId", userId).
|
||||
State(HTTPPageStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPPageDAO) NotifyUpdate(tx *dbs.Tx, pageId int64) error {
|
||||
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithPageId(tx, pageId)
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPPage 特殊页面
|
||||
type HTTPPage struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
StatusList string `field:"statusList"` // 状态列表
|
||||
Url string `field:"url"` // 页面URL
|
||||
NewStatus int32 `field:"newStatus"` // 新状态码
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Body string `field:"body"` // 页面内容
|
||||
BodyType string `field:"bodyType"` // 内容类型
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
StatusList dbs.JSON `field:"statusList"` // 状态列表
|
||||
Url string `field:"url"` // 页面URL
|
||||
NewStatus int32 `field:"newStatus"` // 新状态码
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Body string `field:"body"` // 页面内容
|
||||
BodyType string `field:"bodyType"` // 内容类型
|
||||
}
|
||||
|
||||
type HTTPPageOperator struct {
|
||||
|
||||
@@ -97,19 +97,19 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
|
||||
|
||||
config := &serverconfigs.HTTPRewriteRule{}
|
||||
config.Id = int64(rule.Id)
|
||||
config.IsOn = rule.IsOn == 1
|
||||
config.IsOn = rule.IsOn
|
||||
config.Pattern = rule.Pattern
|
||||
config.Replace = rule.Replace
|
||||
config.Mode = rule.Mode
|
||||
config.RedirectStatus = types.Int(rule.RedirectStatus)
|
||||
config.ProxyHost = rule.ProxyHost
|
||||
config.IsBreak = rule.IsBreak == 1
|
||||
config.IsBreak = rule.IsBreak
|
||||
config.WithQuery = rule.WithQuery == 1
|
||||
|
||||
// conds
|
||||
if len(rule.Conds) > 0 {
|
||||
conds := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(rule.Conds), conds)
|
||||
err = json.Unmarshal(rule.Conds, conds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// 重写规则
|
||||
type HTTPRewriteRule struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Pattern string `field:"pattern"` // 匹配规则
|
||||
Replace string `field:"replace"` // 跳转后的地址
|
||||
Mode string `field:"mode"` // 替换模式
|
||||
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
|
||||
ProxyHost string `field:"proxyHost"` // 代理的主机名
|
||||
IsBreak uint8 `field:"isBreak"` // 是否终止解析
|
||||
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
|
||||
Conds string `field:"conds"` // 匹配条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Pattern string `field:"pattern"` // 匹配规则
|
||||
Replace string `field:"replace"` // 跳转后的地址
|
||||
Mode string `field:"mode"` // 替换模式
|
||||
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
|
||||
ProxyHost string `field:"proxyHost"` // 代理的主机名
|
||||
IsBreak bool `field:"isBreak"` // 是否终止解析
|
||||
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
|
||||
Conds dbs.JSON `field:"conds"` // 匹配条件
|
||||
}
|
||||
|
||||
type HTTPRewriteRuleOperator struct {
|
||||
|
||||
@@ -94,14 +94,14 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.HTTPWebConfig{}
|
||||
var config = &serverconfigs.HTTPWebConfig{}
|
||||
config.Id = webId
|
||||
config.IsOn = web.IsOn == 1
|
||||
config.IsOn = web.IsOn
|
||||
|
||||
// root
|
||||
if IsNotNull(web.Root) {
|
||||
rootConfig := &serverconfigs.HTTPRootConfig{}
|
||||
err = json.Unmarshal([]byte(web.Root), rootConfig)
|
||||
err = json.Unmarshal(web.Root, rootConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// compression
|
||||
if IsNotNull(web.Compression) {
|
||||
compression := &serverconfigs.HTTPCompressionConfig{}
|
||||
err = json.Unmarshal([]byte(web.Compression), compression)
|
||||
err = json.Unmarshal(web.Compression, compression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// charset
|
||||
if IsNotNull(web.Charset) {
|
||||
charsetConfig := &serverconfigs.HTTPCharsetConfig{}
|
||||
err = json.Unmarshal([]byte(web.Charset), charsetConfig)
|
||||
err = json.Unmarshal(web.Charset, charsetConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// headers
|
||||
if IsNotNull(web.RequestHeader) {
|
||||
ref := &shared.HTTPHeaderPolicyRef{}
|
||||
err = json.Unmarshal([]byte(web.RequestHeader), ref)
|
||||
err = json.Unmarshal(web.RequestHeader, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
|
||||
if IsNotNull(web.ResponseHeader) {
|
||||
ref := &shared.HTTPHeaderPolicyRef{}
|
||||
err = json.Unmarshal([]byte(web.ResponseHeader), ref)
|
||||
err = json.Unmarshal(web.ResponseHeader, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// shutdown
|
||||
if IsNotNull(web.Shutdown) {
|
||||
shutdownConfig := &serverconfigs.HTTPShutdownConfig{}
|
||||
err = json.Unmarshal([]byte(web.Shutdown), shutdownConfig)
|
||||
err = json.Unmarshal(web.Shutdown, shutdownConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// pages
|
||||
if IsNotNull(web.Pages) {
|
||||
pages := []*serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal([]byte(web.Pages), &pages)
|
||||
err = json.Unmarshal(web.Pages, &pages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -226,7 +226,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 访问日志
|
||||
if IsNotNull(web.AccessLog) {
|
||||
accessLogConfig := &serverconfigs.HTTPAccessLogRef{}
|
||||
err = json.Unmarshal([]byte(web.AccessLog), accessLogConfig)
|
||||
err = json.Unmarshal(web.AccessLog, accessLogConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 统计配置
|
||||
if IsNotNull(web.Stat) {
|
||||
statRef := &serverconfigs.HTTPStatRef{}
|
||||
err = json.Unmarshal([]byte(web.Stat), statRef)
|
||||
err = json.Unmarshal(web.Stat, statRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -246,7 +246,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 缓存配置
|
||||
if IsNotNull(web.Cache) {
|
||||
cacheConfig := &serverconfigs.HTTPCacheConfig{}
|
||||
err = json.Unmarshal([]byte(web.Cache), &cacheConfig)
|
||||
err = json.Unmarshal(web.Cache, &cacheConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -258,7 +258,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 防火墙配置
|
||||
if IsNotNull(web.Firewall) {
|
||||
firewallRef := &firewallconfigs.HTTPFirewallRef{}
|
||||
err = json.Unmarshal([]byte(web.Firewall), firewallRef)
|
||||
err = json.Unmarshal(web.Firewall, firewallRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 路由规则
|
||||
if IsNotNull(web.Locations) {
|
||||
refs := []*serverconfigs.HTTPLocationRef{}
|
||||
err = json.Unmarshal([]byte(web.Locations), &refs)
|
||||
err = json.Unmarshal(web.Locations, &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -299,7 +299,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 跳转
|
||||
if IsNotNull(web.RedirectToHttps) {
|
||||
redirectToHTTPSConfig := &serverconfigs.HTTPRedirectToHTTPSConfig{}
|
||||
err = json.Unmarshal([]byte(web.RedirectToHttps), redirectToHTTPSConfig)
|
||||
err = json.Unmarshal(web.RedirectToHttps, redirectToHTTPSConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -309,7 +309,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// Websocket
|
||||
if IsNotNull(web.Websocket) {
|
||||
ref := &serverconfigs.HTTPWebsocketRef{}
|
||||
err = json.Unmarshal([]byte(web.Websocket), ref)
|
||||
err = json.Unmarshal(web.Websocket, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -328,7 +328,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 重写规则
|
||||
if IsNotNull(web.RewriteRules) {
|
||||
refs := []*serverconfigs.HTTPRewriteRef{}
|
||||
err = json.Unmarshal([]byte(web.RewriteRules), &refs)
|
||||
err = json.Unmarshal(web.RewriteRules, &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -347,7 +347,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 主机跳转
|
||||
if IsNotNull(web.HostRedirects) {
|
||||
redirects := []*serverconfigs.HTTPHostRedirectConfig{}
|
||||
err = json.Unmarshal([]byte(web.HostRedirects), &redirects)
|
||||
err = json.Unmarshal(web.HostRedirects, &redirects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -357,7 +357,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// Fastcgi
|
||||
if IsNotNull(web.Fastcgi) {
|
||||
ref := &serverconfigs.HTTPFastcgiRef{}
|
||||
err = json.Unmarshal([]byte(web.Fastcgi), ref)
|
||||
err = json.Unmarshal(web.Fastcgi, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -381,7 +381,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// 认证
|
||||
if IsNotNull(web.Auth) {
|
||||
authConfig := &serverconfigs.HTTPAuthConfig{}
|
||||
err = json.Unmarshal([]byte(web.Auth), authConfig)
|
||||
err = json.Unmarshal(web.Auth, authConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -402,7 +402,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// WebP
|
||||
if IsNotNull(web.Webp) {
|
||||
var webpConfig = &serverconfigs.WebPImageConfig{}
|
||||
err = json.Unmarshal([]byte(web.Webp), webpConfig)
|
||||
err = json.Unmarshal(web.Webp, webpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -412,7 +412,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
// RemoteAddr
|
||||
if IsNotNull(web.RemoteAddr) {
|
||||
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{}
|
||||
err = json.Unmarshal([]byte(web.RemoteAddr), remoteAddrConfig)
|
||||
err = json.Unmarshal(web.RemoteAddr, remoteAddrConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -426,7 +426,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
if len(web.RequestLimit) > 0 {
|
||||
var requestLimitConfig = &serverconfigs.HTTPRequestLimitConfig{}
|
||||
if len(web.RequestLimit) > 0 {
|
||||
err = json.Unmarshal([]byte(web.RequestLimit), requestLimitConfig)
|
||||
err = json.Unmarshal(web.RequestLimit, requestLimitConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -438,7 +438,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
if len(web.RequestScripts) > 0 {
|
||||
var requestScriptsConfig = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
if len(web.RequestScripts) > 0 {
|
||||
err = json.Unmarshal([]byte(web.RequestScripts), requestScriptsConfig)
|
||||
err = json.Unmarshal(web.RequestScripts, requestScriptsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,40 +1,42 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPWeb HTTP Web
|
||||
type HTTPWeb struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Root string `field:"root"` // 根目录
|
||||
Charset string `field:"charset"` // 字符集
|
||||
Shutdown string `field:"shutdown"` // 临时关闭页面配置
|
||||
Pages string `field:"pages"` // 特殊页面
|
||||
RedirectToHttps string `field:"redirectToHttps"` // 跳转到HTTPS设置
|
||||
Indexes string `field:"indexes"` // 首页文件列表
|
||||
MaxRequestBodySize string `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
|
||||
RequestHeader string `field:"requestHeader"` // 请求Header配置
|
||||
ResponseHeader string `field:"responseHeader"` // 响应Header配置
|
||||
AccessLog string `field:"accessLog"` // 访问日志配置
|
||||
Stat string `field:"stat"` // 统计配置
|
||||
Gzip string `field:"gzip"` // Gzip配置(v0.3.2弃用)
|
||||
Compression string `field:"compression"` // 压缩配置
|
||||
Cache string `field:"cache"` // 缓存配置
|
||||
Firewall string `field:"firewall"` // 防火墙设置
|
||||
Locations string `field:"locations"` // 路由规则配置
|
||||
Websocket string `field:"websocket"` // Websocket设置
|
||||
RewriteRules string `field:"rewriteRules"` // 重写规则配置
|
||||
HostRedirects string `field:"hostRedirects"` // 域名跳转
|
||||
Fastcgi string `field:"fastcgi"` // Fastcgi配置
|
||||
Auth string `field:"auth"` // 认证策略配置
|
||||
Webp string `field:"webp"` // WebP配置
|
||||
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
|
||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||
RequestLimit string `field:"requestLimit"` // 请求限制
|
||||
RequestScripts string `field:"requestScripts"` // 请求脚本
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Root dbs.JSON `field:"root"` // 根目录
|
||||
Charset dbs.JSON `field:"charset"` // 字符集
|
||||
Shutdown dbs.JSON `field:"shutdown"` // 临时关闭页面配置
|
||||
Pages dbs.JSON `field:"pages"` // 特殊页面
|
||||
RedirectToHttps dbs.JSON `field:"redirectToHttps"` // 跳转到HTTPS设置
|
||||
Indexes dbs.JSON `field:"indexes"` // 首页文件列表
|
||||
MaxRequestBodySize dbs.JSON `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
|
||||
RequestHeader dbs.JSON `field:"requestHeader"` // 请求Header配置
|
||||
ResponseHeader dbs.JSON `field:"responseHeader"` // 响应Header配置
|
||||
AccessLog dbs.JSON `field:"accessLog"` // 访问日志配置
|
||||
Stat dbs.JSON `field:"stat"` // 统计配置
|
||||
Gzip dbs.JSON `field:"gzip"` // Gzip配置(v0.3.2弃用)
|
||||
Compression dbs.JSON `field:"compression"` // 压缩配置
|
||||
Cache dbs.JSON `field:"cache"` // 缓存配置
|
||||
Firewall dbs.JSON `field:"firewall"` // 防火墙设置
|
||||
Locations dbs.JSON `field:"locations"` // 路由规则配置
|
||||
Websocket dbs.JSON `field:"websocket"` // Websocket设置
|
||||
RewriteRules dbs.JSON `field:"rewriteRules"` // 重写规则配置
|
||||
HostRedirects dbs.JSON `field:"hostRedirects"` // 域名跳转
|
||||
Fastcgi dbs.JSON `field:"fastcgi"` // Fastcgi配置
|
||||
Auth dbs.JSON `field:"auth"` // 认证策略配置
|
||||
Webp dbs.JSON `field:"webp"` // WebP配置
|
||||
RemoteAddr dbs.JSON `field:"remoteAddr"` // 客户端IP配置
|
||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||
RequestLimit dbs.JSON `field:"requestLimit"` // 请求限制
|
||||
RequestScripts dbs.JSON `field:"requestScripts"` // 请求脚本
|
||||
}
|
||||
|
||||
type HTTPWebOperator struct {
|
||||
|
||||
@@ -37,7 +37,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableHTTPWebsocket 启用条目
|
||||
func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -46,7 +46,7 @@ func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableHTTPWebsocket 禁用条目
|
||||
func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(websocketId).
|
||||
@@ -58,7 +58,7 @@ func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64
|
||||
return this.NotifyUpdate(tx, websocketId)
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledHTTPWebsocket 查找启用中的条目
|
||||
func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*HTTPWebsocket, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -70,7 +70,7 @@ func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*H
|
||||
return result.(*HTTPWebsocket), err
|
||||
}
|
||||
|
||||
// 组合配置
|
||||
// ComposeWebsocketConfig 组合配置
|
||||
func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int64) (*serverconfigs.HTTPWebsocketConfig, error) {
|
||||
websocket, err := this.FindEnabledHTTPWebsocket(tx, websocketId)
|
||||
if err != nil {
|
||||
@@ -81,12 +81,12 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
|
||||
}
|
||||
config := &serverconfigs.HTTPWebsocketConfig{}
|
||||
config.Id = int64(websocket.Id)
|
||||
config.IsOn = websocket.IsOn == 1
|
||||
config.IsOn = websocket.IsOn
|
||||
config.AllowAllOrigins = websocket.AllowAllOrigins == 1
|
||||
|
||||
if IsNotNull(websocket.AllowedOrigins) {
|
||||
origins := []string{}
|
||||
err = json.Unmarshal([]byte(websocket.AllowedOrigins), &origins)
|
||||
err = json.Unmarshal(websocket.AllowedOrigins, &origins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
|
||||
|
||||
if IsNotNull(websocket.HandshakeTimeout) {
|
||||
duration := &shared.TimeDuration{}
|
||||
err = json.Unmarshal([]byte(websocket.HandshakeTimeout), duration)
|
||||
err = json.Unmarshal(websocket.HandshakeTimeout, duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 创建Websocket配置
|
||||
// CreateWebsocket 创建Websocket配置
|
||||
func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) (websocketId int64, err error) {
|
||||
op := NewHTTPWebsocketOperator()
|
||||
op.IsOn = true
|
||||
@@ -130,7 +130,7 @@ func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON [
|
||||
return types.Int64(op.Id), err
|
||||
}
|
||||
|
||||
// 修改Websocket配置
|
||||
// UpdateWebsocket 修改Websocket配置
|
||||
func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) error {
|
||||
if websocketId <= 0 {
|
||||
return errors.New("invalid websocketId")
|
||||
@@ -159,7 +159,7 @@ func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, han
|
||||
return this.NotifyUpdate(tx, websocketId)
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPWebsocketDAO) NotifyUpdate(tx *dbs.Tx, websocketId int64) error {
|
||||
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithWebsocketId(tx, websocketId)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// Websocket设置
|
||||
type HTTPWebsocket struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
HandshakeTimeout string `field:"handshakeTimeout"` // 握手超时时间
|
||||
AllowAllOrigins uint8 `field:"allowAllOrigins"` // 是否支持所有源
|
||||
AllowedOrigins string `field:"allowedOrigins"` // 支持的源域名列表
|
||||
RequestSameOrigin uint8 `field:"requestSameOrigin"` // 是否请求一样的Origin
|
||||
RequestOrigin string `field:"requestOrigin"` // 请求Origin
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
HandshakeTimeout dbs.JSON `field:"handshakeTimeout"` // 握手超时时间
|
||||
AllowAllOrigins uint8 `field:"allowAllOrigins"` // 是否支持所有源
|
||||
AllowedOrigins dbs.JSON `field:"allowedOrigins"` // 支持的源域名列表
|
||||
RequestSameOrigin uint8 `field:"requestSameOrigin"` // 是否请求一样的Origin
|
||||
RequestOrigin string `field:"requestOrigin"` // 请求Origin
|
||||
}
|
||||
|
||||
type HTTPWebsocketOperator struct {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
@@ -19,6 +22,20 @@ const (
|
||||
IPItemStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
var ticker = time.NewTicker(1 * time.Minute)
|
||||
for range ticker.C {
|
||||
err := SharedIPItemDAO.CleanExpiredIPItems(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("IPItemDAO", "clean expired ip items failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type IPItemType = string
|
||||
|
||||
const (
|
||||
@@ -248,13 +265,13 @@ func (this *IPItemDAO) UpdateIPItem(tx *dbs.Tx, itemId int64, ipFrom string, ipT
|
||||
}
|
||||
|
||||
// CountIPItemsWithListId 计算IP数量
|
||||
func (this *IPItemDAO) CountIPItemsWithListId(tx *dbs.Tx, listId int64, ipFrom string, ipTo string, keyword string) (int64, error) {
|
||||
func (this *IPItemDAO) CountIPItemsWithListId(tx *dbs.Tx, listId int64, ipFrom string, ipTo string, keyword string, eventLevel string) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(IPItemStateEnabled).
|
||||
Attr("listId", listId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(ipFrom LIKE :keyword OR ipTo LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(ipFrom) > 0 {
|
||||
query.Attr("ipFrom", ipFrom)
|
||||
@@ -262,17 +279,20 @@ func (this *IPItemDAO) CountIPItemsWithListId(tx *dbs.Tx, listId int64, ipFrom s
|
||||
if len(ipTo) > 0 {
|
||||
query.Attr("ipTo", ipTo)
|
||||
}
|
||||
if len(eventLevel) > 0 {
|
||||
query.Attr("eventLevel", eventLevel)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListIPItemsWithListId 查找IP列表
|
||||
func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword string, ipFrom string, ipTo string, offset int64, size int64) (result []*IPItem, err error) {
|
||||
func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword string, ipFrom string, ipTo string, eventLevel string, offset int64, size int64) (result []*IPItem, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(IPItemStateEnabled).
|
||||
Attr("listId", listId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(ipFrom LIKE :keyword OR ipTo LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(ipFrom) > 0 {
|
||||
query.Attr("ipFrom", ipFrom)
|
||||
@@ -280,6 +300,9 @@ func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword s
|
||||
if len(ipTo) > 0 {
|
||||
query.Attr("ipTo", ipTo)
|
||||
}
|
||||
if len(eventLevel) > 0 {
|
||||
query.Attr("eventLevel", eventLevel)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
@@ -291,35 +314,6 @@ func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword s
|
||||
|
||||
// ListIPItemsAfterVersion 根据版本号查找IP列表
|
||||
func (this *IPItemDAO) ListIPItemsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*IPItem, err error) {
|
||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
||||
ones, _, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
||||
Param("timestamp", time.Now().Unix()).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(100).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var expiredId = one.GetInt64("id")
|
||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = this.Query(tx).
|
||||
Pk(expiredId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("expiredAt", 0).
|
||||
Set("version", newVersion).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
// 这里不要设置状态参数,因为我们要知道哪些是删除的
|
||||
Gt("version", version).
|
||||
@@ -384,7 +378,7 @@ func (this *IPItemDAO) ExistsEnabledItem(tx *dbs.Tx, itemId int64) (bool, error)
|
||||
}
|
||||
|
||||
// CountAllEnabledIPItems 计算数量
|
||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool) (int64, error) {
|
||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool, eventLevel string, listType string) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
@@ -392,11 +386,20 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
||||
if listId > 0 {
|
||||
query.Attr("listId", listId)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
if len(listType) > 0 {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1 AND type=:listType))")
|
||||
query.Param("listType", listType)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(eventLevel) > 0 {
|
||||
query.Attr("eventLevel", eventLevel)
|
||||
}
|
||||
|
||||
return query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
@@ -405,7 +408,7 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
||||
}
|
||||
|
||||
// ListAllEnabledIPItems 搜索所有IP
|
||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool, offset int64, size int64) (result []*IPItem, err error) {
|
||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool, eventLevel string, listType string, offset int64, size int64) (result []*IPItem, err error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
@@ -413,11 +416,19 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64
|
||||
if listId > 0 {
|
||||
query.Attr("listId", listId)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
if len(listType) > 0 {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1 AND type=:listType))")
|
||||
query.Param("listType", listType)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(eventLevel) > 0 {
|
||||
query.Attr("eventLevel", eventLevel)
|
||||
}
|
||||
_, err = query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
@@ -438,6 +449,51 @@ func (this *IPItemDAO) UpdateItemsRead(tx *dbs.Tx) error {
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CleanExpiredIPItems 清除过期数据
|
||||
func (this *IPItemDAO) CleanExpiredIPItems(tx *dbs.Tx) error {
|
||||
// 删除 N 天之前过期的数据
|
||||
_, err := this.Query(tx).
|
||||
Where("expiredAt<=:timestamp").
|
||||
State(IPItemStateDisabled).
|
||||
Param("timestamp", time.Now().Unix()-7*86400). // N 天之前过期的
|
||||
Limit(10000). // 限制条数,防止数量过多导致超时
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
||||
ones, _, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
||||
Param("timestamp", time.Now().Unix()).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(500).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var expiredId = one.GetInt64("id")
|
||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 这里不重置过期时间用于清理
|
||||
_, err = this.Query(tx).
|
||||
Pk(expiredId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("version", newVersion).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
// 获取ListId
|
||||
@@ -464,7 +520,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -472,7 +528,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
} else {
|
||||
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIds(tx)
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -524,7 +580,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||
@@ -27,3 +31,34 @@ func TestIPItemDAO_DisableIPItemsWithListId(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_ListIPItemsAfterVersion(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
_, err := SharedIPItemDAO.ListIPItemsAfterVersion(tx, 0, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_CreateManyIPs(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var dao = NewIPItemDAO()
|
||||
var n = 10
|
||||
for i := 0; i < n; i++ {
|
||||
itemId, err := dao.CreateIPItem(tx, firewallconfigs.GlobalListId, "192."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255)), "", time.Now().Unix()+86400, "test", IPItemTypeIPv4, "warning", 0, 0, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = itemId
|
||||
/**err = dao.Query(tx).Pk(itemId).Set("state", 0).UpdateQuickly()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}**/
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ type IPItem struct {
|
||||
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
|
||||
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
|
||||
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
|
||||
IsRead uint8 `field:"isRead"` // 是否已读
|
||||
IsRead bool `field:"isRead"` // 是否已读
|
||||
}
|
||||
|
||||
type IPItemOperator struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
@@ -22,11 +23,11 @@ var listTypeCacheMap = map[int64]*IPList{} // listId => *IPList
|
||||
var DefaultGlobalIPList = &IPList{
|
||||
Id: uint32(firewallconfigs.GlobalListId),
|
||||
Name: "全局封锁名单",
|
||||
IsPublic: 1,
|
||||
IsGlobal: 1,
|
||||
IsPublic: true,
|
||||
IsGlobal: true,
|
||||
Type: "black",
|
||||
State: IPListStateEnabled,
|
||||
IsOn: 1,
|
||||
IsOn: true,
|
||||
}
|
||||
|
||||
type IPListDAO dbs.DAO
|
||||
@@ -184,6 +185,10 @@ func (this *IPListDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
|
||||
// CheckUserIPList 检查用户权限
|
||||
func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) error {
|
||||
if userId == 0 || listId == 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
ok, err := this.Query(tx).
|
||||
Pk(listId).
|
||||
Attr("userId", userId).
|
||||
@@ -194,6 +199,18 @@ func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) e
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查是否被用户的服务所使用
|
||||
policyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, policyId := range policyIds {
|
||||
if SharedHTTPFirewallPolicyDAO.CheckUserFirewallPolicy(tx, userId, policyId) == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
@@ -205,7 +222,7 @@ func (this *IPListDAO) CountAllEnabledIPLists(tx *dbs.Tx, listType string, isPub
|
||||
Attr("isPublic", isPublic)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR description LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
@@ -218,7 +235,7 @@ func (this *IPListDAO) ListEnabledIPLists(tx *dbs.Tx, listType string, isPublic
|
||||
Attr("isPublic", isPublic)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR description LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.Offset(offset).
|
||||
Limit(size).
|
||||
@@ -284,7 +301,7 @@ func (this *IPListDAO) NotifyUpdate(tx *dbs.Tx, listId int64, taskType NodeTaskT
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, taskType)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, taskType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user