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

Fix #7262: mulitpart decoder wrapping unwanted errors #7265

Conversation

LaurenceWarne
Copy link
Contributor

Hi, this PR implements a fix for #7262 by only catching errors related to decoding failures in MultipartDecoder.

Thanks!

Comment on lines -141 to -143
.handleError {
case e: InvalidMessageBodyFailure => Left(e)
case e => Left(InvalidMessageBodyFailure("Invalid multipart body", Some(e)))
Copy link
Member

Choose a reason for hiding this comment

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

Sorry for being late to the party. But I'd like to express my opinion without claiming to strictness. I could be wrong, but exceptions being thrown by public API become its contact. Here in MultipartDecoder, any exception is transformed to InvalidMessageBodyFailure. I guess we can't resolve the initial issue without impacting the public contract, but what if we try to minimise it? What I precisely suggest, in short:

  1. Move org.http4s.server.middleware.EntityLimiter.EntityTooLarge to the core module.
  2. Use it in the EntityLimiter Middleware.
  3. Propagate it directly in the error handling via org.http4s.InvalidMessageBodyFailure#cause.

@armanbilge @LaurenceWarne wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So we would maintain existing behaviour except for special casing the EntityTooLarge exception? If that would be preferable I'm happy to do it.

Propagate it directly in the error handling via org.http4s.InvalidMessageBodyFailure#cause.

I may not be understanding correctly, but InvalidMessageBodyFailure.message doesn't appear to use cause, so we wouldn't see the specific error (I guess we could change details)? An alternative could be to use Pull.raiseError[F](InvalidMessageBodyFailure("Entity too large")) in the middleware, though I guess this would alter existing behaviour also?

Copy link
Member

Choose a reason for hiding this comment

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

but exceptions being thrown by public API become its contact

@danicheg I see what you're saying, but meh. The constraint is Concurrent[F] so users should be prepared for any Throwable. If the API was GenConcurrent[F, InvalidMessageBodyFailure] then I agree we could not change that explicit contract, but that's not the case. This was just a bug.

.handleError {
case e: InvalidMessageBodyFailure => Left(e)
case e => Left(InvalidMessageBodyFailure("Invalid multipart body", Some(e)))
.recover { case e: DecodeFailure =>
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 MessageBodyFailure is the right level of granularity. DecodeFailure is too general e.g. applies to headers.

Suggested change
.recover { case e: DecodeFailure =>
.recover { case e: MessageBodyFailure =>

@armanbilge armanbilge linked an issue Nov 9, 2023 that may be closed by this pull request
Comment on lines 257 to 261
mkDecoder.use { decoder =>
val decoded = decoder.decode(request, true)
val result = decoded.value
assertIO(result.attempt, Left(CustomError))
}.assert
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
mkDecoder.use { decoder =>
val decoded = decoder.decode(request, true)
val result = decoded.value
assertIO(result.attempt, Left(CustomError))
}.assert
mkDecoder.use(_.decode(request, true).value).intercept[CustomError.type]

@danicheg
Copy link
Member

LGTM!

@armanbilge armanbilge merged commit 8744d6c into http4s:series/0.23 Nov 10, 2023
17 checks passed
@LaurenceWarne
Copy link
Contributor Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module:core series/0.23 PRs targeting 0.23.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EntityLimiter with Multipart Error
3 participants