75 lines
2.5 KiB
Go
75 lines
2.5 KiB
Go
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)
|
||
}
|