chore: establish local platform baseline

This commit is contained in:
Codex Local
2026-08-26 06:41:54 +08:00
commit 29bdf4900f
575 changed files with 95644 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
package httpapi
import (
"context"
"errors"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"data-terminal-cloud/internal/deviceauth"
"data-terminal-cloud/internal/identity"
)
type fakeRateLimiter struct {
result RateLimitResult
err error
calls int
scopes []string
}
func (f *fakeRateLimiter) Allow(_ context.Context, scope, identifier string) (RateLimitResult, error) {
f.calls++
f.scopes = append(f.scopes, scope+":"+identifier)
return f.result, f.err
}
func TestRateLimitRejectsBusinessRequest(t *testing.T) {
limiter := &fakeRateLimiter{result: RateLimitResult{Allowed: false, RetryAfter: 1500 * time.Millisecond}}
handler := Middleware(slog.Default(), "test", 1024, limiter, http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
t.Fatal("downstream handler must not be called")
}))
request := httptest.NewRequest(http.MethodGet, "/api/v1/items", nil)
request.RemoteAddr = "192.0.2.1:1234"
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
if recorder.Code != http.StatusTooManyRequests || recorder.Header().Get("Retry-After") != "2" {
t.Fatalf("status = %d, retry-after = %q", recorder.Code, recorder.Header().Get("Retry-After"))
}
if !strings.Contains(recorder.Body.String(), "RATE_LIMITED") {
t.Fatalf("unexpected body: %s", recorder.Body.String())
}
}
func TestUserRateLimitUsesVerifiedUserAndSelectedTenant(t *testing.T) {
limiter := &fakeRateLimiter{result: RateLimitResult{Allowed: true, Remaining: 7}}
called := false
handler := UserRateLimit(slog.Default(), limiter, http.HandlerFunc(func(http.ResponseWriter, *http.Request) { called = true }))
request := httptest.NewRequest(http.MethodGet, "/api/v1/households", nil)
request.Header.Set("X-Tenant-Id", "tenant-public-id")
request = request.WithContext(identity.WithPrincipal(request.Context(), identity.Principal{Issuer: "issuer", Subject: "user-subject"}))
handler.ServeHTTP(httptest.NewRecorder(), request)
if !called || strings.Join(limiter.scopes, ",") != "user:issuer\x00user-subject,tenant:tenant-public-id" {
t.Fatalf("called=%t scopes=%q", called, limiter.scopes)
}
}
func TestDeviceRateLimitRejectsVerifiedDeviceScopeBeforeTenant(t *testing.T) {
limiter := &fakeRateLimiter{result: RateLimitResult{Allowed: false, RetryAfter: time.Second}}
handler := DeviceRateLimit(slog.Default(), limiter, http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
t.Fatal("downstream handler must not be called")
}))
request := httptest.NewRequest(http.MethodGet, "/device/v2/config", nil)
request = request.WithContext(deviceauth.WithIdentity(request.Context(), deviceauth.Identity{ID: "device-internal", TenantID: "tenant-internal"}))
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
if recorder.Code != http.StatusTooManyRequests || recorder.Header().Get("X-RateLimit-Scope") != "device" {
t.Fatalf("status=%d headers=%v", recorder.Code, recorder.Header())
}
if strings.Join(limiter.scopes, ",") != "device:device-internal" {
t.Fatalf("scopes=%q", limiter.scopes)
}
}
func TestRateLimitSkipsHealthAndFailsOpen(t *testing.T) {
limiter := &fakeRateLimiter{err: errors.New("redis unavailable")}
downstreamCalls := 0
handler := Middleware(slog.Default(), "test", 1024, limiter, http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
downstreamCalls++
writer.WriteHeader(http.StatusNoContent)
}))
for _, path := range []string{"/health/live", "/api/v1/items"} {
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, path, nil))
if recorder.Code != http.StatusNoContent {
t.Fatalf("path %s status = %d", path, recorder.Code)
}
}
if downstreamCalls != 2 || limiter.calls != 1 {
t.Fatalf("downstream calls = %d, limiter calls = %d", downstreamCalls, limiter.calls)
}
}
func TestBodyLimitRejectsKnownOversizedRequestBeforeHandler(t *testing.T) {
called := false
handler := Middleware(slog.Default(), "test", 16, nil, http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
called = true
}))
request := httptest.NewRequest(http.MethodPost, "/api/v1/items", strings.NewReader(strings.Repeat("x", 17)))
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
if recorder.Code != http.StatusRequestEntityTooLarge || called {
t.Fatalf("status=%d called=%t body=%s", recorder.Code, called, recorder.Body.String())
}
if !strings.Contains(recorder.Body.String(), "REQUEST_BODY_TOO_LARGE") {
t.Fatalf("unexpected body: %s", recorder.Body.String())
}
}