🐛 fix(handlers): 统一错误响应为安全 JSON 并补参数校验

- 新增 respondError:JSON 安全编码,客户端错误返回 400,服务端错误返回 500
- 收编 book/content/media/category 中 13 处 fmt.Fprintf 内联 JSON,修复错误信息含引号/换行时产出非法 JSON 的问题
- search/detail/catalog/multi-detail/content/multi-content/item-summary/audio/video 补必需参数校验,缺参返回 400
- search 的 offset/tab_type 非数字时返回 400,不再静默置 0
- 补齐 multi-detail/multi-content 的请求统计计数
- 新增 error_response_test.go:3 个测试锁定错误响应行为
- openapi.yaml 新增 ServerError 响应组件,15 个业务接口补 400/500 响应定义

BREAKING CHANGE: 业务接口错误不再返回 HTTP 200,缺参返回 400,上游失败返回 500
This commit is contained in:
chenxin committed 2026-09-29 22:47:01 +08:00
1 parent 1eccebedf9
commit d1774a3902
7 files changed
+209 -52

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
package handlers
import (
"encoding/json"
"net/http/httptest"
"testing"
)
// TestRespondErrorProducesValidJSON 错误信息含引号/换行时输出仍须是合法 JSON
func TestRespondErrorProducesValidJSON(t *testing.T) {
w := httptest.NewRecorder()
respondError(w, "上游返回了 \"引号\" 和\n换行", false)
var body map[string]interface{}
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
t.Fatalf("非法 JSON: %v, body: %s", err, w.Body.String())
}
if body["code"].(float64) != -1 {
t.Errorf("code 应为 -1, got %v", body["code"])
}
if w.Code != 500 {
t.Errorf("服务端错误应返回 500, got %d", w.Code)
}
}
// TestRespondErrorClientErr 客户端错误应返回 400
func TestRespondErrorClientErr(t *testing.T) {
w := httptest.NewRecorder()
respondError(w, "缺少 book_id 参数", true)
if w.Code != 400 {
t.Errorf("客户端错误应返回 400, got %d", w.Code)
}
}
// TestHandleDetailMissingParam 缺少必需参数返回 400 而非透传到上游
func TestHandleDetailMissingParam(t *testing.T) {
w := httptest.NewRecorder()
HandleDetail(w, httptest.NewRequest("GET", "/detail", nil))
if w.Code != 400 {
t.Errorf("缺参应返回 400, got %d, body: %s", w.Code, w.Body.String())
}
}