From b6efd99ea39c86db31b2f90f5beb12d33fce15dd Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 28 Mar 2026 20:21:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=89=93=E9=80=9A=E7=BD=91=E5=85=B3?= =?UTF-8?q?=E5=92=8C=E7=94=A8=E6=88=B7=E6=B3=A8=E5=86=8C=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=20HTTP=20=E7=AB=AF=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/gateway/cmd/main.go | 12 +++- backend/gateway/go.mod | 2 + backend/gateway/internal/router/router.go | 66 ++++++++++++++++++- .../gateway/internal/service/user_service.go | 42 ++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 backend/gateway/internal/service/user_service.go diff --git a/backend/gateway/cmd/main.go b/backend/gateway/cmd/main.go index f56cca3..4e5ad5e 100644 --- a/backend/gateway/cmd/main.go +++ b/backend/gateway/cmd/main.go @@ -7,7 +7,9 @@ import ( "backend/gateway/internal/config" "backend/gateway/internal/router" + "backend/gateway/internal/service" "backend/gateway/internal/ws" + "backend/shared/pkg/logger" ) func main() { @@ -21,14 +23,22 @@ func main() { hub := ws.NewHub() go hub.Run() + // 初始化用户服务 + userService, err := service.NewUserService(cfg) + if err != nil { + log.Fatalf("Failed to initialize user service: %v", err) + } + logger.Info("User service initialized successfully") + // 创建路由器 - r := router.NewRouter(hub) + r := router.NewRouter(hub, userService) // 启动服务器 serverAddr := fmt.Sprintf(":%d", cfg.Server.Port) log.Printf("Gateway service starting on %s", serverAddr) log.Printf("WebSocket endpoint: ws://localhost%s/ws", serverAddr) log.Printf("Health check: http://localhost%s/health", serverAddr) + log.Printf("User register endpoint: http://localhost%s/api/user/register", serverAddr) if err := http.ListenAndServe(serverAddr, r.SetupRoutes()); err != nil { log.Fatalf("Failed to start server: %v", err) diff --git a/backend/gateway/go.mod b/backend/gateway/go.mod index 43e3902..efe62c8 100644 --- a/backend/gateway/go.mod +++ b/backend/gateway/go.mod @@ -5,4 +5,6 @@ go 1.26.1 require ( github.com/gorilla/websocket v1.5.1 github.com/spf13/viper v1.19.0 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.33.0 ) \ No newline at end of file diff --git a/backend/gateway/internal/router/router.go b/backend/gateway/internal/router/router.go index c1cabc1..f67cc3f 100644 --- a/backend/gateway/internal/router/router.go +++ b/backend/gateway/internal/router/router.go @@ -1,9 +1,11 @@ package router import ( + "encoding/json" "log" "net/http" + "backend/gateway/internal/service" "backend/gateway/internal/ws" "github.com/gorilla/websocket" @@ -19,12 +21,14 @@ var upgrader = websocket.Upgrader{ } type Router struct { - hub *ws.Hub + hub *ws.Hub + userService *service.UserService } -func NewRouter(hub *ws.Hub) *Router { +func NewRouter(hub *ws.Hub, userService *service.UserService) *Router { return &Router{ - hub: hub, + hub: hub, + userService: userService, } } @@ -37,9 +41,65 @@ func (r *Router) SetupRoutes() http.Handler { // 健康检查 mux.HandleFunc("/health", r.handleHealth) + // 用户注册 + mux.HandleFunc("/api/user/register", r.handleRegister) + return mux } +// 注册请求结构 +type registerRequest struct { + Account string `json:"account"` + Password string `json:"password"` +} + +// 注册响应结构 +type registerResponse struct { + UserID string `json:"user_id"` + Account string `json:"account"` + Message string `json:"message"` + Code int `json:"code"` +} + +// handleRegister 处理用户注册请求 +func (r *Router) handleRegister(w http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + w.Write([]byte(`{"code": 405, "message": "Method not allowed"}`)) + return + } + + // 解析请求体 + var registerReq registerRequest + if err := json.NewDecoder(req.Body).Decode(®isterReq); err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(`{"code": 400, "message": "Invalid request body"}`)) + return + } + + // 调用用户服务注册 + resp, err := r.userService.Register(req.Context(), registerReq.Account, registerReq.Password) + if err != nil { + log.Printf("Register failed: %v", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"code": 500, "message": "Internal server error"}`)) + return + } + + // 构造响应 + response := registerResponse{ + UserID: resp.UserId, + Account: resp.Account, + Message: resp.Response.Message, + Code: int(resp.Response.Code), + } + + // 返回响应 + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(response) +} + func (r *Router) handleWebSocket(w http.ResponseWriter, req *http.Request) { conn, err := upgrader.Upgrade(w, req, nil) if err != nil { diff --git a/backend/gateway/internal/service/user_service.go b/backend/gateway/internal/service/user_service.go new file mode 100644 index 0000000..438f85a --- /dev/null +++ b/backend/gateway/internal/service/user_service.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + + "backend/gateway/internal/config" + "backend/shared/pkg/logger" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + // 导入生成的 proto 代码 + userpb "backend/services/user-svc/proto" +) + +type UserService struct { + client userpb.UserServiceClient +} + +func NewUserService(cfg *config.Config) (*UserService, error) { + // 连接到用户服务 + conn, err := grpc.Dial(cfg.Services.UserService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + logger.Error("Failed to connect to user service: %v", err) + return nil, err + } + + // 创建 gRPC 客户端 + client := userpb.NewUserServiceClient(conn) + + return &UserService{client: client}, nil +} + +// Register 用户注册 +func (s *UserService) Register(ctx context.Context, account, password string) (*userpb.RegisterResponse, error) { + req := &userpb.RegisterRequest{ + Account: account, + Password: password, + } + + return s.client.Register(ctx, req) +}