From 06780fdfb8ded8631e98697c4748a834770ed247 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 31 May 2023 14:43:22 -0400 Subject: [PATCH 1/4] chore: Prometheus timing to latency endpoint --- coderd/coderd.go | 5 +++-- enterprise/wsproxy/wsproxy.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 7319fee6aa70e..6260afdd50fb7 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -405,6 +405,7 @@ func New(options *Options) *API { derpHandler := derphttp.Handler(api.DERPServer) derpHandler, api.derpCloseFunc = tailnet.WithWebsocketSupport(api.DERPServer, derpHandler) cors := httpmw.Cors(options.DeploymentValues.Dangerous.AllowAllCors.Value()) + prometheusMW := httpmw.Prometheus(options.PrometheusRegistry) r.Use( cors, @@ -414,7 +415,7 @@ func New(options *Options) *API { httpmw.AttachRequestID, httpmw.ExtractRealIP(api.RealIPConfig), httpmw.Logger(api.Logger), - httpmw.Prometheus(options.PrometheusRegistry), + prometheusMW, // SubdomainAppMW checks if the first subdomain is a valid app URL. If // it is, it will serve that application. // @@ -832,7 +833,7 @@ func New(options *Options) *API { // This is the only route we add before all the middleware. // We want to time the latency of the request, so any middleware will // interfere with that timing. - rootRouter.Get("/latency-check", cors(LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL)).ServeHTTP) + rootRouter.Get("/latency-check", prometheusMW(cors(LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL))).ServeHTTP) rootRouter.Mount("/", r) api.RootHandler = rootRouter diff --git a/enterprise/wsproxy/wsproxy.go b/enterprise/wsproxy/wsproxy.go index 2c91ba15556ba..435754d223a44 100644 --- a/enterprise/wsproxy/wsproxy.go +++ b/enterprise/wsproxy/wsproxy.go @@ -193,6 +193,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) { // The primary coderd dashboard needs to make some GET requests to // the workspace proxies to check latency. corsMW := httpmw.Cors(opts.AllowAllCors, opts.DashboardURL.String()) + prometheusMW := httpmw.Prometheus(s.PrometheusRegistry) // Routes apiRateLimiter := httpmw.RateLimit(opts.APIRateLimit, time.Minute) @@ -205,7 +206,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) { httpmw.AttachRequestID, httpmw.ExtractRealIP(s.Options.RealIPConfig), httpmw.Logger(s.Logger), - httpmw.Prometheus(s.PrometheusRegistry), + prometheusMW, corsMW, // HandleSubdomain is a middleware that handles all requests to the @@ -258,7 +259,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) { // See coderd/coderd.go for why we need this. rootRouter := chi.NewRouter() // Make sure to add the cors middleware to the latency check route. - rootRouter.Get("/latency-check", corsMW(coderd.LatencyCheck(opts.AllowAllCors, s.DashboardURL, s.AppServer.AccessURL)).ServeHTTP) + rootRouter.Get("/latency-check", prometheusMW(corsMW(coderd.LatencyCheck(opts.AllowAllCors, s.DashboardURL, s.AppServer.AccessURL))).ServeHTTP) rootRouter.Mount("/", r) s.Handler = rootRouter From b7a77c70bc9c4b10a21171b6038d25c6753452a2 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 31 May 2023 15:00:16 -0400 Subject: [PATCH 2/4] Prevent panic --- coderd/coderd.go | 5 ++++- enterprise/wsproxy/wsproxy.go | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 6260afdd50fb7..c173ed70462b2 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -833,7 +833,10 @@ func New(options *Options) *API { // This is the only route we add before all the middleware. // We want to time the latency of the request, so any middleware will // interfere with that timing. - rootRouter.Get("/latency-check", prometheusMW(cors(LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL))).ServeHTTP) + rootRouter.Route("/latency-check", func(r chi.Router) { + r.Use(tracing.StatusWriterMiddleware, prometheusMW, cors) + r.Get("/", LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL)) + }) rootRouter.Mount("/", r) api.RootHandler = rootRouter diff --git a/enterprise/wsproxy/wsproxy.go b/enterprise/wsproxy/wsproxy.go index 435754d223a44..9bbdd801380bc 100644 --- a/enterprise/wsproxy/wsproxy.go +++ b/enterprise/wsproxy/wsproxy.go @@ -259,7 +259,10 @@ func New(ctx context.Context, opts *Options) (*Server, error) { // See coderd/coderd.go for why we need this. rootRouter := chi.NewRouter() // Make sure to add the cors middleware to the latency check route. - rootRouter.Get("/latency-check", prometheusMW(corsMW(coderd.LatencyCheck(opts.AllowAllCors, s.DashboardURL, s.AppServer.AccessURL))).ServeHTTP) + rootRouter.Route("/latency-check", func(r chi.Router) { + r.Use(tracing.StatusWriterMiddleware, prometheusMW, corsMW) + r.Get("/", coderd.LatencyCheck(opts.AllowAllCors, s.DashboardURL, s.AppServer.AccessURL)) + }) rootRouter.Mount("/", r) s.Handler = rootRouter From d85635cdbd81e5340b4d03bcf0a941feda078760 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 31 May 2023 15:12:01 -0400 Subject: [PATCH 3/4] Skip preflight: --- coderd/coderd.go | 5 +---- coderd/latencycheck.go | 23 ++++++++--------------- enterprise/wsproxy/wsproxy.go | 5 +---- site/src/contexts/useProxyLatency.ts | 3 --- 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index c173ed70462b2..aae1a0f60c5e5 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -833,10 +833,7 @@ func New(options *Options) *API { // This is the only route we add before all the middleware. // We want to time the latency of the request, so any middleware will // interfere with that timing. - rootRouter.Route("/latency-check", func(r chi.Router) { - r.Use(tracing.StatusWriterMiddleware, prometheusMW, cors) - r.Get("/", LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL)) - }) + rootRouter.Get("/latency-check", tracing.StatusWriterMiddleware(prometheusMW(LatencyCheck())).ServeHTTP) rootRouter.Mount("/", r) api.RootHandler = rootRouter diff --git a/coderd/latencycheck.go b/coderd/latencycheck.go index 84d12841a739b..8a0d8e27ae797 100644 --- a/coderd/latencycheck.go +++ b/coderd/latencycheck.go @@ -2,8 +2,6 @@ package coderd import ( "net/http" - "net/url" - "strings" ) // LatencyCheck is an endpoint for the web ui to measure latency with. @@ -11,22 +9,17 @@ import ( // only be set in dev modes. // //nolint:revive -func LatencyCheck(allowAll bool, allowedOrigins ...*url.URL) http.HandlerFunc { - allowed := make([]string, 0, len(allowedOrigins)) - for _, origin := range allowedOrigins { - // Allow the origin without a path - tmp := *origin - tmp.Path = "" - allowed = append(allowed, strings.TrimSuffix(origin.String(), "/")) - } - if allowAll { - allowed = append(allowed, "*") - } - origins := strings.Join(allowed, ",") +func LatencyCheck() http.HandlerFunc { return func(rw http.ResponseWriter, r *http.Request) { // Allowing timing information to be shared. This allows the browser // to exclude TLS handshake timing. - rw.Header().Set("Timing-Allow-Origin", origins) + rw.Header().Set("Timing-Allow-Origin", "*") + // Always allow all CORs on this route. + rw.Header().Set("Access-Control-Allow-Origin", "*") + rw.Header().Set("Access-Control-Allow-Headers", "*") + rw.Header().Set("Access-Control-Allow-Credentials", "false") + rw.Header().Set("Access-Control-Allow-Methods", "*") rw.WriteHeader(http.StatusOK) + _, _ = rw.Write([]byte("OK")) } } diff --git a/enterprise/wsproxy/wsproxy.go b/enterprise/wsproxy/wsproxy.go index 9bbdd801380bc..fce5e0cc7a3b1 100644 --- a/enterprise/wsproxy/wsproxy.go +++ b/enterprise/wsproxy/wsproxy.go @@ -259,10 +259,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) { // See coderd/coderd.go for why we need this. rootRouter := chi.NewRouter() // Make sure to add the cors middleware to the latency check route. - rootRouter.Route("/latency-check", func(r chi.Router) { - r.Use(tracing.StatusWriterMiddleware, prometheusMW, corsMW) - r.Get("/", coderd.LatencyCheck(opts.AllowAllCors, s.DashboardURL, s.AppServer.AccessURL)) - }) + rootRouter.Get("/latency-check", tracing.StatusWriterMiddleware(prometheusMW(coderd.LatencyCheck())).ServeHTTP) rootRouter.Mount("/", r) s.Handler = rootRouter diff --git a/site/src/contexts/useProxyLatency.ts b/site/src/contexts/useProxyLatency.ts index 7588898883ab8..1175657c79052 100644 --- a/site/src/contexts/useProxyLatency.ts +++ b/site/src/contexts/useProxyLatency.ts @@ -128,9 +128,6 @@ export const useProxyLatency = ( const proxyRequests = Object.keys(proxyChecks).map((latencyURL) => { return axios.get(latencyURL, { withCredentials: false, - // Must add a custom header to make the request not a "simple request" - // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests - headers: { "X-LATENCY-CHECK": "true" }, }) }) From fbb8d98e9c0b5221bf52ac4eee6452eddc2a32c0 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 5 Jun 2023 18:11:45 -0500 Subject: [PATCH 4/4] CI stuck?