-
Notifications
You must be signed in to change notification settings - Fork 839
Enforce HTTP method required by most API endpoints #3228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
pracucci
merged 3 commits into
cortexproject:master
from
pracucci:fix-api-endpoints-methods
Sep 25, 2020
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 |
|---|---|---|
|
|
@@ -101,11 +101,17 @@ func New(cfg Config, serverCfg server.Config, s *server.Server, logger log.Logge | |
| return api, nil | ||
| } | ||
|
|
||
| func (a *API) RegisterRoute(path string, handler http.Handler, auth bool, methods ...string) { | ||
| a.registerRouteWithRouter(a.server.HTTP, path, handler, auth, methods...) | ||
| // RegisterRoute registers a single route enforcing HTTP methods. A single | ||
| // route is expected to be specific about which HTTP methods are supported. | ||
| func (a *API) RegisterRoute(path string, handler http.Handler, auth bool, method string, methods ...string) { | ||
| a.registerRouteWithRouter(a.server.HTTP, path, handler, auth, method, methods...) | ||
| } | ||
|
|
||
| func (a *API) registerRouteWithRouter(router *mux.Router, path string, handler http.Handler, auth bool, methods ...string) { | ||
| // RegisterRoute registers a single route to a router, enforcing HTTP methods. A single | ||
| // route is expected to be specific about which HTTP methods are supported. | ||
| func (a *API) registerRouteWithRouter(router *mux.Router, path string, handler http.Handler, auth bool, method string, methods ...string) { | ||
| methods = append([]string{method}, methods...) | ||
|
|
||
| level.Debug(a.logger).Log("msg", "api: registering route", "methods", strings.Join(methods, ","), "path", path, "auth", auth) | ||
| if auth { | ||
| handler = a.authMiddleware.Wrap(handler) | ||
|
|
@@ -148,7 +154,7 @@ func fakeRemoteAddr(handler http.Handler) http.Handler { | |
| func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, target, apiEnabled bool) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/multitenant_alertmanager/status", "Alertmanager Status") | ||
| // Ensure this route is registered before the prefixed AM route | ||
| a.RegisterRoute("/multitenant_alertmanager/status", am.GetStatusHandler(), false) | ||
| a.RegisterRoute("/multitenant_alertmanager/status", am.GetStatusHandler(), false, "GET") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gotjosh Do you see problem with this? |
||
|
|
||
| // UI components lead to a large number of routes to support, utilize a path prefix instead | ||
| a.RegisterRoutesWithPrefix(a.cfg.AlertmanagerHTTPPrefix, am, true) | ||
|
|
@@ -157,7 +163,7 @@ func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, tar | |
| // If the target is Alertmanager, enable the legacy behaviour. Otherwise only enable | ||
| // the component routed API. | ||
| if target { | ||
| a.RegisterRoute("/status", am.GetStatusHandler(), false) | ||
| a.RegisterRoute("/status", am.GetStatusHandler(), false, "GET") | ||
| a.RegisterRoutesWithPrefix(a.cfg.LegacyHTTPPrefix, am, true) | ||
| } | ||
|
|
||
|
|
@@ -173,25 +179,25 @@ func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, tar | |
| func (a *API) RegisterAPI(httpPathPrefix string, cfg interface{}) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/config", "Current Config") | ||
|
|
||
| a.RegisterRoute("/config", configHandler(cfg), false) | ||
| a.RegisterRoute("/", indexHandler(httpPathPrefix, a.indexPage), false) | ||
| a.RegisterRoute("/debug/fgprof", fgprof.Handler(), false) | ||
| a.RegisterRoute("/config", configHandler(cfg), false, "GET") | ||
| a.RegisterRoute("/", indexHandler(httpPathPrefix, a.indexPage), false, "GET") | ||
| a.RegisterRoute("/debug/fgprof", fgprof.Handler(), false, "GET") | ||
| } | ||
|
|
||
| // RegisterDistributor registers the endpoints associated with the distributor. | ||
| func (a *API) RegisterDistributor(d *distributor.Distributor, pushConfig distributor.Config) { | ||
| a.RegisterRoute("/api/v1/push", push.Handler(pushConfig, a.sourceIPs, d.Push), true) | ||
| a.RegisterRoute("/api/v1/push", push.Handler(pushConfig, a.sourceIPs, d.Push), true, "POST") | ||
pracucci marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| a.indexPage.AddLink(SectionAdminEndpoints, "/distributor/all_user_stats", "Usage Statistics") | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/distributor/ha_tracker", "HA Tracking Status") | ||
|
|
||
| a.RegisterRoute("/distributor/all_user_stats", http.HandlerFunc(d.AllUserStatsHandler), false) | ||
| a.RegisterRoute("/distributor/ha_tracker", d.HATracker, false) | ||
| a.RegisterRoute("/distributor/all_user_stats", http.HandlerFunc(d.AllUserStatsHandler), false, "GET") | ||
| a.RegisterRoute("/distributor/ha_tracker", d.HATracker, false, "GET") | ||
|
|
||
| // Legacy Routes | ||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/push", push.Handler(pushConfig, a.sourceIPs, d.Push), true) | ||
| a.RegisterRoute("/all_user_stats", http.HandlerFunc(d.AllUserStatsHandler), false) | ||
| a.RegisterRoute("/ha-tracker", d.HATracker, false) | ||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/push", push.Handler(pushConfig, a.sourceIPs, d.Push), true, "POST") | ||
| a.RegisterRoute("/all_user_stats", http.HandlerFunc(d.AllUserStatsHandler), false, "GET") | ||
| a.RegisterRoute("/ha-tracker", d.HATracker, false, "GET") | ||
| } | ||
|
|
||
| // RegisterIngester registers the ingesters HTTP and GRPC service | ||
|
|
@@ -200,14 +206,14 @@ func (a *API) RegisterIngester(i *ingester.Ingester, pushConfig distributor.Conf | |
|
|
||
| a.indexPage.AddLink(SectionDangerous, "/ingester/flush", "Trigger a Flush of data from Ingester to storage") | ||
| a.indexPage.AddLink(SectionDangerous, "/ingester/shutdown", "Trigger Ingester Shutdown (Dangerous)") | ||
| a.RegisterRoute("/ingester/flush", http.HandlerFunc(i.FlushHandler), false) | ||
| a.RegisterRoute("/ingester/shutdown", http.HandlerFunc(i.ShutdownHandler), false) | ||
| a.RegisterRoute("/ingester/push", push.Handler(pushConfig, a.sourceIPs, i.Push), true) // For testing and debugging. | ||
| a.RegisterRoute("/ingester/flush", http.HandlerFunc(i.FlushHandler), false, "GET", "POST") | ||
| a.RegisterRoute("/ingester/shutdown", http.HandlerFunc(i.ShutdownHandler), false, "GET", "POST") | ||
| a.RegisterRoute("/ingester/push", push.Handler(pushConfig, a.sourceIPs, i.Push), true, "POST") // For testing and debugging. | ||
|
|
||
| // Legacy Routes | ||
| a.RegisterRoute("/flush", http.HandlerFunc(i.FlushHandler), false) | ||
| a.RegisterRoute("/shutdown", http.HandlerFunc(i.ShutdownHandler), false) | ||
| a.RegisterRoute("/push", push.Handler(pushConfig, a.sourceIPs, i.Push), true) // For testing and debugging. | ||
| a.RegisterRoute("/flush", http.HandlerFunc(i.FlushHandler), false, "GET", "POST") | ||
| a.RegisterRoute("/shutdown", http.HandlerFunc(i.ShutdownHandler), false, "GET", "POST") | ||
| a.RegisterRoute("/push", push.Handler(pushConfig, a.sourceIPs, i.Push), true, "POST") // For testing and debugging. | ||
| } | ||
|
|
||
| // RegisterPurger registers the endpoints associated with the Purger/DeleteStore. They do not exactly | ||
|
|
@@ -230,10 +236,10 @@ func (a *API) RegisterPurger(store *purger.DeleteStore, deleteRequestCancelPerio | |
| // API is not enabled only the ring route is registered. | ||
| func (a *API) RegisterRuler(r *ruler.Ruler, apiEnabled bool) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/ruler/ring", "Ruler Ring Status") | ||
| a.RegisterRoute("/ruler/ring", r, false) | ||
| a.RegisterRoute("/ruler/ring", r, false, "GET", "POST") | ||
|
|
||
| // Legacy Ring Route | ||
| a.RegisterRoute("/ruler_ring", r, false) | ||
| a.RegisterRoute("/ruler_ring", r, false, "GET", "POST") | ||
|
|
||
| if apiEnabled { | ||
| // Prometheus Rule API Routes | ||
|
|
@@ -267,24 +273,24 @@ func (a *API) RegisterRuler(r *ruler.Ruler, apiEnabled bool) { | |
| // RegisterRing registers the ring UI page associated with the distributor for writes. | ||
| func (a *API) RegisterRing(r *ring.Ring) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/ingester/ring", "Ingester Ring Status") | ||
| a.RegisterRoute("/ingester/ring", r, false) | ||
| a.RegisterRoute("/ingester/ring", r, false, "GET", "POST") | ||
|
|
||
| // Legacy Route | ||
| a.RegisterRoute("/ring", r, false) | ||
| a.RegisterRoute("/ring", r, false, "GET", "POST") | ||
| } | ||
|
|
||
| // RegisterStoreGateway registers the ring UI page associated with the store-gateway. | ||
| func (a *API) RegisterStoreGateway(s *storegateway.StoreGateway) { | ||
| storegatewaypb.RegisterStoreGatewayServer(a.server.GRPC, s) | ||
|
|
||
| a.indexPage.AddLink(SectionAdminEndpoints, "/store-gateway/ring", "Store Gateway Ring") | ||
| a.RegisterRoute("/store-gateway/ring", http.HandlerFunc(s.RingHandler), false) | ||
| a.RegisterRoute("/store-gateway/ring", http.HandlerFunc(s.RingHandler), false, "GET", "POST") | ||
| } | ||
|
|
||
| // RegisterCompactor registers the ring UI page associated with the compactor. | ||
| func (a *API) RegisterCompactor(c *compactor.Compactor) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/compactor/ring", "Compactor Ring Status") | ||
| a.RegisterRoute("/compactor/ring", http.HandlerFunc(c.RingHandler), false) | ||
| a.RegisterRoute("/compactor/ring", http.HandlerFunc(c.RingHandler), false, "GET", "POST") | ||
| } | ||
|
|
||
| // RegisterQuerier registers the Prometheus routes supported by the | ||
|
|
@@ -322,11 +328,11 @@ func (a *API) RegisterQuerier( | |
| ) | ||
|
|
||
| // these routes are always registered to the default server | ||
| a.RegisterRoute("/api/v1/user_stats", http.HandlerFunc(distributor.UserStatsHandler), true) | ||
| a.RegisterRoute("/api/v1/chunks", querier.ChunksHandler(queryable), true) | ||
| a.RegisterRoute("/api/v1/user_stats", http.HandlerFunc(distributor.UserStatsHandler), true, "GET") | ||
| a.RegisterRoute("/api/v1/chunks", querier.ChunksHandler(queryable), true, "GET") | ||
|
|
||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/user_stats", http.HandlerFunc(distributor.UserStatsHandler), true) | ||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/chunks", querier.ChunksHandler(queryable), true) | ||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/user_stats", http.HandlerFunc(distributor.UserStatsHandler), true, "GET") | ||
| a.RegisterRoute(a.cfg.LegacyHTTPPrefix+"/chunks", querier.ChunksHandler(queryable), true, "GET") | ||
|
|
||
| // these routes are either registered the default server OR to an internal mux. The internal mux is | ||
| // for use in a single binary mode when both the query frontend and the querier would attempt to claim these routes | ||
|
|
@@ -424,5 +430,5 @@ func (a *API) RegisterQueryFrontend(f *frontend.Frontend) { | |
| // or a future module manager #2291 | ||
| func (a *API) RegisterServiceMapHandler(handler http.Handler) { | ||
| a.indexPage.AddLink(SectionAdminEndpoints, "/services", "Service Status") | ||
| a.RegisterRoute("/services", handler, false) | ||
| a.RegisterRoute("/services", handler, false, "GET") | ||
| } | ||
This file was deleted.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should make /flush, /shutdown and push POST-only? It would make flush and shutdown links on index page not working from browser, which may be a good thing (no accidental click from browser, or prefetching, or recursive link-following robots).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is POST only but the CHANGELOG was wrong. Fixed, thanks!
I agree would be safer. If do so, we should consider:
tools/migrate-ingester-statefulsets.shbecause callsGET /shutdown, but then we would have to use something different thanwget(andcurlis not available in Cortex images)/HTML page because if you click on that they will fail (so there's no point linking them, the https://cortexmetrics.io/docs/api/ will be enough)Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid point. What about we include little tool in the image to call those endpoints? We could fix another problems with included wget too -- it doesn't like 204. I'd suggest separate PR for all that.
I would keep them in the index page (it's useful to know that given Cortex supports it), but add a note that they are POST-only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've the feeling it's overkilled. Installing
curlin our Docker images could be just easier.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curlalso doesn't like 204 and returns non-zero exit code. We could simplify our script if we had this.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to making them
POSTonly!+1 to showing them in index page but mention that they only support
POST.Not too familiar with the script though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you agree if I do it in a separate PR? We need to find a solution for the
wgetreplacement and I would like to avoid blocking this PR because of that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened an issue for /flush and /shutdown:
#3243