OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class _HttpHeaders implements HttpHeaders { | 5 class _HttpHeaders implements HttpHeaders { |
6 _HttpHeaders() : _headers = new Map<String, List<String>>(); | 6 _HttpHeaders() : _headers = new Map<String, List<String>>(); |
7 | 7 |
8 List<String> operator[](String name) { | 8 List<String> operator[](String name) { |
9 name = name.toLowerCase(); | 9 name = name.toLowerCase(); |
10 return _headers[name]; | 10 return _headers[name]; |
(...skipping 14 matching lines...) Expand all Loading... |
25 if (value is List) { | 25 if (value is List) { |
26 for (int i = 0; i < value.length; i++) { | 26 for (int i = 0; i < value.length; i++) { |
27 _add(name, value[i]); | 27 _add(name, value[i]); |
28 } | 28 } |
29 } else { | 29 } else { |
30 _add(name, value); | 30 _add(name, value); |
31 } | 31 } |
32 } | 32 } |
33 | 33 |
34 void set(String name, Object value) { | 34 void set(String name, Object value) { |
| 35 name = name.toLowerCase(); |
35 _checkMutable(); | 36 _checkMutable(); |
36 removeAll(name); | 37 removeAll(name); |
37 add(name, value); | 38 add(name, value); |
38 } | 39 } |
39 | 40 |
40 void remove(String name, Object value) { | 41 void remove(String name, Object value) { |
41 _checkMutable(); | 42 _checkMutable(); |
42 name = name.toLowerCase(); | 43 name = name.toLowerCase(); |
43 List<String> values = _headers[name]; | 44 List<String> values = _headers[name]; |
44 if (values != null) { | 45 if (values != null) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 109 } |
109 | 110 |
110 void set expires(Date expires) { | 111 void set expires(Date expires) { |
111 _checkMutable(); | 112 _checkMutable(); |
112 // Format "Expires" header with date in Greenwich Mean Time (GMT). | 113 // Format "Expires" header with date in Greenwich Mean Time (GMT). |
113 String formatted = | 114 String formatted = |
114 _HttpUtils.formatDate(expires.changeTimeZone(new TimeZone.utc())); | 115 _HttpUtils.formatDate(expires.changeTimeZone(new TimeZone.utc())); |
115 _set("expires", formatted); | 116 _set("expires", formatted); |
116 } | 117 } |
117 | 118 |
| 119 ContentType get contentType() { |
| 120 var values = _headers["content-type"]; |
| 121 if (values != null) { |
| 122 return new ContentType.fromString(values[0]); |
| 123 } else { |
| 124 return new ContentType(); |
| 125 } |
| 126 } |
| 127 |
| 128 void set contentType(ContentType contentType) { |
| 129 _checkMutable(); |
| 130 _set("content-type", contentType.toString()); |
| 131 } |
| 132 |
118 void _add(String name, Object value) { | 133 void _add(String name, Object value) { |
119 // TODO(sgjesse): Add immutable state throw HttpException is immutable. | 134 // TODO(sgjesse): Add immutable state throw HttpException is immutable. |
120 if (name.toLowerCase() == "date") { | 135 if (name.toLowerCase() == "date") { |
121 if (value is Date) { | 136 if (value is Date) { |
122 date = value; | 137 date = value; |
123 } else if (value is String) { | 138 } else if (value is String) { |
124 _set("date", value); | 139 _set("date", value); |
125 } else { | 140 } else { |
126 throw new HttpException("Unexpected type for header named $name"); | 141 throw new HttpException("Unexpected type for header named $name"); |
127 } | 142 } |
(...skipping 20 matching lines...) Expand all Loading... |
148 _port = HttpClient.DEFAULT_HTTP_PORT; | 163 _port = HttpClient.DEFAULT_HTTP_PORT; |
149 } else { | 164 } else { |
150 try { | 165 try { |
151 _port = Math.parseInt(value.substring(pos + 1)); | 166 _port = Math.parseInt(value.substring(pos + 1)); |
152 } catch (BadNumberFormatException e) { | 167 } catch (BadNumberFormatException e) { |
153 _port = null; | 168 _port = null; |
154 } | 169 } |
155 } | 170 } |
156 _set("host", value); | 171 _set("host", value); |
157 } | 172 } |
| 173 } else if (name.toLowerCase() == "content-type") { |
| 174 _set("content-type", value); |
158 } else { | 175 } else { |
159 name = name.toLowerCase(); | 176 name = name.toLowerCase(); |
160 List<String> values = _headers[name]; | 177 List<String> values = _headers[name]; |
161 if (values == null) { | 178 if (values == null) { |
162 values = new List<String>(); | 179 values = new List<String>(); |
163 _headers[name] = values; | 180 _headers[name] = values; |
164 } | 181 } |
165 values.add(value.toString()); | 182 values.add(value.toString()); |
166 } | 183 } |
167 } | 184 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 239 } |
223 | 240 |
224 bool _mutable = true; // Are the headers currently mutable? | 241 bool _mutable = true; // Are the headers currently mutable? |
225 Map<String, List<String>> _headers; | 242 Map<String, List<String>> _headers; |
226 | 243 |
227 String _host; | 244 String _host; |
228 int _port; | 245 int _port; |
229 } | 246 } |
230 | 247 |
231 | 248 |
| 249 class _HeaderValue implements HeaderValue { |
| 250 _HeaderValue([String this.value = ""]); |
| 251 |
| 252 _HeaderValue.fromString(String value) { |
| 253 // Parse the string. |
| 254 _parse(value); |
| 255 } |
| 256 |
| 257 Map<String, String> get parameters() { |
| 258 if (_parameters == null) _parameters = new Map<String, String>(); |
| 259 return _parameters; |
| 260 } |
| 261 |
| 262 String toString() { |
| 263 StringBuffer sb = new StringBuffer(); |
| 264 sb.add(value); |
| 265 if (parameters != null && parameters.length > 0) { |
| 266 _parameters.forEach((String name, String value) { |
| 267 sb.add("; "); |
| 268 sb.add(name); |
| 269 sb.add("="); |
| 270 sb.add(value); |
| 271 }); |
| 272 } |
| 273 return sb.toString(); |
| 274 } |
| 275 |
| 276 void _parse(String s) { |
| 277 int index = 0; |
| 278 |
| 279 bool done() => index == s.length; |
| 280 |
| 281 void skipWS() { |
| 282 while (!done()) { |
| 283 if (s[index] != " " && s[index] != "\t") return; |
| 284 index++; |
| 285 } |
| 286 } |
| 287 |
| 288 String parseValue() { |
| 289 int start = index; |
| 290 while (!done()) { |
| 291 if (s[index] == " " || s[index] == "\t" || s[index] == ";") break; |
| 292 index++; |
| 293 } |
| 294 return s.substring(start, index).toLowerCase(); |
| 295 } |
| 296 |
| 297 void expect(String expected) { |
| 298 if (done()) throw new HttpException("Failed to parse header value [$s]"); |
| 299 if (s[index] != expected) { |
| 300 throw new HttpException("Failed to parse header value [$s]"); |
| 301 } |
| 302 index++; |
| 303 } |
| 304 |
| 305 void parseParameters() { |
| 306 _parameters = new Map<String, String>(); |
| 307 |
| 308 String parseParameterName() { |
| 309 int start = index; |
| 310 while (!done()) { |
| 311 if (s[index] == " " || s[index] == "\t" || s[index] == "=") break; |
| 312 index++; |
| 313 } |
| 314 return s.substring(start, index).toLowerCase(); |
| 315 } |
| 316 |
| 317 String parseParameterValue() { |
| 318 if (s[index] == "\"") { |
| 319 // Parse quoted value. |
| 320 StringBuffer sb = new StringBuffer(); |
| 321 index++; |
| 322 while (!done()) { |
| 323 if (s[index] == "\\") { |
| 324 if (index + 1 == s.length) { |
| 325 throw new HttpException("Failed to parse header value [$s]"); |
| 326 } |
| 327 index++; |
| 328 } else if (s[index] == "\"") { |
| 329 index++; |
| 330 break; |
| 331 } |
| 332 sb.add(s[index]); |
| 333 index++; |
| 334 } |
| 335 return sb.toString(); |
| 336 } else { |
| 337 // Parse non-quoted value. |
| 338 return parseValue(); |
| 339 } |
| 340 } |
| 341 |
| 342 while (!done()) { |
| 343 skipWS(); |
| 344 if (done()) return; |
| 345 String name = parseParameterName(); |
| 346 skipWS(); |
| 347 expect("="); |
| 348 skipWS(); |
| 349 String value = parseParameterValue(); |
| 350 _parameters[name] = value; |
| 351 skipWS(); |
| 352 if (done()) return; |
| 353 expect(";"); |
| 354 } |
| 355 } |
| 356 |
| 357 skipWS(); |
| 358 value = parseValue(); |
| 359 skipWS(); |
| 360 if (done()) return; |
| 361 expect(";"); |
| 362 parseParameters(); |
| 363 } |
| 364 |
| 365 String value; |
| 366 Map<String, String> _parameters; |
| 367 } |
| 368 |
| 369 |
| 370 class _ContentType extends _HeaderValue implements ContentType { |
| 371 _ContentType([String this._primaryType = "", String this._subType = ""]); |
| 372 |
| 373 _ContentType.fromString(String value) : super.fromString(value); |
| 374 |
| 375 String get value() => "$_primaryType/$_subType"; |
| 376 |
| 377 void set value(String s) { |
| 378 int index = s.indexOf("/"); |
| 379 if (index == -1 || index == (s.length - 1)) { |
| 380 primaryType = s.trim().toLowerCase(); |
| 381 subType = ""; |
| 382 } else { |
| 383 primaryType = s.substring(0, index).trim().toLowerCase(); |
| 384 subType = s.substring(index + 1).trim().toLowerCase(); |
| 385 } |
| 386 } |
| 387 |
| 388 String get primaryType() => _primaryType; |
| 389 |
| 390 void set primaryType(String s) { |
| 391 _primaryType = s; |
| 392 } |
| 393 |
| 394 String get subType() => _subType; |
| 395 |
| 396 void set subType(String s) { |
| 397 _subType = s; |
| 398 } |
| 399 |
| 400 String get charset() => parameters["charset"]; |
| 401 |
| 402 void set charset(String s) { |
| 403 parameters["charset"] = s; |
| 404 } |
| 405 |
| 406 String _primaryType = ""; |
| 407 String _subType = ""; |
| 408 } |
| 409 |
| 410 |
232 class _HttpRequestResponseBase { | 411 class _HttpRequestResponseBase { |
233 final int START = 0; | 412 final int START = 0; |
234 final int HEADER_SENT = 1; | 413 final int HEADER_SENT = 1; |
235 final int DONE = 2; | 414 final int DONE = 2; |
236 final int UPGRADED = 3; | 415 final int UPGRADED = 3; |
237 | 416 |
238 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) | 417 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) |
239 : _headers = new _HttpHeaders() { | 418 : _headers = new _HttpHeaders() { |
240 _state = START; | 419 _state = START; |
241 } | 420 } |
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1647 | 1826 |
1648 | 1827 |
1649 class _RedirectInfo implements RedirectInfo { | 1828 class _RedirectInfo implements RedirectInfo { |
1650 const _RedirectInfo(int this.statusCode, | 1829 const _RedirectInfo(int this.statusCode, |
1651 String this.method, | 1830 String this.method, |
1652 Uri this.location); | 1831 Uri this.location); |
1653 final int statusCode; | 1832 final int statusCode; |
1654 final String method; | 1833 final String method; |
1655 final Uri location; | 1834 final Uri location; |
1656 } | 1835 } |
OLD | NEW |