@@ -44,9 +44,6 @@ abstract class Message {
44
44
/// This can be read via [read] or [readAsString] .
45
45
final Body _body;
46
46
47
- /// The parsed version of the Content-Type header in [headers] .
48
- final MediaType _contentType;
49
-
50
47
/// Creates a new [Message] .
51
48
///
52
49
/// [body] is the message body. It may be either a [String] , a [List<int>] , a
@@ -61,25 +58,30 @@ abstract class Message {
61
58
/// Content-Type header, it will be set to "application/octet-stream".
62
59
Message (body,
63
60
{Encoding encoding,
64
- Map <String , String > headers,
65
- Map <String , Object > context})
61
+ Map <String , String > headers,
62
+ Map <String , Object > context})
66
63
: this .__(body, _determineMediaType (body, encoding, headers), headers,
67
- context);
64
+ context);
68
65
69
66
Message .__(body, MediaType contentType, Map <String , String > headers,
70
67
Map <String , Object > context)
71
- : this ._(new Body (body, encodingForMediaType (contentType, null )),
72
- contentType, headers, context);
68
+ : this ._(new Body (body, encodingForMediaType (contentType, null )), contentType,
69
+ headers, context);
73
70
74
71
Message ._(Body body, MediaType contentType, Map <String , String > headers,
75
72
Map <String , Object > context)
73
+ : this .fromValues (body, _adjustHeaders (headers, body, contentType), context);
74
+
75
+ /// Creates a new [Message] .
76
+ ///
77
+ /// This constructor should be used when no computation is required for the
78
+ /// [body] , [headers] or [context] .
79
+ Message .fromValues (
80
+ Body body, Map <String , String > headers, Map <String , Object > context)
76
81
: _body = body,
77
- headers = new HttpUnmodifiableMap <String >(
78
- _adjustHeaders (headers, body, contentType),
79
- ignoreKeyCase: true ),
82
+ headers = new HttpUnmodifiableMap <String >(headers, ignoreKeyCase: true ),
80
83
context =
81
- new HttpUnmodifiableMap <Object >(context, ignoreKeyCase: false ),
82
- _contentType = contentType;
84
+ new HttpUnmodifiableMap <Object >(context, ignoreKeyCase: false );
83
85
84
86
/// If `true` , the stream returned by [read] won't emit any bytes.
85
87
///
@@ -104,7 +106,11 @@ abstract class Message {
104
106
/// the MIME type, without any Content-Type parameters.
105
107
///
106
108
/// If [headers] doesn't have a Content-Type header, this will be `null` .
107
- String get mimeType => _contentType? .mimeType;
109
+ String get mimeType {
110
+ var contentType = _contentType;
111
+ if (contentType == null ) return null ;
112
+ return contentType.mimeType;
113
+ }
108
114
109
115
/// The encoding of the body returned by [read] .
110
116
///
@@ -113,7 +119,24 @@ abstract class Message {
113
119
///
114
120
/// If [headers] doesn't have a Content-Type header or it specifies an
115
121
/// encoding that [dart:convert] doesn't support, this will be `null` .
116
- Encoding get encoding => _body.encoding;
122
+ Encoding get encoding {
123
+ var contentType = _contentType;
124
+ if (contentType == null ) return null ;
125
+ if (! contentType.parameters.containsKey ('charset' )) return null ;
126
+ return Encoding .getByName (contentType.parameters['charset' ]);
127
+ }
128
+
129
+ /// The parsed version of the Content-Type header in [headers] .
130
+ ///
131
+ /// This is cached for efficient access.
132
+ MediaType get _contentType {
133
+ if (_contentTypeCache != null ) return _contentTypeCache;
134
+ if (! headers.containsKey ('content-type' )) return null ;
135
+ _contentTypeCache = new MediaType .parse (headers['content-type' ]);
136
+ return _contentTypeCache;
137
+ }
138
+
139
+ MediaType _contentTypeCache;
117
140
118
141
/// Returns the message body as byte chunks.
119
142
///
@@ -139,7 +162,7 @@ abstract class Message {
139
162
140
163
/// Determines the media type based on the [headers] , [encoding] and [body] .
141
164
static MediaType _determineMediaType (
142
- body, Encoding encoding, Map <String , String > headers) =>
165
+ body, Encoding encoding, Map <String , String > headers) =>
143
166
_headerMediaType (headers, encoding) ?? _defaultMediaType (body, encoding);
144
167
145
168
static MediaType _defaultMediaType (body, Encoding encoding) {
@@ -166,7 +189,7 @@ abstract class Message {
166
189
var contentType = new MediaType .parse (contentTypeHeader);
167
190
var parameters = {
168
191
'charset' :
169
- encoding? .name ?? contentType.parameters['charset' ] ?? UTF8 .name
192
+ encoding? .name ?? contentType.parameters['charset' ] ?? UTF8 .name
170
193
};
171
194
172
195
return contentType.change (parameters: parameters);
0 commit comments