Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] I modified it based on examples/helloworld and found that client/main.go reported an error when executing. I am not sure if it is a BUG. #3331

Closed
DrReMain opened this issue May 25, 2024 · 1 comment · May be fixed by #3311
Labels
question Further information is requested

Comments

@DrReMain
Copy link

原案例:https://github.com/go-kratos/examples/tree/main/helloworld

.
├── client
│   └── main.go
├── go.mod
├── go.sum
├── helloworld
│   ├── helloworld.pb.go
│   ├── helloworld.proto
│   ├── helloworld_grpc.pb.go
│   └── helloworld_http.pb.go
└── server
    └── main.go
// helloworld/helloworld.proto
// exec: kratos proto client helloworld/helloworld.proto
syntax = "proto3";

package helloworld;

import "google/api/annotations.proto";

option go_package = "kratos-examples/helloworld/helloworld";

message UserCreateRequest {
  string name = 1;
  int32 age = 2;
}
message UserCreateReply {
  bool success = 1;
}
message UserUpdateRequest {
  string user_id = 1;
  string name = 2;
  int32 age = 3;
}
message UserUpdateReply {
  bool success = 1;
}
message UserDeleteRequest {
  string user_id = 1;
}
message UserDeleteReply {
  bool success = 1;
}
service User {
  rpc UserCreate (UserCreateRequest) returns (UserCreateReply) {
    option (google.api.http) = {
      post: "/user/create",
      body: "*"
    };
  }
  rpc UserUpdate (UserUpdateRequest) returns (UserUpdateReply) {
    option (google.api.http) = {
      put: "/user/{user_id}",
      body: "*"
    };
  }
  rpc UserDelete (UserDeleteRequest) returns (UserDeleteReply) {
    option (google.api.http) = {
      delete: "/user/{user_id}"
    };
  }
}
// server/main.go
package main

import (
	"context"
	"fmt"
	"log"
	"strings"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"

	"helloworld/helloworld"
)

type server struct {
	helloworld.UnimplementedUserServer
}

func (s *server) UserCreate(ctx context.Context, in *helloworld.UserCreateRequest) (*helloworld.UserCreateReply, error) {
	log.Printf("[P]: %+v \n", in)
	if strings.TrimSpace(in.Name) == "" {
		return nil, errors.BadRequest("custom_error", fmt.Sprintf("invalid argument %s", in.Name))
	}
	return &helloworld.UserCreateReply{Success: true}, nil
}

func (s *server) UserUpdate(ctx context.Context, in *helloworld.UserUpdateRequest) (*helloworld.UserUpdateReply, error) {
	log.Printf("[P]: %+v \n", in)
	if strings.TrimSpace(in.UserId) == "" {
		return nil, errors.BadRequest("custom_error", fmt.Sprintf("invalid argument %s", in.UserId))
	}
	return &helloworld.UserUpdateReply{Success: true}, nil
}

func (s *server) UserDelete(ctx context.Context, in *helloworld.UserDeleteRequest) (*helloworld.UserDeleteReply, error) {
	log.Printf("[P]: %+v \n", in)
	if strings.TrimSpace(in.UserId) == "" {
		return nil, errors.BadRequest("custom_error", fmt.Sprintf("invalid argument %s", in.UserId))
	}
	return &helloworld.UserDeleteReply{Success: true}, nil
}

func main() {
	s := new(server)

	grpcSrv := grpc.NewServer(
		grpc.Address(":9000"), grpc.Middleware(recovery.Recovery()))
	helloworld.RegisterUserServer(grpcSrv, s)

	httpSrv := http.NewServer(
		http.Address(":8000"), http.Middleware(recovery.Recovery()))
	helloworld.RegisterUserHTTPServer(httpSrv, s)

	app := kratos.New(
		kratos.Name("HELLOWORLD_USER"), kratos.Server(
			grpcSrv,
			httpSrv,
		))
	if err := app.Run(); err != nil {
		log.Fatal(err)
	}
}
// client/main.go
package main

import (
	"context"
	"log"

	"github.com/go-kratos/kratos/v2/middleware/recovery"
	transgrpc "github.com/go-kratos/kratos/v2/transport/grpc"
	transhttp "github.com/go-kratos/kratos/v2/transport/http"

	pb "helloworld/helloworld"
)

func main() {
	callHTTP()
	callGRPC()
}

func callHTTP() {
	conn, err := transhttp.NewClient(
		context.Background(), transhttp.WithMiddleware(recovery.Recovery()), transhttp.WithEndpoint("127.0.0.1:8000"))
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	client := pb.NewUserHTTPClient(conn)

	reply2, err := client.UserCreate(context.Background(), &pb.UserCreateRequest{Name: "xiaoming"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http reply2] UserCreate %+v\n", reply2)
	reply3, err := client.UserCreate(context.Background(), &pb.UserCreateRequest{Name: "xiaoming", Age: 20})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http reply3] UserCreate %+v\n", reply3)

	reply5, err := client.UserUpdate(context.Background(), &pb.UserUpdateRequest{UserId: "123"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http reply5] UserUpdate %+v\n", reply5)
	reply6, err := client.UserUpdate(context.Background(), &pb.UserUpdateRequest{UserId: "456", Name: "xiaohong"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http reply6] UserUpdate %+v\n", reply6)

	reply8, err := client.UserDelete(context.Background(), &pb.UserDeleteRequest{UserId: "789"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http reply8] UserDelete %+v\n", reply8)
}

func callGRPC() {
	conn, err := transgrpc.DialInsecure(
		context.Background(), transgrpc.WithEndpoint("127.0.0.1:9000"), transgrpc.WithMiddleware(recovery.Recovery()))
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	client := pb.NewUserClient(conn)

	reply2, err := client.UserCreate(context.Background(), &pb.UserCreateRequest{Name: "xiaoming"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] UserCreate %+v\n", reply2)
	reply3, err := client.UserCreate(context.Background(), &pb.UserCreateRequest{Name: "xiaoming", Age: 20})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] UserCreate %+v\n", reply3)

	reply5, err := client.UserUpdate(context.Background(), &pb.UserUpdateRequest{UserId: "123"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] UserCreate %+v\n", reply5)
	reply6, err := client.UserUpdate(context.Background(), &pb.UserUpdateRequest{UserId: "456", Name: "xiaohong"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] UserCreate %+v\n", reply6)

	reply8, err := client.UserDelete(context.Background(), &pb.UserDeleteRequest{UserId: "789"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] UserCreate %+v\n", reply8)
}

go run server/main.go 后正常启动

go run client/main.go
会出现如下错误,也就是这个例子中的http.PUT和http.DELETE在client报错

2024/05/26 01:50:38 [http reply2] UserCreate success:true
2024/05/26 01:50:38 [http reply3] UserCreate success:true
2024/05/26 01:50:38 error: code = 404 reason =  message =  metadata = map[] cause = proto: syntax > error (line 1:1): unexpected token 404
exit status 1

如果使用postman按照client中的所有方式,均可以正常请求并返回
通过执行client/main.go,post接口正常返回。
经调试,不确定是不是因为PUT和DELETE的url为/user/{user_id}造成的
@DrReMain DrReMain added the question Further information is requested label May 25, 2024
@kratos-ci-bot kratos-ci-bot changed the title [Question] 根据examples/helloworld修改了一下,发现client/main.go执行报错,不确定是不是BUG [Question] I modified it based on examples/helloworld and found that client/main.go reported an error when executing. I am not sure if it is a BUG. May 25, 2024
@lonetrail
Copy link

It is a known bug of the generated http client. For the UserUpdate operation, the generated HTTP client sends requests to the path /user/ instead of user/123 as expected by the server. This should be fixed after the pull request #3311 is merged.

The bug exists when path variable is more than one word. You can replace user_id into id in path variable and request body to avoid this bug for this moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants