Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: runtime/bin/http_impl.dart

Issue 10414076: Support for cookies in the HTTP library (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class _HttpHeaders implements HttpHeaders { 5 class _HttpHeaders implements HttpHeaders {
6 _HttpHeaders() : _headers = new Map<String, List<String>>(); 6 _HttpHeaders() : _headers = new Map<String, List<String>>();
7 7
8 List<String> operator[](String name) { 8 List<String> operator[](String name) {
9 name = name.toLowerCase(); 9 name = name.toLowerCase();
10 return _headers[name]; 10 return _headers[name];
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 void removeAll(String name) { 53 void removeAll(String name) {
54 _checkMutable(); 54 _checkMutable();
55 name = name.toLowerCase(); 55 name = name.toLowerCase();
56 _headers.remove(name); 56 _headers.remove(name);
57 } 57 }
58 58
59 void forEach(void f(String name, List<String> values)) { 59 void forEach(void f(String name, List<String> values)) {
60 _headers.forEach(f); 60 _headers.forEach(f);
61 } 61 }
62 62
63 void noFolding(String name) {
64 if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>();
65 _noFoldingHeaders.add(name);
66 }
67
63 String get host() => _host; 68 String get host() => _host;
64 69
65 void set host(String host) { 70 void set host(String host) {
66 _checkMutable(); 71 _checkMutable();
67 _host = host; 72 _host = host;
68 _updateHostHeader(); 73 _updateHostHeader();
69 } 74 }
70 75
71 int get port() => _port; 76 int get port() => _port;
72 77
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 _checkMutable() { 198 _checkMutable() {
194 if (!_mutable) throw new HttpException("HTTP headers are not mutable"); 199 if (!_mutable) throw new HttpException("HTTP headers are not mutable");
195 } 200 }
196 201
197 _updateHostHeader() { 202 _updateHostHeader() {
198 bool defaultPort = _port == null || _port == HttpClient.DEFAULT_HTTP_PORT; 203 bool defaultPort = _port == null || _port == HttpClient.DEFAULT_HTTP_PORT;
199 String portPart = defaultPort ? "" : ":$_port"; 204 String portPart = defaultPort ? "" : ":$_port";
200 _set("host", "$host$portPart"); 205 _set("host", "$host$portPart");
201 } 206 }
202 207
208 _foldHeader(String name) {
209 if (name == "set-cookie" ||
210 (_noFoldingHeaders != null &&
211 _noFoldingHeaders.indexOf(name) != -1)) {
212 return false;
213 }
214 return true;
215 }
216
203 _write(_HttpConnectionBase connection) { 217 _write(_HttpConnectionBase connection) {
204 final COLONSP = const [_CharCode.COLON, _CharCode.SP]; 218 final COLONSP = const [_CharCode.COLON, _CharCode.SP];
205 final COMMASP = const [_CharCode.COMMA, _CharCode.SP]; 219 final COMMASP = const [_CharCode.COMMA, _CharCode.SP];
206 final CRLF = const [_CharCode.CR, _CharCode.LF]; 220 final CRLF = const [_CharCode.CR, _CharCode.LF];
207 221
208 // Format headers. 222 // Format headers.
209 _headers.forEach((String name, List<String> values) { 223 _headers.forEach((String name, List<String> values) {
224 bool fold = _foldHeader(name);
210 List<int> data; 225 List<int> data;
211 data = name.charCodes(); 226 data = name.charCodes();
212 connection._write(data); 227 connection._write(data);
213 connection._write(COLONSP); 228 connection._write(COLONSP);
214 for (int i = 0; i < values.length; i++) { 229 for (int i = 0; i < values.length; i++) {
215 if (i > 0) { 230 if (i > 0) {
216 connection._write(COMMASP); 231 if (fold) {
232 connection._write(COMMASP);
233 } else {
234 connection._write(CRLF);
235 data = name.charCodes();
236 connection._write(data);
237 connection._write(COLONSP);
238 }
217 } 239 }
218 data = values[i].charCodes(); 240 data = values[i].charCodes();
219 connection._write(data); 241 connection._write(data);
220 } 242 }
221 connection._write(CRLF); 243 connection._write(CRLF);
222 }); 244 });
223 } 245 }
224 246
225 String toString() { 247 String toString() {
226 StringBuffer sb = new StringBuffer(); 248 StringBuffer sb = new StringBuffer();
227 _headers.forEach((String name, List<String> values) { 249 _headers.forEach((String name, List<String> values) {
228 sb.add(name); 250 sb.add(name);
229 sb.add(": "); 251 sb.add(": ");
252 bool fold = _foldHeader(name);
230 for (int i = 0; i < values.length; i++) { 253 for (int i = 0; i < values.length; i++) {
231 if (i > 0) { 254 if (i > 0) {
232 sb.add(", "); 255 if (fold) {
256 sb.add(", ");
257 } else {
258 sb.add("\n");
259 sb.add(name);
260 sb.add(": ");
261 }
233 } 262 }
234 sb.add(values[i]); 263 sb.add(values[i]);
235 } 264 }
236 sb.add("\n"); 265 sb.add("\n");
237 }); 266 });
238 return sb.toString(); 267 return sb.toString();
239 } 268 }
240 269
241 bool _mutable = true; // Are the headers currently mutable? 270 bool _mutable = true; // Are the headers currently mutable?
242 Map<String, List<String>> _headers; 271 Map<String, List<String>> _headers;
272 List<String> _noFoldingHeaders;
243 273
244 String _host; 274 String _host;
245 int _port; 275 int _port;
246 } 276 }
247 277
248 278
249 class _HeaderValue implements HeaderValue { 279 class _HeaderValue implements HeaderValue {
250 _HeaderValue([String this.value = ""]); 280 _HeaderValue([String this.value = ""]);
251 281
252 _HeaderValue.fromString(String value) { 282 _HeaderValue.fromString(String value) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 431
402 void set charset(String s) { 432 void set charset(String s) {
403 parameters["charset"] = s; 433 parameters["charset"] = s;
404 } 434 }
405 435
406 String _primaryType = ""; 436 String _primaryType = "";
407 String _subType = ""; 437 String _subType = "";
408 } 438 }
409 439
410 440
441 class _Cookie implements Cookie {
442 _Cookie([String this.name, String this.value]);
Mads Ager (google) 2012/05/23 13:31:05 I would add a blank line after the first construct
Søren Gjesse 2012/05/24 11:34:21 Done.
443 _Cookie.fromSetCookieValue(String value) {
444 // Parse the Set-Cookie header value.
445 _parseSetCookieValue(value);
446 }
447
448 // Parse a Set-Cookie header value according to the rules in RFC 6265.
449 void _parseSetCookieValue(String s) {
450 int index = 0;
451
452 bool done() => index == s.length;
453
454 String parseName() {
455 int start = index;
456 while (!done()) {
457 if (s[index] == "=") break;
458 index++;
459 }
460 return s.substring(start, index).trim().toLowerCase();
461 }
462
463 String parseValue() {
464 int start = index;
465 while (!done()) {
466 if (s[index] == ";") break;
467 index++;
468 }
469 return s.substring(start, index).trim().toLowerCase();
470 }
471
472 void expect(String expected) {
473 if (done()) throw new HttpException("Failed to parse header value [$s]");
474 if (s[index] != expected) {
475 throw new HttpException("Failed to parse header value [$s]");
476 }
477 index++;
478 }
479
480 void parseAttributes() {
481 String parseAttributeName() {
482 int start = index;
483 while (!done()) {
484 if (s[index] == "=" || s[index] == ";") break;
485 index++;
486 }
487 return s.substring(start, index).trim().toLowerCase();
488 }
489
490 String parseAttributeValue() {
491 int start = index;
492 while (!done()) {
493 if (s[index] == ";") break;
494 index++;
495 }
496 return s.substring(start, index).trim().toLowerCase();
497 }
498
499 while (!done()) {
500 String name = parseAttributeName();
501 String value = "";
502 if (!done() && s[index] == "=") {
503 index++; // Skip the = character.
504 value = parseAttributeValue();
505 }
506 if (name == "expires") {
507 expires = _HttpUtils.parseDate(value, strict: false);
508 } else if (name == "max-age") {
509 maxAge = Math.parseInt(value);
510 } else if (name == "domain") {
511 domain = value;
512 } else if (name == "path") {
513 path = value;
514 } else if (name == "httponly") {
515 httpOnly = true;
516 } else if (name == "secure") {
517 secure = true;
518 }
519 if (!done()) index++; // Skip the ; character
520 }
521 }
522
523 name = parseName();
524 if (done() || name.length == 0) {
525 _valid = false;
526 return;
527 }
528 index++; // Skip the = character.
529 value = parseValue();
530 if (done()) return;
531 index++; // Skip the ; character.
532 parseAttributes();
533 }
534
535 String toString() {
536 StringBuffer sb = new StringBuffer();
537 sb.add(name);
538 sb.add("=");
539 sb.add(value);
540 if (expires != null) {
541 sb.add("; Expires=");
542 sb.add(_HttpUtils.formatDate(expires));
543 }
544 if (maxAge != null) {
545 sb.add("; Max-Age=");
546 sb.add(maxAge);
547 }
548 if (domain != null) {
549 sb.add("; Domain=");
550 sb.add(domain);
551 }
552 if (path != null) {
553 sb.add("; Path=");
554 sb.add(path);
555 }
556 if (secure) sb.add("; Secure");
557 if (httpOnly) sb.add("; HttpOnly");
558 return sb.toString();
559 }
560
561 bool isValid() => _valid;
Mads Ager (google) 2012/05/23 13:31:05 I did not notice this in the interface. Add it? Sh
Søren Gjesse 2012/05/24 11:34:21 This was intended for handling validity when const
562
563 String name;
564 String value;
565 Date expires;
566 int maxAge;
567 String domain;
568 String path;
569 bool httpOnly = false;
570 bool secure = false;
571 bool _valid = true;
572 }
573
574
411 class _HttpRequestResponseBase { 575 class _HttpRequestResponseBase {
412 final int START = 0; 576 final int START = 0;
413 final int HEADER_SENT = 1; 577 final int HEADER_SENT = 1;
414 final int DONE = 2; 578 final int DONE = 2;
415 final int UPGRADED = 3; 579 final int UPGRADED = 3;
416 580
417 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) 581 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection)
418 : _headers = new _HttpHeaders() { 582 : _headers = new _HttpHeaders() {
419 _state = START; 583 _state = START;
420 } 584 }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 if (_bodyBytesWritten + bytes > _contentLength) { 706 if (_bodyBytesWritten + bytes > _contentLength) {
543 throw new HttpException("Writing more than specified content length"); 707 throw new HttpException("Writing more than specified content length");
544 } 708 }
545 _bodyBytesWritten += bytes; 709 _bodyBytesWritten += bytes;
546 } 710 }
547 711
548 int _state; 712 int _state;
549 713
550 _HttpConnectionBase _httpConnection; 714 _HttpConnectionBase _httpConnection;
551 _HttpHeaders _headers; 715 _HttpHeaders _headers;
716 List<Cookie> _cookies;
552 String _protocolVersion = "1.1"; 717 String _protocolVersion = "1.1";
553 718
554 // Length of the content body. If this is set to -1 (default value) 719 // Length of the content body. If this is set to -1 (default value)
555 // when starting to send data chunked transfer encoding will be 720 // when starting to send data chunked transfer encoding will be
556 // used. 721 // used.
557 int _contentLength = -1; 722 int _contentLength = -1;
558 // Number of body bytes written. This is only actual body data not 723 // Number of body bytes written. This is only actual body data not
559 // including headers or chunk information of using chinked transfer 724 // including headers or chunk information of using chinked transfer
560 // encoding. 725 // encoding.
561 int _bodyBytesWritten = 0; 726 int _bodyBytesWritten = 0;
562 } 727 }
563 728
564 729
565 // Parsed HTTP request providing information on the HTTP headers. 730 // Parsed HTTP request providing information on the HTTP headers.
566 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest { 731 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest {
567 _HttpRequest(_HttpConnection connection) : super(connection); 732 _HttpRequest(_HttpConnection connection) : super(connection);
568 733
569 String get method() => _method; 734 String get method() => _method;
570 String get uri() => _uri; 735 String get uri() => _uri;
571 String get path() => _path; 736 String get path() => _path;
572 String get queryString() => _queryString; 737 String get queryString() => _queryString;
573 Map get queryParameters() => _queryParameters; 738 Map get queryParameters() => _queryParameters;
574 739
740 List<Cookie> get cookies() {
741 if (_cookies != null) return _cookies;
742
743 // Parse a Cookie header value according to the rules in RFC 6265.
744 void _parseCookieString(String s) {
745 int index = 0;
746
747 bool done() => index == s.length;
748
749 void skipWS() {
750 while (!done()) {
751 if (s[index] != " " && s[index] != "\t") return;
Mads Ager (google) 2012/05/23 13:31:05 indentation
Søren Gjesse 2012/05/24 11:34:21 Done.
752 index++;
753 }
754 }
755
756 String parseName() {
757 int start = index;
758 while (!done()) {
759 if (s[index] == " " || s[index] == "\t" || s[index] == "=") break;
760 index++;
761 }
762 return s.substring(start, index).toLowerCase();
763 }
764
765 String parseValue() {
766 int start = index;
Mads Ager (google) 2012/05/23 13:31:05 indentation
Søren Gjesse 2012/05/24 11:34:21 Done.
767 while (!done()) {
768 if (s[index] == " " || s[index] == "\t" || s[index] == ";") break;
769 index++;
770 }
771 return s.substring(start, index).toLowerCase();
772 }
773
774 void expect(String expected) {
775 if (done()) throw new HttpException("Failed to parse header value [$s]") ;
Mads Ager (google) 2012/05/23 13:31:05 Long line.
Søren Gjesse 2012/05/24 11:34:21 Done.
776 if (s[index] != expected) {
777 throw new HttpException("Failed to parse header value [$s]");
778 }
779 index++;
780 }
781
782 while (!done()) {
783 skipWS();
784 if (done()) return;
785 String name = parseName();
786 skipWS();
787 expect("=");
788 skipWS();
789 String value = parseValue();
790 _cookies.add(new _Cookie(name, value));
791 skipWS();
792 if (done()) return;
793 expect(";");
794 }
795 }
796
797 _cookies = new List<Cookie>();
798 List<String> headerValues = headers["cookie"];
799 if (headerValues != null) {
800 headerValues.forEach((headerValue) => _parseCookieString(headerValue));
801 }
802 return _cookies;
803 }
804
575 InputStream get inputStream() { 805 InputStream get inputStream() {
576 if (_inputStream == null) { 806 if (_inputStream == null) {
577 _inputStream = new _HttpInputStream(this); 807 _inputStream = new _HttpInputStream(this);
578 } 808 }
579 return _inputStream; 809 return _inputStream;
580 } 810 }
581 811
582 String get protocolVersion() => _protocolVersion; 812 String get protocolVersion() => _protocolVersion;
583 813
584 void _onRequestStart(String method, String uri, String version) { 814 void _onRequestStart(String method, String uri, String version) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 if (_outputStream != null) throw new HttpException("Header already sent"); 896 if (_outputStream != null) throw new HttpException("Header already sent");
667 _statusCode = statusCode; 897 _statusCode = statusCode;
668 } 898 }
669 899
670 String get reasonPhrase() => _findReasonPhrase(_statusCode); 900 String get reasonPhrase() => _findReasonPhrase(_statusCode);
671 void set reasonPhrase(String reasonPhrase) { 901 void set reasonPhrase(String reasonPhrase) {
672 if (_outputStream != null) throw new HttpException("Header already sent"); 902 if (_outputStream != null) throw new HttpException("Header already sent");
673 _reasonPhrase = reasonPhrase; 903 _reasonPhrase = reasonPhrase;
674 } 904 }
675 905
906 List<Cookie> get cookies() {
907 if (_cookies == null) _cookies = new List<Cookie>();
908 return _cookies;
909 }
910
676 OutputStream get outputStream() { 911 OutputStream get outputStream() {
677 if (_state >= DONE) throw new HttpException("Response closed"); 912 if (_state >= DONE) throw new HttpException("Response closed");
678 if (_outputStream == null) { 913 if (_outputStream == null) {
679 _outputStream = new _HttpOutputStream(this); 914 _outputStream = new _HttpOutputStream(this);
680 } 915 }
681 return _outputStream; 916 return _outputStream;
682 } 917 }
683 918
684 DetachedSocket detachSocket() { 919 DetachedSocket detachSocket() {
685 if (_state >= DONE) throw new HttpException("Response closed"); 920 if (_state >= DONE) throw new HttpException("Response closed");
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 _writeCRLF(); 1047 _writeCRLF();
813 1048
814 // Determine the value of the "Transfer-Encoding" header based on 1049 // Determine the value of the "Transfer-Encoding" header based on
815 // whether the content length is known. 1050 // whether the content length is known.
816 if (_contentLength > 0) { 1051 if (_contentLength > 0) {
817 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); 1052 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString());
818 } else if (_contentLength < 0) { 1053 } else if (_contentLength < 0) {
819 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); 1054 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
820 } 1055 }
821 1056
1057 // Add all the cookies set to the headers.
1058 if (_cookies != null) {
1059 _cookies.forEach((cookie) {
1060 _headers.add("set-cookie", cookie);
1061 });
1062 }
1063
822 // Write headers. 1064 // Write headers.
823 bool allWritten = _writeHeaders(); 1065 bool allWritten = _writeHeaders();
824 _state = HEADER_SENT; 1066 _state = HEADER_SENT;
825 return allWritten; 1067 return allWritten;
826 } 1068 }
827 1069
828 // Response status code. 1070 // Response status code.
829 int _statusCode; 1071 int _statusCode;
830 String _reasonPhrase; 1072 String _reasonPhrase;
831 _HttpOutputStream _outputStream; 1073 _HttpOutputStream _outputStream;
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 if (_method == "GET") { 1490 if (_method == "GET") {
1249 _contentLength = 0; 1491 _contentLength = 0;
1250 } 1492 }
1251 } 1493 }
1252 1494
1253 void set contentLength(int contentLength) { 1495 void set contentLength(int contentLength) {
1254 if (_state >= HEADER_SENT) throw new HttpException("Header already sent"); 1496 if (_state >= HEADER_SENT) throw new HttpException("Header already sent");
1255 _contentLength = contentLength; 1497 _contentLength = contentLength;
1256 } 1498 }
1257 1499
1500 List<Cookie> get cookies() {
1501 if (_cookies == null) _cookies = new List<Cookie>();
1502 return _cookies;
1503 }
1504
1258 OutputStream get outputStream() { 1505 OutputStream get outputStream() {
1259 if (_state == DONE) throw new HttpException("Request closed"); 1506 if (_state == DONE) throw new HttpException("Request closed");
1260 if (_outputStream == null) { 1507 if (_outputStream == null) {
1261 _outputStream = new _HttpOutputStream(this); 1508 _outputStream = new _HttpOutputStream(this);
1262 } 1509 }
1263 return _outputStream; 1510 return _outputStream;
1264 } 1511 }
1265 1512
1266 // Delegate functions for the HttpOutputStream implementation. 1513 // Delegate functions for the HttpOutputStream implementation.
1267 bool _streamWrite(List<int> buffer, bool copyBuffer) { 1514 bool _streamWrite(List<int> buffer, bool copyBuffer) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 1559
1313 // Determine the value of the "Transfer-Encoding" header based on 1560 // Determine the value of the "Transfer-Encoding" header based on
1314 // whether the content length is known. If there is no content 1561 // whether the content length is known. If there is no content
1315 // neither "Content-Length" nor "Transfer-Encoding" is set 1562 // neither "Content-Length" nor "Transfer-Encoding" is set
1316 if (_contentLength > 0) { 1563 if (_contentLength > 0) {
1317 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); 1564 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString());
1318 } else if (_contentLength < 0) { 1565 } else if (_contentLength < 0) {
1319 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); 1566 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
1320 } 1567 }
1321 1568
1569 // Add the cookies to the headers.
1570 if (_cookies != null) {
1571 StringBuffer sb = new StringBuffer();
1572 for (int i = 0; i < _cookies.length; i++) {
1573 if (i > 0) sb.add("; ");
1574 sb.add(_cookies[i].name);
1575 sb.add("=");
1576 sb.add(_cookies[i].value);
1577 }
1578 _headers.add("cookie", sb.toString());
1579 }
1580
1322 // Write headers. 1581 // Write headers.
1323 _writeHeaders(); 1582 _writeHeaders();
1324 _state = HEADER_SENT; 1583 _state = HEADER_SENT;
1325 } 1584 }
1326 1585
1327 String _method; 1586 String _method;
1328 String _uri; 1587 String _uri;
1329 _HttpClientConnection _connection; 1588 _HttpClientConnection _connection;
1330 _HttpOutputStream _outputStream; 1589 _HttpOutputStream _outputStream;
1331 Function _streamErrorHandler; 1590 Function _streamErrorHandler;
(...skipping 10 matching lines...) Expand all
1342 int get statusCode() => _statusCode; 1601 int get statusCode() => _statusCode;
1343 String get reasonPhrase() => _reasonPhrase; 1602 String get reasonPhrase() => _reasonPhrase;
1344 1603
1345 bool get isRedirect() { 1604 bool get isRedirect() {
1346 return statusCode == HttpStatus.MOVED_PERMANENTLY || 1605 return statusCode == HttpStatus.MOVED_PERMANENTLY ||
1347 statusCode == HttpStatus.FOUND || 1606 statusCode == HttpStatus.FOUND ||
1348 statusCode == HttpStatus.SEE_OTHER || 1607 statusCode == HttpStatus.SEE_OTHER ||
1349 statusCode == HttpStatus.TEMPORARY_REDIRECT; 1608 statusCode == HttpStatus.TEMPORARY_REDIRECT;
1350 } 1609 }
1351 1610
1611 List<Cookie> get cookies() {
1612 if (_cookies != null) return _cookies;
1613 _cookies = new List<Cookie>();
1614 List<String> values = _headers["set-cookie"];
1615 if (values != null) {
1616 values.forEach((value) {
1617 _cookies.add(new Cookie.fromSetCookieValue(value));
1618 });
1619 }
1620 return _cookies;
1621 }
1622
1352 InputStream get inputStream() { 1623 InputStream get inputStream() {
1353 if (_inputStream == null) { 1624 if (_inputStream == null) {
1354 _inputStream = new _HttpInputStream(this); 1625 _inputStream = new _HttpInputStream(this);
1355 } 1626 }
1356 return _inputStream; 1627 return _inputStream;
1357 } 1628 }
1358 1629
1359 void _onRequestStart(String method, String uri, String version) { 1630 void _onRequestStart(String method, String uri, String version) {
1360 // TODO(sgjesse): Error handling 1631 // TODO(sgjesse): Error handling
1361 } 1632 }
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 2097
1827 2098
1828 class _RedirectInfo implements RedirectInfo { 2099 class _RedirectInfo implements RedirectInfo {
1829 const _RedirectInfo(int this.statusCode, 2100 const _RedirectInfo(int this.statusCode,
1830 String this.method, 2101 String this.method,
1831 Uri this.location); 2102 Uri this.location);
1832 final int statusCode; 2103 final int statusCode;
1833 final String method; 2104 final String method;
1834 final Uri location; 2105 final Uri location;
1835 } 2106 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698