Files
pangolin/server/internal/httpapi/routing.go
T

71 lines
2.2 KiB
Go

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)
}