| 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; |
| 222 | 222 |
| 223 String _host; | 223 String _host; |
| 224 int _port; | 224 int _port; |
| 225 } | 225 } |
| 226 | 226 |
| 227 | 227 |
| 228 class _HttpRequestResponseBase { | 228 class _HttpRequestResponseBase { |
| 229 final int START = 0; | 229 final int START = 0; |
| 230 final int HEADER_SENT = 1; | 230 final int HEADER_SENT = 1; |
| 231 final int DONE = 2; | 231 final int DONE = 2; |
| 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 bool get persistentConnection() => _persistentConnection; |
| 240 HttpHeaders get headers() => _headers; | 241 HttpHeaders get headers() => _headers; |
| 241 | 242 |
| 242 bool _write(List<int> data, bool copyBuffer) { | 243 bool _write(List<int> data, bool copyBuffer) { |
| 243 _ensureHeadersSent(); | 244 _ensureHeadersSent(); |
| 244 bool allWritten = true; | 245 bool allWritten = true; |
| 245 if (data.length > 0) { | 246 if (data.length > 0) { |
| 246 if (_contentLength < 0) { | 247 if (_contentLength < 0) { |
| 247 // Write chunk size if transfer encoding is chunked. | 248 // Write chunk size if transfer encoding is chunked. |
| 248 _writeHexString(data.length); | 249 _writeHexString(data.length); |
| 249 _writeCRLF(); | 250 _writeCRLF(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 _HttpHeaders _headers; | 341 _HttpHeaders _headers; |
| 341 | 342 |
| 342 // Length of the content body. If this is set to -1 (default value) | 343 // Length of the content body. If this is set to -1 (default value) |
| 343 // when starting to send data chunked transfer encoding will be | 344 // when starting to send data chunked transfer encoding will be |
| 344 // used. | 345 // used. |
| 345 int _contentLength = -1; | 346 int _contentLength = -1; |
| 346 // Number of body bytes written. This is only actual body data not | 347 // Number of body bytes written. This is only actual body data not |
| 347 // including headers or chunk information of using chinked transfer | 348 // including headers or chunk information of using chinked transfer |
| 348 // encoding. | 349 // encoding. |
| 349 int _bodyBytesWritten = 0; | 350 int _bodyBytesWritten = 0; |
| 351 |
| 352 bool _persistentConnection = true; |
| 350 } | 353 } |
| 351 | 354 |
| 352 | 355 |
| 353 // Parsed HTTP request providing information on the HTTP headers. | 356 // Parsed HTTP request providing information on the HTTP headers. |
| 354 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest { | 357 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest { |
| 355 _HttpRequest(_HttpConnection connection) : super(connection); | 358 _HttpRequest(_HttpConnection connection) : super(connection); |
| 356 | 359 |
| 357 String get method() => _method; | 360 String get method() => _method; |
| 358 String get uri() => _uri; | 361 String get uri() => _uri; |
| 359 String get path() => _path; | 362 String get path() => _path; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 if (_outputStream != null) throw new HttpException("Header already sent"); | 455 if (_outputStream != null) throw new HttpException("Header already sent"); |
| 453 _statusCode = statusCode; | 456 _statusCode = statusCode; |
| 454 } | 457 } |
| 455 | 458 |
| 456 String get reasonPhrase() => _findReasonPhrase(_statusCode); | 459 String get reasonPhrase() => _findReasonPhrase(_statusCode); |
| 457 void set reasonPhrase(String reasonPhrase) { | 460 void set reasonPhrase(String reasonPhrase) { |
| 458 if (_outputStream != null) throw new HttpException("Header already sent"); | 461 if (_outputStream != null) throw new HttpException("Header already sent"); |
| 459 _reasonPhrase = reasonPhrase; | 462 _reasonPhrase = reasonPhrase; |
| 460 } | 463 } |
| 461 | 464 |
| 465 void set persistentConnection(bool persistentConnection) { |
| 466 if (_outputStream != null) throw new HttpException("Header already sent"); |
| 467 _persistentConnection = persistentConnection; |
| 468 } |
| 469 |
| 462 OutputStream get outputStream() { | 470 OutputStream get outputStream() { |
| 463 if (_state >= DONE) throw new HttpException("Response closed"); | 471 if (_state >= DONE) throw new HttpException("Response closed"); |
| 464 if (_outputStream == null) { | 472 if (_outputStream == null) { |
| 465 _outputStream = new _HttpOutputStream(this); | 473 _outputStream = new _HttpOutputStream(this); |
| 466 } | 474 } |
| 467 return _outputStream; | 475 return _outputStream; |
| 468 } | 476 } |
| 469 | 477 |
| 470 Socket detachSocket() { | 478 Socket detachSocket() { |
| 471 if (_state >= DONE) throw new HttpException("Response closed"); | 479 if (_state >= DONE) throw new HttpException("Response closed"); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 _writeSP(); | 595 _writeSP(); |
| 588 data = _statusCode.toString().charCodes(); | 596 data = _statusCode.toString().charCodes(); |
| 589 _httpConnection._write(data); | 597 _httpConnection._write(data); |
| 590 _writeSP(); | 598 _writeSP(); |
| 591 data = reasonPhrase.charCodes(); | 599 data = reasonPhrase.charCodes(); |
| 592 _httpConnection._write(data); | 600 _httpConnection._write(data); |
| 593 _writeCRLF(); | 601 _writeCRLF(); |
| 594 | 602 |
| 595 // Determine the value of the "Connection" header. | 603 // Determine the value of the "Connection" header. |
| 596 if (_protocolVersion == "1.1" && !_persistentConnection) { | 604 if (_protocolVersion == "1.1" && !_persistentConnection) { |
| 597 _headers.set("Connection", "close"); | 605 _headers.add(HttpHeaders.CONNECTION, "close"); |
| 598 } else if (_protocolVersion == "1.0" && _persistentConnection) { | 606 } else if (_protocolVersion == "1.0" && _persistentConnection) { |
| 599 _headers.set("Connection", "keep-alive"); | 607 _headers.add(HttpHeaders.CONNECTION, "keep-alive"); |
| 600 } | 608 } |
| 601 // Determine the value of the "Transfer-Encoding" header based on | 609 // Determine the value of the "Transfer-Encoding" header based on |
| 602 // whether the content length is known. | 610 // whether the content length is known. |
| 603 if (_contentLength > 0) { | 611 if (_contentLength > 0) { |
| 604 _headers.set("Content-Length", _contentLength.toString()); | 612 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); |
| 605 } else { | 613 } else { |
| 606 _headers.set("Transfer-Encoding", "chunked"); | 614 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
| 607 } | 615 } |
| 608 | 616 |
| 609 // Write headers. | 617 // Write headers. |
| 610 bool allWritten = _writeHeaders(); | 618 bool allWritten = _writeHeaders(); |
| 611 _state = HEADER_SENT; | 619 _state = HEADER_SENT; |
| 612 return allWritten; | 620 return allWritten; |
| 613 } | 621 } |
| 614 | 622 |
| 615 // Response status code. | 623 // Response status code. |
| 616 int _statusCode; | 624 int _statusCode; |
| 617 String _reasonPhrase; | 625 String _reasonPhrase; |
| 618 String _protocolVersion; | 626 String _protocolVersion; |
| 619 bool _persistentConnection; | |
| 620 _HttpOutputStream _outputStream; | 627 _HttpOutputStream _outputStream; |
| 621 Function _streamErrorHandler; | 628 Function _streamErrorHandler; |
| 622 } | 629 } |
| 623 | 630 |
| 624 | 631 |
| 625 class _HttpInputStream extends _BaseDataInputStream implements InputStream { | 632 class _HttpInputStream extends _BaseDataInputStream implements InputStream { |
| 626 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) { | 633 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) { |
| 627 _checkScheduleCallbacks(); | 634 _checkScheduleCallbacks(); |
| 628 } | 635 } |
| 629 | 636 |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 void _onResponseStart(int statusCode, String reasonPhrase, String version) { | 871 void _onResponseStart(int statusCode, String reasonPhrase, String version) { |
| 865 // TODO(sgjesse): Error handling. | 872 // TODO(sgjesse): Error handling. |
| 866 } | 873 } |
| 867 | 874 |
| 868 void _onHeaderReceived(String name, String value) { | 875 void _onHeaderReceived(String name, String value) { |
| 869 _request._onHeaderReceived(name, value); | 876 _request._onHeaderReceived(name, value); |
| 870 } | 877 } |
| 871 | 878 |
| 872 void _onHeadersComplete() { | 879 void _onHeadersComplete() { |
| 873 _request._onHeadersComplete(); | 880 _request._onHeadersComplete(); |
| 881 _request._persistentConnection = _httpParser.persistentConnection; |
| 874 _response._persistentConnection = _httpParser.persistentConnection; | 882 _response._persistentConnection = _httpParser.persistentConnection; |
| 875 if (onRequestReceived != null) { | 883 if (onRequestReceived != null) { |
| 876 onRequestReceived(_request, _response); | 884 onRequestReceived(_request, _response); |
| 877 } | 885 } |
| 878 } | 886 } |
| 879 | 887 |
| 880 void _onDataReceived(List<int> data) { | 888 void _onDataReceived(List<int> data) { |
| 881 _request._onDataReceived(data); | 889 _request._onDataReceived(data); |
| 882 } | 890 } |
| 883 | 891 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 if (_method == "GET") { | 1036 if (_method == "GET") { |
| 1029 _contentLength = 0; | 1037 _contentLength = 0; |
| 1030 } | 1038 } |
| 1031 } | 1039 } |
| 1032 | 1040 |
| 1033 void set contentLength(int contentLength) { | 1041 void set contentLength(int contentLength) { |
| 1034 if (_state >= HEADER_SENT) throw new HttpException("Header already sent"); | 1042 if (_state >= HEADER_SENT) throw new HttpException("Header already sent"); |
| 1035 _contentLength = contentLength; | 1043 _contentLength = contentLength; |
| 1036 } | 1044 } |
| 1037 | 1045 |
| 1046 void set persistentConnection(bool persistentConnection) { |
| 1047 if (_state >= HEADER_SENT) throw new HttpException("Header already sent"); |
| 1048 _persistentConnection = persistentConnection; |
| 1049 } |
| 1050 |
| 1038 OutputStream get outputStream() { | 1051 OutputStream get outputStream() { |
| 1039 if (_state == DONE) throw new HttpException("Request closed"); | 1052 if (_state == DONE) throw new HttpException("Request closed"); |
| 1040 if (_outputStream == null) { | 1053 if (_outputStream == null) { |
| 1041 _outputStream = new _HttpOutputStream(this); | 1054 _outputStream = new _HttpOutputStream(this); |
| 1042 } | 1055 } |
| 1043 return _outputStream; | 1056 return _outputStream; |
| 1044 } | 1057 } |
| 1045 | 1058 |
| 1046 // Delegate functions for the HttpOutputStream implementation. | 1059 // Delegate functions for the HttpOutputStream implementation. |
| 1047 bool _streamWrite(List<int> buffer, bool copyBuffer) { | 1060 bool _streamWrite(List<int> buffer, bool copyBuffer) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 // Write request line. | 1096 // Write request line. |
| 1084 data = _method.toString().charCodes(); | 1097 data = _method.toString().charCodes(); |
| 1085 _httpConnection._write(data); | 1098 _httpConnection._write(data); |
| 1086 _writeSP(); | 1099 _writeSP(); |
| 1087 data = _uri.toString().charCodes(); | 1100 data = _uri.toString().charCodes(); |
| 1088 _httpConnection._write(data); | 1101 _httpConnection._write(data); |
| 1089 _writeSP(); | 1102 _writeSP(); |
| 1090 _httpConnection._write(_Const.HTTP11); | 1103 _httpConnection._write(_Const.HTTP11); |
| 1091 _writeCRLF(); | 1104 _writeCRLF(); |
| 1092 | 1105 |
| 1106 // Determine the value of the "Connection" header. |
| 1107 if (!_persistentConnection) { |
| 1108 _headers.add(HttpHeaders.CONNECTION, "close"); |
| 1109 } |
| 1093 // Determine the value of the "Transfer-Encoding" header based on | 1110 // Determine the value of the "Transfer-Encoding" header based on |
| 1094 // whether the content length is known. If there is no content | 1111 // whether the content length is known. If there is no content |
| 1095 // neither "Content-Length" nor "Transfer-Encoding" is set | 1112 // neither "Content-Length" nor "Transfer-Encoding" is set |
| 1096 if (_contentLength > 0) { | 1113 if (_contentLength > 0) { |
| 1097 _headers.set("Content-Length", _contentLength.toString()); | 1114 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); |
| 1098 } else if (_contentLength < 0) { | 1115 } else if (_contentLength < 0) { |
| 1099 _headers.set("Transfer-Encoding", "chunked"); | 1116 _headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
| 1100 } | 1117 } |
| 1101 | 1118 |
| 1102 // Write headers. | 1119 // Write headers. |
| 1103 _writeHeaders(); | 1120 _writeHeaders(); |
| 1104 _state = HEADER_SENT; | 1121 _state = HEADER_SENT; |
| 1105 } | 1122 } |
| 1106 | 1123 |
| 1107 String _method; | 1124 String _method; |
| 1108 String _uri; | 1125 String _uri; |
| 1109 _HttpClientConnection _connection; | 1126 _HttpClientConnection _connection; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 | 1276 |
| 1260 void _onResponseStart(int statusCode, String reasonPhrase, String version) { | 1277 void _onResponseStart(int statusCode, String reasonPhrase, String version) { |
| 1261 _response._onResponseStart(statusCode, reasonPhrase, version); | 1278 _response._onResponseStart(statusCode, reasonPhrase, version); |
| 1262 } | 1279 } |
| 1263 | 1280 |
| 1264 void _onHeaderReceived(String name, String value) { | 1281 void _onHeaderReceived(String name, String value) { |
| 1265 _response._onHeaderReceived(name, value); | 1282 _response._onHeaderReceived(name, value); |
| 1266 } | 1283 } |
| 1267 | 1284 |
| 1268 void _onHeadersComplete() { | 1285 void _onHeadersComplete() { |
| 1286 _response._persistentConnection = _httpParser.persistentConnection; |
| 1269 _response._onHeadersComplete(); | 1287 _response._onHeadersComplete(); |
| 1270 } | 1288 } |
| 1271 | 1289 |
| 1272 void _onDataReceived(List<int> data) { | 1290 void _onDataReceived(List<int> data) { |
| 1273 _response._onDataReceived(data); | 1291 _response._onDataReceived(data); |
| 1274 } | 1292 } |
| 1275 | 1293 |
| 1276 void _onDataEnd(bool close) { | 1294 void _onDataEnd(bool close) { |
| 1277 if (close) _closing = true; | 1295 if (close) _closing = true; |
| 1278 _response._onDataEnd(); | 1296 _response._onDataEnd(); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 _activeSockets.remove(socketConn); | 1517 _activeSockets.remove(socketConn); |
| 1500 sockets.addFirst(socketConn); | 1518 sockets.addFirst(socketConn); |
| 1501 } | 1519 } |
| 1502 | 1520 |
| 1503 Function _onOpen; | 1521 Function _onOpen; |
| 1504 Map<String, Queue<_SocketConnection>> _openSockets; | 1522 Map<String, Queue<_SocketConnection>> _openSockets; |
| 1505 Set<_SocketConnection> _activeSockets; | 1523 Set<_SocketConnection> _activeSockets; |
| 1506 Timer _evictionTimer; | 1524 Timer _evictionTimer; |
| 1507 bool _shutdown; // Has this HTTP client been shutdown? | 1525 bool _shutdown; // Has this HTTP client been shutdown? |
| 1508 } | 1526 } |
| OLD | NEW |