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

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: Review fixes. 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 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 .then((request) => request.close()); 303 .then((request) => request.close());
304 }); 304 });
305 } 305 }
306 306
307 List<String> authChallenge() { 307 List<String> authChallenge() {
308 return proxyAuth ? headers[HttpHeaders.PROXY_AUTHENTICATE] 308 return proxyAuth ? headers[HttpHeaders.PROXY_AUTHENTICATE]
309 : headers[HttpHeaders.WWW_AUTHENTICATE]; 309 : headers[HttpHeaders.WWW_AUTHENTICATE];
310 } 310 }
311 311
312 _Credentials findCredentials(_AuthenticationScheme scheme) { 312 _Credentials findCredentials(_AuthenticationScheme scheme) {
313 return proxyAuth ? _httpClient._findProxyCredentials(_httpRequest._proxy, scheme) 313 return proxyAuth ? _httpClient._findProxyCredentials(_httpRequest._proxy,
314 scheme)
314 : _httpClient._findCredentials(_httpRequest.uri, scheme); 315 : _httpClient._findCredentials(_httpRequest.uri, scheme);
315 } 316 }
316 317
317 void removeCredentials(_Credentials cr) { 318 void removeCredentials(_Credentials cr) {
318 if (proxyAuth) { 319 if (proxyAuth) {
319 _httpClient._removeProxyCredentials(cr); 320 _httpClient._removeProxyCredentials(cr);
320 } else { 321 } else {
321 _httpClient._removeCredentials(cr); 322 _httpClient._removeCredentials(cr);
322 } 323 }
323 } 324 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 }); 405 });
405 } 406 }
406 } 407 }
407 408
408 409
409 abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { 410 abstract class _HttpOutboundMessage<T> extends _IOSinkImpl {
410 // Used to mark when the body should be written. This is used for HEAD 411 // Used to mark when the body should be written. This is used for HEAD
411 // requests and in error handling. 412 // requests and in error handling.
412 bool _encodingSet = false; 413 bool _encodingSet = false;
413 414
415 bool _bufferOutput = true;
416
414 final Uri _uri; 417 final Uri _uri;
415 final _HttpOutgoing _outgoing; 418 final _HttpOutgoing _outgoing;
416 419
417 final _HttpHeaders headers; 420 final _HttpHeaders headers;
418 421
419 _HttpOutboundMessage(Uri uri, 422 _HttpOutboundMessage(Uri uri,
420 String protocolVersion, 423 String protocolVersion,
421 _HttpOutgoing outgoing) 424 _HttpOutgoing outgoing)
422 : super(outgoing, null), 425 : super(outgoing, null),
423 _uri = uri, 426 _uri = uri,
(...skipping 10 matching lines...) Expand all
434 int get contentLength => headers.contentLength; 437 int get contentLength => headers.contentLength;
435 void set contentLength(int contentLength) { 438 void set contentLength(int contentLength) {
436 headers.contentLength = contentLength; 439 headers.contentLength = contentLength;
437 } 440 }
438 441
439 bool get persistentConnection => headers.persistentConnection; 442 bool get persistentConnection => headers.persistentConnection;
440 void set persistentConnection(bool p) { 443 void set persistentConnection(bool p) {
441 headers.persistentConnection = p; 444 headers.persistentConnection = p;
442 } 445 }
443 446
447 bool get bufferOutput => _bufferOutput;
448 void set bufferOutput(bool bufferOutput) {
449 if (_outgoing.headersWritten) throw new StateError("Header already sent");
450 _bufferOutput = bufferOutput;
451 }
452
453
444 Encoding get encoding { 454 Encoding get encoding {
445 if (_encodingSet && _outgoing.headersWritten) { 455 if (_encodingSet && _outgoing.headersWritten) {
446 return _encoding; 456 return _encoding;
447 } 457 }
448 var charset; 458 var charset;
449 if (headers.contentType != null && headers.contentType.charset != null) { 459 if (headers.contentType != null && headers.contentType.charset != null) {
450 charset = headers.contentType.charset; 460 charset = headers.contentType.charset;
451 } else { 461 } else {
452 charset = "iso-8859-1"; 462 charset = "iso-8859-1";
453 } 463 }
454 return Encoding.getByName(charset); 464 return Encoding.getByName(charset);
455 } 465 }
456 466
457 void add(List<int> data) { 467 void add(List<int> data) {
458 if (data.length == 0) return; 468 if (data.length == 0) return;
459 super.add(data); 469 super.add(data);
460 } 470 }
461 471
462 void write(Object obj) { 472 void write(Object obj) {
463 if (!_encodingSet) { 473 if (!_encodingSet) {
464 _encoding = encoding; 474 _encoding = encoding;
465 _encodingSet = true; 475 _encodingSet = true;
466 } 476 }
467 super.write(obj); 477 super.write(obj);
468 } 478 }
469 479
470 void _writeHeader(); 480 void _writeHeader();
481
482 bool get _isConnectionClosed => false;
471 } 483 }
472 484
473 485
474 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> 486 class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
475 implements HttpResponse { 487 implements HttpResponse {
476 int _statusCode = 200; 488 int _statusCode = 200;
477 String _reasonPhrase; 489 String _reasonPhrase;
478 List<Cookie> _cookies; 490 List<Cookie> _cookies;
479 _HttpRequest _httpRequest; 491 _HttpRequest _httpRequest;
480 Duration _deadline; 492 Duration _deadline;
481 Timer _deadlineTimer; 493 Timer _deadlineTimer;
482 494
483 _HttpResponse(Uri uri, 495 _HttpResponse(Uri uri,
484 String protocolVersion, 496 String protocolVersion,
485 _HttpOutgoing outgoing, 497 _HttpOutgoing outgoing,
486 String serverHeader) 498 String serverHeader)
487 : super(uri, protocolVersion, outgoing) { 499 : super(uri, protocolVersion, outgoing) {
488 if (serverHeader != null) headers._add('server', serverHeader); 500 if (serverHeader != null) headers._add('server', serverHeader);
489 } 501 }
490 502
503 bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;
504
491 List<Cookie> get cookies { 505 List<Cookie> get cookies {
492 if (_cookies == null) _cookies = new List<Cookie>(); 506 if (_cookies == null) _cookies = new List<Cookie>();
493 return _cookies; 507 return _cookies;
494 } 508 }
495 509
496 int get statusCode => _statusCode; 510 int get statusCode => _statusCode;
497 void set statusCode(int statusCode) { 511 void set statusCode(int statusCode) {
498 if (_outgoing.headersWritten) throw new StateError("Header already sent"); 512 if (_outgoing.headersWritten) throw new StateError("Header already sent");
499 _statusCode = statusCode; 513 _statusCode = statusCode;
500 } 514 }
(...skipping 30 matching lines...) Expand all
531 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; 545 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;
532 546
533 Duration get deadline => _deadline; 547 Duration get deadline => _deadline;
534 548
535 void set deadline(Duration d) { 549 void set deadline(Duration d) {
536 if (_deadlineTimer != null) _deadlineTimer.cancel(); 550 if (_deadlineTimer != null) _deadlineTimer.cancel();
537 _deadline = d; 551 _deadline = d;
538 552
539 if (_deadline == null) return; 553 if (_deadline == null) return;
540 _deadlineTimer = new Timer(_deadline, () { 554 _deadlineTimer = new Timer(_deadline, () {
541 _outgoing._socketError = true; 555 _httpRequest._httpConnection.destroy();
542 _outgoing.socket.destroy();
543 }); 556 });
544 } 557 }
545 558
546 void _writeHeader() { 559 void _writeHeader() {
547 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 560 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
548 int offset = 0; 561 int offset = 0;
549 562
550 void write(List<int> bytes) { 563 void write(List<int> bytes) {
551 int len = bytes.length; 564 int len = bytes.length;
552 for (int i = 0; i < len; i++) { 565 for (int i = 0; i < len; i++) {
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 " bytes")); 925 " bytes"));
913 } 926 }
914 } 927 }
915 if (headersWritten) return null; 928 if (headersWritten) return null;
916 headersWritten = true; 929 headersWritten = true;
917 Future drainFuture; 930 Future drainFuture;
918 bool isServerSide = outbound is _HttpResponse; 931 bool isServerSide = outbound is _HttpResponse;
919 bool gzip = false; 932 bool gzip = false;
920 if (isServerSide) { 933 if (isServerSide) {
921 var response = outbound; 934 var response = outbound;
922 if (outbound.headers.chunkedTransferEncoding) { 935 if (outbound.bufferOutput && outbound.headers.chunkedTransferEncoding) {
923 List acceptEncodings = 936 List acceptEncodings =
924 response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING]; 937 response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
925 List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING]; 938 List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING];
926 if (acceptEncodings != null && 939 if (acceptEncodings != null &&
927 acceptEncodings 940 acceptEncodings
928 .expand((list) => list.split(",")) 941 .expand((list) => list.split(","))
929 .any((encoding) => encoding.trim().toLowerCase() == "gzip") && 942 .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
930 contentEncoding == null) { 943 contentEncoding == null) {
931 outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip"); 944 outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
932 gzip = true; 945 gzip = true;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 } 1049 }
1037 }); 1050 });
1038 } 1051 }
1039 1052
1040 Future close() { 1053 Future close() {
1041 // If we are already closed, return that future. 1054 // If we are already closed, return that future.
1042 if (_closeFuture != null) return _closeFuture; 1055 if (_closeFuture != null) return _closeFuture;
1043 // If we earlier saw an error, return immediate. The notification to 1056 // If we earlier saw an error, return immediate. The notification to
1044 // _Http*Connection is already done. 1057 // _Http*Connection is already done.
1045 if (_socketError) return new Future.value(outbound); 1058 if (_socketError) return new Future.value(outbound);
1059 if (outbound._isConnectionClosed) return new Future.value(outbound);
1046 if (!headersWritten && !ignoreBody) { 1060 if (!headersWritten && !ignoreBody) {
1047 if (outbound.headers.contentLength == -1) { 1061 if (outbound.headers.contentLength == -1) {
1048 // If no body was written, ignoreBody is false (it's not a HEAD 1062 // If no body was written, ignoreBody is false (it's not a HEAD
1049 // request) and the content-length is unspecified, set contentLength to 1063 // request) and the content-length is unspecified, set contentLength to
1050 // 0. 1064 // 0.
1051 outbound.headers.chunkedTransferEncoding = false; 1065 outbound.headers.chunkedTransferEncoding = false;
1052 outbound.headers.contentLength = 0; 1066 outbound.headers.contentLength = 0;
1053 } else if (outbound.headers.contentLength > 0) { 1067 } else if (outbound.headers.contentLength > 0) {
1054 var error = new HttpException( 1068 var error = new HttpException(
1055 "No content even though contentLength was specified to be " 1069 "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); 1156 _addChunk(data, _gzipAdd);
1143 })); 1157 }));
1144 } 1158 }
1145 } 1159 }
1146 1160
1147 bool _ignoreError(error) 1161 bool _ignoreError(error)
1148 => (error is SocketException || error is TlsException) && 1162 => (error is SocketException || error is TlsException) &&
1149 outbound is HttpResponse; 1163 outbound is HttpResponse;
1150 1164
1151 void _addGZipChunk(chunk, void add(List<int> data)) { 1165 void _addGZipChunk(chunk, void add(List<int> data)) {
1166 if (!outbound.bufferOutput) {
1167 add(chunk);
1168 return;
1169 }
1152 if (chunk.length > _gzipBuffer.length - _gzipBufferLength) { 1170 if (chunk.length > _gzipBuffer.length - _gzipBufferLength) {
1153 add(new Uint8List.view( 1171 add(new Uint8List.view(
1154 _gzipBuffer.buffer, 0, _gzipBufferLength)); 1172 _gzipBuffer.buffer, 0, _gzipBufferLength));
1155 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 1173 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
1156 _gzipBufferLength = 0; 1174 _gzipBufferLength = 0;
1157 } 1175 }
1158 if (chunk.length > _OUTGOING_BUFFER_SIZE) { 1176 if (chunk.length > _OUTGOING_BUFFER_SIZE) {
1159 add(chunk); 1177 add(chunk);
1160 } else { 1178 } else {
1161 _gzipBuffer.setRange(_gzipBufferLength, 1179 _gzipBuffer.setRange(_gzipBufferLength,
1162 _gzipBufferLength + chunk.length, 1180 _gzipBufferLength + chunk.length,
1163 chunk); 1181 chunk);
1164 _gzipBufferLength += chunk.length; 1182 _gzipBufferLength += chunk.length;
1165 } 1183 }
1166 } 1184 }
1167 1185
1168 void _addChunk(chunk, void add(List<int> data)) { 1186 void _addChunk(chunk, void add(List<int> data)) {
1187 if (!outbound.bufferOutput) {
1188 if (_buffer != null) {
1189 // If _buffer is not null, we have not written the header yet. Write
1190 // it now.
1191 add(new Uint8List.view(_buffer.buffer, 0, _length));
1192 _buffer = null;
1193 _length = 0;
1194 }
1195 add(chunk);
1196 return;
1197 }
1169 if (chunk.length > _buffer.length - _length) { 1198 if (chunk.length > _buffer.length - _length) {
1170 add(new Uint8List.view(_buffer.buffer, 0, _length)); 1199 add(new Uint8List.view(_buffer.buffer, 0, _length));
1171 _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 1200 _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
1172 _length = 0; 1201 _length = 0;
1173 } 1202 }
1174 if (chunk.length > _OUTGOING_BUFFER_SIZE) { 1203 if (chunk.length > _OUTGOING_BUFFER_SIZE) {
1175 add(chunk); 1204 add(chunk);
1176 } else { 1205 } else {
1177 _buffer.setRange(_length, _length + chunk.length, chunk); 1206 _buffer.setRange(_length, _length + chunk.length, chunk);
1178 _length += chunk.length; 1207 _length += chunk.length;
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 const _RedirectInfo(this.statusCode, this.method, this.location); 2606 const _RedirectInfo(this.statusCode, this.method, this.location);
2578 } 2607 }
2579 2608
2580 String _getHttpVersion() { 2609 String _getHttpVersion() {
2581 var version = Platform.version; 2610 var version = Platform.version;
2582 // Only include major and minor version numbers. 2611 // Only include major and minor version numbers.
2583 int index = version.indexOf('.', version.indexOf('.') + 1); 2612 int index = version.indexOf('.', version.indexOf('.') + 1);
2584 version = version.substring(0, index); 2613 version = version.substring(0, index);
2585 return 'Dart/$version (dart:io)'; 2614 return 'Dart/$version (dart:io)';
2586 } 2615 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698