| Index: sdk/lib/io/http_headers.dart
|
| diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
|
| index 928334db6c7177c18fd4e2082395767560dacbbc..38da14975dc3d250a9ffb9a2026f4ee06bf00173 100644
|
| --- a/sdk/lib/io/http_headers.dart
|
| +++ b/sdk/lib/io/http_headers.dart
|
| @@ -5,7 +5,8 @@
|
| part of dart.io;
|
|
|
| class _HttpHeaders implements HttpHeaders {
|
| - _HttpHeaders() : _headers = new Map<String, List<String>>();
|
| + _HttpHeaders(String this.protocolVersion)
|
| + : _headers = new Map<String, List<String>>();
|
|
|
| List<String> operator[](String name) {
|
| name = name.toLowerCase();
|
| @@ -67,6 +68,29 @@ class _HttpHeaders implements HttpHeaders {
|
| _noFoldingHeaders.add(name);
|
| }
|
|
|
| + bool get persistentConnection {
|
| + List<String> connection = this[HttpHeaders.CONNECTION];
|
| + if (protocolVersion == "1.1") {
|
| + if (connection == null) return true;
|
| + return !connection.any((value) => value.toLowerCase() == "close");
|
| + } else {
|
| + if (connection == null) return false;
|
| + return connection.any((value) => value.toLowerCase() == "keep-alive");
|
| + }
|
| + }
|
| +
|
| + void set persistentConnection(bool persistentConnection) {
|
| + _checkMutable();
|
| + // Determine the value of the "Connection" header.
|
| + remove(HttpHeaders.CONNECTION, "close");
|
| + remove(HttpHeaders.CONNECTION, "keep-alive");
|
| + if (protocolVersion == "1.1" && !persistentConnection) {
|
| + add(HttpHeaders.CONNECTION, "close");
|
| + } else if (protocolVersion == "1.0" && persistentConnection) {
|
| + add(HttpHeaders.CONNECTION, "keep-alive");
|
| + }
|
| + }
|
| +
|
| int get contentLength => _contentLength;
|
|
|
| void set contentLength(int contentLength) {
|
| @@ -290,7 +314,7 @@ class _HttpHeaders implements HttpHeaders {
|
| return true;
|
| }
|
|
|
| - void _finalize(String protocolVersion) {
|
| + void _finalize() {
|
| // If the content length is not known make sure chunked transfer
|
| // encoding is used for HTTP 1.1.
|
| if (contentLength < 0 && protocolVersion == "1.1") {
|
| @@ -306,7 +330,7 @@ class _HttpHeaders implements HttpHeaders {
|
| _mutable = false;
|
| }
|
|
|
| - _write(_HttpConnectionBase connection) {
|
| + _write(IOSink sink) {
|
| final COLONSP = const [_CharCode.COLON, _CharCode.SP];
|
| final COMMASP = const [_CharCode.COMMA, _CharCode.SP];
|
| final CRLF = const [_CharCode.CR, _CharCode.LF];
|
| @@ -316,7 +340,7 @@ class _HttpHeaders implements HttpHeaders {
|
| var bufferPos = 0;
|
|
|
| void writeBuffer() {
|
| - connection._writeFrom(buffer, 0, bufferPos);
|
| + sink.add(buffer.getRange(0, bufferPos));
|
| bufferPos = 0;
|
| }
|
|
|
| @@ -381,12 +405,78 @@ class _HttpHeaders implements HttpHeaders {
|
| return sb.toString();
|
| }
|
|
|
| + List<Cookie> _parseCookies() {
|
| + // Parse a Cookie header value according to the rules in RFC 6265.
|
| + var cookies = new List<Cookie>();
|
| + void parseCookieString(String s) {
|
| + int index = 0;
|
| +
|
| + bool done() => index == s.length;
|
| +
|
| + void skipWS() {
|
| + while (!done()) {
|
| + if (s[index] != " " && s[index] != "\t") return;
|
| + index++;
|
| + }
|
| + }
|
| +
|
| + String parseName() {
|
| + int start = index;
|
| + while (!done()) {
|
| + if (s[index] == " " || s[index] == "\t" || s[index] == "=") break;
|
| + index++;
|
| + }
|
| + return s.substring(start, index).toLowerCase();
|
| + }
|
| +
|
| + String parseValue() {
|
| + int start = index;
|
| + while (!done()) {
|
| + if (s[index] == " " || s[index] == "\t" || s[index] == ";") break;
|
| + index++;
|
| + }
|
| + return s.substring(start, index).toLowerCase();
|
| + }
|
| +
|
| + void expect(String expected) {
|
| + if (done()) {
|
| + throw new HttpException("Failed to parse header value [$s]");
|
| + }
|
| + if (s[index] != expected) {
|
| + throw new HttpException("Failed to parse header value [$s]");
|
| + }
|
| + index++;
|
| + }
|
| +
|
| + while (!done()) {
|
| + skipWS();
|
| + if (done()) return;
|
| + String name = parseName();
|
| + skipWS();
|
| + expect("=");
|
| + skipWS();
|
| + String value = parseValue();
|
| + cookies.add(new _Cookie(name, value));
|
| + skipWS();
|
| + if (done()) return;
|
| + expect(";");
|
| + }
|
| + }
|
| + List<String> values = this["cookie"];
|
| + if (values != null) {
|
| + values.forEach((headerValue) => parseCookieString(headerValue));
|
| + }
|
| + return cookies;
|
| + }
|
| +
|
| +
|
| bool _mutable = true; // Are the headers currently mutable?
|
| Map<String, List<String>> _headers;
|
| List<String> _noFoldingHeaders;
|
|
|
| int _contentLength = -1;
|
| bool _chunkedTransferEncoding = false;
|
| + final String protocolVersion;
|
| String _host;
|
| int _port;
|
| }
|
|
|