Skip to content
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

feat (AIP-136) Update guidance of billable stateless methods #1124

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

xdtdaniel
Copy link

Proposes changes for AIP-136 regarding the use of GET and POST for stateless methods.

Proposes changes for AIP-136 regarding the use of GET and POST for stateless methods.
@xdtdaniel xdtdaniel requested a review from a team as a code owner May 31, 2023 19:29
Copy link
Contributor

@toumorokoshi toumorokoshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! the guidance LGTM.

I'll add another API design reviewer explicitly.

### Choice of HTTP methods for stateless methods

Stateless method **should** use `GET` HTTP method for retrieval use cases due to
its cache-friendly nature. This can reduce the costs for both the server and the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be worth elaborating: e.g. it's common for web browsers to cache GET requests, and it's understood by clients to be a cacheable response.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! Can you elaborate a bit more on "and it's understood by clients to be a cacheable response" part? What does this mean? Specifically what is "it" referring to? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, by "it" I was referring to the fact that GET methods are cacheable.

and it's understood by clients to be a cacheable response

What I mean is HTTP clients often cache GET responses as GET implies that it's doing data retrieval: https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.1. Specficially:

The response to a GET request is cacheable; a cache MAY use it to
satisfy subsequent GET and HEAD requests unless otherwise indicated
by the Cache-Control header field (Section 5.2 of [RFC7234]).

So custom methods which are cacheable and send no payload should use GET.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I edited it again with a new commit. PTAL!

@toumorokoshi toumorokoshi requested a review from alin04 June 2, 2023 20:05
@toumorokoshi
Copy link
Contributor

@alin04 could you take a look?

aip/general/0136.md Outdated Show resolved Hide resolved
aip/general/0136.md Show resolved Hide resolved
@toumorokoshi toumorokoshi requested a review from alin04 June 9, 2023 16:08
@toumorokoshi
Copy link
Contributor

@xdtdaniel make sure to re-request review once changes are addresses so it'll notify the reviewer.

@alin04 I think a new PR is up for your review.

@xdtdaniel
Copy link
Author

xdtdaniel commented Jun 9, 2023 via email

aip/general/0136.md Outdated Show resolved Hide resolved
Copy link
Contributor

@toumorokoshi toumorokoshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM.

@noahdietz
Copy link
Collaborator

Sorry to nit pick when I wasn't asked for a review, but @toumorokoshi should we try to separate the guidance and the Rationale from each other? There is a lot of reasoning in the guidance, which distracts from the piece of guidance itself. Add me as a reviewer if you want this specific feedback.

HTTP clients such as browsers often cache `GET` responses as `GET` implies that
it is doing data retrieval. Stateless methods that are cacheable and send no
payload **should** use `GET` HTTP method due to its cache-friendly nature.
This can reduce the costs for both the server and the client.
Copy link

@loudej loudej Jul 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I don't believe cacheability to informs the choice of method for rest api.

On one hand, per RFC the response returned by non-GET operations may carry an entity that has cacheable implications.

https://datatracker.ietf.org/doc/html/rfc7231#section-7.2

   In a successful response to a state-changing request, validator
   fields describe the new representation that has replaced the prior
   selected representation as a result of processing the request.

   For example, an ETag header field in a 201 (Created) response
   communicates the entity-tag of the newly created resource's
   representation, so that it can be used in later conditional requests
   to prevent the "lost update" problem [[RFC7232](https://datatracker.ietf.org/doc/html/rfc7232)].

So the litmus test is less like "is your response cacheable?" and more like "is the URI (path+query) the address of a data or of a function?" --- and if the URI is the address of data --- do all of the idempotent and non-idempotent methods acting on that URI comply with the RFC necessary to be cacheable?

And that's the other hand, our API are actually miles away from cacheable and would take effort to change that... Like:

  • return an etag json field has no semantic meaning - the response would need to contain an ETag response header instead
  • the format of our ETag isn't right. it doesn't matter if it's a guid or not - but the string value must contain starting and ending with double-quote characters
  • both the mutating and non-mutating URI would need to have the same path+query for cache hits, cache invalidation, and optimistic concurrency. the way we have processing-instruction parameters appear as query arguments (like update_mask=xxx and etag=yyy) means that PATCH and DELETE operations are correlated to different cache entries than the GET's response represents
  • and speaking of ?etag=yyy precondition field --- for browser and httpclient cacheability what we'd need to accept are the If-Match yyy and If-None-Match: yyy request header parameters.

(I think those would be great to do --- but without that using a cache-enabled api httpclient does more harm than good. w/out etag and 304 response code it can actively prevent you from reaching past stale data --- especially if PUT/PATCH/DELETE aren't invalidating cache entries by URI properly)

(Also worth noting this isn't unusual --- many (most?) (almost all??) systems with REST API interfaces don't go down the road of http-defined cachability. I suppose that's because (unlike a 70k js or png file) by the time you've paid for the round-trip, done the mandatory authn/authz for the operation, and drawn sufficient info from the DB to known that the etag verifier is up-to-date ---- returning 304 and saving the typically smaller response of an average API doesn't have much ROI left)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Louis for the comment. I think it makes sense to emphasize the part of how uri informs the operation - is it more of a data retrieval or something more complicated than that. Let me rephrase this part. I will wait for Noah's comment as well to make the change together. Thanks!

@xdtdaniel
Copy link
Author

Sorry to nit pick when I wasn't asked for a review, but @toumorokoshi should we try to separate the guidance and the Rationale from each other? There is a lot of reasoning in the guidance, which distracts from the piece of guidance itself. Add me as a reviewer if you want this specific feedback.

Hi @noahdietz can you help adding yourself as a reviewer? I am not sure if I can add you as a reviewer. Thanks!

Copy link
Collaborator

@noahdietz noahdietz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize that this API doesn't have a Rationale section (see AIP-8) yet, but we should add one with this change to separate out the guidance from the reason why this guidance is necessary/beneficial.

Comment on lines +178 to +179
HTTP clients such as browsers often cache `GET` responses as `GET` implies that
it is doing data retrieval. Stateless methods that are cacheable and send no
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP clients such as browsers often cache `GET` responses as `GET` implies that
it is doing data retrieval.

This is rationale, not guidance


HTTP clients such as browsers often cache `GET` responses as `GET` implies that
it is doing data retrieval. Stateless methods that are cacheable and send no
payload **should** use `GET` HTTP method due to its cache-friendly nature.
Copy link
Collaborator

@noahdietz noahdietz Jul 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

due to its cache-friendly nature. 

This is rationale, not guidance.

HTTP clients such as browsers often cache `GET` responses as `GET` implies that
it is doing data retrieval. Stateless methods that are cacheable and send no
payload **should** use `GET` HTTP method due to its cache-friendly nature.
This can reduce the costs for both the server and the client.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can reduce the costs for both the server and the client.

This is rationale, not guidance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants