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

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

Issue 10315002: Improve the handling of the connection header (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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698