package http import ( "encoding/json" "net/http" roomv1 "hyapp/api/proto/room/v1" "hyapp/pkg/idgen" "hyapp/services/gateway-service/internal/auth" "hyapp/services/gateway-service/internal/client" ) // Handler 负责把 HTTP JSON 请求转换为 room-service gRPC 调用。 type Handler struct { roomClient client.RoomClient } // NewHandler 初始化 gateway HTTP 入口。 func NewHandler(roomClient client.RoomClient) *Handler { return &Handler{roomClient: roomClient} } // Routes 注册首版房间命令 HTTP 接口。 func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler { mux := http.NewServeMux() mux.Handle("/rooms/create", jwtVerifier.Middleware(http.HandlerFunc(h.createRoom))) mux.Handle("/rooms/join", jwtVerifier.Middleware(http.HandlerFunc(h.joinRoom))) mux.Handle("/rooms/leave", jwtVerifier.Middleware(http.HandlerFunc(h.leaveRoom))) mux.Handle("/rooms/mic/up", jwtVerifier.Middleware(http.HandlerFunc(h.micUp))) mux.Handle("/rooms/mic/down", jwtVerifier.Middleware(http.HandlerFunc(h.micDown))) mux.Handle("/rooms/mic/change", jwtVerifier.Middleware(http.HandlerFunc(h.changeMicSeat))) mux.Handle("/rooms/user/mute", jwtVerifier.Middleware(http.HandlerFunc(h.muteUser))) mux.Handle("/rooms/user/kick", jwtVerifier.Middleware(http.HandlerFunc(h.kickUser))) mux.Handle("/rooms/gift/send", jwtVerifier.Middleware(http.HandlerFunc(h.sendGift))) return mux } func (h *Handler) createRoom(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` OwnerUserID int64 `json:"owner_user_id"` HostUserID int64 `json:"host_user_id"` SeatCount int32 `json:"seat_count"` Mode string `json:"mode"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.CreateRoom(request.Context(), &roomv1.CreateRoomRequest{ Meta: meta(request, body.RoomID), OwnerUserId: body.OwnerUserID, HostUserId: body.HostUserID, SeatCount: body.SeatCount, Mode: body.Mode, }) write(writer, resp, err) } func (h *Handler) joinRoom(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` Role string `json:"role"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.JoinRoom(request.Context(), &roomv1.JoinRoomRequest{ Meta: meta(request, body.RoomID), Role: body.Role, }) write(writer, resp, err) } func (h *Handler) leaveRoom(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.LeaveRoom(request.Context(), &roomv1.LeaveRoomRequest{ Meta: meta(request, body.RoomID), }) write(writer, resp, err) } func (h *Handler) micUp(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` SeatNo int32 `json:"seat_no"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.MicUp(request.Context(), &roomv1.MicUpRequest{ Meta: meta(request, body.RoomID), SeatNo: body.SeatNo, }) write(writer, resp, err) } func (h *Handler) micDown(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` TargetUserID int64 `json:"target_user_id"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.MicDown(request.Context(), &roomv1.MicDownRequest{ Meta: meta(request, body.RoomID), TargetUserId: body.TargetUserID, }) write(writer, resp, err) } func (h *Handler) changeMicSeat(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` TargetUserID int64 `json:"target_user_id"` SeatNo int32 `json:"seat_no"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.ChangeMicSeat(request.Context(), &roomv1.ChangeMicSeatRequest{ Meta: meta(request, body.RoomID), TargetUserId: body.TargetUserID, SeatNo: body.SeatNo, }) write(writer, resp, err) } func (h *Handler) muteUser(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` TargetUserID int64 `json:"target_user_id"` Muted bool `json:"muted"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.MuteUser(request.Context(), &roomv1.MuteUserRequest{ Meta: meta(request, body.RoomID), TargetUserId: body.TargetUserID, Muted: body.Muted, }) write(writer, resp, err) } func (h *Handler) kickUser(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` TargetUserID int64 `json:"target_user_id"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.KickUser(request.Context(), &roomv1.KickUserRequest{ Meta: meta(request, body.RoomID), TargetUserId: body.TargetUserID, }) write(writer, resp, err) } func (h *Handler) sendGift(writer http.ResponseWriter, request *http.Request) { var body struct { RoomID string `json:"room_id"` TargetUserID int64 `json:"target_user_id"` GiftID string `json:"gift_id"` GiftCount int32 `json:"gift_count"` GiftUnitValue int64 `json:"gift_unit_value"` } if !decode(writer, request, &body) { return } resp, err := h.roomClient.SendGift(request.Context(), &roomv1.SendGiftRequest{ Meta: meta(request, body.RoomID), TargetUserId: body.TargetUserID, GiftId: body.GiftID, GiftCount: body.GiftCount, GiftUnitValue: body.GiftUnitValue, }) write(writer, resp, err) } func meta(request *http.Request, roomID string) *roomv1.RequestMeta { return &roomv1.RequestMeta{ RequestId: idgen.New("req"), CommandId: idgen.New("cmd"), ActorUserId: auth.UserIDFromContext(request.Context()), RoomId: roomID, GatewayNodeId: "gateway-local", SessionId: idgen.New("sess"), SentAtMs: 0, } } func decode(writer http.ResponseWriter, request *http.Request, out any) bool { if err := json.NewDecoder(request.Body).Decode(out); err != nil { http.Error(writer, err.Error(), http.StatusBadRequest) return false } return true } func write(writer http.ResponseWriter, body any, err error) { if err != nil { http.Error(writer, err.Error(), http.StatusBadGateway) return } writer.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(writer).Encode(body) }