Я пытаюсь создать приложение для микросервиса, используя шлюз grpc, но столкнулся с небольшой проблемой. Когда я пытаюсь отправить запрос в API, мои поля инициализируются как нулевое значение. Я впервые пробую шлюз grpc, так что проблема может быть довольно глупой.
Вот мой запрос:
{
"amount": 20000,
"bill": 1010,
"email": "[email protected]",
"employeeID": 1,
"userID": 1,
"orgID": 1,
"feedback": "good",
"grade": 5,
"isCommissionCompensated": true,
"redirectURL": "https://google.com",
"failRedirectURL": "https://google.com",
"paymentMethod": "CARD"
}
Вот прототип файла шлюза grpc
syntax = "proto3";
option go_package = "/paymentProto";
import "google/api/annotations.proto";
package payment;
service PaymentService {
rpc PayIn(PayInRequest) returns(PayInResponse) {
option(google.api.http) = {
post: "/payment/pay_in"
};
}
}
message PayInRequest {
uint64 userID = 1;
uint64 employeeID = 2;
uint64 orgID = 3;
string redirectURL = 4;
string failRedirectURL = 5;
double amount = 6;
string email = 7;
string feedback = 8;
uint32 grade = 9;
bool isCommissionCompensated = 10;
optional double bill = 11;
string paymentMethod = 12;
}
message PayInResponse {
string payInForm = 1;
}
У меня есть метод, который инициализирует мой сервер
func (s *Server) Run() error {
s.MapHandlers()
var eg errgroup.Group
eg.Go(s.RunPaymentGRPC)
eg.Go(s.RunPaymentHTTP)
if err := eg.Wait(); err != nil {
return errors.Wrap(err, "Server.Run")
}
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logger.Info("Shutting down Payment server...")
s.grpcServer.GracefulStop()
logger.Info("Success!")
return nil
}
И 3 метода, инициализирующих шлюз:
func (s *Server) MapHandlers() {
logger.Info("Trying to map handlers...")
paymentUC := paymentUsecase.NewPaymentUC()
paymentHandlers := paymentDelivery.NewHandlers(paymentUC)
paymentProto.RegisterPaymentServiceServer(s.grpcServer, paymentHandlers)
logger.Info("Success!")
}
func (s *Server) RunPaymentHTTP() error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
logger.Info("Trying to run http server")
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
err := paymentProto.RegisterPaymentServiceHandlerFromEndpoint(ctx, s.mux, s.cfg.PaymentServer.Grpc.Host, opts)
if err != nil {
return errors.Wrap(err, "failed to register gRPC gateway")
}
logger.Infof("Serving http on %s", s.cfg.PaymentServer.Http.Host)
if err := http.ListenAndServe(s.cfg.PaymentServer.Http.Host, s.mux); err != nil {
return errors.Wrap(err, "failed to serve")
}
logger.Info("Success!")
return nil
}
func (s *Server) RunPaymentGRPC() error {
lis, err := net.Listen("tcp", s.cfg.PaymentServer.Grpc.Host)
if err != nil {
return errors.Wrapf(err, "failed to listen: %v", s.cfg.PaymentServer.Grpc.Host)
}
logger.Infof("Serving gRPC on %s", s.cfg.PaymentServer.Grpc.Host)
if err := s.grpcServer.Serve(lis); err != nil {
return errors.Wrap(err, "failed to serve gRPC server")
}
return nil
}
И вот структура, которая реализует мой сгенерированный код прото-файла
type PaymentHandlers struct {
paymentUC PaymentUC
paymentProto.UnimplementedPaymentServiceServer
}
func NewHandlers(paymentUC PaymentUC) *PaymentHandlers {
return &PaymentHandlers{
paymentUC: paymentUC,
}
}
func (h *PaymentHandlers) PayIn(
ctx context.Context,
request *paymentProto.PayInRequest,
) (*paymentProto.PayInResponse, error) {
ctx, span := otel.Tracer("api-gateway").Start(ctx, "PaymentHandlers.PayIn")
defer span.End()
return &paymentProto.PayInResponse{
PayInForm: "success",
}, nil
}
И когда я пытаюсь отправить запрос, в моей сгенерированной структуре есть такие поля
В чем может быть проблема? Заранее спасибо!
Ну, я отправляю http-запрос на свой сервис через почтальона. «Пожалуйста, уточните «мои поля инициализируются как нулевое значение»» — ну, вы можете видеть это на моем скриншоте. Структура имеет поля с нулевым значением.
Можете ли вы попробовать добавить строку body: "*" в прототип службы и убедиться, что ваша проблема решена? ``` service PaymentService { rpc PayIn(PayInRequest) return(PayInResponse) { option(google.api.http) = { post: "/paid/pay_in" body: "*" }; } } ```

В вашем прототипе сервиса отсутствует body: "*", что может быть причиной проблемы. Можете ли вы попробовать добавить его и посмотреть, решит ли это проблему?
service PaymentService {
rpc PayIn(PayInRequest) returns(PayInResponse) {
option(google.api.http) = {
post: "/payment/pay_in"
body: "*"
};
}
}
Как упоминается в прототипе аннотации Google API:
Любые поля в сообщении запроса, которые не связаны шаблоном пути, автоматически становятся параметрами HTTP-запроса, если нет тела HTTP-запроса.
Поэтому я подозреваю, что ваше сообщение получает нулевые значения для полей, поскольку не указаны параметры запроса URL-адреса и отсутствует аннотация тела.
Пожалуйста, уточните «мои поля инициализируются как нулевое значение». Вы используете термин «шлюз». Могу ли я предположить, что вы не имеете в виду grpc-шлюз? Как именно вы вызываете службу?