OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 class _HttpHeaders implements HttpHeaders { | 7 class _HttpHeaders implements HttpHeaders { |
8 final Map<String, List<String>> _headers; | 8 final Map<String, List<String>> _headers; |
9 final String protocolVersion; | 9 final String protocolVersion; |
10 | 10 |
(...skipping 24 matching lines...) Expand all Loading... | |
35 List<String> values = _headers[name]; | 35 List<String> values = _headers[name]; |
36 if (values == null) return null; | 36 if (values == null) return null; |
37 if (values.length > 1) { | 37 if (values.length > 1) { |
38 throw new HttpException("More than one value for header $name"); | 38 throw new HttpException("More than one value for header $name"); |
39 } | 39 } |
40 return values[0]; | 40 return values[0]; |
41 } | 41 } |
42 | 42 |
43 void add(String name, value) { | 43 void add(String name, value) { |
44 _checkMutable(); | 44 _checkMutable(); |
45 _addAll(name.toLowerCase(), value); | 45 _addAll(_validateField(name), value); |
46 } | 46 } |
47 | 47 |
48 void _addAll(String name, value) { | 48 void _addAll(String name, value) { |
Søren Gjesse
2014/07/04 09:24:54
Add
assert(name == _validateField(name));
here a
Anders Johnsen
2014/07/04 11:03:49
Done.
| |
49 if (value is List) { | 49 if (value is List) { |
Søren Gjesse
2014/07/04 09:24:54
Btw. shouldn't this be just Iterable?
Anders Johnsen
2014/07/04 11:03:49
Yeah.
| |
50 value.forEach((v) => _add(name, v)); | 50 value.forEach((v) => _add(name, _validateValue(v))); |
51 } else { | 51 } else { |
52 _add(name, value); | 52 _add(name, _validateValue(value)); |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 void set(String name, Object value) { | 56 void set(String name, Object value) { |
57 _checkMutable(); | 57 _checkMutable(); |
58 name = name.toLowerCase(); | 58 name = _validateField(name); |
59 _headers.remove(name); | 59 _headers.remove(name); |
60 _addAll(name, value); | 60 _addAll(name, value); |
61 } | 61 } |
62 | 62 |
63 void remove(String name, Object value) { | 63 void remove(String name, Object value) { |
64 _checkMutable(); | 64 _checkMutable(); |
65 name = name.toLowerCase(); | 65 name = _validateField(name); |
66 value = _validateValue(value); | |
66 List<String> values = _headers[name]; | 67 List<String> values = _headers[name]; |
67 if (values != null) { | 68 if (values != null) { |
68 int index = values.indexOf(value); | 69 int index = values.indexOf(value); |
69 if (index != -1) { | 70 if (index != -1) { |
70 values.removeRange(index, index + 1); | 71 values.removeRange(index, index + 1); |
71 } | 72 } |
72 if (values.length == 0) _headers.remove(name); | 73 if (values.length == 0) _headers.remove(name); |
73 } | 74 } |
74 } | 75 } |
75 | 76 |
76 void removeAll(String name) { | 77 void removeAll(String name) { |
77 _checkMutable(); | 78 _checkMutable(); |
78 name = name.toLowerCase(); | 79 name = _validateField(name); |
79 _headers.remove(name); | 80 _headers.remove(name); |
80 } | 81 } |
81 | 82 |
82 void forEach(void f(String name, List<String> values)) { | 83 void forEach(void f(String name, List<String> values)) { |
83 _headers.forEach(f); | 84 _headers.forEach(f); |
84 } | 85 } |
85 | 86 |
86 void noFolding(String name) { | 87 void noFolding(String name) { |
87 if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>(); | 88 if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>(); |
88 _noFoldingHeaders.add(name); | 89 _noFoldingHeaders.add(name); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 } | 244 } |
244 } | 245 } |
245 | 246 |
246 void set contentType(ContentType contentType) { | 247 void set contentType(ContentType contentType) { |
247 _checkMutable(); | 248 _checkMutable(); |
248 _set(HttpHeaders.CONTENT_TYPE, contentType.toString()); | 249 _set(HttpHeaders.CONTENT_TYPE, contentType.toString()); |
249 } | 250 } |
250 | 251 |
251 // [name] must be a lower-case version of the name. | 252 // [name] must be a lower-case version of the name. |
252 void _add(String name, value) { | 253 void _add(String name, value) { |
253 assert(name == name.toLowerCase()); | 254 assert(name == _validateField(name)); |
254 // Use the length as index on what method to call. This is notable | 255 // Use the length as index on what method to call. This is notable |
255 // faster than computing hash and looking up in a hash-map. | 256 // faster than computing hash and looking up in a hash-map. |
256 switch (name.length) { | 257 switch (name.length) { |
257 case 4: | 258 case 4: |
258 if (HttpHeaders.DATE == name) { | 259 if (HttpHeaders.DATE == name) { |
259 _addDate(name, value); | 260 _addDate(name, value); |
260 return; | 261 return; |
261 } | 262 } |
262 if (HttpHeaders.HOST == name) { | 263 if (HttpHeaders.HOST == name) { |
263 _addHost(name, value); | 264 _addHost(name, value); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 } | 393 } |
393 | 394 |
394 void _addValue(String name, Object value) { | 395 void _addValue(String name, Object value) { |
395 List<String> values = _headers[name]; | 396 List<String> values = _headers[name]; |
396 if (values == null) { | 397 if (values == null) { |
397 values = new List<String>(); | 398 values = new List<String>(); |
398 _headers[name] = values; | 399 _headers[name] = values; |
399 } | 400 } |
400 if (value is DateTime) { | 401 if (value is DateTime) { |
401 values.add(HttpDate.format(value)); | 402 values.add(HttpDate.format(value)); |
403 } else if (value is String) { | |
404 values.add(value); | |
402 } else { | 405 } else { |
403 values.add(value.toString()); | 406 values.add(_validateValue(value.toString())); |
404 } | 407 } |
405 } | 408 } |
406 | 409 |
407 void _set(String name, String value) { | 410 void _set(String name, String value) { |
408 assert(name == name.toLowerCase()); | 411 assert(name == _validateField(name)); |
409 List<String> values = new List<String>(); | 412 List<String> values = new List<String>(); |
410 _headers[name] = values; | 413 _headers[name] = values; |
411 values.add(value); | 414 values.add(value); |
412 } | 415 } |
413 | 416 |
414 _checkMutable() { | 417 _checkMutable() { |
415 if (!_mutable) throw new HttpException("HTTP headers are not mutable"); | 418 if (!_mutable) throw new HttpException("HTTP headers are not mutable"); |
416 } | 419 } |
417 | 420 |
418 _updateHostHeader() { | 421 _updateHostHeader() { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 continue; | 558 continue; |
556 } | 559 } |
557 } | 560 } |
558 } | 561 } |
559 List<String> values = _headers[HttpHeaders.COOKIE]; | 562 List<String> values = _headers[HttpHeaders.COOKIE]; |
560 if (values != null) { | 563 if (values != null) { |
561 values.forEach((headerValue) => parseCookieString(headerValue)); | 564 values.forEach((headerValue) => parseCookieString(headerValue)); |
562 } | 565 } |
563 return cookies; | 566 return cookies; |
564 } | 567 } |
568 | |
569 static String _validateField(String field) { | |
570 for (var i = 0; i < field.length; i++) { | |
571 if (!_HttpParser._isTokenChar(field.codeUnitAt(i))) { | |
572 throw new FormatException( | |
573 "Invalid HTTP header field: ${JSON.encode(field)}"); | |
Søren Gjesse
2014/07/04 09:24:54
Lets be precise: field -> field name
Anders Johnsen
2014/07/04 11:03:49
Done.
| |
574 } | |
575 } | |
576 return field.toLowerCase(); | |
577 } | |
578 | |
579 static _validateValue(value) { | |
580 if (value is! String) return value; | |
581 for (var i = 0; i < value.length; i++) { | |
582 if (!_HttpParser._isValueChar(value.codeUnitAt(i))) { | |
583 throw new FormatException( | |
584 "Invalid HTTP header value: ${JSON.encode(value)}"); | |
Søren Gjesse
2014/07/04 09:24:54
value -> field value
Anders Johnsen
2014/07/04 11:03:50
Done.
| |
585 } | |
586 } | |
587 return value; | |
588 } | |
565 } | 589 } |
566 | 590 |
567 | 591 |
568 class _HeaderValue implements HeaderValue { | 592 class _HeaderValue implements HeaderValue { |
569 String _value; | 593 String _value; |
570 Map<String, String> _parameters; | 594 Map<String, String> _parameters; |
571 Map<String, String> _unmodifiableParameters; | 595 Map<String, String> _unmodifiableParameters; |
572 | 596 |
573 _HeaderValue([String this._value = "", Map<String, String> parameters]) { | 597 _HeaderValue([String this._value = "", Map<String, String> parameters]) { |
574 if (parameters != null) { | 598 if (parameters != null) { |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
908 (codeUnit >= 0x23 && codeUnit <= 0x2B) || | 932 (codeUnit >= 0x23 && codeUnit <= 0x2B) || |
909 (codeUnit >= 0x2D && codeUnit <= 0x3A) || | 933 (codeUnit >= 0x2D && codeUnit <= 0x3A) || |
910 (codeUnit >= 0x3C && codeUnit <= 0x5B) || | 934 (codeUnit >= 0x3C && codeUnit <= 0x5B) || |
911 (codeUnit >= 0x5D && codeUnit <= 0x7E))) { | 935 (codeUnit >= 0x5D && codeUnit <= 0x7E))) { |
912 throw new FormatException( | 936 throw new FormatException( |
913 "Invalid character in cookie value, code unit: '$codeUnit'"); | 937 "Invalid character in cookie value, code unit: '$codeUnit'"); |
914 } | 938 } |
915 } | 939 } |
916 } | 940 } |
917 } | 941 } |
OLD | NEW |