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 10 matching lines...) Expand all Loading... | |
| 21 | 21 |
| 22 _HttpHeaders(this.protocolVersion, | 22 _HttpHeaders(this.protocolVersion, |
| 23 {int defaultPortForScheme: HttpClient.DEFAULT_HTTP_PORT}) | 23 {int defaultPortForScheme: HttpClient.DEFAULT_HTTP_PORT}) |
| 24 : _headers = new HashMap<String, List<String>>(), | 24 : _headers = new HashMap<String, List<String>>(), |
| 25 _defaultPortForScheme = defaultPortForScheme { | 25 _defaultPortForScheme = defaultPortForScheme { |
| 26 if (protocolVersion == "1.0") { | 26 if (protocolVersion == "1.0") { |
| 27 _persistentConnection = false; | 27 _persistentConnection = false; |
| 28 } | 28 } |
| 29 } | 29 } |
| 30 | 30 |
| 31 List<String> operator[](String name) => _headers[name.toLowerCase()]; | 31 List<String> operator[](String name) => _headers[_toLowerCase(name)]; |
| 32 | 32 |
| 33 String value(String name) { | 33 String value(String name) { |
| 34 name = name.toLowerCase(); | 34 name = _toLowerCase(name); |
| 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(_toLowerCase(name), value); |
| 46 } | 46 } |
| 47 | 47 |
| 48 void _addAll(String name, value) { | 48 void _addAll(String name, value) { |
| 49 if (value is List) { | 49 if (value is List) { |
| 50 value.forEach((v) => _add(name, v)); | 50 value.forEach((v) => _add(name, v)); |
| 51 } else { | 51 } else { |
| 52 _add(name, value); | 52 _add(name, 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 = _toLowerCase(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 = _toLowerCase(name); |
| 66 List<String> values = _headers[name]; | 66 List<String> values = _headers[name]; |
| 67 if (values != null) { | 67 if (values != null) { |
| 68 int index = values.indexOf(value); | 68 int index = values.indexOf(value); |
| 69 if (index != -1) { | 69 if (index != -1) { |
| 70 values.removeRange(index, index + 1); | 70 values.removeRange(index, index + 1); |
| 71 } | 71 } |
| 72 if (values.length == 0) _headers.remove(name); | 72 if (values.length == 0) _headers.remove(name); |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 void removeAll(String name) { | 76 void removeAll(String name) { |
| 77 _checkMutable(); | 77 _checkMutable(); |
| 78 name = name.toLowerCase(); | 78 name = _toLowerCase(name); |
| 79 _headers.remove(name); | 79 _headers.remove(name); |
| 80 } | 80 } |
| 81 | 81 |
| 82 void forEach(void f(String name, List<String> values)) { | 82 void forEach(void f(String name, List<String> values)) { |
| 83 _headers.forEach(f); | 83 _headers.forEach(f); |
| 84 } | 84 } |
| 85 | 85 |
| 86 void noFolding(String name) { | 86 void noFolding(String name) { |
| 87 if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>(); | 87 if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>(); |
| 88 _noFoldingHeaders.add(name); | 88 _noFoldingHeaders.add(name); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 } | 322 } |
| 323 } | 323 } |
| 324 } | 324 } |
| 325 _set(HttpHeaders.HOST, value); | 325 _set(HttpHeaders.HOST, value); |
| 326 } else { | 326 } else { |
| 327 throw new HttpException("Unexpected type for header named $name"); | 327 throw new HttpException("Unexpected type for header named $name"); |
| 328 } | 328 } |
| 329 break; | 329 break; |
| 330 | 330 |
| 331 case HttpHeaders.CONNECTION: | 331 case HttpHeaders.CONNECTION: |
| 332 var lowerCaseValue = value.toLowerCase(); | 332 var lowerCaseValue = _toLowerCase(value); |
| 333 if (lowerCaseValue == 'close') { | 333 if (lowerCaseValue == 'close') { |
| 334 _persistentConnection = false; | 334 _persistentConnection = false; |
| 335 } else if (lowerCaseValue == 'keep-alive') { | 335 } else if (lowerCaseValue == 'keep-alive') { |
| 336 _persistentConnection = true; | 336 _persistentConnection = true; |
| 337 } | 337 } |
| 338 _addValue(name, value); | 338 _addValue(name, value); |
| 339 break; | 339 break; |
| 340 | 340 |
| 341 case HttpHeaders.CONTENT_TYPE: | 341 case HttpHeaders.CONTENT_TYPE: |
| 342 _set(HttpHeaders.CONTENT_TYPE, value); | 342 _set(HttpHeaders.CONTENT_TYPE, value); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 354 _headers[name] = values; | 354 _headers[name] = values; |
| 355 } | 355 } |
| 356 if (value is DateTime) { | 356 if (value is DateTime) { |
| 357 values.add(HttpDate.format(value)); | 357 values.add(HttpDate.format(value)); |
| 358 } else { | 358 } else { |
| 359 values.add(value.toString()); | 359 values.add(value.toString()); |
| 360 } | 360 } |
| 361 } | 361 } |
| 362 | 362 |
| 363 void _set(String name, String value) { | 363 void _set(String name, String value) { |
| 364 assert(name == name.toLowerCase()); | 364 assert(name == _toLowerCase(name)); |
| 365 List<String> values = new List<String>(); | 365 List<String> values = new List<String>(); |
| 366 _headers[name] = values; | 366 _headers[name] = values; |
| 367 values.add(value); | 367 values.add(value); |
| 368 } | 368 } |
| 369 | 369 |
| 370 _checkMutable() { | 370 _checkMutable() { |
| 371 if (!_mutable) throw new HttpException("HTTP headers are not mutable"); | 371 if (!_mutable) throw new HttpException("HTTP headers are not mutable"); |
| 372 } | 372 } |
| 373 | 373 |
| 374 _updateHostHeader() { | 374 _updateHostHeader() { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 continue; | 511 continue; |
| 512 } | 512 } |
| 513 } | 513 } |
| 514 } | 514 } |
| 515 List<String> values = _headers[HttpHeaders.COOKIE]; | 515 List<String> values = _headers[HttpHeaders.COOKIE]; |
| 516 if (values != null) { | 516 if (values != null) { |
| 517 values.forEach((headerValue) => parseCookieString(headerValue)); | 517 values.forEach((headerValue) => parseCookieString(headerValue)); |
| 518 } | 518 } |
| 519 return cookies; | 519 return cookies; |
| 520 } | 520 } |
| 521 | |
| 522 static String _toLowerCase(String str) { | |
| 523 int toLowerCase(int byte) { | |
| 524 final int aCode = "A".codeUnitAt(0); | |
|
kevmoo
2014/03/24 17:50:16
Is this only run the first time the method is call
Anders Johnsen
2014/03/24 19:02:59
When looking at the SSA of the VM, it's heavily in
kevmoo
2014/03/24 19:04:05
If they are only used in http_headers, just leave
Anders Johnsen
2014/03/24 19:05:04
Yeah, but so far there is two places it's used (pa
Søren Gjesse
2014/03/25 07:54:25
Yes, as you have noticed we have the _CharCodes co
| |
| 525 final int zCode = "Z".codeUnitAt(0); | |
| 526 final int delta = "a".codeUnitAt(0) - aCode; | |
| 527 return (aCode <= byte && byte <= zCode) ? byte + delta : byte; | |
| 528 } | |
| 529 | |
| 530 final length = str.length; | |
| 531 var result = new List(length); | |
| 532 for (int i = 0; i < length; i++) { | |
| 533 int codeUnit = str.codeUnitAt(i); | |
| 534 if (codeUnit > 127) { | |
| 535 throw new HttpException("HTTP header must be in ASCII encoding"); | |
| 536 } | |
| 537 result[i] = toLowerCase(codeUnit); | |
|
Søren Gjesse
2014/03/25 07:54:25
I don't see the need to a function call here (even
Anders Johnsen
2014/03/25 13:33:40
Pulled out and shared across all of IO.
| |
| 538 } | |
| 539 return new String.fromCharCodes(result); | |
| 540 } | |
| 521 } | 541 } |
| 522 | 542 |
| 523 | 543 |
| 524 class _HeaderValue implements HeaderValue { | 544 class _HeaderValue implements HeaderValue { |
| 525 String _value; | 545 String _value; |
| 526 _UnmodifiableMap<String, String> _parameters; | 546 _UnmodifiableMap<String, String> _parameters; |
| 527 | 547 |
| 528 _HeaderValue([String this._value = "", Map<String, String> parameters]) { | 548 _HeaderValue([String this._value = "", Map<String, String> parameters]) { |
| 529 if (parameters != null) { | 549 if (parameters != null) { |
| 530 _parameters = | 550 _parameters = |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 892 void clear() { | 912 void clear() { |
| 893 throw new UnsupportedError("Cannot modify an unmodifiable map"); | 913 throw new UnsupportedError("Cannot modify an unmodifiable map"); |
| 894 } | 914 } |
| 895 void forEach(void f(K key, V value)) => _map.forEach(f); | 915 void forEach(void f(K key, V value)) => _map.forEach(f); |
| 896 Iterable<K> get keys => _map.keys; | 916 Iterable<K> get keys => _map.keys; |
| 897 Iterable<V> get values => _map.values; | 917 Iterable<V> get values => _map.values; |
| 898 int get length => _map.length; | 918 int get length => _map.length; |
| 899 bool get isEmpty => _map.isEmpty; | 919 bool get isEmpty => _map.isEmpty; |
| 900 bool get isNotEmpty => _map.isNotEmpty; | 920 bool get isNotEmpty => _map.isNotEmpty; |
| 901 } | 921 } |
| OLD | NEW |