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

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

Issue 2618523005: Make HTTP headers use a growing buffer, not a fixed-size 8K one. (Closed)
Patch Set: Remove error message and tests expecting it. Created 3 years, 11 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
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | tests/standalone/io/http_client_request_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 typedef void _BytesConsumer(List<int> bytes); 9 typedef void _BytesConsumer(List<int> bytes);
10 10
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 if (_deadlineTimer != null) _deadlineTimer.cancel(); 567 if (_deadlineTimer != null) _deadlineTimer.cancel();
568 _deadline = d; 568 _deadline = d;
569 569
570 if (_deadline == null) return; 570 if (_deadline == null) return;
571 _deadlineTimer = new Timer(_deadline, () { 571 _deadlineTimer = new Timer(_deadline, () {
572 _httpRequest._httpConnection.destroy(); 572 _httpRequest._httpConnection.destroy();
573 }); 573 });
574 } 574 }
575 575
576 void _writeHeader() { 576 void _writeHeader() {
577 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 577 BytesBuilder buffer = new _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
578 int offset = 0;
579
580 void write(List<int> bytes) {
581 int len = bytes.length;
582 for (int i = 0; i < len; i++) {
583 buffer[offset + i] = bytes[i];
584 }
585 offset += len;
586 }
587 578
588 // Write status line. 579 // Write status line.
589 if (headers.protocolVersion == "1.1") { 580 if (headers.protocolVersion == "1.1") {
590 write(_Const.HTTP11); 581 buffer.add(_Const.HTTP11);
591 } else { 582 } else {
592 write(_Const.HTTP10); 583 buffer.add(_Const.HTTP10);
593 } 584 }
594 buffer[offset++] = _CharCode.SP; 585 buffer.addByte(_CharCode.SP);
595 write(statusCode.toString().codeUnits); 586 buffer.add(statusCode.toString().codeUnits);
596 buffer[offset++] = _CharCode.SP; 587 buffer.addByte(_CharCode.SP);
597 write(reasonPhrase.codeUnits); 588 buffer.add(reasonPhrase.codeUnits);
598 buffer[offset++] = _CharCode.CR; 589 buffer.addByte(_CharCode.CR);
599 buffer[offset++] = _CharCode.LF; 590 buffer.addByte(_CharCode.LF);
600 591
601 var session = _httpRequest._session; 592 var session = _httpRequest._session;
602 if (session != null && !session._destroyed) { 593 if (session != null && !session._destroyed) {
603 // Mark as not new. 594 // Mark as not new.
604 session._isNew = false; 595 session._isNew = false;
605 // Make sure we only send the current session id. 596 // Make sure we only send the current session id.
606 bool found = false; 597 bool found = false;
607 for (int i = 0; i < cookies.length; i++) { 598 for (int i = 0; i < cookies.length; i++) {
608 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) { 599 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
609 cookies[i] 600 cookies[i]
(...skipping 13 matching lines...) Expand all
623 // Add all the cookies set to the headers. 614 // Add all the cookies set to the headers.
624 if (_cookies != null) { 615 if (_cookies != null) {
625 _cookies.forEach((cookie) { 616 _cookies.forEach((cookie) {
626 headers.add(HttpHeaders.SET_COOKIE, cookie); 617 headers.add(HttpHeaders.SET_COOKIE, cookie);
627 }); 618 });
628 } 619 }
629 620
630 headers._finalize(); 621 headers._finalize();
631 622
632 // Write headers. 623 // Write headers.
633 offset = headers._write(buffer, offset); 624 headers._build(buffer);
634 buffer[offset++] = _CharCode.CR; 625 buffer.addByte(_CharCode.CR);
635 buffer[offset++] = _CharCode.LF; 626 buffer.addByte(_CharCode.LF);
636 _outgoing.setHeader(buffer, offset); 627 Uint8List headerBytes = buffer.takeBytes();
628 _outgoing.setHeader(headerBytes, headerBytes.length);
637 } 629 }
638 630
639 String _findReasonPhrase(int statusCode) { 631 String _findReasonPhrase(int statusCode) {
640 if (_reasonPhrase != null) { 632 if (_reasonPhrase != null) {
641 return _reasonPhrase; 633 return _reasonPhrase;
642 } 634 }
643 635
644 switch (statusCode) { 636 switch (statusCode) {
645 case HttpStatus.CONTINUE: return "Continue"; 637 case HttpStatus.CONTINUE: return "Continue";
646 case HttpStatus.SWITCHING_PROTOCOLS: return "Switching Protocols"; 638 case HttpStatus.SWITCHING_PROTOCOLS: return "Switching Protocols";
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 if (_httpClientConnection._proxyTunnel) { 806 if (_httpClientConnection._proxyTunnel) {
815 return uriStartingFromPath(); 807 return uriStartingFromPath();
816 } else { 808 } else {
817 return uri.removeFragment().toString(); 809 return uri.removeFragment().toString();
818 } 810 }
819 } 811 }
820 } 812 }
821 } 813 }
822 814
823 void _writeHeader() { 815 void _writeHeader() {
824 Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 816 BytesBuilder buffer = new _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
825 int offset = 0;
826
827 void write(List<int> bytes) {
828 int len = bytes.length;
829 for (int i = 0; i < len; i++) {
830 buffer[offset + i] = bytes[i];
831 }
832 offset += len;
833 }
834 817
835 // Write the request method. 818 // Write the request method.
836 write(method.codeUnits); 819 buffer.add(method.codeUnits);
837 buffer[offset++] = _CharCode.SP; 820 buffer.addByte(_CharCode.SP);
838 // Write the request URI. 821 // Write the request URI.
839 write(_requestUri().codeUnits); 822 buffer.add(_requestUri().codeUnits);
840 buffer[offset++] = _CharCode.SP; 823 buffer.addByte(_CharCode.SP);
841 // Write HTTP/1.1. 824 // Write HTTP/1.1.
842 write(_Const.HTTP11); 825 buffer.add(_Const.HTTP11);
843 buffer[offset++] = _CharCode.CR; 826 buffer.addByte(_CharCode.CR);
844 buffer[offset++] = _CharCode.LF; 827 buffer.addByte(_CharCode.LF);
845 828
846 // Add the cookies to the headers. 829 // Add the cookies to the headers.
847 if (!cookies.isEmpty) { 830 if (!cookies.isEmpty) {
848 StringBuffer sb = new StringBuffer(); 831 StringBuffer sb = new StringBuffer();
849 for (int i = 0; i < cookies.length; i++) { 832 for (int i = 0; i < cookies.length; i++) {
850 if (i > 0) sb.write("; "); 833 if (i > 0) sb.write("; ");
851 sb..write(cookies[i].name)..write("=")..write(cookies[i].value); 834 sb..write(cookies[i].name)..write("=")..write(cookies[i].value);
852 } 835 }
853 headers.add(HttpHeaders.COOKIE, sb.toString()); 836 headers.add(HttpHeaders.COOKIE, sb.toString());
854 } 837 }
855 838
856 headers._finalize(); 839 headers._finalize();
857 840
858 // Write headers. 841 // Write headers.
859 offset = headers._write(buffer, offset); 842 headers._build(buffer);
860 buffer[offset++] = _CharCode.CR; 843 buffer.addByte(_CharCode.CR);
861 buffer[offset++] = _CharCode.LF; 844 buffer.addByte(_CharCode.LF);
862 _outgoing.setHeader(buffer, offset); 845 Uint8List headerBytes = buffer.takeBytes();
846 _outgoing.setHeader(headerBytes, headerBytes.length);
863 } 847 }
864 } 848 }
865 849
866 // Used by _HttpOutgoing as a target of a chunked converter for gzip 850 // Used by _HttpOutgoing as a target of a chunked converter for gzip
867 // compression. 851 // compression.
868 class _HttpGZipSink extends ByteConversionSink { 852 class _HttpGZipSink extends ByteConversionSink {
869 final _BytesConsumer _consume; 853 final _BytesConsumer _consume;
870 _HttpGZipSink(this._consume); 854 _HttpGZipSink(this._consume);
871 855
872 void add(List<int> chunk) { 856 void add(List<int> chunk) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 912
929 bool _socketError = false; 913 bool _socketError = false;
930 914
931 _HttpOutboundMessage outbound; 915 _HttpOutboundMessage outbound;
932 916
933 _HttpOutgoing(this.socket); 917 _HttpOutgoing(this.socket);
934 918
935 // Returns either a future or 'null', if it was able to write headers 919 // Returns either a future or 'null', if it was able to write headers
936 // immediately. 920 // immediately.
937 Future writeHeaders({bool drainRequest: true, bool setOutgoing: true}) { 921 Future writeHeaders({bool drainRequest: true, bool setOutgoing: true}) {
938 Future write() {
939 try {
940 outbound._writeHeader();
941 } catch (_) {
942 // Headers too large.
943 return new Future.error(new HttpException(
944 "Headers size exceeded the of '$_OUTGOING_BUFFER_SIZE'"
945 " bytes"));
946 }
947 return null;
948 }
949
950 if (headersWritten) return null; 922 if (headersWritten) return null;
951 headersWritten = true; 923 headersWritten = true;
952 Future drainFuture; 924 Future drainFuture;
953 bool gzip = false; 925 bool gzip = false;
954 if (outbound is _HttpResponse) { 926 if (outbound is _HttpResponse) {
955 // Server side. 927 // Server side.
956 _HttpResponse response = outbound; 928 _HttpResponse response = outbound;
957 if (response._httpRequest._httpServer.autoCompress && 929 if (response._httpRequest._httpServer.autoCompress &&
958 outbound.bufferOutput && 930 outbound.bufferOutput &&
959 outbound.headers.chunkedTransferEncoding) { 931 outbound.headers.chunkedTransferEncoding) {
960 List acceptEncodings = 932 List acceptEncodings =
961 response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING]; 933 response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
962 List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING]; 934 List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING];
963 if (acceptEncodings != null && 935 if (acceptEncodings != null &&
964 acceptEncodings 936 acceptEncodings
965 .expand((list) => list.split(",")) 937 .expand((list) => list.split(","))
966 .any((encoding) => encoding.trim().toLowerCase() == "gzip") && 938 .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
967 contentEncoding == null) { 939 contentEncoding == null) {
968 outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip"); 940 outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
969 gzip = true; 941 gzip = true;
970 } 942 }
971 } 943 }
972 if (drainRequest && !response._httpRequest._incoming.hasSubscriber) { 944 if (drainRequest && !response._httpRequest._incoming.hasSubscriber) {
973 drainFuture = response._httpRequest.drain().catchError((_) {}); 945 drainFuture = response._httpRequest.drain().catchError((_) {});
974 } 946 }
975 } else { 947 } else {
976 drainRequest = false; 948 drainRequest = false;
977 } 949 }
978 if (ignoreBody) { 950 if (!ignoreBody) {
979 return write(); 951 if (setOutgoing) {
980 } 952 int contentLength = outbound.headers.contentLength;
981 if (setOutgoing) { 953 if (outbound.headers.chunkedTransferEncoding) {
982 int contentLength = outbound.headers.contentLength; 954 chunked = true;
983 if (outbound.headers.chunkedTransferEncoding) { 955 if (gzip) this.gzip = true;
984 chunked = true; 956 } else if (contentLength >= 0) {
985 if (gzip) this.gzip = true; 957 this.contentLength = contentLength;
986 } else if (contentLength >= 0) { 958 }
987 this.contentLength = contentLength; 959 }
960 if (drainFuture != null) {
961 return drainFuture.then((_) => outbound._writeHeader());
988 } 962 }
989 } 963 }
990 if (drainFuture != null) { 964 outbound._writeHeader();
991 return drainFuture.then((_) => write()); 965 return null;
992 }
993 return write();
994 } 966 }
995 967
996 968
997 Future addStream(Stream<List<int>> stream) { 969 Future addStream(Stream<List<int>> stream) {
998 if (_socketError) { 970 if (_socketError) {
999 stream.listen(null).cancel(); 971 stream.listen(null).cancel();
1000 return new Future.value(outbound); 972 return new Future.value(outbound);
1001 } 973 }
1002 if (ignoreBody) { 974 if (ignoreBody) {
1003 stream.drain().catchError((_) {}); 975 stream.drain().catchError((_) {});
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 if (future != null) { 1125 if (future != null) {
1154 return _closeFuture = future.whenComplete(finalize); 1126 return _closeFuture = future.whenComplete(finalize);
1155 } 1127 }
1156 return _closeFuture = finalize(); 1128 return _closeFuture = finalize();
1157 } 1129 }
1158 1130
1159 Future<Socket> get done => _doneCompleter.future; 1131 Future<Socket> get done => _doneCompleter.future;
1160 1132
1161 void setHeader(List<int> data, int length) { 1133 void setHeader(List<int> data, int length) {
1162 assert(_length == 0); 1134 assert(_length == 0);
1163 assert(data.length == _OUTGOING_BUFFER_SIZE);
1164 _buffer = data; 1135 _buffer = data;
1165 _length = length; 1136 _length = length;
1166 } 1137 }
1167 1138
1168 void set gzip(bool value) { 1139 void set gzip(bool value) {
1169 _gzip = value; 1140 _gzip = value;
1170 if (_gzip) { 1141 if (_gzip) {
1171 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE); 1142 _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
1172 assert(_gzipSink == null); 1143 assert(_gzipSink == null);
1173 _gzipSink = new ZLibEncoder(gzip: true) 1144 _gzipSink = new ZLibEncoder(gzip: true)
(...skipping 1717 matching lines...) Expand 10 before | Expand all | Expand 10 after
2891 const _RedirectInfo(this.statusCode, this.method, this.location); 2862 const _RedirectInfo(this.statusCode, this.method, this.location);
2892 } 2863 }
2893 2864
2894 String _getHttpVersion() { 2865 String _getHttpVersion() {
2895 var version = Platform.version; 2866 var version = Platform.version;
2896 // Only include major and minor version numbers. 2867 // Only include major and minor version numbers.
2897 int index = version.indexOf('.', version.indexOf('.') + 1); 2868 int index = version.indexOf('.', version.indexOf('.') + 1);
2898 version = version.substring(0, index); 2869 version = version.substring(0, index);
2899 return 'Dart/$version (dart:io)'; 2870 return 'Dart/$version (dart:io)';
2900 } 2871 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | tests/standalone/io/http_client_request_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698