OLD | NEW |
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 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 } | 460 } |
461 | 461 |
462 OutputStream get outputStream() { | 462 OutputStream get outputStream() { |
463 if (_state >= DONE) throw new HttpException("Response closed"); | 463 if (_state >= DONE) throw new HttpException("Response closed"); |
464 if (_outputStream == null) { | 464 if (_outputStream == null) { |
465 _outputStream = new _HttpOutputStream(this); | 465 _outputStream = new _HttpOutputStream(this); |
466 } | 466 } |
467 return _outputStream; | 467 return _outputStream; |
468 } | 468 } |
469 | 469 |
470 Socket detachSocket() { | 470 DetachedSocket detachSocket() { |
471 if (_state >= DONE) throw new HttpException("Response closed"); | 471 if (_state >= DONE) throw new HttpException("Response closed"); |
472 // Ensure that headers are written. | 472 // Ensure that headers are written. |
473 if (_state == START) { | 473 if (_state == START) { |
474 _writeHeader(); | 474 _writeHeader(); |
475 } | 475 } |
476 _state = UPGRADED; | 476 _state = UPGRADED; |
477 // Ensure that any trailing data is written. | 477 // Ensure that any trailing data is written. |
478 _writeDone(); | 478 _writeDone(); |
479 // Indicate to the connection that the response handling is done. | 479 // Indicate to the connection that the response handling is done. |
480 return _httpConnection._detachSocket(); | 480 return _httpConnection._detachSocket(); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 // Determine the value of the "Connection" header. | 595 // Determine the value of the "Connection" header. |
596 if (_protocolVersion == "1.1" && !_persistentConnection) { | 596 if (_protocolVersion == "1.1" && !_persistentConnection) { |
597 _headers.set("Connection", "close"); | 597 _headers.set("Connection", "close"); |
598 } else if (_protocolVersion == "1.0" && _persistentConnection) { | 598 } else if (_protocolVersion == "1.0" && _persistentConnection) { |
599 _headers.set("Connection", "keep-alive"); | 599 _headers.set("Connection", "keep-alive"); |
600 } | 600 } |
601 // Determine the value of the "Transfer-Encoding" header based on | 601 // Determine the value of the "Transfer-Encoding" header based on |
602 // whether the content length is known. | 602 // whether the content length is known. |
603 if (_contentLength > 0) { | 603 if (_contentLength > 0) { |
604 _headers.set("Content-Length", _contentLength.toString()); | 604 _headers.set("Content-Length", _contentLength.toString()); |
605 } else { | 605 } else if (_contentLength < 0) { |
606 _headers.set("Transfer-Encoding", "chunked"); | 606 _headers.set("Transfer-Encoding", "chunked"); |
607 } | 607 } |
608 | 608 |
609 // Write headers. | 609 // Write headers. |
610 bool allWritten = _writeHeaders(); | 610 bool allWritten = _writeHeaders(); |
611 _state = HEADER_SENT; | 611 _state = HEADER_SENT; |
612 return allWritten; | 612 return allWritten; |
613 } | 613 } |
614 | 614 |
615 // Response status code. | 615 // Response status code. |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 if (available == 0) { | 738 if (available == 0) { |
739 return; | 739 return; |
740 } | 740 } |
741 | 741 |
742 ByteArray buffer = new ByteArray(available); | 742 ByteArray buffer = new ByteArray(available); |
743 int bytesRead = _socket.readList(buffer, 0, available); | 743 int bytesRead = _socket.readList(buffer, 0, available); |
744 if (bytesRead > 0) { | 744 if (bytesRead > 0) { |
745 int parsed = _httpParser.writeList(buffer, 0, bytesRead); | 745 int parsed = _httpParser.writeList(buffer, 0, bytesRead); |
746 if (!_httpParser.upgrade) { | 746 if (!_httpParser.upgrade) { |
747 if (parsed != bytesRead) { | 747 if (parsed != bytesRead) { |
748 // TODO(sgjesse): Error handling. | 748 if (_socket != null) { |
749 _close(); | 749 // TODO(sgjesse): Error handling. |
| 750 _close(); |
| 751 } |
750 } | 752 } |
751 } | 753 } |
752 } | 754 } |
753 } | 755 } |
754 | 756 |
755 void _onClosed() { | 757 void _onClosed() { |
756 _closing = true; | 758 _closing = true; |
757 _onConnectionClosed(null); | 759 _onConnectionClosed(null); |
758 } | 760 } |
759 | 761 |
760 void _onError(e) { | 762 void _onError(e) { |
761 // If an error occurs, make sure to close the socket if one is associated. | 763 // If an error occurs, make sure to close the socket if one is associated. |
762 _error = true; | 764 _error = true; |
763 if (_socket != null) { | 765 if (_socket != null) { |
764 _socket.close(); | 766 _socket.close(); |
765 } | 767 } |
766 _onConnectionClosed(e); | 768 _onConnectionClosed(e); |
767 } | 769 } |
768 | 770 |
769 Socket _detachSocket() { | 771 DetachedSocket _detachSocket() { |
770 _socket.onData = null; | 772 _socket.onData = null; |
771 // TODO(sgjesse): Handle getting the write handler when using output stream. | |
772 //_socket.onWrite = null; | |
773 _socket.onClosed = null; | 773 _socket.onClosed = null; |
774 _socket.onError = null; | 774 _socket.onError = null; |
| 775 _socket.outputStream.onNoPendingWrites = null; |
775 Socket socket = _socket; | 776 Socket socket = _socket; |
776 _socket = null; | 777 _socket = null; |
777 if (onDetach) onDetach(); | 778 if (onDetach != null) onDetach(); |
778 return socket; | 779 return new _DetachedSocket(socket, _httpParser.unparsedData); |
779 } | 780 } |
780 | 781 |
781 abstract void _onConnectionClosed(e); | 782 abstract void _onConnectionClosed(e); |
782 abstract void _responseDone(); | 783 abstract void _responseDone(); |
783 | 784 |
784 void set _onNoPendingWrites(void callback()) { | 785 void set _onNoPendingWrites(void callback()) { |
785 if (!_error) { | 786 if (!_error) { |
786 _socket.outputStream.onNoPendingWrites = callback; | 787 _socket.outputStream.onNoPendingWrites = callback; |
787 } | 788 } |
788 } | 789 } |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 _socketConn = null; | 1225 _socketConn = null; |
1225 } | 1226 } |
1226 | 1227 |
1227 HttpClientRequest open(String method, String uri) { | 1228 HttpClientRequest open(String method, String uri) { |
1228 _method = method; | 1229 _method = method; |
1229 _request = new _HttpClientRequest(method, uri, this); | 1230 _request = new _HttpClientRequest(method, uri, this); |
1230 _response = new _HttpClientResponse(this); | 1231 _response = new _HttpClientResponse(this); |
1231 return _request; | 1232 return _request; |
1232 } | 1233 } |
1233 | 1234 |
| 1235 DetachedSocket detachSocket() { |
| 1236 return _detachSocket(); |
| 1237 } |
| 1238 |
1234 void _onConnectionClosed(e) { | 1239 void _onConnectionClosed(e) { |
1235 // Socket is closed either due to an error or due to normal socket close. | 1240 // Socket is closed either due to an error or due to normal socket close. |
1236 if (e != null) { | 1241 if (e != null) { |
1237 if (_onErrorCallback != null) { | 1242 if (_onErrorCallback != null) { |
1238 _onErrorCallback(e); | 1243 _onErrorCallback(e); |
1239 } | 1244 } |
1240 } | 1245 } |
1241 _closing = true; | 1246 _closing = true; |
1242 if (e != null) { | 1247 if (e != null) { |
1243 // Propagate the error to the streams. | 1248 // Propagate the error to the streams. |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 _activeSockets.remove(socketConn); | 1504 _activeSockets.remove(socketConn); |
1500 sockets.addFirst(socketConn); | 1505 sockets.addFirst(socketConn); |
1501 } | 1506 } |
1502 | 1507 |
1503 Function _onOpen; | 1508 Function _onOpen; |
1504 Map<String, Queue<_SocketConnection>> _openSockets; | 1509 Map<String, Queue<_SocketConnection>> _openSockets; |
1505 Set<_SocketConnection> _activeSockets; | 1510 Set<_SocketConnection> _activeSockets; |
1506 Timer _evictionTimer; | 1511 Timer _evictionTimer; |
1507 bool _shutdown; // Has this HTTP client been shutdown? | 1512 bool _shutdown; // Has this HTTP client been shutdown? |
1508 } | 1513 } |
| 1514 |
| 1515 |
| 1516 class _DetachedSocket implements DetachedSocket { |
| 1517 _DetachedSocket(this._socket, this._unparsedData); |
| 1518 Socket get socket() => _socket; |
| 1519 List<int> get unparsedData() => _unparsedData; |
| 1520 Socket _socket; |
| 1521 List<int> _unparsedData; |
| 1522 } |
OLD | NEW |