优化结构

This commit is contained in:
Yvan
2026-08-21 21:37:30 +08:00
parent a2ce3ae218
commit e4ba0dced9
41 changed files with 3646 additions and 364 deletions
@@ -1,7 +1,9 @@
package middleware
import (
"bytes"
"io"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
@@ -63,3 +65,60 @@ func TestAccessLogAllowsMediaLimitOnlyOnUploadRoute(t *testing.T) {
t.Fatalf("status=%d called=%v body=%s", response.Code, called, response.Body.String())
}
}
func TestAccessLogRedactsPaymentCallbackPayloadAndHeaders(t *testing.T) {
gin.SetMode(gin.TestMode)
var logs bytes.Buffer
logger := slog.New(slog.NewTextHandler(&logs, &slog.HandlerOptions{Level: slog.LevelInfo}))
runtime := conf.NewRuntime(nil, &conf.AdminBackend{Zap: &conf.AdminBackend_Zap{AccessReqBody: true, AccessReqHeaders: true, AccessRespData: true}})
engine := gin.New()
engine.Use(AccessLog(runtime, logger, "test"))
engine.POST("/api/payment/callback/:provider", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"body": "callback-response-secret"})
})
request := httptest.NewRequest(http.MethodPost, "/api/payment/callback/alipay?signature=query-secret", strings.NewReader("payment-body-secret"))
request.Header.Set("Content-Type", "application/json; boundary=credential-secret")
request.Header.Set("Authorization", "Bearer header-secret")
request.Header.Set("X-Alipay-Signature", "signature-secret")
response := httptest.NewRecorder()
engine.ServeHTTP(response, request)
logText := logs.String()
for _, secret := range []string{"payment-body-secret", "query-secret", "header-secret", "signature-secret", "callback-response-secret", "credential-secret"} {
if strings.Contains(logText, secret) {
t.Fatalf("payment callback secret leaked into access log: %q in %s", secret, logText)
}
}
for _, marker := range []string{"payment_callback=true", "payment_provider=alipay", "body_sha256=", "http_status=200"} {
if !strings.Contains(logText, marker) {
t.Fatalf("payment callback access summary missing %q: %s", marker, logText)
}
}
}
func TestAccessLogOmitsPaymentIntegrationConfigBody(t *testing.T) {
gin.SetMode(gin.TestMode)
var logs bytes.Buffer
logger := slog.New(slog.NewTextHandler(&logs, &slog.HandlerOptions{Level: slog.LevelInfo}))
runtime := conf.NewRuntime(nil, &conf.AdminBackend{Zap: &conf.AdminBackend_Zap{AccessReqBody: true, AccessReqHeaders: true, AccessRespData: true}})
engine := gin.New()
engine.Use(AccessLog(runtime, logger, "test"))
engine.PUT("/api/integration/configs/:kind/:provider", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"code": 0}) })
body := `{"enabled":true,"config":{"key":"saobei-secret","certificate_blob":"certificate-secret","unknown_credential":"credential-secret"}}`
request := httptest.NewRequest(http.MethodPut, "/api/integration/configs/payment/saobei", strings.NewReader(body))
request.Header.Set("Content-Type", "application/json")
response := httptest.NewRecorder()
engine.ServeHTTP(response, request)
logText := logs.String()
for _, secret := range []string{"saobei-secret", "certificate-secret", "credential-secret"} {
if strings.Contains(logText, secret) {
t.Fatalf("payment configuration secret leaked into access log: %q in %s", secret, logText)
}
}
if !strings.Contains(logText, "支付配置正文已省略") || !strings.Contains(logText, "body_sha256=") {
t.Fatalf("payment configuration summary missing: %s", logText)
}
}