Skip to content
This repository was archived by the owner on Nov 5, 2024. It is now read-only.

Commit 5cd2843

Browse files
committed
[proxy]请求匹配条件增加文件存在和文件不存在两个操作符
1 parent cf192ca commit 5cd2843

4 files changed

Lines changed: 165 additions & 4 deletions

File tree

teaconfigs/shared/request_cond.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import (
55
"encoding/binary"
66
"encoding/json"
77
"errors"
8+
"github.com/iwind/TeaGo/Tea"
89
"github.com/iwind/TeaGo/lists"
910
"github.com/iwind/TeaGo/types"
1011
"github.com/iwind/TeaGo/utils/string"
1112
"net"
13+
"os"
1214
"path/filepath"
1315
"regexp"
1416
"strings"
@@ -328,6 +330,32 @@ func (this *RequestCond) Match(formatter func(source string) string) bool {
328330
return this.ipToInt64(net.ParseIP(paramValue))%10 == types.Int64(this.Value)
329331
case RequestCondOperatorIPMod100:
330332
return this.ipToInt64(net.ParseIP(paramValue))%100 == types.Int64(this.Value)
333+
case RequestCondOperatorFileExist:
334+
index := strings.Index(paramValue, "?")
335+
if index > -1 {
336+
paramValue = paramValue[:index]
337+
}
338+
if len(paramValue) == 0 {
339+
return false
340+
}
341+
if !filepath.IsAbs(paramValue) {
342+
paramValue = Tea.Root + Tea.DS + paramValue
343+
}
344+
stat, err := os.Stat(paramValue)
345+
return err == nil && !stat.IsDir()
346+
case RequestCondOperatorFileNotExist:
347+
index := strings.Index(paramValue, "?")
348+
if index > -1 {
349+
paramValue = paramValue[:index]
350+
}
351+
if len(paramValue) == 0 {
352+
return true
353+
}
354+
if !filepath.IsAbs(paramValue) {
355+
paramValue = Tea.Root + Tea.DS + paramValue
356+
}
357+
stat, err := os.Stat(paramValue)
358+
return err != nil || stat.IsDir()
331359
}
332360

333361
return false

teaconfigs/shared/request_cond_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package shared
33
import (
44
"bytes"
55
"fmt"
6+
"github.com/iwind/TeaGo/Tea"
67
"github.com/iwind/TeaGo/assert"
78
"net"
89
"regexp"
@@ -685,6 +686,83 @@ func TestRequestCond_File(t *testing.T) {
685686
return source
686687
}))
687688
}
689+
690+
{
691+
cond := RequestCond{
692+
Param: "a.png",
693+
Operator: RequestCondOperatorFileExist,
694+
}
695+
a.IsNil(cond.Validate())
696+
a.IsFalse(cond.Match(func(source string) string {
697+
return source
698+
}))
699+
}
700+
701+
{
702+
cond := RequestCond{
703+
Param: Tea.Root + "/README.md",
704+
Operator: RequestCondOperatorFileExist,
705+
}
706+
a.IsNil(cond.Validate())
707+
a.IsTrue(cond.Match(func(source string) string {
708+
return source
709+
}))
710+
}
711+
712+
{
713+
cond := RequestCond{
714+
Param: Tea.Root + "/README.md?v=1",
715+
Operator: RequestCondOperatorFileExist,
716+
}
717+
a.IsNil(cond.Validate())
718+
a.IsTrue(cond.Match(func(source string) string {
719+
return source
720+
}))
721+
}
722+
723+
{
724+
cond := RequestCond{
725+
Param: Tea.Root,
726+
Operator: RequestCondOperatorFileExist,
727+
}
728+
a.IsNil(cond.Validate())
729+
a.IsFalse(cond.Match(func(source string) string {
730+
return source
731+
}))
732+
}
733+
734+
{
735+
cond := RequestCond{
736+
Param: Tea.Root,
737+
Operator: RequestCondOperatorFileExist,
738+
}
739+
a.IsNil(cond.Validate())
740+
a.IsFalse(cond.Match(func(source string) string {
741+
return source
742+
}))
743+
}
744+
745+
{
746+
cond := RequestCond{
747+
Param: "a.png",
748+
Operator: RequestCondOperatorFileNotExist,
749+
}
750+
a.IsNil(cond.Validate())
751+
a.IsTrue(cond.Match(func(source string) string {
752+
return source
753+
}))
754+
}
755+
756+
{
757+
cond := RequestCond{
758+
Param: Tea.Root + "/README.md",
759+
Operator: RequestCondOperatorFileNotExist,
760+
}
761+
a.IsNil(cond.Validate())
762+
a.IsFalse(cond.Match(func(source string) string {
763+
return source
764+
}))
765+
}
688766
}
689767

690768
func TestRequestCond_MimeType(t *testing.T) {

teaconfigs/shared/request_operators.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const (
4646
RequestCondOperatorIPMod10 RequestCondOperator = "ip mod 10"
4747
RequestCondOperatorIPMod100 RequestCondOperator = "ip mod 100"
4848
RequestCondOperatorIPMod RequestCondOperator = "ip mod"
49+
50+
// 文件相关
51+
RequestCondOperatorFileExist RequestCondOperator = "file exist"
52+
RequestCondOperatorFileNotExist RequestCondOperator = "file not exist"
4953
)
5054

5155
// 所有的运算符
@@ -206,5 +210,17 @@ func AllRequestOperators() []maps.Map {
206210
"op": RequestCondOperatorIPMod,
207211
"description": "对IP参数值取模,对比值格式为:除数,余数,比如10,1",
208212
},
213+
214+
{
215+
"name": "文件存在",
216+
"op": RequestCondOperatorFileExist,
217+
"description": "判断参数值解析后的文件是否存在",
218+
},
219+
220+
{
221+
"name": "文件不存在",
222+
"op": RequestCondOperatorFileNotExist,
223+
"description": "判断参数值解析后的文件是否不存在",
224+
},
209225
}
210226
}

teaproxy/request.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net/url"
2424
"os"
2525
"path/filepath"
26+
"strconv"
2627
"strings"
2728
"time"
2829
)
@@ -129,6 +130,8 @@ type Request struct {
129130
gzip *teaconfigs.GzipConfig
130131
debug bool
131132

133+
locationContext *teaconfigs.LocationConfig // 当前变量的上下文 *Location ...
134+
132135
hasForwardHeader bool
133136
}
134137

@@ -219,6 +222,8 @@ func (this *Request) reset(rawRequest *http.Request) {
219222

220223
this.accessLog = nil
221224

225+
this.locationContext = nil
226+
222227
this.gzip = nil
223228
this.debug = false
224229

@@ -331,6 +336,7 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
331336
if !location.On {
332337
continue
333338
}
339+
this.locationContext = location
334340
if locationMatches, ok := location.Match(rawPath, this.Format); ok {
335341
this.addVarMapping(locationMatches)
336342

@@ -363,6 +369,7 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
363369
}
364370
if location.RedirectToHttps && this.rawScheme == "http" {
365371
this.redirectToHttps = true
372+
this.locationContext = nil
366373
return nil
367374
}
368375

@@ -428,6 +435,7 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
428435
this.rewriteIsExternal = true
429436
this.rewriteRedirectMode = rule.RedirectMode()
430437
this.rewriteProxyHost = rule.ProxyHost
438+
this.locationContext = nil
431439
return nil
432440
}
433441

@@ -436,12 +444,14 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
436444
this.rewriteReplace = replace
437445
this.rewriteIsExternal = false
438446
this.rewriteRedirectMode = teaconfigs.RewriteFlagRedirect
447+
this.locationContext = nil
439448
return nil
440449
}
441450

442451
newURI, err := url.ParseRequestURI(replace)
443452
if err != nil {
444453
this.uri = replace
454+
this.locationContext = nil
445455
return nil
446456
}
447457
if len(newURI.RawQuery) > 0 {
@@ -458,18 +468,23 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
458468

459469
switch rule.TargetType() {
460470
case teaconfigs.RewriteTargetURL:
471+
this.locationContext = nil
461472
return this.configure(server, redirects, rule.IsBreak)
462473
case teaconfigs.RewriteTargetProxy:
463474
proxyId := rule.TargetProxy()
464475
server := SharedManager.FindServer(proxyId)
465476
if server == nil {
477+
this.locationContext = nil
466478
return errors.New("server with '" + proxyId + "' not found")
467479
}
468480
if !server.On {
481+
this.locationContext = nil
469482
return errors.New("server with '" + proxyId + "' not available now")
470483
}
484+
this.locationContext = nil
471485
return this.configure(server, redirects, rule.IsBreak)
472486
}
487+
this.locationContext = nil
473488
return nil
474489
}
475490
}
@@ -497,18 +512,22 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
497512
if len(location.Proxy) > 0 {
498513
server := SharedManager.FindServer(location.Proxy)
499514
if server == nil {
515+
this.locationContext = nil
500516
return errors.New("server with '" + location.Proxy + "' not found")
501517
}
502518
if !server.On {
519+
this.locationContext = nil
503520
return errors.New("server with '" + location.Proxy + "' not available now")
504521
}
522+
this.locationContext = nil
505523
return this.configure(server, redirects, breakRewrite)
506524
}
507525

508526
// backends
509527
if len(location.Backends) > 0 {
510528
backend := location.NextBackend(this.backendCall)
511529
if backend == nil {
530+
this.locationContext = nil
512531
return errors.New("no backends available")
513532
}
514533
if len(this.backendCall.ResponseCallbacks) > 0 {
@@ -536,9 +555,11 @@ func (this *Request) configure(server *teaconfigs.ServerConfig, redirects int, b
536555
if location.Websocket != nil && location.Websocket.On {
537556
this.backend = location.Websocket.NextBackend(this.backendCall)
538557
this.websocket = location.Websocket
558+
this.locationContext = nil
539559
return nil
540560
}
541561
}
562+
this.locationContext = nil
542563
}
543564

544565
// 如果经过location找到了相关配置,就终止
@@ -1137,7 +1158,7 @@ func (this *Request) Format(source string) string {
11371158
}
11381159
return addr
11391160
case "remotePort":
1140-
return fmt.Sprintf("%d", this.requestRemotePort())
1161+
return strconv.Itoa(this.requestRemotePort())
11411162
case "remoteUser":
11421163
return this.requestRemoteUser()
11431164
case "requestURI", "requestUri":
@@ -1151,7 +1172,20 @@ func (this *Request) Format(source string) string {
11511172
case "requestMethod":
11521173
return this.requestMethod()
11531174
case "requestFilename":
1154-
return this.requestFilename()
1175+
filename := this.requestFilename()
1176+
if len(filename) > 0 {
1177+
return filename
1178+
}
1179+
1180+
if this.locationContext != nil && len(this.locationContext.Root) > 0 {
1181+
return filepath.Clean(this.locationContext.Root + this.requestPath())
1182+
}
1183+
1184+
if len(this.root) > 0 {
1185+
return filepath.Clean(this.root + this.requestPath())
1186+
}
1187+
1188+
return ""
11551189
case "scheme":
11561190
return this.rawScheme
11571191
case "serverProtocol", "proto":
@@ -1161,7 +1195,7 @@ func (this *Request) Format(source string) string {
11611195
case "bodyBytesSent":
11621196
return fmt.Sprintf("%d", this.responseWriter.SentBodyBytes())
11631197
case "status":
1164-
return fmt.Sprintf("%d", this.responseWriter.StatusCode())
1198+
return strconv.Itoa(this.responseWriter.StatusCode())
11651199
case "statusMessage":
11661200
return http.StatusText(this.responseWriter.StatusCode())
11671201
case "timeISO8601":
@@ -1191,7 +1225,12 @@ func (this *Request) Format(source string) string {
11911225
case "serverName":
11921226
return this.serverName
11931227
case "serverPort":
1194-
return fmt.Sprintf("%d", this.requestServerPort())
1228+
return strconv.Itoa(this.requestServerPort())
1229+
case "documentRoot":
1230+
if this.locationContext != nil && len(this.locationContext.Root) > 0 {
1231+
return this.locationContext.Root
1232+
}
1233+
return this.root
11951234
}
11961235

11971236
dotIndex := strings.Index(varName, ".")

0 commit comments

Comments
 (0)