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

Nullable body spec #6689

Open
wants to merge 14 commits into
base: 3.3.x
Choose a base branch
from
Open

Nullable body spec #6689

wants to merge 14 commits into from

Conversation

mattmoss
Copy link
Contributor

Fixes #3064

@mattmoss mattmoss requested a review from jameskleeh December 23, 2021 17:36
@mattmoss mattmoss changed the base branch from 3.2.x to 3.3.x February 8, 2022 16:40
Comment on lines +103 to +108
if (source.getAttribute(REQUEST_BINDING_UNSATISFIED).isPresent() && typeVariable.get().isNullable()) {
return () -> Optional.of(source);
} else {
source.setAttribute(REQUEST_BINDING_UNSATISFIED, true);
return ArgumentBinder.BindingResult.UNSATISFIED;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a hack, can you explain this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This chunk of code is here to handle HttpRequest<@Nullable T> and similar.

For a request with an empty body, the first time the argument binder is called, the body is not yet decoded. The previous version of the code would simply return UNSATISFIED. When the second pass (w/ a decoded body) comes around, the situation is still that body is still null, and returns UNSATISFIED again, even though the the request has @Nullable T body type.

The first solution to try was just:

                  if (typeVariable.get().isNullable()) {
                        return () -> Optional.of(source);
                    } else {
                        return ArgumentBinder.BindingResult.UNSATISFIED;
                    }

First attempt to find would see the body was empty and typeVariable nullable, so it returned the lambda () -> Optional.of(source). This works for when the body is null. But if the request has a non-null body, the first pass sees the type variable as nullable, and returns the lambda, but this interferes with the second pass (after non-null body is decoded) which should return new FullHttpRequest(...).

To get around this, I use a custom attribute on the first pass to maintain existing behavior (pre-body-decode). But for the second pass, if the body is still null (determined because the attribute exists) AND the type variable is nullable, then returns the lambda () -> Optional.of(source), which makes all @Nullable T cases happy without messing up other cases/tests.

Comment on lines -350 to -356
/**
* @return A converter that returns bytebufs to objects
*/
protected TypeConverter<ByteBuf, Object> byteBufToObjectConverter() {
return (object, targetType, context) -> conversionService.convert(object.toString(context.getCharset()), targetType, context);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not a breaking change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't find any uses of this (which does a strange toString conversion that interferes with other more useful conversions). No tests broke, and no one seemed to think this was a problem when it was brought up during last engineering meeting.

Copy link
Contributor

Choose a reason for hiding this comment

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

@graemerocher The presence of the converter prevents proper conversion of ByteBuf to container types. In general I don't think it makes sense because if we don't know the target type we shouldn't assume that a string based conversion will succeed or will be desirable

@CLAassistant
Copy link

CLAassistant commented Apr 7, 2023

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 3 committers have signed the CLA.

✅ sdelamo
❌ Matthew Moss
❌ manuelmartinoracle


Matthew Moss seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

HttpRequest<Optional<ByteBuffer<*>>> still requires a request body when it should be optional
6 participants