lib/checker: Implement X-Original-URI support (#1015)
This commit is contained in:
parent
f3cd6c9ca4
commit
d1d631a18a
3 changed files with 101 additions and 0 deletions
|
|
@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Bump AI-robots.txt to version 1.39
|
- Bump AI-robots.txt to version 1.39
|
||||||
- Add a default block rule for Huawei Cloud.
|
- Add a default block rule for Huawei Cloud.
|
||||||
- Add a default block rule for Alibaba Cloud.
|
- Add a default block rule for Alibaba Cloud.
|
||||||
|
- Add X-Request-URI support so that Subrequest Authentication has path support.
|
||||||
|
|
||||||
### Security-relevant changes
|
### Security-relevant changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,13 @@ func NewPathChecker(rexStr string) (checker.Impl, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc *PathChecker) Check(r *http.Request) (bool, error) {
|
func (pc *PathChecker) Check(r *http.Request) (bool, error) {
|
||||||
|
originalUrl := r.Header.Get("X-Original-URI")
|
||||||
|
if originalUrl != "" {
|
||||||
|
if pc.regexp.MatchString(originalUrl) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if pc.regexp.MatchString(r.URL.Path) {
|
if pc.regexp.MatchString(r.URL.Path) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,3 +198,96 @@ func TestHeaderExistsChecker(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPathChecker_XOriginalURI(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
regex string
|
||||||
|
xOriginalURI string
|
||||||
|
urlPath string
|
||||||
|
headerKey string
|
||||||
|
expectedMatch bool
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "X-Original-URI matches regex (with trailing space - current typo)",
|
||||||
|
regex: "^/api/.*",
|
||||||
|
xOriginalURI: "/api/users",
|
||||||
|
urlPath: "/different/path",
|
||||||
|
headerKey: "X-Original-URI",
|
||||||
|
expectedMatch: true,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "X-Original-URI doesn't match, falls back to URL.Path",
|
||||||
|
regex: "^/admin/.*",
|
||||||
|
xOriginalURI: "/api/users",
|
||||||
|
urlPath: "/admin/dashboard",
|
||||||
|
headerKey: "X-Original-URI",
|
||||||
|
expectedMatch: true,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Neither X-Original-URI nor URL.Path match",
|
||||||
|
regex: "^/admin/.*",
|
||||||
|
xOriginalURI: "/api/users",
|
||||||
|
urlPath: "/public/info",
|
||||||
|
headerKey: "X-Original-URI ",
|
||||||
|
expectedMatch: false,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Empty X-Original-URI, URL.Path matches",
|
||||||
|
regex: "^/static/.*",
|
||||||
|
xOriginalURI: "",
|
||||||
|
urlPath: "/static/css/style.css",
|
||||||
|
headerKey: "X-Original-URI",
|
||||||
|
expectedMatch: true,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Complex regex matching X-Original-URI",
|
||||||
|
regex: `^/api/v[0-9]+/(users|posts)/[0-9]+$`,
|
||||||
|
xOriginalURI: "/api/v1/users/123",
|
||||||
|
urlPath: "/different",
|
||||||
|
headerKey: "X-Original-URI",
|
||||||
|
expectedMatch: true,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Create the PathChecker
|
||||||
|
pc, err := NewPathChecker(tt.regex)
|
||||||
|
if err != nil {
|
||||||
|
if !tt.expectError {
|
||||||
|
t.Fatalf("NewPathChecker() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.expectError {
|
||||||
|
t.Fatal("NewPathChecker() expected error but got none")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "http://example.com"+tt.urlPath, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.xOriginalURI != "" {
|
||||||
|
req.Header.Set(tt.headerKey, tt.xOriginalURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
match, err := pc.Check(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Check() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if match != tt.expectedMatch {
|
||||||
|
t.Errorf("Check() = %v, want %v", match, tt.expectedMatch)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue