Initial commit
This commit is contained in:
73
server/internal/httpapi/response.go
Normal file
73
server/internal/httpapi/response.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const maxJSONBody = 1 << 20
|
||||
|
||||
type apiError struct {
|
||||
Status int
|
||||
Code string
|
||||
Message string
|
||||
Details any
|
||||
}
|
||||
|
||||
func (e *apiError) Error() string { return e.Code + ": " + e.Message }
|
||||
|
||||
func writeJSON(w http.ResponseWriter, status int, value any) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(status)
|
||||
_ = json.NewEncoder(w).Encode(value)
|
||||
}
|
||||
|
||||
func writeError(w http.ResponseWriter, err error) {
|
||||
var target *apiError
|
||||
if !errors.As(err, &target) {
|
||||
target = &apiError{Status: http.StatusInternalServerError, Code: "INTERNAL_ERROR", Message: "服务暂时不可用"}
|
||||
}
|
||||
body := map[string]any{
|
||||
"error": map[string]any{
|
||||
"code": target.Code,
|
||||
"message": target.Message,
|
||||
},
|
||||
}
|
||||
if target.Details != nil {
|
||||
body["error"].(map[string]any)["details"] = target.Details
|
||||
}
|
||||
writeJSON(w, target.Status, body)
|
||||
}
|
||||
|
||||
func decodeJSON(r *http.Request, dst any) error {
|
||||
decoder := json.NewDecoder(io.LimitReader(r.Body, maxJSONBody))
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(dst); err != nil {
|
||||
return &apiError{Status: http.StatusBadRequest, Code: "INVALID_JSON", Message: "请求内容格式不正确"}
|
||||
}
|
||||
if err := decoder.Decode(&struct{}{}); !errors.Is(err, io.EOF) {
|
||||
return &apiError{Status: http.StatusBadRequest, Code: "INVALID_JSON", Message: "请求只能包含一个 JSON 对象"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func marshalResponse(value any) ([]byte, error) {
|
||||
body, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func requestHash(value any) (string, error) {
|
||||
body, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sum := sha256.Sum256(body)
|
||||
return hex.EncodeToString(sum[:]), nil
|
||||
}
|
||||
Reference in New Issue
Block a user