Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@NthPortal
Copy link
Contributor

Add Status.UnprocessableContent and associated dsl bits.
Deprecate Status.UnprocessableEntity and associated dsl bits.

It has been called Unprocessable Content for almost 3 years (see RFC 9110). I'm a bit surprised no one else has noticed this, but even more than that, I have no idea how I only found out it was no longer called Unprocessable Entity this morning.

Also, this was far more work than I signed up for when I thought to myself "oh, I'll just quickly fix the name in http4s," but such is life.

Add `Status.UnprocessableContent` and associated dsl bits.
Deprecate `Status.UnprocessableEntity` and associated dsl bits.
@mergify mergify bot added series/0.23 PRs targeting 0.23.x module:core module:dsl labels Apr 7, 2025
@NthPortal
Copy link
Contributor Author

side note: I still don't know when it stopped being specifically part of WebDAV, which is what I'd actually set out to find

Comment on lines +219 to +221
val UnprocessableContent: Status = register(trust(422, "Unprocessable Content"))
@deprecated("now called UnprocessableContent", since = "0.23.31")
val UnprocessableEntity: Status = UnprocessableContent
Copy link
Member

Choose a reason for hiding this comment

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

I'm afraid this refactoring might be too invasive for end users. First, it could trigger a lot of deprecation warnings (or even break builds if the -Xfatal-warnings option is enabled). Second, some servers or clients might parse the reason phrase (FWIW), so I doubt refactoring Unprocessable Entity -> Unprocessable Content is legit when done this way. For example, both Netty and Armeria use the Unprocessable Entity. Personally, I think we might add UnprocessableContent alongside UnprocessableEntity and spice them with references to the RFC in scaladocs. WDYT?

Copy link
Contributor Author

@NthPortal NthPortal Apr 7, 2025

Choose a reason for hiding this comment

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

First, it could trigger a lot of deprecation warnings (or even break builds if the -Xfatal-warnings option is enabled)

-Wconf:cat=deprecation&origin=org\.http4s\..*UnprocessableEntity.*:s (or :w or :ws if you just want it to not be fatal).

also, this is a general argument against deprecating things ever.

also also, as deprecations go, you can literally find/replace this one. and/or, someone can write a scalafix migration for this and have scala-steward apply it automatically, if they want to and know how.

also also also, not deprecating it would make switching to UnprocessableContent in 1.0.0 quite bad form, even though there are technically no compatibility guarantees.

Second, some servers or clients might parse the reason phrase (FWIW)

I don't think we should concern ourself with users who actively shoot themselves in the foot. the reason phrase is only intended for human users, and the numeric code has always been there as the intended thing for automata to use.

from the scaladoc of Status:

* '''Note: ''' the reason is not important to the protocol and is not considered in equality checks.

For example, both Netty and Armeria use the Unprocessable Entity

a more compelling argument would be linking rejected PRs adding UNPROCESSABLE_CONTENT. all this establishes is that no one has bothered to make such PRs. regardless, I would not find that argument compelling either, but I especially don't find this one compelling.

WDYT?

I think we should keep up with the HTTP spec

Copy link
Member

Choose a reason for hiding this comment

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

I think we should keep up with the HTTP spec

Could you point to the specific part of RFC 9110 that deprecates the use of Unprocessable Entity in favour of Unprocessable Content? I agree that we should follow the mandatory parts of the HTTP spec — the ones marked as MUST, and effectively also SHOULD.

Copy link
Contributor Author

@NthPortal NthPortal Apr 7, 2025

Choose a reason for hiding this comment

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

Could you point to the specific part of RFC 9110 that deprecates the use of Unprocessable Entity in favour of Unprocessable Content?

from RFC 9110 § 15.1 (emphasis mine):

The status codes listed below are defined in this specification. The reason phrases listed here are only recommendations -- they can be replaced by local equivalents or left out altogether without affecting the protocol.

the point is, it's called "Unprocessable Content" in the spec, therefore the http4s API should also call it that, so that people who read the spec can find it and won't be confused. org.http4s.Status.UnprocessableEntity is deprecated because the spec no longer calls it "Unprocessable Entity", and deprecation is how you evolve APIs. it would be both confusing and bad API design to have two slightly different versions of HTTP status 422 which are both considered acceptable.

you're right, we do not have to do this, but by the same token, we didn't have to use any of the other reason phrases listed in the spec as the names in the http4s API, and yet we did. consistency is nice.


why are you gatekeeping deprecating things?!

also, why are you nitpicking my gentle response to your question of "WDYT?" and ignoring everything else I said? I think I was pretty clear that I'm trying to align the API with the current terminology used by the spec. I guess next time you ask "WDYT?" I'll just say "No."

Copy link
Member

Choose a reason for hiding this comment

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

why are you gatekeeping deprecating things?!
also, why are you nitpicking my gentle response to your question of "WDYT?" and ignoring everything else I said? I think I was pretty clear that I'm trying to align the API with the current terminology used by the spec. I guess next time you ask "WDYT?" I'll just say "No."

For my defence, I was simply expressing my humble opinion — a freedom I believe every human being should have. I didn’t intend to nitpick or criticise unnecessarily. Moreover, I didn’t find my wording harsh; in fact, I thought it was as gentle as yours. If I happen to disagree with something, just as you might with my views, that should be fine (I mean acceptable). I don’t wish to prolong this debate, and I hope you understand my position as clearly as I understand yours.

Returning to the matter of this PR..
My main point is that deprecation can be invasive for end users. Anything that breaks binary compatibility (not the case here), as well as source compatibility, should be carefully weighed. In this particular case, we're deprecating an API for something that, as you pointed out in the RFC, "can be replaced by local equivalents or left out altogether without affecting the protocol." I'm simply trying to assess whether the benefit justifies the potential distraction for users. I also referenced other giants in the field who hasn’t changed this aspect since RFC 4918, to suggest that this isn’t a violation of the HTTP spec — as it seemed you were implying earlier in the thread.

Ultimately, this is just my perspective. Fortunately, http4s has many other maintainers who may see it differently and choose to move forward with these changes. As per current policy, a single approval is enough for a PR to be merged.

Copy link
Contributor

@hamnis hamnis left a comment

Choose a reason for hiding this comment

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

I think aligning with the spec is good. Thanks for the PR

@hamnis hamnis merged commit d260523 into http4s:series/0.23 Apr 12, 2025
17 checks passed
@NthPortal NthPortal deleted the 422-name branch April 14, 2025 16:44
Comment on lines +684 to +686
ProblemFilters.exclude[ReversedMissingMethodProblem](
"org.http4s.dsl.impl.Statuses.org$http4s$dsl$impl$Statuses$_setter_$UnprocessableContent_="
),
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, these are real, binary-breaking issues. @ahjohannessen encountered it in smithy4s.

java.lang.AbstractMethodError: Receiver class smithy4s.http4s.swagger.PartiallyAppliedDocs$$anon$1 does not define or inherit an implementation of the resolved method 'abstract void org$http4s$dsl$impl$Statuses$_setter_$UnprocessableContent_$eq(org.http4s.Status)' of interface org.http4s.dsl.impl.Statuses.
    at org.http4s.dsl.impl.Statuses.$init$(Statuses.scala:66)
    at smithy4s.http4s.swagger.Docs.<init>(Docs.scala:31)
    at smithy4s.http4s.swagger.PartiallyAppliedDocs$$anon$1.<init>(PartiallyAppliedDocs.scala:34)
    at smithy4s.http4s.swagger.PartiallyAppliedDocs.apply(PartiallyAppliedDocs.scala:41)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, biscuits. I'm sorry.

I confess I don't understand how/why that error happens

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants