Skip to content

Add isSafe and isIdempotent to HTTPRequest.Method#129

Open
tkshsbcue wants to merge 1 commit into
apple:mainfrom
tkshsbcue:add-method-semantics
Open

Add isSafe and isIdempotent to HTTPRequest.Method#129
tkshsbcue wants to merge 1 commit into
apple:mainfrom
tkshsbcue:add-method-semantics

Conversation

@tkshsbcue

Copy link
Copy Markdown

Motivation

RFC 9110 classifies request methods by two properties that HTTP clients and servers frequently need:

  • Safe (§9.2.1): the method has essentially read-only semantics — the client does not request, and does not expect, any state change on the origin server.
  • Idempotent (§9.2.2): repeating an identical request has the same intended effect as making it once.

These drive everyday decisions like "may I automatically retry this failed request?" and "is this response cacheable?". Today a user has to hand-maintain their own set of method names to answer them.

What this does

HTTPRequest.Method already carried an internal isSafe helper, but it was:

  1. Dead code — never referenced anywhere in the package, so unusable by clients.
  2. Incorrect — it omitted TRACE, which RFC 9110 defines as safe.

This replaces it with two public, documented computed properties:

Property true for
isSafe GET, HEAD, OPTIONS, TRACE (and the QUERY draft method the type already models)
isIdempotent every safe method, plus PUT and DELETE

Because the classification is derived from the method token, it works for methods built from arbitrary strings (HTTPRequest.Method("GET")) as well as the static members. Unknown methods are conservatively reported as neither safe nor idempotent.

HTTPRequest.Method.get.isSafe          // true
HTTPRequest.Method.get.isIdempotent    // true  (safe ⇒ idempotent)
HTTPRequest.Method.delete.isSafe       // false
HTTPRequest.Method.delete.isIdempotent // true
HTTPRequest.Method.post.isIdempotent   // false

Testing

Adds testMethodSafety and testMethodSafetyFromString covering the safe, idempotent-but-unsafe, and neither buckets, plus classification of methods constructed from strings. Full suite (22 tests) passes.

Notes

  • Purely additive public API; no behavior changes to existing functionality.
  • The removed isSafe was internal and unused, so nothing in the package depended on it.

References:

RFC 9110 classifies request methods by two properties that callers
frequently need: whether a method is "safe" (read-only semantics) and
whether it is "idempotent" (repeating the request has the same effect as
making it once). These properties drive common decisions such as whether
a failed request may be retried automatically or whether a response may
be cached.

The type previously carried an internal `isSafe` helper that was never
referenced anywhere, and it also misclassified TRACE, which RFC 9110
defines as safe.

Replace it with public `isSafe` and `isIdempotent` computed properties:

- `isSafe` is true for GET, HEAD, OPTIONS, TRACE (and the QUERY draft
  method that the type already models).
- `isIdempotent` is true for PUT and DELETE in addition to every safe
  method.

The properties are derived from the method token, so they work for
methods constructed from arbitrary strings as well as the provided static
members, and unknown methods are conservatively reported as neither safe
nor idempotent.

https://www.rfc-editor.org/rfc/rfc9110.html#name-safe-methods
https://www.rfc-editor.org/rfc/rfc9110.html#name-idempotent-methods
@tkshsbcue

Copy link
Copy Markdown
Author

@guoye-zhang hope you can review my PR

@guoye-zhang

Copy link
Copy Markdown
Contributor

This API addition will require more discussions. I'm not certain that exposing safe and idempotent as read-only properties is correct. HTTP method is extensible and this prevents users from defining new idempotent methods.

However, adding a new stored property is also tricky since it will complicate equality and coding, and the info is not sent over the wire. Should we allow someone to set POST as idempotent? For now I think the decision of what's safe/idempotent should be made by the HTTP loader.

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.

2 participants