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; |
} |