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

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 228453002: Add bufferOutput to HttpServer, HttpResponse and HttpClientRequest. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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) 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 const int _OUTGOING_BUFFER_SIZE = 8 * 1024; 7 const int _OUTGOING_BUFFER_SIZE = 8 * 1024;
8 8
9 class _HttpIncoming extends Stream<List<int>> { 9 class _HttpIncoming extends Stream<List<int>> {
10 final int _transferLength; 10 final int _transferLength;
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 }); 404 });
405 } 405 }
406 } 406 }
407 407
408 408
409 abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { 409 abstract class _HttpOutboundMessage<T> extends _IOSinkImpl {
410 // Used to mark when the body should be written. This is used for HEAD 410 // Used to mark when the body should be written. This is used for HEAD
411 // requests and in error handling. 411 // requests and in error handling.
412 bool _encodingSet = false; 412 bool _encodingSet = false;
413 413
414 bool bufferOutput;
Søren Gjesse 2014/04/08 11:54:25 What happens if this is changed while the body is
Anders Johnsen 2014/04/08 12:40:07 Done. Sadly, this is needed, as zlib buffers as we
415
414 final Uri _uri; 416 final Uri _uri;
415 final _HttpOutgoing _outgoing; 417 final _HttpOutgoing _outgoing;
416 418
417 final _HttpHeaders headers; 419 final _HttpHeaders headers;
418 420
419 _HttpOutboundMessage(Uri uri, 421 _HttpOutboundMessage(Uri uri,
420 String protocolVersion, 422 String protocolVersion,
421 _HttpOutgoing outgoing) 423 _HttpOutgoing outgoing,
424 this.bufferOutput)
422 : super(outgoing, null), 425 : super(outgoing, null),
423 _uri = uri, 426 _uri = uri,
424 headers = new _HttpHeaders( 427 headers = new _HttpHeaders(
425 protocolVersion, 428 protocolVersion,
426 defaultPortForScheme: uri.scheme == 'https' ? 429 defaultPortForScheme: uri.scheme == 'https' ?
427 HttpClient.DEFAULT_HTTPS_PORT : 430 HttpClient.DEFAULT_HTTPS_PORT :
428 HttpClient.DEFAULT_HTTP_PORT), 431 HttpClient.DEFAULT_HTTP_PORT),
429 _outgoing = outgoing { 432 _outgoing = outgoing {
430 _outgoing.outbound = this; 433 _outgoing.outbound = this;
431 _encodingMutable = false; 434 _encodingMutable = false;
(...skipping 29 matching lines...) Expand all
461 464
462 void write(Object obj) { 465 void write(Object obj) {
463 if (!_encodingSet) { 466 if (!_encodingSet) {
464 _encoding = encoding; 467 _encoding = encoding;
465 _encodingSet = true; 468 _encodingSet = true;
466 } 469 }
467 super.write(obj); 470 super.write(obj);
468 } 471 }
469 472
470 void _writeHeader(); 473 void _writeHeader();
474
475 bool get _isConnectionClosed => false;
471 } 476 }
472 477
473 478
474 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> 479 class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
475 implements HttpResponse { 480 implements HttpResponse {
476 int _statusCode = 200; 481 int _statusCode = 200;
477 String _reasonPhrase; 482 String _reasonPhrase;
478 List<Cookie> _cookies; 483 List<Cookie> _cookies;
479 _HttpRequest _httpRequest; 484 _HttpRequest _httpRequest;
480 Duration _deadline; 485 Duration _deadline;
481 Timer _deadlineTimer; 486 Timer _deadlineTimer;
482 487
483 _HttpResponse(Uri uri, 488 _HttpResponse(Uri uri,
484 String protocolVersion, 489 String protocolVersion,
485 _HttpOutgoing outgoing, 490 _HttpOutgoing outgoing,
486 String serverHeader) 491 String serverHeader,
487 : super(uri, protocolVersion, outgoing) { 492 bool bufferOutput)
493 : super(uri, protocolVersion, outgoing, bufferOutput) {
488 if (serverHeader != null) headers._add('server', serverHeader); 494 if (serverHeader != null) headers._add('server', serverHeader);
489 } 495 }
490 496
497 bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;
498
491 List<Cookie> get cookies { 499 List<Cookie> get cookies {
492 if (_cookies == null) _cookies = new List<Cookie>(); 500 if (_cookies == null) _cookies = new List<Cookie>();
493 return _cookies; 501 return _cookies;
494 } 502 }
495 503
496 int get statusCode => _statusCode; 504 int get statusCode => _statusCode;
497 void set statusCode(int statusCode) { 505 void set statusCode(int statusCode) {
498 if (_outgoing.headersWritten) throw new StateError("Header already sent"); 506 if (_outgoing.headersWritten) throw new StateError("Header already sent");
499 _statusCode = statusCode; 507 _statusCode = statusCode;
500 } 508 }
(...skipping 30 matching lines...) Expand all
531 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; 539 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;
532 540
533 Duration get deadline => _deadline; 541 Duration get deadline => _deadline;
534 542
535 void set deadline(Duration d) { 543 void set deadline(Duration d) {
536 if (_deadlineTimer != null) _deadlineTimer.cancel(); 544 if (_deadlineTimer != null) _deadlineTimer.cancel();
537 _deadline = d; 545 _deadline = d;
538 546
539 if (_deadline == null) return; 547 if (_deadline == null) return;
540 _deadlineTimer = new Timer(_deadline, () { 548 _deadlineTimer = new Timer(_deadline, () {
541 _outgoing._socketError = true; 549 _httpRequest._httpConnection.destroy();
542 _outgoing.socket.destroy();
543 }); 550 });
544 } 551 }
545 552
546 void _writeHeader() { 553 void _writeHeader() {
547 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 554 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
548 int offset = 0; 555 int offset = 0;
549 556
550 void write(List<int> bytes) { 557 void write(List<int> bytes) {
551 int len = bytes.length; 558 int len = bytes.length;
552 for (int i = 0; i < len; i++) { 559 for (int i = 0; i < len; i++) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 689
683 // TODO(ajohnsen): Get default value from client? 690 // TODO(ajohnsen): Get default value from client?
684 bool _followRedirects = true; 691 bool _followRedirects = true;
685 692
686 int _maxRedirects = 5; 693 int _maxRedirects = 5;
687 694
688 List<RedirectInfo> _responseRedirects = []; 695 List<RedirectInfo> _responseRedirects = [];
689 696
690 _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy, 697 _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
691 this._httpClient, this._httpClientConnection) 698 this._httpClient, this._httpClientConnection)
692 : super(uri, "1.1", outgoing), 699 : super(uri, "1.1", outgoing, true),
693 uri = uri { 700 uri = uri {
694 // GET and HEAD have 'content-length: 0' by default. 701 // GET and HEAD have 'content-length: 0' by default.
695 if (method == "GET" || method == "HEAD") { 702 if (method == "GET" || method == "HEAD") {
696 contentLength = 0; 703 contentLength = 0;
697 } else { 704 } else {
698 headers.chunkedTransferEncoding = true; 705 headers.chunkedTransferEncoding = true;
699 } 706 }
700 } 707 }
701 708
702 Future<HttpClientResponse> get done { 709 Future<HttpClientResponse> get done {
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 } 1043 }
1037 }); 1044 });
1038 } 1045 }
1039 1046
1040 Future close() { 1047 Future close() {
1041 // If we are already closed, return that future. 1048 // If we are already closed, return that future.
1042 if (_closeFuture != null) return _closeFuture; 1049 if (_closeFuture != null) return _closeFuture;
1043 // If we earlier saw an error, return immediate. The notification to 1050 // If we earlier saw an error, return immediate. The notification to
1044 // _Http*Connection is already done. 1051 // _Http*Connection is already done.
1045 if (_socketError) return new Future.value(outbound); 1052 if (_socketError) return new Future.value(outbound);
1053 if (outbound._isConnectionClosed) return new Future.value(outbound);
1046 if (!headersWritten && !ignoreBody) { 1054 if (!headersWritten && !ignoreBody) {
1047 if (outbound.headers.contentLength == -1) { 1055 if (outbound.headers.contentLength == -1) {
1048 // If no body was written, ignoreBody is false (it's not a HEAD 1056 // If no body was written, ignoreBody is false (it's not a HEAD
1049 // request) and the content-length is unspecified, set contentLength to 1057 // request) and the content-length is unspecified, set contentLength to
1050 // 0. 1058 // 0.
1051 outbound.headers.chunkedTransferEncoding = false; 1059 outbound.headers.chunkedTransferEncoding = false;
1052 outbound.headers.contentLength = 0; 1060 outbound.headers.contentLength = 0;
1053 } else if (outbound.headers.contentLength > 0) { 1061 } else if (outbound.headers.contentLength > 0) {
1054 var error = new HttpException( 1062 var error = new HttpException(
1055 "No content even though contentLength was specified to be " 1063 "No content even though contentLength was specified to be "
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 _addChunk(data, _gzipAdd); 1150 _addChunk(data, _gzipAdd);
1143 })); 1151 }));
1144 } 1152 }
1145 } 1153 }
1146 1154
1147 bool _ignoreError(error) 1155 bool _ignoreError(error)
1148 => (error is SocketException || error is TlsException) && 1156 => (error is SocketException || error is TlsException) &&
1149 outbound is HttpResponse; 1157 outbound is HttpResponse;
1150 1158
1151 void _addGZipChunk(chunk, void add(List<int> data)) { 1159 void _addGZipChunk(chunk, void add(List<int> data)) {
1160 if (!outbound.bufferOutput) {
1161 add(chunk);
1162 return;
1163 }
1152 if (chunk.length > _gzipBuffer.length - _gzipBufferLength) { 1164 if (chunk.length > _gzipBuffer.length - _gzipBufferLength) {
1153 add(new Uint8List.view( 1165 add(new Uint8List.view(
1154 _gzipBuffer.buffer, 0, _gzipBufferLength)); 1166 _gzipBuffer.buffer, 0, _gzipBufferLength));
1155 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 1167 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
1156 _gzipBufferLength = 0; 1168 _gzipBufferLength = 0;
1157 } 1169 }
1158 if (chunk.length > _OUTGOING_BUFFER_SIZE) { 1170 if (chunk.length > _OUTGOING_BUFFER_SIZE) {
1159 add(chunk); 1171 add(chunk);
1160 } else { 1172 } else {
1161 _gzipBuffer.setRange(_gzipBufferLength, 1173 _gzipBuffer.setRange(_gzipBufferLength,
1162 _gzipBufferLength + chunk.length, 1174 _gzipBufferLength + chunk.length,
1163 chunk); 1175 chunk);
1164 _gzipBufferLength += chunk.length; 1176 _gzipBufferLength += chunk.length;
1165 } 1177 }
1166 } 1178 }
1167 1179
1168 void _addChunk(chunk, void add(List<int> data)) { 1180 void _addChunk(chunk, void add(List<int> data)) {
1181 if (!outbound.bufferOutput) {
1182 if (_buffer != null) {
1183 add(new Uint8List.view(_buffer.buffer, 0, _length));
Søren Gjesse 2014/04/08 11:54:25 Please add a comment on why you are doing this.
Anders Johnsen 2014/04/08 12:40:07 Done.
1184 _buffer = null;
1185 _length = 0;
1186 }
1187 add(chunk);
1188 return;
1189 }
1169 if (chunk.length > _buffer.length - _length) { 1190 if (chunk.length > _buffer.length - _length) {
1170 add(new Uint8List.view(_buffer.buffer, 0, _length)); 1191 add(new Uint8List.view(_buffer.buffer, 0, _length));
1171 _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 1192 _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
1172 _length = 0; 1193 _length = 0;
1173 } 1194 }
1174 if (chunk.length > _OUTGOING_BUFFER_SIZE) { 1195 if (chunk.length > _OUTGOING_BUFFER_SIZE) {
1175 add(chunk); 1196 add(chunk);
1176 } else { 1197 } else {
1177 _buffer.setRange(_length, _length + chunk.length, chunk); 1198 _buffer.setRange(_length, _length + chunk.length, chunk);
1178 _length += chunk.length; 1199 _length += chunk.length;
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after
1896 if (closing) destroy(); 1917 if (closing) destroy();
1897 }); 1918 });
1898 // Only handle one incoming request at the time. Keep the 1919 // Only handle one incoming request at the time. Keep the
1899 // stream paused until the request has been send. 1920 // stream paused until the request has been send.
1900 _subscription.pause(); 1921 _subscription.pause();
1901 _state = _ACTIVE; 1922 _state = _ACTIVE;
1902 var outgoing = new _HttpOutgoing(_socket); 1923 var outgoing = new _HttpOutgoing(_socket);
1903 var response = new _HttpResponse(incoming.uri, 1924 var response = new _HttpResponse(incoming.uri,
1904 incoming.headers.protocolVersion, 1925 incoming.headers.protocolVersion,
1905 outgoing, 1926 outgoing,
1906 _httpServer.serverHeader); 1927 _httpServer.serverHeader,
1928 _httpServer.bufferOutput);
1907 var request = new _HttpRequest(response, incoming, _httpServer, this); 1929 var request = new _HttpRequest(response, incoming, _httpServer, this);
1908 _streamFuture = outgoing.done 1930 _streamFuture = outgoing.done
1909 .then((_) { 1931 .then((_) {
1910 response.deadline = null; 1932 response.deadline = null;
1911 if (_state == _DETACHED) return; 1933 if (_state == _DETACHED) return;
1912 if (response.persistentConnection && 1934 if (response.persistentConnection &&
1913 request.persistentConnection && 1935 request.persistentConnection &&
1914 incoming.fullBodyRead && 1936 incoming.fullBodyRead &&
1915 !_httpParser.upgrade && 1937 !_httpParser.upgrade &&
1916 !_httpServer.closed) { 1938 !_httpServer.closed) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 bool get _isActive => _state == _ACTIVE; 1993 bool get _isActive => _state == _ACTIVE;
1972 bool get _isIdle => _state == _IDLE; 1994 bool get _isIdle => _state == _IDLE;
1973 bool get _isClosing => _state == _CLOSING; 1995 bool get _isClosing => _state == _CLOSING;
1974 bool get _isDetached => _state == _DETACHED; 1996 bool get _isDetached => _state == _DETACHED;
1975 } 1997 }
1976 1998
1977 1999
1978 // HTTP server waiting for socket connections. 2000 // HTTP server waiting for socket connections.
1979 class _HttpServer extends Stream<HttpRequest> implements HttpServer { 2001 class _HttpServer extends Stream<HttpRequest> implements HttpServer {
1980 String serverHeader; 2002 String serverHeader;
2003 bool bufferOutput = true;
1981 2004
1982 Duration _idleTimeout; 2005 Duration _idleTimeout;
1983 Timer _idleTimer; 2006 Timer _idleTimer;
1984 2007
1985 static Future<HttpServer> bind(address, int port, int backlog) { 2008 static Future<HttpServer> bind(address, int port, int backlog) {
1986 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { 2009 return ServerSocket.bind(address, port, backlog: backlog).then((socket) {
1987 return new _HttpServer._(socket, true); 2010 return new _HttpServer._(socket, true);
1988 }); 2011 });
1989 } 2012 }
1990 2013
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 const _RedirectInfo(this.statusCode, this.method, this.location); 2600 const _RedirectInfo(this.statusCode, this.method, this.location);
2578 } 2601 }
2579 2602
2580 String _getHttpVersion() { 2603 String _getHttpVersion() {
2581 var version = Platform.version; 2604 var version = Platform.version;
2582 // Only include major and minor version numbers. 2605 // Only include major and minor version numbers.
2583 int index = version.indexOf('.', version.indexOf('.') + 1); 2606 int index = version.indexOf('.', version.indexOf('.') + 1);
2584 version = version.substring(0, index); 2607 version = version.substring(0, index);
2585 return 'Dart/$version (dart:io)'; 2608 return 'Dart/$version (dart:io)';
2586 } 2609 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698