# Packages
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
# README
server
- HTTP Routing, Logging & Telemetry
Task-Board
- Complete Documentation
- Middleware Unit-Testing
Documentation
Official godoc
documentation (with examples) can be found at the Package Registry.
Usage
Add Package Dependency
go get -u github.com/x-ethr/server
Import & Implement
main.go
package main
import (
"context"
"errors"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"path/filepath"
"runtime"
"time"
"github.com/x-ethr/server"
"github.com/x-ethr/server/logging"
"github.com/x-ethr/server/middleware"
"github.com/x-ethr/server/middleware/name"
"github.com/x-ethr/server/middleware/servername"
"github.com/x-ethr/server/middleware/timeout"
"github.com/x-ethr/server/middleware/tracing"
"github.com/x-ethr/server/middleware/versioning"
"github.com/x-ethr/server/telemetry"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"authentication-service/internal/api/login"
"authentication-service/internal/api/metadata"
"authentication-service/internal/api/refresh"
"authentication-service/internal/api/registration"
)
// header is a dynamically linked string value - defaults to "server" - which represents the server name.
var header string = "server"
// service is a dynamically linked string value - defaults to "service" - which represents the service name.
var service string = "service"
// version is a dynamically linked string value - defaults to "development" - which represents the service's version.
var version string = "development" // production builds have version dynamically linked
// ctx, cancel represent the server's runtime context and cancellation handler.
var ctx, cancel = context.WithCancel(context.Background())
// port represents a cli flag that sets the server listening port
var port = flag.String("port", "8080", "Server Listening Port.")
var logger *slog.Logger
var (
tracer = otel.Tracer(service)
)
func main() {
middlewares := server.Middleware()
middlewares.Add(middleware.New().Path().Middleware)
middlewares.Add(middleware.New().Envoy().Middleware)
middlewares.Add(middleware.New().Timeout().Configuration(func(options *timeout.Settings) { options.Timeout = 30 * time.Second }).Middleware)
middlewares.Add(middleware.New().Server().Configuration(func(options *servername.Settings) { options.Server = header }).Middleware)
middlewares.Add(middleware.New().Service().Configuration(func(options *name.Settings) { options.Service = service }).Middleware)
middlewares.Add(middleware.New().Version().Configuration(func(options *versioning.Settings) { options.Version.Service = version }).Middleware)
middlewares.Add(middleware.New().Telemetry().Middleware)
middlewares.Add(middleware.New().Tracer().Configuration(func(options *tracing.Settings) { options.Tracer = tracer }).Middleware)
mux := http.NewServeMux()
mux.Handle("GET /", otelhttp.WithRouteTag("/", metadata.Handler))
mux.Handle("POST /register", otelhttp.WithRouteTag("/register", registration.Handler))
mux.Handle("POST /refresh", otelhttp.WithRouteTag("/refresh", refresh.Handler))
mux.Handle("POST /login", otelhttp.WithRouteTag("/login", login.Handler))
mux.HandleFunc("GET /health", server.Health)
// Start the HTTP server
slog.Info("Starting Server ...", slog.String("local", fmt.Sprintf("http://localhost:%s", *(port))))
api := server.Server(ctx, mux, middlewares, *port)
// Issue Cancellation Handler
server.Interrupt(ctx, cancel, api)
// Telemetry Setup
shutdown, e := telemetry.Setup(ctx, service, version, func(options *telemetry.Settings) {
if version == "development" && os.Getenv("CI") == "" {
options.Zipkin.Enabled = false
options.Tracer.Local = true
options.Metrics.Local = true
options.Logs.Local = true
}
})
if e != nil {
panic(e)
}
defer func() {
e = errors.Join(e, shutdown(ctx))
}()
// <-- Blocking
if e := api.ListenAndServe(); e != nil && !(errors.Is(e, http.ErrServerClosed)) {
slog.ErrorContext(ctx, "Error During Server's Listen & Serve Call ...", slog.String("error", e.Error()))
os.Exit(100)
}
// --> Exit
{
slog.InfoContext(ctx, "Graceful Shutdown Complete")
// Waiter
<-ctx.Done()
}
}
func init() {
flag.Parse()
level := slog.Level(-8)
if os.Getenv("CI") == "true" {
level = slog.LevelDebug
}
logging.Level(level)
slog.SetLogLoggerLevel(level)
if service == "service" && os.Getenv("CI") != "true" {
_, file, _, ok := runtime.Caller(0)
if ok {
service = filepath.Base(filepath.Dir(file))
}
}
handler := logging.Logger(func(o *logging.Options) { o.Service = service })
logger = slog.New(handler)
slog.SetDefault(logger)
}
- Please refer to the code examples for additional usage and implementation details.
- See https://pkg.go.dev/github.com/x-ethr/server for additional documentation.
Contributions
See the Contributing Guide for additional details on getting started.