-
-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api,pkg): create generic server package for services
- Loading branch information
1 parent
3800fc0
commit fb2c0fe
Showing
16 changed files
with
290 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package server | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/getsentry/sentry-go" | ||
"github.com/labstack/echo/v4" | ||
"github.com/shellhub-io/shellhub/api/pkg/echo/handlers" | ||
) | ||
|
||
// Echo is a wrapper around the Echo HTTP server with simplified lifecycle management. | ||
type Echo struct { | ||
echo *echo.Echo | ||
} | ||
|
||
var _ Server[*echo.Echo] = new(Echo) | ||
|
||
// Underlying returns the underlying HTTP server. | ||
func (s *Echo) Underlying() *echo.Echo { | ||
return s.echo | ||
} | ||
|
||
// Close closes the server. | ||
func (s *Echo) Close() error { | ||
return s.echo.Close() | ||
} | ||
|
||
// Start starts the server at a given address. | ||
func (s *Echo) Start(addr string) error { | ||
return s.echo.Start(addr) | ||
} | ||
|
||
// Listen starts the HTTP server, listing for connections in [ServerListenDefaultAddress]. | ||
func (s *Echo) Listen() error { | ||
return s.echo.Start(ServerListenDefaultAddress) | ||
} | ||
|
||
// SentryOption enables, if DSN is a valid value, the error reporter for a Sentry's server. | ||
var SentryOption = func(dsn string) func(server *echo.Echo) { | ||
return func(server *echo.Echo) { | ||
if dsn != "" { | ||
reporter, err := sentry.NewClient(sentry.ClientOptions{ //nolint:exhaustruct | ||
Dsn: dsn, | ||
Release: os.Getenv("SHELLHUB_VERSION"), | ||
EnableTracing: true, | ||
TracesSampleRate: 1, | ||
}) | ||
if err != nil { | ||
server.HTTPErrorHandler = handlers.NewErrors(nil) | ||
|
||
return | ||
} | ||
|
||
server.HTTPErrorHandler = handlers.NewErrors(reporter) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Package server The server package provides a flexible and configurable HTTP server framework for ShellHub services. | ||
// It offers a generic server creation mechanism with built-in middleware, error handling, and routing capabilities. | ||
package server | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/labstack/echo/v4/middleware" | ||
"github.com/shellhub-io/shellhub/api/pkg/echo/handlers" | ||
"github.com/shellhub-io/shellhub/api/pkg/gateway" | ||
pkgmiddleware "github.com/shellhub-io/shellhub/pkg/middleware" | ||
) | ||
|
||
// ServerListenDefaultAddress is the default address used by the HTTP server to listen for connections. | ||
const ServerListenDefaultAddress = ":8080" | ||
|
||
// Server is the interface that should be implemented to create a HTTP server for ShellHub services. | ||
type Server[S any] interface { | ||
// Underlying returns the underlying HTTP server used. | ||
Underlying() S | ||
// Close closes the server. | ||
Close() error | ||
// Start starts the server at a given address. | ||
Start(addr string) error | ||
// Listen starts the HTTP server, listing for connections in [ServerListenDefaultAddress]. | ||
Listen() error | ||
} | ||
|
||
// Route represents a loader of routes to the underlying HTTP server. | ||
type Route[H any] func(server *echo.Echo, handler H) | ||
|
||
// Option is used to pass custom configurations to the underlying HTTP server. | ||
type Option func(server *echo.Echo) | ||
|
||
type Handler[S any] interface { | ||
GetService() S | ||
} | ||
|
||
// NewDefaultServer uses [echo] to create a default HTTP server meet to be used as ShellHub services, aggregating the | ||
// middlewares, binder, validator, environmental variables, features, and anything related to service providing. | ||
func NewDefaultServer[H Handler[any]]( | ||
ctx context.Context, | ||
handler H, | ||
middlewares []echo.MiddlewareFunc, | ||
routes []Route[H], | ||
options []Option, | ||
) Server[*echo.Echo] { //nolint:whitespace | ||
e := echo.New() | ||
|
||
e.Binder = handlers.NewBinder() | ||
e.Validator = handlers.NewValidator() | ||
e.HTTPErrorHandler = handlers.NewErrors(nil) | ||
e.IPExtractor = echo.ExtractIPFromRealIPHeader() | ||
|
||
for _, option := range options { | ||
option(e) | ||
} | ||
|
||
// NOTE: As recommend by Echo's, this middleware should be registered before any other middleware, and custom | ||
// context cannot be defined in a middleware before the router ran (Pre) | ||
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { | ||
return func(c echo.Context) error { | ||
ctx := gateway.NewContext(handler.GetService(), c) | ||
|
||
return next(ctx) | ||
} | ||
}) | ||
e.Use(middleware.RequestID()) | ||
e.Use(middleware.Secure()) | ||
e.Use(pkgmiddleware.Log) | ||
|
||
if middlewares != nil { | ||
e.Use(middlewares...) | ||
} | ||
|
||
for _, route := range routes { | ||
route(e, handler) | ||
} | ||
|
||
// NOTE: When context received is done, we close the HTTP server. | ||
go func() { | ||
<-ctx.Done() | ||
|
||
e.Close() | ||
}() | ||
|
||
return &Echo{ | ||
echo: e, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
package routes | ||
|
||
import ( | ||
svc "github.com/shellhub-io/shellhub/api/services" | ||
"github.com/shellhub-io/shellhub/api/services" | ||
) | ||
|
||
type Handler struct { | ||
service svc.Service | ||
service services.Service | ||
} | ||
|
||
func NewHandler(s svc.Service) *Handler { | ||
func (h *Handler) GetService() any { | ||
return h.service | ||
} | ||
|
||
func NewHandler(s services.Service) *Handler { | ||
return &Handler{service: s} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.