Skip to content

Set FusedTransformer as default#2250

Merged
ueman merged 14 commits into
cfug:mainfrom
knaeckeKami:default_transformer
Jun 18, 2024
Merged

Set FusedTransformer as default#2250
ueman merged 14 commits into
cfug:mainfrom
knaeckeKami:default_transformer

Conversation

@knaeckeKami

@knaeckeKami knaeckeKami commented Jun 17, 2024

Copy link
Copy Markdown
Contributor

New Pull Request Checklist

  • I have read the Documentation
  • I have searched for a similar pull request in the project and found none
  • I have updated this branch with the latest main branch to avoid conflicts (via merge from master or rebase)
  • I have added the required tests to prove the fix/feature I'm adding
  • I have updated the documentation (if necessary)
  • I have run the tests without failures
  • I have updated the CHANGELOG.md in the corresponding package

Additional context and info (if any)

Also fix three oversights in the transformer

  • Fix parsing content as JSON when Content-Type is like application/json but ResponseType == .plain

  • HEAD requests have an empty body, even when Content-Length is >0. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD . I did not take this into account. This is also fixed now.

  • Respect custom decoders returning null

@knaeckeKami
knaeckeKami requested a review from a team as a code owner June 17, 2024 20:21

@ueman ueman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks again! I have no objections to changing the default transformer, but I'd like to hear the opinions on it from the others

Comment thread dio/lib/src/dio_mixin.dart Outdated
@override
Transformer transformer = BackgroundTransformer();
Transformer transformer =
FusedTransformer(contentLengthIsolateThreshold: 50 * 1024);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you add a comment explaining this specific number? Is it chosen rather arbitrarily or an educated guess?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does it make sense to be configurable?

@knaeckeKami knaeckeKami Jun 17, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

50 * 1024 is the hardcoded default in BackgroundTransformer, I chose the same to keep the behavior as close as possible to the old one.
I did not measure how long it takes to decode on smartphones with the new approach. I copied the rationale for the 50 KiB threshold from BackgroundTransformer now.

IMO it makes sense to make it configurable, for example, when running the whole HTTP client in a background isolate already, users might not care about blocking the isolate for a few milliseconds, so they could set a higher (or -1 to disable spawning new isolates completely).

Comment thread dio/CHANGELOG.md
Comment thread dio/lib/src/transformers/fused_transformer.dart
} else if (customResponseDecoder != null) {
return decodedResponse;
} else {
if (responseBytes.isEmpty) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any references?

@knaeckeKami knaeckeKami Jun 17, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, did not mean to commit that. Is unnecessary, utf8.decode returns an empty string anyway on an empty bytes list. removed.

Comment on lines +121 to +123
// Successful HEAD requests don't have a response body, even if the content-length header
// present.
final contentLengthHeaderImpliesContent = options.method != 'HEAD';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  • With CONNECT too although it's an edge case?
  • Also the MDN reference would be helpful to be placed here.
  • Could the name be neverHasResponseBody and then flip all conditions to the opposite?
final neverHasResponseBody = options.method == 'CONNECT' || options.method == 'HEAD';

if (neverHasResponseBody || !hasContentLengthHeader) {
  // ...
}

@knaeckeKami knaeckeKami Jun 17, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The issue only occurs when the ResponseType is .json, the response body has a Content-Type of application/json, and a Content-Length header with a value > 0, but no response body.

A valid CONNECT response will have no Content-Type and no Content-Length header, so the transformer won't try to parse it as json.

A server MUST NOT send any Transfer-Encoding or Content-Length header fields in a 2xx (Successful) response to CONNECT. A client MUST ignore any Content-Length or Transfer-Encoding header fields received in a successful response to CONNECT.

I mean sure, we could also support invalid responses to CONNECT, but I'd argue if a user want's that, they should just set the ResponseType to .plain, .bytes or .stream. or use their own decoder / transformer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Cool, thanks for the explanation. But the flag should be flipped because if you are using its opposite result always you should simply flip it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

true. done

Comment thread dio/test/transformer_test.dart Outdated
Comment thread dio/lib/src/dio_mixin.dart Outdated
knaeckeKami and others added 2 commits June 18, 2024 13:00
Co-authored-by: Alex Li <github@alexv525.com>
Signed-off-by: Martin Kamleithner <martin.kamleithner@gmail.com>
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage Report: Only Changed Files listed

Package Base Coverage New Coverage Difference
dio/lib/src/transformers/fused_transformer.dart 🟢 84.09% 🟢 91.3% 🟢 7.21%
dio/lib/src/transformers/sync_transformer.dart 🟢 100% 🟢 84.21% 🔴 -15.79%
Overall Coverage 🟢 82.45% 🟢 82.48% 🟢 0.03%

Minimum allowed coverage is 0%, this run produced 82.48%

@AlexV525 AlexV525 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@ueman
ueman merged commit 47abf18 into cfug:main Jun 18, 2024
ueman added a commit that referenced this pull request Sep 3, 2024
fixes #2279 

This improves handling of the following case:

- ResponseType is json
- Server Content-Type is json
- Server Content-Length is nonzero
- Response Body is empty

This can happen in some cases according to HTTP spec (e.g. HEAD
requests), but some servers return responses like this (see #2279) also
in other cases, even if it violates the HTTP spec.

With #2250, in some of these cases dio would throw an exception, which
caused a regression for some users; see #2279
I do believe that dio should handle these cases for gracefully,

This PR brings back the previous behavior of returning null.  

### New Pull Request Checklist

- [x] I have read the
[Documentation](https://pub.dev/documentation/dio/latest/)
- [x] I have searched for a similar pull request in the
[project](https://github.com/cfug/dio/pulls) and found none
- [x] I have updated this branch with the latest `main` branch to avoid
conflicts (via merge from master or rebase)
- [x] I have added the required tests to prove the fix/feature I'm
adding
- [x] I have updated the documentation (if necessary)
- [x] I have run the tests without failures
- [x] I have updated the `CHANGELOG.md` in the corresponding package

### Additional context and info (if any)

<!-- Provide more context and info about the PR. -->

---------

Signed-off-by: Martin Kamleithner <martin.kamleithner@gmail.com>
Co-authored-by: Jonas Uekötter <ueman@users.noreply.github.com>
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.

4 participants