Description
In #1102 we recently touched on the concept of deprecation of unused api endpoints. I'm not necessarily advocating for the removal of these routes, but I think they help provide concrete examples for discussing our stability guarantees when it comes to the api.
First, a few questions to consider:
- Should we require an RFC style process for removing old endpoints?
- If so, should we also require the process for reviewing the addition of new endpoints?
- Where would we communicate these changes so that external users are aware of proposed changes?
- Should we instrument endpoints to confirm that that are no unexpected users before removal? Would reviewing logs be sufficient?
- What exactly constitutes a breaking change?
- For
cargo
endpoints, we should always return a200
result status. Are we effectively committed to the same for other routes? (See HTTP error codes are barely used #712) - Is it okay to remove
Option<T>
fields from a json return type, or must we retain the field with aNone
value? In other words, is it okay to break clients that handle a nil value for a field but error when the field is absent?
- For
Okay, so on to some specific examples!
GET /versions/:version_id
and GET /crates/:crate_id/:version
These 2 routes are implemented in version::show()
. There isn't really much reason for these to be combined as the endpoint has different semantics depending on if the :crate_id is present or not. I think this should be properly split into two endpoints.
For GET /versions/:version_id
I don't expect there to be any external users at all as in order to use this api it is necessary to know the database id number for the version you seek. The primary way I see to obtain this is through GET /crates/:crate_id
, but this endpoint already returns an array of versions containing all of this data. If there are any external users of this endpoint then we're probably doing duplicate effort to serve them.
GET /crates/:crate_id/:version
has a much better interface, as crate_id
and version
are both human readable names and it is possible that some endpoints are constructing this URL on their own. This could be an argument for keeping this version of the endpoint around for longer, or at least doing more due-diligence to ensure there are no external uses.
GET /versions
This is very similar to the GET /versions/:version_id
endpoint, except it accepts multiple id[]
query parameters and returns a list of versions. Again, in order to make use of this endpoint the user has to already know the database id of the version.
JSON result type for GET /crates/:crate_id/:version/download
This endpoint is used by cargo and redirects to a URL on S3. However, if the request's Accept
header contains json
then we construct a 200
response with JSON data. The frontend code that used this code path was removed in #916 and had already been commented out for 3 years at the time.
While this code path is quite trivial, are we committed to keeping this until some far distant /api/v2
is released? (This is a slightly strange example because this is primarily a cargo
route so I don't think this route would ever be removed even if other v1
endpoints are removed. At best we would remove this special case.)
Summary
In summary, I'm not suggesting that we remove any of these endpoints at this time. If we come up with a policy that allows for removal I would rank them as:
- The endpoints that use raw database ids are low risk for removal.
- The endpoint that uses human readable path segments is medium risk for removal.
- The JSON response type for the download endpoint is medium risk for removal. We should probably add a comment describing the situation.
With these examples in mind, where do you fall on the scale between: "all endpoints must remain stable until /v2
" and "cargo
is our only official stability guarantee but we do our best to keep everyone happy"? There are of course mid-points along this scale. For instance, we could work with users of our api to triage the endpoints they are using and potentially expose them through an official client crate to encourage best practices.