feat(routing): GET/POST /v1/me/routing 端点 + openapi
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/wangjia/pangolin/server/internal/apierr"
|
||||
"github.com/wangjia/pangolin/server/internal/auth"
|
||||
"github.com/wangjia/pangolin/server/internal/routing"
|
||||
)
|
||||
|
||||
// RoutingAPI serves /v1/me/routing: the user's configurable routing profile
|
||||
// (可配置分流). GET returns the stored profile or routing.Default() when the
|
||||
// user hasn't customized one yet; POST validates and upserts.
|
||||
type RoutingAPI struct {
|
||||
store *routing.Store
|
||||
}
|
||||
|
||||
// NewRoutingAPI creates a RoutingAPI backed by the given routing.Store.
|
||||
func NewRoutingAPI(store *routing.Store) *RoutingAPI { return &RoutingAPI{store: store} }
|
||||
|
||||
// GetProfile handles GET /v1/me/routing.
|
||||
func (a *RoutingAPI) GetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
uid, ok := auth.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
apierr.WriteJSON(w, http.StatusUnauthorized, apierr.ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
p, err := a.store.Get(r.Context(), uid)
|
||||
if err != nil {
|
||||
apierr.WriteJSON(w, http.StatusInternalServerError, apierr.ErrInternal)
|
||||
return
|
||||
}
|
||||
if p == nil {
|
||||
p = routing.Default()
|
||||
}
|
||||
writeJSON(w, http.StatusOK, p)
|
||||
}
|
||||
|
||||
// SaveProfile handles POST /v1/me/routing. On validation failure it returns
|
||||
// 400 with every offending field reported at once (no partial save).
|
||||
func (a *RoutingAPI) SaveProfile(w http.ResponseWriter, r *http.Request) {
|
||||
uid, ok := auth.UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
apierr.WriteJSON(w, http.StatusUnauthorized, apierr.ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
var p routing.Profile
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64*1024)).Decode(&p); err != nil {
|
||||
apierr.WriteJSON(w, http.StatusBadRequest, apierr.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
p.Normalize()
|
||||
if errs := p.Validate(); len(errs) > 0 {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"code": "routing_invalid",
|
||||
"message_zh": "规则校验未通过",
|
||||
"message_en": "Rule validation failed",
|
||||
"errors": errs,
|
||||
})
|
||||
return
|
||||
}
|
||||
if err := a.store.Upsert(r.Context(), uid, &p); err != nil {
|
||||
apierr.WriteJSON(w, http.StatusInternalServerError, apierr.ErrInternal)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, &p)
|
||||
}
|
||||
Reference in New Issue
Block a user