From b87580442acf92cf7b0f10789afda36fab09ecbb Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:48:46 +0000 Subject: [PATCH] refactor(api): centralize server setup in NewAPIServer Refactored the API server setup to improve modularity and simplify the main application entry point. - Created a new `NewAPIServer` function in `cmd/api/server.go` that encapsulates the creation and configuration of the `http.ServeMux`. - This new function now handles the registration of all API routes, including the GraphQL endpoint (`/query`), the GraphQL Playground (`/playground`), and the Prometheus metrics endpoint (`/metrics`). - Simplified `cmd/api/main.go` by removing the manual `ServeMux` creation and instead calling the new `NewAPIServer` function. - This change makes the `main` function cleaner and more focused on its core responsibilities of application initialization and graceful shutdown. --- cmd/api/main.go | 15 ++++----------- cmd/api/server.go | 38 ++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/cmd/api/main.go b/cmd/api/main.go index 8e68af8..482608d 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -23,7 +23,6 @@ import ( "tercul/internal/platform/search" "time" - "github.com/99designs/gqlgen/graphql/playground" "github.com/pressly/goose/v3" "github.com/prometheus/client_golang/prometheus" "github.com/weaviate/weaviate-go-client/v5/weaviate" @@ -156,19 +155,13 @@ func main() { App: application, } - // Create the main API handler with all middleware. - apiHandler := NewServerWithAuth(resolver, jwtManager, metrics, obsLogger) + // Create the consolidated API server with all routes. + apiHandler := NewAPIServer(resolver, jwtManager, metrics, obsLogger, reg) - // Create the main ServeMux and register all handlers. - mux := http.NewServeMux() - mux.Handle("/query", apiHandler) - mux.Handle("/playground", playground.Handler("GraphQL Playground", "/query")) - mux.Handle("/metrics", observability.PrometheusHandler(reg)) - - // Create a single HTTP server with the main mux. + // Create the main HTTP server. mainServer := &http.Server{ Addr: cfg.ServerPort, - Handler: mux, + Handler: apiHandler, } app_log.Info(fmt.Sprintf("API server listening on port %s", cfg.ServerPort)) diff --git a/cmd/api/server.go b/cmd/api/server.go index b7f1d79..2c15a1b 100644 --- a/cmd/api/server.go +++ b/cmd/api/server.go @@ -7,28 +7,42 @@ import ( "tercul/internal/platform/auth" "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/prometheus/client_golang/prometheus" ) -// NewServerWithAuth creates a new GraphQL server with authentication and observability middleware -func NewServerWithAuth(resolver *graphql.Resolver, jwtManager *auth.JWTManager, metrics *observability.Metrics, logger *observability.Logger) http.Handler { +// NewAPIServer creates a new http.ServeMux and configures it with all the API routes, +// including the GraphQL endpoint, GraphQL Playground, and Prometheus metrics. +func NewAPIServer( + resolver *graphql.Resolver, + jwtManager *auth.JWTManager, + metrics *observability.Metrics, + logger *observability.Logger, + reg *prometheus.Registry, +) *http.ServeMux { + // Configure the GraphQL server c := graphql.Config{Resolvers: resolver} c.Directives.Binding = graphql.Binding - // Create the server with the custom error presenter - srv := handler.NewDefaultServer(graphql.NewExecutableSchema(c)) - srv.SetErrorPresenter(graphql.NewErrorPresenter()) + // Create the core GraphQL handler + graphqlHandler := handler.NewDefaultServer(graphql.NewExecutableSchema(c)) + graphqlHandler.SetErrorPresenter(graphql.NewErrorPresenter()) - // Create a middleware chain. The order is important. - // Middlewares are applied from bottom to top, so the last one added is the first to run. + // Create the middleware chain for the GraphQL endpoint. + // Middlewares are applied from bottom to top. var chain http.Handler - chain = srv + chain = graphqlHandler chain = metrics.PrometheusMiddleware(chain) - // LoggingMiddleware needs to run after auth and tracing to get all context. - chain = observability.LoggingMiddleware(logger)(chain) + chain = observability.LoggingMiddleware(logger)(chain) // Must run after auth and tracing chain = auth.GraphQLAuthMiddleware(jwtManager)(chain) chain = observability.TracingMiddleware(chain) chain = observability.RequestIDMiddleware(chain) - // Return the handler chain directly. The caller is responsible for routing. - return chain + // Create a new ServeMux and register all handlers + mux := http.NewServeMux() + mux.Handle("/query", chain) + mux.Handle("/playground", playground.Handler("GraphQL Playground", "/query")) + mux.Handle("/metrics", observability.PrometheusHandler(reg)) + + return mux } \ No newline at end of file