package http import ( "net/http" roomv1 "hyapp/api/proto/room/v1" "hyapp/pkg/idgen" "hyapp/services/gateway-service/internal/auth" "hyapp/services/gateway-service/internal/client" ) // Handler 是 gateway 的 HTTP transport adapter。 // 它只依赖跨服务 client,不持有房间状态,也不直接实现房间命令语义。 type Handler struct { roomClient client.RoomClient userClient client.UserAuthClient userIdentityClient client.UserIdentityClient } // NewHandler 装配 gateway HTTP handler 的内部依赖。 func NewHandler(roomClient client.RoomClient, userClient ...client.UserAuthClient) *Handler { handler := &Handler{roomClient: roomClient} if len(userClient) > 0 { handler.userClient = userClient[0] } return handler } // NewHandlerWithClients 装配完整 gateway HTTP handler。 // 保留 NewHandler 是为了不破坏只测 room/auth transport 的旧测试构造。 func NewHandlerWithClients(roomClient client.RoomClient, userClient client.UserAuthClient, userIdentityClient client.UserIdentityClient) *Handler { return &Handler{ roomClient: roomClient, userClient: userClient, userIdentityClient: userIdentityClient, } } // meta 把外部 HTTP 请求上下文转换成 room-service 命令元信息。 // 当前 gateway 只生成命令入口所需的最小追踪字段,状态版本和幂等落点由 room-service 负责。 func meta(request *http.Request, roomID string) *roomv1.RequestMeta { return &roomv1.RequestMeta{ RequestId: requestIDFromContext(request.Context()), CommandId: idgen.New("cmd"), ActorUserId: auth.UserIDFromContext(request.Context()), RoomId: roomID, GatewayNodeId: "gateway-local", SessionId: idgen.New("sess"), SentAtMs: 0, } } // decode 统一处理 HTTP JSON 入参解析失败分支。 // gateway 在这里拒绝非法 JSON,不做房间业务校验,避免把 Room Cell 规则复制到入口层。 func decode(writer http.ResponseWriter, request *http.Request, out any) bool { if err := decodeJSON(request.Body, out); err != nil { writeError(writer, request, http.StatusBadRequest, codeInvalidJSON, "invalid request body") return false } return true } // write 统一把内部 gRPC 调用结果转换为 HTTP JSON 响应。 // 首版不在 gateway 细分 gRPC 错误码,避免入口层提前耦合 room-service 的业务错误模型。 func write(writer http.ResponseWriter, request *http.Request, body any, err error) { if err != nil { writeRPCError(writer, request, err) return } writeOK(writer, request, body) }