feat(platform-api): enforce request timeout

This commit is contained in:
lingniu
2026-07-04 00:55:43 +08:00
parent 081f8b5099
commit 4bfaf8c4c8
5 changed files with 57 additions and 1 deletions

View File

@@ -35,5 +35,12 @@ func NewServer(cfg config.Config) http.Handler {
}
}
api := platform.NewHandler(platform.NewService(store))
return static.Handler(cfg.StaticDir, api)
return withRequestTimeout(static.Handler(cfg.StaticDir, api), cfg.RequestTimeout)
}
func withRequestTimeout(next http.Handler, timeout time.Duration) http.Handler {
if timeout <= 0 {
return next
}
return http.TimeoutHandler(next, timeout, `{"error":{"code":"REQUEST_TIMEOUT","message":"请求处理超时"},"traceId":"timeout","timestamp":0}`)
}

View File

@@ -0,0 +1,29 @@
package app
import (
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestWithRequestTimeoutAddsContextDeadline(t *testing.T) {
handler := withRequestTimeout(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
deadline, ok := r.Context().Deadline()
if !ok {
t.Fatal("request context should have deadline")
}
if time.Until(deadline) > 250*time.Millisecond {
t.Fatalf("deadline too far away: %s", time.Until(deadline))
}
w.WriteHeader(http.StatusNoContent)
}), 200*time.Millisecond)
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/ops/health", nil)
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusNoContent {
t.Fatalf("status = %d", rec.Code)
}
}

View File

@@ -3,6 +3,7 @@ package config
import (
"os"
"strconv"
"time"
)
type Config struct {
@@ -18,6 +19,7 @@ type Config struct {
TDengineDatabase string
CapacityCheckBin string
AuthToken string
RequestTimeout time.Duration
}
func Load() Config {
@@ -34,6 +36,7 @@ func Load() Config {
TDengineDatabase: env("TDENGINE_DATABASE", "lingniu_vehicle_ts"),
CapacityCheckBin: os.Getenv("CAPACITY_CHECK_BIN"),
AuthToken: os.Getenv("AUTH_TOKEN"),
RequestTimeout: time.Duration(envInt("REQUEST_TIMEOUT_MS", 5000)) * time.Millisecond,
}
}

View File

@@ -0,0 +1,16 @@
package config
import (
"testing"
"time"
)
func TestLoadReadsRequestTimeout(t *testing.T) {
t.Setenv("REQUEST_TIMEOUT_MS", "1200")
cfg := Load()
if cfg.RequestTimeout != 1200*time.Millisecond {
t.Fatalf("RequestTimeout = %s, want 1.2s", cfg.RequestTimeout)
}
}

View File

@@ -35,6 +35,7 @@ TDENGINE_DSN=root:***@ws(172.17.111.57:6041)/
TDENGINE_DATABASE=lingniu_vehicle_ts
CAPACITY_CHECK_BIN=/opt/lingniu-go-native/current/capacity-check
AUTH_TOKEN=***
REQUEST_TIMEOUT_MS=5000
```
## Health