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

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

Issue 10008083: Add HTTP/1.0 support and simplify persistent connections handling (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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) 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 _HttpRequestResponseBase { 5 class _HttpRequestResponseBase {
6 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) 6 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection)
7 : _contentLength = -1, 7 : _contentLength = -1,
8 _keepAlive = false,
9 _headers = new Map(); 8 _headers = new Map();
10 9
11 int get contentLength() => _contentLength; 10 int get contentLength() => _contentLength;
12 bool get keepAlive() => _keepAlive;
13 Map get headers() => _headers; 11 Map get headers() => _headers;
14 12
15 void _setHeader(String name, String value) { 13 void _setHeader(String name, String value) {
16 _headers[name.toLowerCase()] = value; 14 _headers[name.toLowerCase()] = value;
17 } 15 }
18 16
19 bool _write(List<int> data, bool copyBuffer) { 17 bool _write(List<int> data, bool copyBuffer) {
20 bool allWritten = true; 18 bool allWritten = true;
21 if (data.length > 0) { 19 if (data.length > 0) {
22 if (_contentLength < 0) { 20 if (_contentLength < 0) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 return _httpConnection._write(SP); 96 return _httpConnection._write(SP);
99 } 97 }
100 98
101 _HttpConnectionBase _httpConnection; 99 _HttpConnectionBase _httpConnection;
102 Map<String, String> _headers; 100 Map<String, String> _headers;
103 101
104 // Length of the content body. If this is set to -1 (default value) 102 // Length of the content body. If this is set to -1 (default value)
105 // when starting to send data chunked transfer encoding will be 103 // when starting to send data chunked transfer encoding will be
106 // used. 104 // used.
107 int _contentLength; 105 int _contentLength;
108 bool _keepAlive;
109 } 106 }
110 107
111 108
112 // Parsed HTTP request providing information on the HTTP headers. 109 // Parsed HTTP request providing information on the HTTP headers.
113 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest { 110 class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest {
114 _HttpRequest(_HttpConnection connection) : super(connection); 111 _HttpRequest(_HttpConnection connection) : super(connection);
115 112
116 String get method() => _method; 113 String get method() => _method;
117 String get uri() => _uri; 114 String get uri() => _uri;
118 String get path() => _path; 115 String get path() => _path;
119 String get queryString() => _queryString; 116 String get queryString() => _queryString;
120 Map get queryParameters() => _queryParameters; 117 Map get queryParameters() => _queryParameters;
121 118
122 InputStream get inputStream() { 119 InputStream get inputStream() {
123 if (_inputStream == null) { 120 if (_inputStream == null) {
124 _inputStream = new _HttpInputStream(this); 121 _inputStream = new _HttpInputStream(this);
125 } 122 }
126 return _inputStream; 123 return _inputStream;
127 } 124 }
128 125
129 void _onRequestStart(String method, String uri) { 126 void _onRequestStart(String method, String uri, String version) {
130 _method = method; 127 _method = method;
131 _uri = uri; 128 _uri = uri;
132 _parseRequestUri(uri); 129 _parseRequestUri(uri);
133 } 130 }
134 131
135 void _onHeaderReceived(String name, String value) { 132 void _onHeaderReceived(String name, String value) {
136 _setHeader(name, value); 133 _setHeader(name, value);
137 } 134 }
138 135
139 void _onHeadersComplete() { 136 void _onHeadersComplete() {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 _HttpResponse(_HttpConnection httpConnection) 200 _HttpResponse(_HttpConnection httpConnection)
204 : super(httpConnection), 201 : super(httpConnection),
205 _statusCode = HttpStatus.OK, 202 _statusCode = HttpStatus.OK,
206 _state = START; 203 _state = START;
207 204
208 void set contentLength(int contentLength) { 205 void set contentLength(int contentLength) {
209 if (_outputStream != null) throw new HttpException("Header already sent"); 206 if (_outputStream != null) throw new HttpException("Header already sent");
210 _contentLength = contentLength; 207 _contentLength = contentLength;
211 } 208 }
212 209
213 void set keepAlive(bool keepAlive) {
214 if (_outputStream != null) throw new HttpException("Header already sent");
215 _keepAlive = keepAlive;
216 }
217
218 int get statusCode() => _statusCode; 210 int get statusCode() => _statusCode;
219 void set statusCode(int statusCode) { 211 void set statusCode(int statusCode) {
220 if (_outputStream != null) throw new HttpException("Header already sent"); 212 if (_outputStream != null) throw new HttpException("Header already sent");
221 _statusCode = statusCode; 213 _statusCode = statusCode;
222 } 214 }
223 215
224 String get reasonPhrase() => _findReasonPhrase(_statusCode); 216 String get reasonPhrase() => _findReasonPhrase(_statusCode);
225 void set reasonPhrase(String reasonPhrase) { 217 void set reasonPhrase(String reasonPhrase) {
226 if (_outputStream != null) throw new HttpException("Header already sent"); 218 if (_outputStream != null) throw new HttpException("Header already sent");
227 _reasonPhrase = reasonPhrase; 219 _reasonPhrase = reasonPhrase;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 case HttpStatus.HTTP_VERSION_NOT_SUPPORTED: 341 case HttpStatus.HTTP_VERSION_NOT_SUPPORTED:
350 return "Http Version not supported"; 342 return "Http Version not supported";
351 default: return "Status $statusCode"; 343 default: return "Status $statusCode";
352 } 344 }
353 } 345 }
354 346
355 bool _writeHeader() { 347 bool _writeHeader() {
356 List<int> data; 348 List<int> data;
357 349
358 // Write status line. 350 // Write status line.
359 _httpConnection._write(_Const.HTTP11); 351 if (_protocolVersion == "1.1") {
352 _httpConnection._write(_Const.HTTP11);
353 } else {
354 _httpConnection._write(_Const.HTTP10);
355 }
360 _writeSP(); 356 _writeSP();
361 data = _statusCode.toString().charCodes(); 357 data = _statusCode.toString().charCodes();
362 _httpConnection._write(data); 358 _httpConnection._write(data);
363 _writeSP(); 359 _writeSP();
364 data = reasonPhrase.charCodes(); 360 data = reasonPhrase.charCodes();
365 _httpConnection._write(data); 361 _httpConnection._write(data);
366 _writeCRLF(); 362 _writeCRLF();
367 363
368 // Determine the value of the "Connection" header 364 // Determine the value of the "Connection" header.
369 // based on the keep alive state. 365 if (_protocolVersion == "1.1" && !_persistentConnection) {
370 setHeader("Connection", keepAlive ? "keep-alive" : "close"); 366 setHeader("Connection", "close");
367 } else if (_protocolVersion == "1.0" && _persistentConnection) {
368 setHeader("Connection", "keep-alive");
369 }
371 // Determine the value of the "Transfer-Encoding" header based on 370 // Determine the value of the "Transfer-Encoding" header based on
372 // whether the content length is known. 371 // whether the content length is known.
373 if (_contentLength >= 0) { 372 if (_contentLength >= 0) {
374 setHeader("Content-Length", _contentLength.toString()); 373 setHeader("Content-Length", _contentLength.toString());
375 } else { 374 } else {
376 setHeader("Transfer-Encoding", "chunked"); 375 setHeader("Transfer-Encoding", "chunked");
377 } 376 }
378 377
379 // Write headers. 378 // Write headers.
380 bool allWritten = _writeHeaders(); 379 bool allWritten = _writeHeaders();
381 _state = HEADERS_SENT; 380 _state = HEADERS_SENT;
382 return allWritten; 381 return allWritten;
383 } 382 }
384 383
385 // Response status code. 384 // Response status code.
386 int _statusCode; 385 int _statusCode;
387 String _reasonPhrase; 386 String _reasonPhrase;
387 String _protocolVersion;
388 Date _expires; 388 Date _expires;
389 bool _persistentConnection;
389 _HttpOutputStream _outputStream; 390 _HttpOutputStream _outputStream;
390 int _state; 391 int _state;
391 Function _streamErrorHandler; 392 Function _streamErrorHandler;
392 } 393 }
393 394
394 395
395 class _HttpInputStream extends _BaseDataInputStream implements InputStream { 396 class _HttpInputStream extends _BaseDataInputStream implements InputStream {
396 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) { 397 _HttpInputStream(_HttpRequestResponseBase this._requestOrResponse) {
397 _checkScheduleCallbacks(); 398 _checkScheduleCallbacks();
398 } 399 }
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 547
547 Queue _sendBuffers; 548 Queue _sendBuffers;
548 } 549 }
549 550
550 551
551 // HTTP server connection over a socket. 552 // HTTP server connection over a socket.
552 class _HttpConnection extends _HttpConnectionBase { 553 class _HttpConnection extends _HttpConnectionBase {
553 _HttpConnection(HttpServer this._server) { 554 _HttpConnection(HttpServer this._server) {
554 // Register HTTP parser callbacks. 555 // Register HTTP parser callbacks.
555 _httpParser.requestStart = 556 _httpParser.requestStart =
556 (method, uri) => _onRequestStart(method, uri); 557 (method, uri, version) => _onRequestStart(method, uri, version);
557 _httpParser.responseStart = 558 _httpParser.responseStart =
558 (statusCode, reasonPhrase) => 559 (statusCode, reasonPhrase, version) =>
559 _onResponseStart(statusCode, reasonPhrase); 560 _onResponseStart(statusCode, reasonPhrase, version);
560 _httpParser.headerReceived = 561 _httpParser.headerReceived =
561 (name, value) => _onHeaderReceived(name, value); 562 (name, value) => _onHeaderReceived(name, value);
562 _httpParser.headersComplete = () => _onHeadersComplete(); 563 _httpParser.headersComplete = () => _onHeadersComplete();
563 _httpParser.dataReceived = (data) => _onDataReceived(data); 564 _httpParser.dataReceived = (data) => _onDataReceived(data);
564 _httpParser.dataEnd = (close) => _onDataEnd(close); 565 _httpParser.dataEnd = (close) => _onDataEnd(close);
565 _httpParser.error = (e) => _onError(e); 566 _httpParser.error = (e) => _onError(e);
566 } 567 }
567 568
568 void _onConnectionClosed(Exception e) { 569 void _onConnectionClosed(Exception e) {
569 if (e != null && onError != null) { 570 if (e != null && onError != null) {
(...skipping 17 matching lines...) Expand all
587 return; 588 return;
588 } 589 }
589 590
590 // Processing a request. 591 // Processing a request.
591 if (e == null) { 592 if (e == null) {
592 // Indicate connection close to the HTTP parser. 593 // Indicate connection close to the HTTP parser.
593 _httpParser.connectionClosed(); 594 _httpParser.connectionClosed();
594 } 595 }
595 } 596 }
596 597
597 void _onRequestStart(String method, String uri) { 598 void _onRequestStart(String method, String uri, String version) {
598 // Create new request and response objects for this request. 599 // Create new request and response objects for this request.
599 _request = new _HttpRequest(this); 600 _request = new _HttpRequest(this);
600 _response = new _HttpResponse(this); 601 _response = new _HttpResponse(this);
601 _request._onRequestStart(method, uri); 602 _request._onRequestStart(method, uri, version);
603 _response._protocolVersion = version;
602 } 604 }
603 605
604 void _onResponseStart(int statusCode, String reasonPhrase) { 606 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
605 // TODO(sgjesse): Error handling. 607 // TODO(sgjesse): Error handling.
606 } 608 }
607 609
608 void _onHeaderReceived(String name, String value) { 610 void _onHeaderReceived(String name, String value) {
609 _request._onHeaderReceived(name, value); 611 _request._onHeaderReceived(name, value);
610 } 612 }
611 613
612 void _onHeadersComplete() { 614 void _onHeadersComplete() {
613 _request._onHeadersComplete(); 615 _request._onHeadersComplete();
614 _response.keepAlive = _httpParser.keepAlive; 616 _response._persistentConnection = _httpParser.persistentConnection;
615 if (onRequestReceived != null) { 617 if (onRequestReceived != null) {
616 onRequestReceived(_request, _response); 618 onRequestReceived(_request, _response);
617 } 619 }
618 } 620 }
619 621
620 void _onDataReceived(List<int> data) { 622 void _onDataReceived(List<int> data) {
621 _request._onDataReceived(data); 623 _request._onDataReceived(data);
622 } 624 }
623 625
624 void _onDataEnd(bool close) { 626 void _onDataEnd(bool close) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 : super(connection), 725 : super(connection),
724 _state = START { 726 _state = START {
725 _connection = connection; 727 _connection = connection;
726 // Default GET requests to have no content. 728 // Default GET requests to have no content.
727 if (_method == "GET") { 729 if (_method == "GET") {
728 _contentLength = 0; 730 _contentLength = 0;
729 } 731 }
730 } 732 }
731 733
732 void set contentLength(int contentLength) => _contentLength = contentLength; 734 void set contentLength(int contentLength) => _contentLength = contentLength;
733 void set keepAlive(bool keepAlive) => _keepAlive = keepAlive;
734 735
735 String get host() => _host; 736 String get host() => _host;
736 void set host(String host) { 737 void set host(String host) {
737 _host = host; 738 _host = host;
738 _updateHostHeader(); 739 _updateHostHeader();
739 } 740 }
740 741
741 int get port() => _port; 742 int get port() => _port;
742 void set port(int port) { 743 void set port(int port) {
743 _port = port; 744 _port = port;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 // Write request line. 820 // Write request line.
820 data = _method.toString().charCodes(); 821 data = _method.toString().charCodes();
821 _httpConnection._write(data); 822 _httpConnection._write(data);
822 _writeSP(); 823 _writeSP();
823 data = _uri.toString().charCodes(); 824 data = _uri.toString().charCodes();
824 _httpConnection._write(data); 825 _httpConnection._write(data);
825 _writeSP(); 826 _writeSP();
826 _httpConnection._write(_Const.HTTP11); 827 _httpConnection._write(_Const.HTTP11);
827 _writeCRLF(); 828 _writeCRLF();
828 829
829 // Determine the value of the "Connection" header
830 // based on the keep alive state.
831 setHeader("Connection", keepAlive ? "keep-alive" : "close");
832 // Determine the value of the "Transfer-Encoding" header based on 830 // Determine the value of the "Transfer-Encoding" header based on
833 // whether the content length is known. 831 // whether the content length is known.
834 if (_contentLength >= 0) { 832 if (_contentLength >= 0) {
835 setHeader("Content-Length", _contentLength.toString()); 833 setHeader("Content-Length", _contentLength.toString());
836 } else { 834 } else {
837 setHeader("Transfer-Encoding", "chunked"); 835 setHeader("Transfer-Encoding", "chunked");
838 } 836 }
839 837
840 // Write headers. 838 // Write headers.
841 _writeHeaders(); 839 _writeHeaders();
(...skipping 29 matching lines...) Expand all
871 869
872 Map get headers() => _headers; 870 Map get headers() => _headers;
873 871
874 InputStream get inputStream() { 872 InputStream get inputStream() {
875 if (_inputStream == null) { 873 if (_inputStream == null) {
876 _inputStream = new _HttpInputStream(this); 874 _inputStream = new _HttpInputStream(this);
877 } 875 }
878 return _inputStream; 876 return _inputStream;
879 } 877 }
880 878
881 void _onRequestStart(String method, String uri) { 879 void _onRequestStart(String method, String uri, String version) {
882 // TODO(sgjesse): Error handling 880 // TODO(sgjesse): Error handling
883 } 881 }
884 882
885 void _onResponseStart(int statusCode, String reasonPhrase) { 883 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
886 _statusCode = statusCode; 884 _statusCode = statusCode;
887 _reasonPhrase = reasonPhrase; 885 _reasonPhrase = reasonPhrase;
888 } 886 }
889 887
890 void _onHeaderReceived(String name, String value) { 888 void _onHeaderReceived(String name, String value) {
891 _setHeader(name, value); 889 _setHeader(name, value);
892 } 890 }
893 891
894 void _onHeadersComplete() { 892 void _onHeadersComplete() {
895 _buffer = new _BufferList(); 893 _buffer = new _BufferList();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 937
940 class _HttpClientConnection 938 class _HttpClientConnection
941 extends _HttpConnectionBase implements HttpClientConnection { 939 extends _HttpConnectionBase implements HttpClientConnection {
942 _HttpClientConnection(_HttpClient this._client); 940 _HttpClientConnection(_HttpClient this._client);
943 941
944 void _connectionEstablished(_SocketConnection socketConn) { 942 void _connectionEstablished(_SocketConnection socketConn) {
945 super._connectionEstablished(socketConn._socket); 943 super._connectionEstablished(socketConn._socket);
946 _socketConn = socketConn; 944 _socketConn = socketConn;
947 // Register HTTP parser callbacks. 945 // Register HTTP parser callbacks.
948 _httpParser.requestStart = 946 _httpParser.requestStart =
949 (method, uri) => _onRequestStart(method, uri); 947 (method, uri, version) => _onRequestStart(method, uri, version);
950 _httpParser.responseStart = 948 _httpParser.responseStart =
951 (statusCode, reasonPhrase) => 949 (statusCode, reasonPhrase, version) =>
952 _onResponseStart(statusCode, reasonPhrase); 950 _onResponseStart(statusCode, reasonPhrase, version);
953 _httpParser.headerReceived = 951 _httpParser.headerReceived =
954 (name, value) => _onHeaderReceived(name, value); 952 (name, value) => _onHeaderReceived(name, value);
955 _httpParser.headersComplete = () => _onHeadersComplete(); 953 _httpParser.headersComplete = () => _onHeadersComplete();
956 _httpParser.dataReceived = (data) => _onDataReceived(data); 954 _httpParser.dataReceived = (data) => _onDataReceived(data);
957 _httpParser.dataEnd = (closed) => _onDataEnd(closed); 955 _httpParser.dataEnd = (closed) => _onDataEnd(closed);
958 _httpParser.error = (e) => _onError(e); 956 _httpParser.error = (e) => _onError(e);
959 // Tell the HTTP parser the method it is expecting a response to. 957 // Tell the HTTP parser the method it is expecting a response to.
960 _httpParser.responseToMethod = _method; 958 _httpParser.responseToMethod = _method;
961 } 959 }
962 960
963 void _responseDone() { 961 void _responseDone() {
964 if (_closing) { 962 if (_closing) {
965 if (_socket != null) { 963 if (_socket != null) {
966 _socket.close(); 964 _socket.close();
967 } 965 }
968 } else { 966 } else {
969 _client._returnSocketConnection(_socketConn); 967 _client._returnSocketConnection(_socketConn);
970 } 968 }
971 _socket = null; 969 _socket = null;
972 _socketConn = null; 970 _socketConn = null;
973 } 971 }
974 972
975 HttpClientRequest open(String method, String uri) { 973 HttpClientRequest open(String method, String uri) {
976 _method = method; 974 _method = method;
977 _request = new _HttpClientRequest(method, uri, this); 975 _request = new _HttpClientRequest(method, uri, this);
978 _request.keepAlive = true;
979 _response = new _HttpClientResponse(this); 976 _response = new _HttpClientResponse(this);
980 return _request; 977 return _request;
981 } 978 }
982 979
983 void _onConnectionClosed(Exception e) { 980 void _onConnectionClosed(Exception e) {
984 // Socket is closed either due to an error or due to normal socket close. 981 // Socket is closed either due to an error or due to normal socket close.
985 if (e != null) { 982 if (e != null) {
986 if (_onErrorCallback != null) { 983 if (_onErrorCallback != null) {
987 _onErrorCallback(e); 984 _onErrorCallback(e);
988 } 985 }
989 } 986 }
990 _closing = true; 987 _closing = true;
991 if (e != null) { 988 if (e != null) {
992 // Propagate the error to the streams. 989 // Propagate the error to the streams.
993 if (_response != null && _response._streamErrorHandler != null) { 990 if (_response != null && _response._streamErrorHandler != null) {
994 _response._streamErrorHandler(e); 991 _response._streamErrorHandler(e);
995 } 992 }
996 _responseDone(); 993 _responseDone();
997 } else { 994 } else {
998 // If there was no socket error the socket was closed 995 // If there was no socket error the socket was closed
999 // normally. Indicate closing to the HTTP Parser as there might 996 // normally. Indicate closing to the HTTP Parser as there might
1000 // still be an HTTP error. 997 // still be an HTTP error.
1001 _httpParser.connectionClosed(); 998 _httpParser.connectionClosed();
1002 } 999 }
1003 } 1000 }
1004 1001
1005 void _onRequestStart(String method, String uri) { 1002 void _onRequestStart(String method, String uri, String version) {
1006 // TODO(sgjesse): Error handling. 1003 // TODO(sgjesse): Error handling.
1007 } 1004 }
1008 1005
1009 void _onResponseStart(int statusCode, String reasonPhrase) { 1006 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
1010 _response._onResponseStart(statusCode, reasonPhrase); 1007 _response._onResponseStart(statusCode, reasonPhrase, version);
1011 } 1008 }
1012 1009
1013 void _onHeaderReceived(String name, String value) { 1010 void _onHeaderReceived(String name, String value) {
1014 _response._onHeaderReceived(name, value); 1011 _response._onHeaderReceived(name, value);
1015 } 1012 }
1016 1013
1017 void _onHeadersComplete() { 1014 void _onHeadersComplete() {
1018 _response._onHeadersComplete(); 1015 _response._onHeadersComplete();
1019 } 1016 }
1020 1017
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 sockets.addFirst(socketConn); 1243 sockets.addFirst(socketConn);
1247 socketConn._markReturned(); 1244 socketConn._markReturned();
1248 } 1245 }
1249 1246
1250 Function _onOpen; 1247 Function _onOpen;
1251 Map<String, Queue<_SocketConnection>> _openSockets; 1248 Map<String, Queue<_SocketConnection>> _openSockets;
1252 Set<_SocketConnection> _activeSockets; 1249 Set<_SocketConnection> _activeSockets;
1253 Timer _evictionTimer; 1250 Timer _evictionTimer;
1254 bool _shutdown; // Has this HTTP client been shutdown? 1251 bool _shutdown; // Has this HTTP client been shutdown?
1255 } 1252 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698