-
Notifications
You must be signed in to change notification settings - Fork 380
Fix content type within Message #120
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
Conversation
@nex3 if this is the approach you want I'll comment up the functions/methods before merging. |
@nex3 so I made |
lib/src/body.dart
Outdated
@@ -36,25 +38,20 @@ class Body { | |||
/// used to convert it to a [Stream<List<int>>]. | |||
factory Body(body, [Encoding encoding]) { | |||
if (body is Body) return body; | |||
if (body == null) | |||
return new Body._(new Stream.fromIterable([]), encoding, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new Stream.fromIterable()
could be const Stream.empty()
. It might be even cleaner to return a static _empty
field here, though, to avoid any allocations in the common case of an empty body.
Nit: use curly braces.
lib/src/body.dart
Outdated
|
||
if (body is Map) { | ||
body = mapToQuery(body, encoding: encoding); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't this in the if/else
chain with the other type tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value of body
becomes a String
at this point so it will end up in the is String
which would then encode it.
body = mapToQuery(body, encoding: encoding); | ||
} | ||
|
||
if (body is String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happened to the branch where encoding == null
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should never be null
since the encoding is calculated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean when it's set to UTF8
above? But then you're marking ASCII-only bodies as UTF8 when a text/plain
content type would do. The old behavior here was correct, there's no need to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'll take a look at what 0.11 was doing here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not 0.11, just the previous code in master.
lib/src/message.dart
Outdated
|
||
Message._(Body body, Map<String, String> headers, Map<String, Object> context) | ||
Message.__(body, MediaType contentType, Map<String, String> headers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__
isn't a good name for a constructor--it doesn't communicate what the difference is between this and the other unnamed constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
K I think I need to rename this anyways so it could be used in the multipart implementation.
I also didn't like fromValues
but didn't have any better ideas last night.
lib/src/message.dart
Outdated
Message._(Body body, Map<String, String> headers, Map<String, Object> context) | ||
Message.__(body, MediaType contentType, Map<String, String> headers, | ||
Map<String, Object> context) | ||
: this._(new Body(body, encodingForMediaType(contentType, null)), contentType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new Body(...)
invocation looks wrong to me... the Body
's encoding shouldn't ever come from the headers, it should only come from the explicit encoding passed by the user. So this should continue to be new Body(body, encoding)
, which means you don't have to do this many-layered-constructor thing anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_determineMediaType
is what determines the encoding for the body. If encoding
is set directly then it should override what is in content-type
header so that value can be used when creating the body.
This reflects the behavior of this test https://github.com/dart-lang/http/blob/master/test/request_test.dart#L152-L158
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this is written currently, the encoding passed to new Body()
can come from headers
. That's not correct. It should only ever come from the encoding
parameter, or from the default value (which should be UTF-8).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So just to be clear if someone were to set content-type: 'application/json; charset=iso-8859-1'
and not set encoding
to LATIN when creating a Request
it should not encode the body with LATIN it should be UTF8 encoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, and the header should be updated accordingly.
lib/src/message.dart
Outdated
/// | ||
/// This constructor should be used when no computation is required for the | ||
/// [body], [headers] or [context]. | ||
Message.fromValues( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the performance motivation for having this constructor, but I'd like to focus on API shape and correctness for now and leave optimizations like this for later (ideally driven by real data).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'll rework this accordingly.
1fb0ee5
to
5c7b451
Compare
@nex3 should be good to go. I think I addressed all your feedback. |
@@ -27,6 +29,9 @@ class Body { | |||
/// determined efficiently. | |||
final int contentLength; | |||
|
|||
/// An empty stream for use with empty bodies. | |||
static const _emptyStream = const Stream.empty(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant store an instance of Body
statically:
static _empty = new Body._(const Stream.empty(), null, 0);
Creating a static field for a const value doesn't do anything since const constructors are already canonicalized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was looking at implementing this but the issue is that calling read removes the stream.
Do you instead want an EmptyBody class that lets you call read() multiple times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you instead want an EmptyBody class that lets you call read() multiple times?
Yeah, I think this is the way to go. That matches the behavior of const Stream.empty()
, too.
body = mapToQuery(body, encoding: encoding); | ||
} | ||
|
||
if (body is String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean when it's set to UTF8
above? But then you're marking ASCII-only bodies as UTF8 when a text/plain
content type would do. The old behavior here was correct, there's no need to change it.
|
||
Message._(Body body, Map<String, String> headers, Map<String, Object> context) | ||
Message.withContentType(Body body, MediaType contentType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want this constructor here. The shape of the constructors from before this CL is generally correct; the only change should be adding a {bool bodyIsMap: false}
parameter to new Message._()
and _adjustHeaders()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had planned to use it with http.MultiPart
since the MediaType
requires a boundary which would be randomly generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have _adjustHeaders()
do some logic like
if (body is MultipartBody) {
contentType = "multipart/mixed; boundary=${body.boundary}";
}
Attempt to fix
content-type
withinMessage
.Fixes #101