sensu / sensu-go

Simple. Scalable. Multi-cloud monitoring.
https://sensu.io
MIT License
1.03k stars 175 forks source link

API endpoints with a trailing slash return 404 #3547

Open calebhailey opened 4 years ago

calebhailey commented 4 years ago

Expected Behavior

API endpoints should work the same with and without trailing slashes.

Current Behavior

Most API endpoints in Sensu Go will 404 if a trailing slash is added to the API route.

Example: POST /entities vs POST /entities/

$ curl -i -XPOST -H "Authorization: Key $SENSU_API_KEY" -H "Content-Type: application/json"   -d '{"entity_class":"proxy","metadata":{"name":"example-01","namespace":"default"}}'   http://127.0.0.1:8080/api/core/v2/namespaces/default/entities
HTTP/1.1 201 Created
Content-Type: application/json
Sensu-Entity-Count: 1
Sensu-Entity-Limit: 100
Sensu-Entity-Warning: 
Date: Thu, 06 Feb 2020 23:48:45 GMT
Content-Length: 0

$ curl -i -XPOST -H "Authorization: Key $SENSU_API_KEY" -H "Content-Type: application/json"   -d '{"entity_class":"proxy","metadata":{"name":"example-02","namespace":"default"}}'   http://127.0.0.1:8080/api/core/v2/namespaces/default/entities/
HTTP/1.1 404 Not Found
Date: Thu, 06 Feb 2020 23:48:50 GMT
Content-Length: 33
Content-Type: text/plain; charset=utf-8

{"code":2,"message":"not found"}

Example: POST /events/ vs POST /events

$ curl -i -XPOST -H "Authorization: Key $SENSU_API_KEY" -H "Content-Type: application/json" -d '{"entity":{"metadata":{"name":"1-424242"},"entity_class":"proxy"},"check":{"metadata":{"name":"my-app"},"status":2,"interval":5,"output":"ERROR: failed to connect to database."}}'   http://127.0.0.1:8080/api/core/v2/namespaces/default/events/
HTTP/1.1 404 Not Found
Date: Thu, 06 Feb 2020 23:51:22 GMT
Content-Length: 33
Content-Type: text/plain; charset=utf-8

{"code":2,"message":"not found"}

$ curl -i -XPOST -H "Authorization: Key $SENSU_API_KEY" -H "Content-Type: application/json"   -d '{"entity":{"metadata":{"name":"1-424242"},"entity_class":"proxy"},"check":{"metadata":{"name":"my-app"},"status":2,"interval":5,"output":"ERROR: failed to connect to database."}}'   http://127.0.0.1:8080/api/core/v2/namespaces/default/events
HTTP/1.1 201 Created
Content-Type: application/json
Sensu-Entity-Count: 2
Sensu-Entity-Limit: 100
Sensu-Entity-Warning: 
Date: Thu, 06 Feb 2020 23:51:26 GMT
Content-Length: 0

Example: GET /entities/ vs GET /entities

$ curl -i -XGET -H "Authorization: Key $SENSU_API_KEY" http://127.0.0.1:8080/api/core/v2/namespaces/default/entities/
HTTP/1.1 404 Not Found
Date: Thu, 06 Feb 2020 23:55:34 GMT
Content-Length: 33
Content-Type: text/plain; charset=utf-8

{"code":2,"message":"not found"}

$ curl -i -XGET -H "Authorization: Key $SENSU_API_KEY" http://127.0.0.1:8080/api/core/v2/namespaces/default/entities
HTTP/1.1 200 OK
Content-Type: application/json
Sensu-Entity-Count: 2
Sensu-Entity-Limit: 100
Sensu-Entity-Warning: 
Date: Thu, 06 Feb 2020 23:55:35 GMT
Content-Length: 915

[{"entity_class":"proxy","system":{"network":{"interfaces":null}},"subscriptions":null,"last_seen":0,"deregister":false,"deregistration":{},"metadata":{"name":"1-424242","namespace":"default"},"sensu_agent_version":""},{"entity_class":"agent","system":{"hostname":"20c28352433a","os":"linux","platform":"alpine","platform_family":"alpine","platform_version":"3.8.1","network":{"interfaces":[{"name":"lo","addresses":["127.0.0.1/8"]},{"name":"tunl0","addresses":null},{"name":"ip6tnl0","addresses":null},{"name":"eth0","mac":"02:42:ac:13:00:03","addresses":["172.19.0.3/16"]}]},"arch":"amd64"},"subscriptions":["linux","entity:20c28352433a"],"last_seen":1581033331,"deregister":true,"deregistration":{},"user":"agent","redact":["password","passwd","pass","api_key","api_token","access_key","secret_key","private_key","secret"],"metadata":{"name":"20c28352433a","namespace":"default"},"sensu_agent_version":"5.17.1"}]

Possible Solution

Support routes with and without the trailing slash?

Steps to Reproduce (for bugs)

See examples above.

Context

Let's make this easier for our users!

Your Environment

palourde commented 4 years ago

I believe we could use https://godoc.org/github.com/gorilla/mux#Router.StrictSlash

palourde commented 4 years ago

Actually I don't think we can rely on the StrictSlash method:

The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed request will be made as a GET by most clients.

&

Special case: when a route sets a path prefix using the PathPrefix() method, strict slash is ignored for that route because the redirect behavior can't be determined from a prefix alone.

I'm no longer sure how to achieve that without adding a bunch of complexity 🤔

calebhailey commented 3 years ago

It appears this is occurring on the Agent /events API (/events works, /events/ returns a 404).