diff --git a/cmd/oidcgate/helpers_test.go b/cmd/oidcgate/helpers_test.go new file mode 100644 index 0000000..042e831 --- /dev/null +++ b/cmd/oidcgate/helpers_test.go @@ -0,0 +1,15 @@ +package main + +import "github.com/lukaszraczylo/traefikoidc" + +type traefikoidcConfigStub struct { + callbackURL string + logoutURL string +} + +func (s traefikoidcConfigStub) AsOIDC() traefikoidc.Config { + return traefikoidc.Config{ + CallbackURL: s.callbackURL, + LogoutURL: s.logoutURL, + } +} diff --git a/cmd/oidcgate/server.go b/cmd/oidcgate/server.go new file mode 100644 index 0000000..fc960c4 --- /dev/null +++ b/cmd/oidcgate/server.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "net/http" + "time" +) + +// buildMux wires all six routes onto a single ServeMux: +// +// /healthz, /readyz, AuthPath, StartPath, OIDC.CallbackURL, OIDC.LogoutURL. +// +// The same `middleware` instance is delegated to by all four OIDC routes; +// the synthetic success handler is wired into the middleware at construction +// time (in main.go) so it doesn't appear here. +func buildMux(cfg *Config, middleware http.Handler, ready readyReporter) *http.ServeMux { + mux := http.NewServeMux() + mux.Handle("/healthz", newHealthzHandler()) + mux.Handle("/readyz", newReadyzHandler(ready)) + mux.Handle(cfg.AuthPath, newAuthHandler(middleware)) + mux.Handle(cfg.StartPath, newStartHandler(middleware)) + mux.Handle(cfg.OIDC.CallbackURL, newCallbackHandler(middleware, cfg.OIDC.CallbackURL)) + mux.Handle(cfg.OIDC.LogoutURL, newLogoutHandler(middleware, cfg.OIDC.LogoutURL)) + return mux +} + +// buildServer wraps the mux in an http.Server with sensible timeouts. +func buildServer(cfg *Config, mux http.Handler) *http.Server { //nolint:unused + return &http.Server{ + Addr: cfg.Listen, + Handler: mux, + ReadHeaderTimeout: 10 * time.Second, + IdleTimeout: 120 * time.Second, + } +} + +// shutdown gracefully stops the server with a 15s deadline. +func shutdown(srv *http.Server) error { //nolint:unused + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + return srv.Shutdown(ctx) +} diff --git a/cmd/oidcgate/server_test.go b/cmd/oidcgate/server_test.go new file mode 100644 index 0000000..2c0edcd --- /dev/null +++ b/cmd/oidcgate/server_test.go @@ -0,0 +1,42 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestMux_RoutesAllEndpoints(t *testing.T) { + stub := &stubMiddleware{ + fn: func(rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusOK) }, + } + mux := buildMux(&Config{ + Listen: ":0", + AuthPath: "/oauth2/auth", + StartPath: "/oauth2/start", + OIDC: traefikoidcConfigStub{ + callbackURL: "/oauth2/callback", + logoutURL: "/oauth2/logout", + }.AsOIDC(), + }, stub, &readyStub{ready: true}) + + cases := []struct { + path string + method string + want int + }{ + {"/healthz", http.MethodGet, http.StatusOK}, + {"/readyz", http.MethodGet, http.StatusOK}, + {"/oauth2/auth", http.MethodGet, http.StatusOK}, + {"/oauth2/start", http.MethodGet, http.StatusOK}, + {"/oauth2/callback", http.MethodGet, http.StatusOK}, + {"/oauth2/logout", http.MethodPost, http.StatusOK}, + } + for _, c := range cases { + rec := httptest.NewRecorder() + mux.ServeHTTP(rec, httptest.NewRequest(c.method, c.path, nil)) + if rec.Code != c.want { + t.Errorf("%s %s: want %d, got %d", c.method, c.path, c.want, rec.Code) + } + } +}