Chromium Code Reviews| 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 |