mirror of
https://github.com/gin-gonic/gin.git
synced 2026-04-29 15:08:19 +08:00
refactor(recovery): inline header prefix check and strengthen case tests
Drop the small hasHeaderPrefixFold helper and inline the len+EqualFold check in secureRequestDump for a simpler, single-site hardcoded replacement. Also switch the existing lowercase/mixed-case Authorization tests to write directly to r.Header (bypassing http.Header.Set canonicalization) so they actually exercise case-insensitive matching on the wire, and add uppercase Authorization plus lowercase/uppercase Proxy-Authorization cases.
This commit is contained in:
parent
3f1b179fdc
commit
528a95d48d
13
recovery.go
13
recovery.go
@ -100,22 +100,21 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
|
||||
func secureRequestDump(r *http.Request) string {
|
||||
httpRequest, _ := httputil.DumpRequest(r, false)
|
||||
lines := strings.Split(bytesconv.BytesToString(httpRequest), "\r\n")
|
||||
const (
|
||||
authPrefix = "Authorization:"
|
||||
proxyPrefix = "Proxy-Authorization:"
|
||||
)
|
||||
for i, line := range lines {
|
||||
switch {
|
||||
case hasHeaderPrefixFold(line, "Authorization:"):
|
||||
case len(line) >= len(authPrefix) && strings.EqualFold(line[:len(authPrefix)], authPrefix):
|
||||
lines[i] = "Authorization: *"
|
||||
case hasHeaderPrefixFold(line, "Proxy-Authorization:"):
|
||||
case len(line) >= len(proxyPrefix) && strings.EqualFold(line[:len(proxyPrefix)], proxyPrefix):
|
||||
lines[i] = "Proxy-Authorization: *"
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\r\n")
|
||||
}
|
||||
|
||||
// hasHeaderPrefixFold reports whether line begins with prefix, ignoring ASCII case.
|
||||
func hasHeaderPrefixFold(line, prefix string) bool {
|
||||
return len(line) >= len(prefix) && strings.EqualFold(line[:len(prefix)], prefix)
|
||||
}
|
||||
|
||||
func defaultHandleRecovery(c *Context, _ any) {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@ -274,20 +274,32 @@ func TestSecureRequestDump(t *testing.T) {
|
||||
wantNotContain: "Bearer secret-token",
|
||||
},
|
||||
{
|
||||
// Bypass http.Header.Set canonicalization to put a lowercase
|
||||
// header name on the wire and verify case-insensitive matching.
|
||||
name: "authorization header lowercase",
|
||||
req: func() *http.Request {
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||
r.Header.Set("authorization", "some-secret")
|
||||
r.Header["authorization"] = []string{"some-secret"}
|
||||
return r
|
||||
}(),
|
||||
wantContains: "Authorization: *",
|
||||
wantNotContain: "some-secret",
|
||||
},
|
||||
{
|
||||
name: "AUTHORIZATION header uppercase",
|
||||
req: func() *http.Request {
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||
r.Header["AUTHORIZATION"] = []string{"UPPER-SECRET"}
|
||||
return r
|
||||
}(),
|
||||
wantContains: "Authorization: *",
|
||||
wantNotContain: "UPPER-SECRET",
|
||||
},
|
||||
{
|
||||
name: "Authorization header mixed case",
|
||||
req: func() *http.Request {
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||
r.Header.Set("AuThOrIzAtIoN", "token123")
|
||||
r.Header["AuThOrIzAtIoN"] = []string{"token123"}
|
||||
return r
|
||||
}(),
|
||||
wantContains: "Authorization: *",
|
||||
@ -303,6 +315,26 @@ func TestSecureRequestDump(t *testing.T) {
|
||||
wantContains: "Proxy-Authorization: *",
|
||||
wantNotContain: "Basic cHJveHk6c2VjcmV0",
|
||||
},
|
||||
{
|
||||
name: "proxy-authorization header lowercase",
|
||||
req: func() *http.Request {
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||
r.Header["proxy-authorization"] = []string{"Basic bG93ZXI="}
|
||||
return r
|
||||
}(),
|
||||
wantContains: "Proxy-Authorization: *",
|
||||
wantNotContain: "Basic bG93ZXI=",
|
||||
},
|
||||
{
|
||||
name: "PROXY-AUTHORIZATION header uppercase",
|
||||
req: func() *http.Request {
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||
r.Header["PROXY-AUTHORIZATION"] = []string{"Basic VVBQRVI="}
|
||||
return r
|
||||
}(),
|
||||
wantContains: "Proxy-Authorization: *",
|
||||
wantNotContain: "Basic VVBQRVI=",
|
||||
},
|
||||
{
|
||||
name: "No Authorization header",
|
||||
req: func() *http.Request {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user