I am newbie in Go. I try to write server in Go. I write auth part in GRPC. But main functionality I want to build with REST. I write code for GRPC and REST. But when I launch my server, only REST works. My GRPC just not responding.
grpc.go application
type App struct {
log *slog.Logger
gRPCServer *grpc.Server
port int
}
// New creates new gRPC server app.
func New(
log *slog.Logger,
authService authgrpc.Auth,
port int,
) *App {
recoveryOpts := []recovery.Option{
recovery.WithRecoveryHandler(func(p interface{}) (err error) {
log.Error("Recovered from panic", slog.Any("panic", p))
return status.Errorf(codes.Internal, "internal error")
}),
}
gRPCServer := grpc.NewServer(grpc.ChainUnaryInterceptor(
recovery.UnaryServerInterceptor(recoveryOpts...),
logging.UnaryServerInterceptor(InterceptorLogger(log), loggingOpts...),
))
authgrpc.Register(gRPCServer, authService)
return &App{
log: log,
gRPCServer: gRPCServer,
port: port,
}
}
// MustRun runs gRPC server and panics if any error occurs.
func (a *App) MustRun() {
if err := a.Run(); err != nil {
panic(err)
}
}
// Run runs gRPC server.
func (a *App) Run() error {
const op = "grpcapp.Run"
l, err := net.Listen("tcp", fmt.Sprintf(":%d", a.port))
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
a.log.Info("grpc server started", slog.String("addr", l.Addr().String()))
if err := a.gRPCServer.Serve(l); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
// Stop stops gRPC server.
func (a *App) Stop() {
const op = "grpcapp.Stop"
a.log.With(slog.String("op", op)).
Info("stopping gRPC server", slog.Int("port", a.port))
a.gRPCServer.GracefulStop()
}
rest.go application
type App struct {
log *slog.Logger
httpServer *http.Server
port int
coreService *core.Core
}
func New(
log *slog.Logger,
coreService *core.Core,
port int,
) *App {
return &App{
log: log,
port: port,
coreService: coreService,
}
}
// MustRun runs the HTTP server and panics if any error occurs.
func (a *App) MustRun() {
if err := a.Run(); err != nil {
panic(err)
}
}
// Run runs the HTTP server.
func (a *App) Run() error {
const op = "restapp.Run"
router := mux.NewRouter()
router.HandleFunc("/author", a.coreService.GetAuthorHandler).Methods("GET")
a.httpServer = &http.Server{
Addr: fmt.Sprintf(":%d", a.port),
Handler: router,
}
if err := a.httpServer.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
rest and grpc builders
type App struct {
log *slog.Logger
GRPCServer *grpcapp.App
RestServer *restapp.App
port int
}
func NewGrpc(
log *slog.Logger,
port int,
storagePath string,
tokenTTL time.Duration,
) *App {
storage, err := sqlite.New(storagePath)
if err != nil {
panic(err)
}
authService := auth.New(log, storage, storage, storage, tokenTTL)
grpcApp := grpcapp.New(log, authService, port)
return &App{
log: log,
GRPCServer: grpcApp,
port: port,
}
}
func NewRest(
log *slog.Logger,
port int,
storagePath string,
tokenTTL time.Duration,
) *App {
storage, err := sqlite.New(storagePath)
if err != nil {
panic(err)
}
coreService := core.New(log, storage, tokenTTL)
restApp := restapp.New(log, coreService, port)
return &App{
log: log,
RestServer: restApp,
port: port,
}
}
rest handler
type AuthorProvider interface {
Author(ctx context.Context) ([]models.Author, error)
}
type Core struct {
log *slog.Logger
authorProvider AuthorProvider
tokenTTL time.Duration
}
func New(
log *slog.Logger,
authorProvider AuthorProvider,
tokenTTL time.Duration,
) *Core {
return &Core{
log: log,
authorProvider: authorProvider,
tokenTTL: tokenTTL,
}
}
func (c *Core) GetAuthorHandler(w http.ResponseWriter, r *http.Request) {
const op = "core.GetAuthorHandler"
// Retrieve author data using AuthorProvider
authors, err := c.authorProvider.Author(r.Context())
if err != nil {
http.Error(w, fmt.Sprintf("%s: %v", op, err), http.StatusInternalServerError)
return
}
// Encode authors data as JSON response
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(authors); err != nil {
http.Error(w, fmt.Sprintf("%s: %v", op, err), http.StatusInternalServerError)
return
}
}
I tried launch GRPC and REST on same and different ports. But it's not help. I also tried to put GRPC inside REST but it is little bit complex for me just now. Anyone can figure out how to fix it?
I run GRPC and REST on different ports and different goroutines: