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 _HttpIncoming extends Stream<List<int>> { | 7 class _HttpIncoming extends Stream<List<int>> { |
8 final int _transferLength; | 8 final int _transferLength; |
9 final Completer _dataCompleter = new Completer(); | 9 final Completer _dataCompleter = new Completer(); |
10 Stream<List<int>> _stream; | 10 Stream<List<int>> _stream; |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 | 695 |
696 // The HttpClient this request belongs to. | 696 // The HttpClient this request belongs to. |
697 final _HttpClient _httpClient; | 697 final _HttpClient _httpClient; |
698 final _HttpClientConnection _httpClientConnection; | 698 final _HttpClientConnection _httpClientConnection; |
699 | 699 |
700 final Completer<HttpClientResponse> _responseCompleter | 700 final Completer<HttpClientResponse> _responseCompleter |
701 = new Completer<HttpClientResponse>(); | 701 = new Completer<HttpClientResponse>(); |
702 | 702 |
703 final bool _usingProxy; | 703 final bool _usingProxy; |
704 | 704 |
| 705 Future<HttpClientResponse> _response; |
| 706 |
705 // TODO(ajohnsen): Get default value from client? | 707 // TODO(ajohnsen): Get default value from client? |
706 bool _followRedirects = true; | 708 bool _followRedirects = true; |
707 | 709 |
708 int _maxRedirects = 5; | 710 int _maxRedirects = 5; |
709 | 711 |
710 List<RedirectInfo> _responseRedirects = []; | 712 List<RedirectInfo> _responseRedirects = []; |
711 | 713 |
712 _HttpClientRequest(_HttpOutgoing outgoing, | 714 _HttpClientRequest(_HttpOutgoing outgoing, |
713 Uri this.uri, | 715 Uri this.uri, |
714 String this.method, | 716 String this.method, |
715 bool this._usingProxy, | 717 bool this._usingProxy, |
716 _HttpClient this._httpClient, | 718 _HttpClient this._httpClient, |
717 _HttpClientConnection this._httpClientConnection) | 719 _HttpClientConnection this._httpClientConnection) |
718 : super("1.1", outgoing) { | 720 : super("1.1", outgoing) { |
719 // GET and HEAD have 'content-length: 0' by default. | 721 // GET and HEAD have 'content-length: 0' by default. |
720 if (method == "GET" || method == "HEAD") { | 722 if (method == "GET" || method == "HEAD") { |
721 contentLength = 0; | 723 contentLength = 0; |
722 } | 724 } |
723 } | 725 } |
724 | 726 |
725 Future<HttpClientResponse> get response => _responseCompleter.future; | 727 Future<HttpClientResponse> get response { |
| 728 if (_response == null) { |
| 729 _response = Future.wait([_responseCompleter.future, super.done]) |
| 730 .then((list) => list[0]); |
| 731 } |
| 732 return _response; |
| 733 } |
| 734 |
| 735 Future<HttpClientResponse> get done => response; |
| 736 |
| 737 Future<HttpClientResponse> pipe(Stream<List<int>> stream) { |
| 738 super.pipe(stream); |
| 739 return response; |
| 740 } |
726 | 741 |
727 Future<HttpClientResponse> close() { | 742 Future<HttpClientResponse> close() { |
728 super.close(); | 743 super.close(); |
729 return response; | 744 return response; |
730 } | 745 } |
731 | 746 |
732 int get maxRedirects => _maxRedirects; | 747 int get maxRedirects => _maxRedirects; |
733 void set maxRedirects(int maxRedirects) { | 748 void set maxRedirects(int maxRedirects) { |
734 if (_headersWritten) throw new StateError("Request already sent"); | 749 if (_headersWritten) throw new StateError("Request already sent"); |
735 _maxRedirects = maxRedirects; | 750 _maxRedirects = maxRedirects; |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 // Look for credentials. | 1001 // Look for credentials. |
987 _Credentials cr = _httpClient._findCredentials(uri); | 1002 _Credentials cr = _httpClient._findCredentials(uri); |
988 if (cr != null) { | 1003 if (cr != null) { |
989 cr.authorize(request); | 1004 cr.authorize(request); |
990 } | 1005 } |
991 } | 1006 } |
992 // Start sending the request (lazy, delayed until the user provides | 1007 // Start sending the request (lazy, delayed until the user provides |
993 // data). | 1008 // data). |
994 _httpParser.responseToMethod = method; | 1009 _httpParser.responseToMethod = method; |
995 _streamFuture = outgoing.onStream((stream) { | 1010 _streamFuture = outgoing.onStream((stream) { |
996 // Sending request, set up response completer. | 1011 return _socket.writeStream(stream) |
997 _nextResponseCompleter = new Completer(); | 1012 .then((s) { |
| 1013 // Request sent, set up response completer. |
| 1014 _nextResponseCompleter = new Completer(); |
998 | 1015 |
999 var requestFuture = _socket.writeStream(stream) | 1016 // Listen for response. |
1000 .catchError((e) { | 1017 _nextResponseCompleter.future |
| 1018 .then((incoming) { |
| 1019 incoming.dataDone.then((_) { |
| 1020 if (incoming.headers.persistentConnection && |
| 1021 request.persistentConnection) { |
| 1022 // Return connection, now we are done. |
| 1023 _httpClient._returnConnection(this); |
| 1024 _subscription.resume(); |
| 1025 } else { |
| 1026 destroy(); |
| 1027 } |
| 1028 }); |
| 1029 request._onIncoming(incoming); |
| 1030 }) |
| 1031 // If we see a state error, we failed to get the 'first' |
| 1032 // element. |
| 1033 // Transform the error to a HttpParserException, for |
| 1034 // consistency. |
| 1035 .catchError((error) { |
| 1036 throw new HttpParserException( |
| 1037 "Connection closed before data was received"); |
| 1038 }, test: (error) => error is StateError) |
| 1039 .catchError((error) { |
| 1040 // We are done with the socket. |
| 1041 destroy(); |
| 1042 request._onError(error); |
| 1043 }); |
| 1044 |
| 1045 // Resume the parser now we have a handler. |
| 1046 _subscription.resume(); |
| 1047 return s; |
| 1048 }, onError: (e) { |
1001 destroy(); | 1049 destroy(); |
1002 throw e; | 1050 throw e; |
1003 }); | 1051 }); |
1004 | |
1005 // Listen for response. | |
1006 _nextResponseCompleter.future | |
1007 .then((incoming) { | |
1008 incoming.dataDone.then((_) { | |
1009 if (incoming.headers.persistentConnection && | |
1010 request.persistentConnection) { | |
1011 // Be sure we have written the full request. | |
1012 requestFuture | |
1013 .then((_) { | |
1014 // Return connection, now we are done. | |
1015 _httpClient._returnConnection(this); | |
1016 _subscription.resume(); | |
1017 }, | |
1018 onError: (_) { | |
1019 // Already handled. | |
1020 }); | |
1021 } else { | |
1022 destroy(); | |
1023 } | |
1024 }); | |
1025 request._onIncoming(incoming); | |
1026 }) | |
1027 // If we see a state error, we failed to get the 'first' element. | |
1028 // Transform the error to a HttpParserException, for consistency. | |
1029 .catchError((error) { | |
1030 throw new HttpParserException( | |
1031 "Connection closed before data was received"); | |
1032 }, test: (error) => error is StateError) | |
1033 .catchError((error) { | |
1034 // We are done with the socket. | |
1035 destroy(); | |
1036 request._onError(error); | |
1037 }); | |
1038 // Resume the parser now we have a handler. | |
1039 _subscription.resume(); | |
1040 return requestFuture; | |
1041 }); | 1052 }); |
1042 return request; | 1053 return request; |
1043 } | 1054 } |
1044 | 1055 |
1045 Future<Socket> detachSocket() { | 1056 Future<Socket> detachSocket() { |
1046 return _streamFuture | 1057 return _streamFuture |
1047 .then((_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()), | 1058 .then((_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()), |
1048 onError: (_) {}); | 1059 onError: (_) {}); |
1049 } | 1060 } |
1050 | 1061 |
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1809 | 1820 |
1810 | 1821 |
1811 class _RedirectInfo implements RedirectInfo { | 1822 class _RedirectInfo implements RedirectInfo { |
1812 const _RedirectInfo(int this.statusCode, | 1823 const _RedirectInfo(int this.statusCode, |
1813 String this.method, | 1824 String this.method, |
1814 Uri this.location); | 1825 Uri this.location); |
1815 final int statusCode; | 1826 final int statusCode; |
1816 final String method; | 1827 final String method; |
1817 final Uri location; | 1828 final Uri location; |
1818 } | 1829 } |
OLD | NEW |