| 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 }); | 201 }); |
| 202 } | 202 } |
| 203 | 203 |
| 204 String toString() { | 204 String toString() { |
| 205 StringBuffer sb = new StringBuffer(); | 205 StringBuffer sb = new StringBuffer(); |
| 206 _headers.forEach((String name, List<String> values) { | 206 _headers.forEach((String name, List<String> values) { |
| 207 sb.add(name); | 207 sb.add(name); |
| 208 sb.add(": "); | 208 sb.add(": "); |
| 209 for (int i = 0; i < values.length; i++) { | 209 for (int i = 0; i < values.length; i++) { |
| 210 if (i > 0) { | 210 if (i > 0) { |
| 211 sb.add(": "); | 211 sb.add(", "); |
| 212 } | 212 } |
| 213 sb.add(values[i]); | 213 sb.add(values[i]); |
| 214 } | 214 } |
| 215 sb.add("\n"); | 215 sb.add("\n"); |
| 216 }); | 216 }); |
| 217 return sb.toString(); | 217 return sb.toString(); |
| 218 } | 218 } |
| 219 | 219 |
| 220 bool _mutable = true; // Are the headers currently mutable? | 220 bool _mutable = true; // Are the headers currently mutable? |
| 221 Map<String, List<String>> _headers; | 221 Map<String, List<String>> _headers; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 232 final int UPGRADED = 3; | 232 final int UPGRADED = 3; |
| 233 | 233 |
| 234 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) | 234 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) |
| 235 : _headers = new _HttpHeaders() { | 235 : _headers = new _HttpHeaders() { |
| 236 _state = START; | 236 _state = START; |
| 237 } | 237 } |
| 238 | 238 |
| 239 int get contentLength() => _contentLength; | 239 int get contentLength() => _contentLength; |
| 240 HttpHeaders get headers() => _headers; | 240 HttpHeaders get headers() => _headers; |
| 241 | 241 |
| 242 bool get persistentConnection() { |
| 243 List<String> connection = headers[HttpHeaders.CONNECTION]; |
| 244 if (_protocolVersion == "1.1") { |
| 245 if (connection == null) return true; |
| 246 return !headers[HttpHeaders.CONNECTION].some( |
| 247 (value) => value.toLowerCase() == "close"); |
| 248 } else { |
| 249 if (connection == null) return false; |
| 250 return headers[HttpHeaders.CONNECTION].some( |
| 251 (value) => value.toLowerCase() == "keep-alive"); |
| 252 } |
| 253 } |
| 254 |
| 255 void set persistentConnection(bool persistentConnection) { |
| 256 if (_outputStream != null) throw new HttpException("Header already sent"); |
| 257 |
| 258 // Determine the value of the "Connection" header. |
| 259 headers.remove(HttpHeaders.CONNECTION, "close"); |
| 260 headers.remove(HttpHeaders.CONNECTION, "keep-alive"); |
| 261 if (_protocolVersion == "1.1" && !persistentConnection) { |
| 262 headers.add(HttpHeaders.CONNECTION, "close"); |
| 263 } else if (_protocolVersion == "1.0" && persistentConnection) { |
| 264 headers.add(HttpHeaders.CONNECTION, "keep-alive"); |
| 265 } |
| 266 } |
| 267 |
| 268 |
| 242 bool _write(List<int> data, bool copyBuffer) { | 269 bool _write(List<int> data, bool copyBuffer) { |
| 243 _ensureHeadersSent(); | 270 _ensureHeadersSent(); |
| 244 bool allWritten = true; | 271 bool allWritten = true; |
| 245 if (data.length > 0) { | 272 if (data.length > 0) { |
| 246 if (_contentLength < 0) { | 273 if (_contentLength < 0) { |
| 247 // Write chunk size if transfer encoding is chunked. | 274 // Write chunk size if transfer encoding is chunked. |
| 248 _writeHexString(data.length); | 275 _writeHexString(data.length); |
| 249 _writeCRLF(); | 276 _writeCRLF(); |
| 250 _httpConnection._write(data, copyBuffer); | 277 _httpConnection._write(data, copyBuffer); |
| 251 allWritten = _writeCRLF(); | 278 allWritten = _writeCRLF(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 if (_bodyBytesWritten + bytes > _contentLength) { | 358 if (_bodyBytesWritten + bytes > _contentLength) { |
| 332 throw new HttpException("Writing more than specified content length"); | 359 throw new HttpException("Writing more than specified content length"); |
| 333 } | 360 } |
| 334 _bodyBytesWritten += bytes; | 361 _bodyBytesWritten += bytes; |
| 335 } | 362 } |
| 336 | 363 |
| 337 int _state; | 364 int _state; |
| 338 | 365 |
| 339 _HttpConnectionBase _httpConnection; | 366 _HttpConnectionBase _httpConnection; |
| 340 _HttpHeaders _headers; | 367 _HttpHeaders _headers; |
| 368 String _protocolVersion = "1.1"; |
| 341 | 369 |
| 342 // Length of the content body. If this is set to -1 (default value) | 370 // Length of the content body. If this is set to -1 (default value) |
| 343 // when starting to send data chunked transfer encoding will be | 371 // when starting to send data chunked transfer encoding will be |
| 344 // used. | 372 // used. |
| 345 int _contentLength = -1; | 373 int _contentLength = -1; |
| 346 // Number of body bytes written. This is only actual body data not | 374 // Number of body bytes written. This is only actual body data not |
| 347 // including headers or chunk information of using chinked transfer | 375 // including headers or chunk information of using chinked transfer |
| 348 // encoding. | 376 // encoding. |
| 349 int _bodyBytesWritten = 0; | 377 int _bodyBytesWritten = 0; |
| 350 } | 378 } |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 _httpConnection._write(_Const.HTTP10); | 613 _httpConnection._write(_Const.HTTP10); |
| 586 } | 614 } |
| 587 _writeSP(); | 615 _writeSP(); |
| 588 data = _statusCode.toString().charCodes(); | 616 data = _statusCode.toString().charCodes(); |
| 589 _httpConnection._write(data); | 617 _httpConnection._write(data); |
| 590 _writeSP(); | 618 _writeSP(); |
| 591 data = reasonPhrase.charCodes(); | 619 data = reasonPhrase.charCodes(); |
| 592 _httpConnection._write(data); | 620 _httpConnection._write(data); |
| 593 _writeCRLF(); | 621 _writeCRLF(); |
| 594 | 622 |
| 595 // Determine the value of the "Connection" header. | |
| 596 if (_protocolVersion == "1.1" && !_persistentConnection) { | |
| 597 _headers.set("Connection", "close"); | |
| 598 } else if (_protocolVersion == "1.0" && _persistentConnection) { | |
| 599 _headers.set("Connection", "keep-alive"); | |
| 600 } | |
| 601 // Determine the value of the "Transfer-Encoding" header based on | 623 // Determine the value of the "Transfer-Encoding" header based on |
| 602 // whether the content length is known. | 624 // whether the content length is known. |
| 603 if (_contentLength > 0) { | 625 if (_contentLength > 0) { |
| 604 _headers.set("Content-Length", _contentLength.toString()); | 626 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); |
| 605 } else { | 627 } else { |
| 606 _headers.set("Transfer-Encoding", "chunked"); | 628 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
| 607 } | 629 } |
| 608 | 630 |
| 609 // Write headers. | 631 // Write headers. |
| 610 bool allWritten = _writeHeaders(); | 632 bool allWritten = _writeHeaders(); |
| 611 _state = HEADER_SENT; | 633 _state = HEADER_SENT; |
| 612 return allWritten; | 634 return allWritten; |
| 613 } | 635 } |
| 614 | 636 |
| 615 // Response status code. | 637 // Response status code. |
| 616 int _statusCode; | 638 int _statusCode; |
| 617 String _reasonPhrase; | 639 String _reasonPhrase; |
| 618 String _protocolVersion; | |
| 619 bool _persistentConnection; | |
| 620 _HttpOutputStream _outputStream; | 640 _HttpOutputStream _outputStream; |
| 621 Function _streamErrorHandler; | 641 Function _streamErrorHandler; |
| 622 } | 642 } |
| 623 | 643 |
| 624 | 644 |
| 625 class _HttpInputStream extends _BaseDataInputStream implements InputStream { | 645 class _HttpInputStream extends _BaseDataInputStream implements InputStream { |
| 626 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) { | 646 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) { |
| 627 _checkScheduleCallbacks(); | 647 _checkScheduleCallbacks(); |
| 628 } | 648 } |
| 629 | 649 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // Indicate connection close to the HTTP parser. | 871 // Indicate connection close to the HTTP parser. |
| 852 _httpParser.connectionClosed(); | 872 _httpParser.connectionClosed(); |
| 853 } | 873 } |
| 854 } | 874 } |
| 855 | 875 |
| 856 void _onRequestStart(String method, String uri, String version) { | 876 void _onRequestStart(String method, String uri, String version) { |
| 857 // Create new request and response objects for this request. | 877 // Create new request and response objects for this request. |
| 858 _request = new _HttpRequest(this); | 878 _request = new _HttpRequest(this); |
| 859 _response = new _HttpResponse(this); | 879 _response = new _HttpResponse(this); |
| 860 _request._onRequestStart(method, uri, version); | 880 _request._onRequestStart(method, uri, version); |
| 881 _request._protocolVersion = version; |
| 861 _response._protocolVersion = version; | 882 _response._protocolVersion = version; |
| 862 } | 883 } |
| 863 | 884 |
| 864 void _onResponseStart(int statusCode, String reasonPhrase, String version) { | 885 void _onResponseStart(int statusCode, String reasonPhrase, String version) { |
| 865 // TODO(sgjesse): Error handling. | 886 // TODO(sgjesse): Error handling. |
| 866 } | 887 } |
| 867 | 888 |
| 868 void _onHeaderReceived(String name, String value) { | 889 void _onHeaderReceived(String name, String value) { |
| 869 _request._onHeaderReceived(name, value); | 890 _request._onHeaderReceived(name, value); |
| 870 } | 891 } |
| 871 | 892 |
| 872 void _onHeadersComplete() { | 893 void _onHeadersComplete() { |
| 873 _request._onHeadersComplete(); | 894 _request._onHeadersComplete(); |
| 874 _response._persistentConnection = _httpParser.persistentConnection; | 895 _response.persistentConnection = _httpParser.persistentConnection; |
| 875 if (onRequestReceived != null) { | 896 if (onRequestReceived != null) { |
| 876 onRequestReceived(_request, _response); | 897 onRequestReceived(_request, _response); |
| 877 } | 898 } |
| 878 } | 899 } |
| 879 | 900 |
| 880 void _onDataReceived(List<int> data) { | 901 void _onDataReceived(List<int> data) { |
| 881 _request._onDataReceived(data); | 902 _request._onDataReceived(data); |
| 882 } | 903 } |
| 883 | 904 |
| 884 void _onDataEnd(bool close) { | 905 void _onDataEnd(bool close) { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1087 data = _uri.toString().charCodes(); | 1108 data = _uri.toString().charCodes(); |
| 1088 _httpConnection._write(data); | 1109 _httpConnection._write(data); |
| 1089 _writeSP(); | 1110 _writeSP(); |
| 1090 _httpConnection._write(_Const.HTTP11); | 1111 _httpConnection._write(_Const.HTTP11); |
| 1091 _writeCRLF(); | 1112 _writeCRLF(); |
| 1092 | 1113 |
| 1093 // Determine the value of the "Transfer-Encoding" header based on | 1114 // Determine the value of the "Transfer-Encoding" header based on |
| 1094 // whether the content length is known. If there is no content | 1115 // whether the content length is known. If there is no content |
| 1095 // neither "Content-Length" nor "Transfer-Encoding" is set | 1116 // neither "Content-Length" nor "Transfer-Encoding" is set |
| 1096 if (_contentLength > 0) { | 1117 if (_contentLength > 0) { |
| 1097 _headers.set("Content-Length", _contentLength.toString()); | 1118 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); |
| 1098 } else if (_contentLength < 0) { | 1119 } else if (_contentLength < 0) { |
| 1099 _headers.set("Transfer-Encoding", "chunked"); | 1120 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
| 1100 } | 1121 } |
| 1101 | 1122 |
| 1102 // Write headers. | 1123 // Write headers. |
| 1103 _writeHeaders(); | 1124 _writeHeaders(); |
| 1104 _state = HEADER_SENT; | 1125 _state = HEADER_SENT; |
| 1105 } | 1126 } |
| 1106 | 1127 |
| 1107 String _method; | 1128 String _method; |
| 1108 String _uri; | 1129 String _uri; |
| 1109 _HttpClientConnection _connection; | 1130 _HttpClientConnection _connection; |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 _activeSockets.remove(socketConn); | 1520 _activeSockets.remove(socketConn); |
| 1500 sockets.addFirst(socketConn); | 1521 sockets.addFirst(socketConn); |
| 1501 } | 1522 } |
| 1502 | 1523 |
| 1503 Function _onOpen; | 1524 Function _onOpen; |
| 1504 Map<String, Queue<_SocketConnection>> _openSockets; | 1525 Map<String, Queue<_SocketConnection>> _openSockets; |
| 1505 Set<_SocketConnection> _activeSockets; | 1526 Set<_SocketConnection> _activeSockets; |
| 1506 Timer _evictionTimer; | 1527 Timer _evictionTimer; |
| 1507 bool _shutdown; // Has this HTTP client been shutdown? | 1528 bool _shutdown; // Has this HTTP client been shutdown? |
| 1508 } | 1529 } |
| OLD | NEW |