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

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

Issue 11410003: Refactoring of the HTTP library (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 years, 1 month 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
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_connection_close_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) 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 // Global constants. 5 // Global constants.
6 class _Const { 6 class _Const {
7 // Bytes for "HTTP". 7 // Bytes for "HTTP".
8 static const HTTP = const [72, 84, 84, 80]; 8 static const HTTP = const [72, 84, 84, 80];
9 // Bytes for "HTTP/1.". 9 // Bytes for "HTTP/1.".
10 static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46]; 10 static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46];
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 * HTTP parser which parses the HTTP stream as data is supplied 96 * HTTP parser which parses the HTTP stream as data is supplied
97 * through the [:writeList:] and [:connectionClosed:] methods. As the 97 * through the [:writeList:] and [:connectionClosed:] methods. As the
98 * data is parsed the following callbacks are called: 98 * data is parsed the following callbacks are called:
99 * 99 *
100 * [:requestStart:] 100 * [:requestStart:]
101 * [:responseStart:] 101 * [:responseStart:]
102 * [:headerReceived:] 102 * [:headerReceived:]
103 * [:headersComplete:] 103 * [:headersComplete:]
104 * [:dataReceived:] 104 * [:dataReceived:]
105 * [:dataEnd:] 105 * [:dataEnd:]
106 * [:closed:]
106 * [:error:] 107 * [:error:]
107 * 108 *
108 * If an HTTP parser error occours it is possible to get an exception 109 * If an HTTP parser error occours it is possible to get an exception
109 * thrown from the [:writeList:] and [:connectionClosed:] methods if 110 * thrown from the [:writeList:] and [:connectionClosed:] methods if
110 * the error callback is not set. 111 * the error callback is not set.
111 * 112 *
112 * The connection upgrades (e.g. switching from HTTP/1.1 to the 113 * The connection upgrades (e.g. switching from HTTP/1.1 to the
113 * WebSocket protocol) is handled in a special way. If connection 114 * WebSocket protocol) is handled in a special way. If connection
114 * upgrade is specified in the headers, then on the callback to 115 * upgrade is specified in the headers, then on the callback to
115 * [:headersComplete:] the [:upgrade:] property on the [:HttpParser:] 116 * [:headersComplete:] the [:upgrade:] property on the [:HttpParser:]
116 * object will be [:true:] indicating that from now on the protocol is 117 * object will be [:true:] indicating that from now on the protocol is
117 * not HTTP anymore and no more callbacks will happen, that is 118 * not HTTP anymore and no more callbacks will happen, that is
118 * [:dataReceived:] and [:dataEnd:] are not called in this case as 119 * [:dataReceived:] and [:dataEnd:] are not called in this case as
119 * there is no more HTTP data. After the upgrade the method 120 * there is no more HTTP data. After the upgrade the method
120 * [:readUnparsedData:] can be used to read any remaining bytes in the 121 * [:readUnparsedData:] can be used to read any remaining bytes in the
121 * HTTP parser which are part of the protocol the connection is 122 * HTTP parser which are part of the protocol the connection is
122 * upgrading to. These bytes cannot be processed by the HTTP parser 123 * upgrading to. These bytes cannot be processed by the HTTP parser
123 * and should be handled according to whatever protocol is being 124 * and should be handled according to whatever protocol is being
124 * upgraded to. 125 * upgraded to.
125 */ 126 */
126 class _HttpParser { 127 class _HttpParser {
127 _HttpParser() { 128 _HttpParser.requestParser() {
129 _requestParser = true;
130 _reset();
131 }
132 _HttpParser.responseParser() {
133 _requestParser = false;
128 _reset(); 134 _reset();
129 } 135 }
130 136
131 // From RFC 2616. 137 // From RFC 2616.
132 // generic-message = start-line 138 // generic-message = start-line
133 // *(message-header CRLF) 139 // *(message-header CRLF)
134 // CRLF 140 // CRLF
135 // [ message-body ] 141 // [ message-body ]
136 // start-line = Request-Line | Status-Line 142 // start-line = Request-Line | Status-Line
137 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF 143 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
(...skipping 20 matching lines...) Expand all
158 if (byte == _Const.HTTP[0]) { 164 if (byte == _Const.HTTP[0]) {
159 // Start parsing method or HTTP version. 165 // Start parsing method or HTTP version.
160 _httpVersionIndex = 1; 166 _httpVersionIndex = 1;
161 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; 167 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION;
162 } else { 168 } else {
163 // Start parsing method. 169 // Start parsing method.
164 if (!_isTokenChar(byte)) { 170 if (!_isTokenChar(byte)) {
165 throw new HttpParserException("Invalid request method"); 171 throw new HttpParserException("Invalid request method");
166 } 172 }
167 _method_or_status_code.addCharCode(byte); 173 _method_or_status_code.addCharCode(byte);
174 if (!_requestParser) {
175 throw new HttpParserException("Invalid response line");
176 }
168 _state = _State.REQUEST_LINE_METHOD; 177 _state = _State.REQUEST_LINE_METHOD;
169 } 178 }
170 break; 179 break;
171 180
172 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: 181 case _State.METHOD_OR_RESPONSE_HTTP_VERSION:
173 if (_httpVersionIndex < _Const.HTTP.length && 182 if (_httpVersionIndex < _Const.HTTP.length &&
174 byte == _Const.HTTP[_httpVersionIndex]) { 183 byte == _Const.HTTP[_httpVersionIndex]) {
175 // Continue parsing HTTP version. 184 // Continue parsing HTTP version.
176 _httpVersionIndex++; 185 _httpVersionIndex++;
177 } else if (_httpVersionIndex == _Const.HTTP.length && 186 } else if (_httpVersionIndex == _Const.HTTP.length &&
178 byte == _CharCode.SLASH) { 187 byte == _CharCode.SLASH) {
179 // HTTP/ parsed. As method is a token this cannot be a 188 // HTTP/ parsed. As method is a token this cannot be a
180 // method anymore. 189 // method anymore.
181 _httpVersionIndex++; 190 _httpVersionIndex++;
191 if (_requestParser) {
192 throw new HttpParserException("Invalid request line");
193 }
182 _state = _State.RESPONSE_HTTP_VERSION; 194 _state = _State.RESPONSE_HTTP_VERSION;
183 } else { 195 } else {
184 // Did not parse HTTP version. Expect method instead. 196 // Did not parse HTTP version. Expect method instead.
185 for (int i = 0; i < _httpVersionIndex; i++) { 197 for (int i = 0; i < _httpVersionIndex; i++) {
186 _method_or_status_code.addCharCode(_Const.HTTP[i]); 198 _method_or_status_code.addCharCode(_Const.HTTP[i]);
187 } 199 }
188 if (byte == _CharCode.SP) { 200 if (byte == _CharCode.SP) {
189 _state = _State.REQUEST_LINE_URI; 201 _state = _State.REQUEST_LINE_URI;
190 } else { 202 } else {
191 _method_or_status_code.addCharCode(byte); 203 _method_or_status_code.addCharCode(byte);
192 _httpVersion = _HttpVersion.UNDETERMINED; 204 _httpVersion = _HttpVersion.UNDETERMINED;
205 if (!_requestParser) {
206 throw new HttpParserException("Invalid response line");
207 }
193 _state = _State.REQUEST_LINE_METHOD; 208 _state = _State.REQUEST_LINE_METHOD;
194 } 209 }
195 } 210 }
196 break; 211 break;
197 212
198 case _State.RESPONSE_HTTP_VERSION: 213 case _State.RESPONSE_HTTP_VERSION:
199 if (_httpVersionIndex < _Const.HTTP1DOT.length) { 214 if (_httpVersionIndex < _Const.HTTP1DOT.length) {
200 // Continue parsing HTTP version. 215 // Continue parsing HTTP version.
201 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]); 216 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]);
202 _httpVersionIndex++; 217 _httpVersionIndex++;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 } 282 }
268 } else { 283 } else {
269 _expect(byte, _CharCode.CR); 284 _expect(byte, _CharCode.CR);
270 _state = _State.REQUEST_LINE_ENDING; 285 _state = _State.REQUEST_LINE_ENDING;
271 } 286 }
272 break; 287 break;
273 288
274 case _State.REQUEST_LINE_ENDING: 289 case _State.REQUEST_LINE_ENDING:
275 _expect(byte, _CharCode.LF); 290 _expect(byte, _CharCode.LF);
276 _messageType = _MessageType.REQUEST; 291 _messageType = _MessageType.REQUEST;
277 if (requestStart != null) { 292 requestStart(_method_or_status_code.toString(),
278 requestStart(_method_or_status_code.toString(), 293 _uri_or_reason_phrase.toString(),
279 _uri_or_reason_phrase.toString(), 294 version);
280 version);
281 }
282 _method_or_status_code.clear(); 295 _method_or_status_code.clear();
283 _uri_or_reason_phrase.clear(); 296 _uri_or_reason_phrase.clear();
284 _state = _State.HEADER_START; 297 _state = _State.HEADER_START;
285 break; 298 break;
286 299
287 case _State.RESPONSE_LINE_STATUS_CODE: 300 case _State.RESPONSE_LINE_STATUS_CODE:
288 if (byte == _CharCode.SP) { 301 if (byte == _CharCode.SP) {
289 if (_method_or_status_code.length != 3) { 302 if (_method_or_status_code.length != 3) {
290 throw new HttpParserException("Invalid response status code"); 303 throw new HttpParserException("Invalid response status code");
291 } 304 }
(...skipping 25 matching lines...) Expand all
317 _expect(byte, _CharCode.LF); 330 _expect(byte, _CharCode.LF);
318 _messageType == _MessageType.RESPONSE; 331 _messageType == _MessageType.RESPONSE;
319 int statusCode = parseInt(_method_or_status_code.toString()); 332 int statusCode = parseInt(_method_or_status_code.toString());
320 if (statusCode < 100 || statusCode > 599) { 333 if (statusCode < 100 || statusCode > 599) {
321 throw new HttpParserException("Invalid response status code"); 334 throw new HttpParserException("Invalid response status code");
322 } else { 335 } else {
323 // Check whether this response will never have a body. 336 // Check whether this response will never have a body.
324 _noMessageBody = 337 _noMessageBody =
325 statusCode <= 199 || statusCode == 204 || statusCode == 304; 338 statusCode <= 199 || statusCode == 204 || statusCode == 304;
326 } 339 }
327 if (responseStart != null) { 340 responseStart(statusCode,
328 responseStart(statusCode, 341 _uri_or_reason_phrase.toString(),
329 _uri_or_reason_phrase.toString(), 342 version);
330 version);
331 }
332 _method_or_status_code.clear(); 343 _method_or_status_code.clear();
333 _uri_or_reason_phrase.clear(); 344 _uri_or_reason_phrase.clear();
334 _state = _State.HEADER_START; 345 _state = _State.HEADER_START;
335 break; 346 break;
336 347
337 case _State.HEADER_START: 348 case _State.HEADER_START:
338 if (byte == _CharCode.CR) { 349 if (byte == _CharCode.CR) {
339 _state = _State.HEADER_ENDING; 350 _state = _State.HEADER_ENDING;
340 } else { 351 } else {
341 // Start of new header field. 352 // Start of new header field.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 List<String> tokens = _tokenizeFieldValue(headerValue); 404 List<String> tokens = _tokenizeFieldValue(headerValue);
394 for (int i = 0; i < tokens.length; i++) { 405 for (int i = 0; i < tokens.length; i++) {
395 String token = tokens[i].toLowerCase(); 406 String token = tokens[i].toLowerCase();
396 if (token == "keep-alive") { 407 if (token == "keep-alive") {
397 _persistentConnection = true; 408 _persistentConnection = true;
398 } else if (token == "close") { 409 } else if (token == "close") {
399 _persistentConnection = false; 410 _persistentConnection = false;
400 } else if (token == "upgrade") { 411 } else if (token == "upgrade") {
401 _connectionUpgrade = true; 412 _connectionUpgrade = true;
402 } 413 }
403 if (headerReceived != null) { 414 headerReceived(headerField, token);
404 headerReceived(headerField, token);
405 }
406 } 415 }
407 reportHeader = false; 416 reportHeader = false;
408 } else if (headerField == "transfer-encoding" && 417 } else if (headerField == "transfer-encoding" &&
409 headerValue.toLowerCase() == "chunked") { 418 headerValue.toLowerCase() == "chunked") {
410 // Ignore the Content-Length header if Transfer-Encoding 419 // Ignore the Content-Length header if Transfer-Encoding
411 // is chunked (RFC 2616 section 4.4) 420 // is chunked (RFC 2616 section 4.4)
412 _chunked = true; 421 _chunked = true;
413 _contentLength = -1; 422 _contentLength = -1;
414 } 423 }
415 if (reportHeader && headerReceived != null) { 424 if (reportHeader) {
416 headerReceived(headerField, headerValue); 425 headerReceived(headerField, headerValue);
417 } 426 }
418 _headerField.clear(); 427 _headerField.clear();
419 _headerValue.clear(); 428 _headerValue.clear();
420 429
421 if (byte == _CharCode.CR) { 430 if (byte == _CharCode.CR) {
422 _state = _State.HEADER_ENDING; 431 _state = _State.HEADER_ENDING;
423 } else { 432 } else {
424 // Start of new header field. 433 // Start of new header field.
425 _headerField.addCharCode(_toLowerCase(byte)); 434 _headerField.addCharCode(_toLowerCase(byte));
426 _state = _State.HEADER_FIELD; 435 _state = _State.HEADER_FIELD;
427 } 436 }
428 } 437 }
429 break; 438 break;
430 439
431 case _State.HEADER_ENDING: 440 case _State.HEADER_ENDING:
432 _expect(byte, _CharCode.LF); 441 _expect(byte, _CharCode.LF);
433 // If a request message has neither Content-Length nor 442 // If a request message has neither Content-Length nor
434 // Transfer-Encoding the message must not have a body (RFC 443 // Transfer-Encoding the message must not have a body (RFC
435 // 2616 section 4.3). 444 // 2616 section 4.3).
436 if (_messageType == _MessageType.REQUEST && 445 if (_messageType == _MessageType.REQUEST &&
437 _contentLength < 0 && 446 _contentLength < 0 &&
438 _chunked == false) { 447 _chunked == false) {
439 _contentLength = 0; 448 _contentLength = 0;
440 } 449 }
441 if (_connectionUpgrade) { 450 if (_connectionUpgrade) {
442 _state = _State.UPGRADED; 451 _state = _State.UPGRADED;
443 if (headersComplete != null) headersComplete(); 452 headersComplete();
444 } else { 453 } else {
445 if (headersComplete != null) headersComplete(); 454 headersComplete();
446 if (_chunked) { 455 if (_chunked) {
447 _state = _State.CHUNK_SIZE; 456 _state = _State.CHUNK_SIZE;
448 _remainingContent = 0; 457 _remainingContent = 0;
449 } else if (_contentLength == 0 || 458 } else if (_contentLength == 0 ||
450 (_messageType == _MessageType.RESPONSE && 459 (_messageType == _MessageType.RESPONSE &&
451 (_noMessageBody || _responseToMethod == "HEAD"))) { 460 (_noMessageBody || _responseToMethod == "HEAD"))) {
452 // If there is no message body get ready to process the 461 // If there is no message body get ready to process the
453 // next request. 462 // next request.
454 _bodyEnd(); 463 _bodyEnd();
455 _reset(); 464 _reset();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 List<int> data; 527 List<int> data;
519 if (_remainingContent == null || 528 if (_remainingContent == null ||
520 dataAvailable <= _remainingContent) { 529 dataAvailable <= _remainingContent) {
521 data = new Uint8List(dataAvailable); 530 data = new Uint8List(dataAvailable);
522 data.setRange(0, dataAvailable, _buffer, _index); 531 data.setRange(0, dataAvailable, _buffer, _index);
523 } else { 532 } else {
524 data = new Uint8List(_remainingContent); 533 data = new Uint8List(_remainingContent);
525 data.setRange(0, _remainingContent, _buffer, _index); 534 data.setRange(0, _remainingContent, _buffer, _index);
526 } 535 }
527 536
528 if (dataReceived != null) dataReceived(data); 537 dataReceived(data);
529 if (_remainingContent != null) { 538 if (_remainingContent != null) {
530 _remainingContent -= data.length; 539 _remainingContent -= data.length;
531 } 540 }
532 _index += data.length; 541 _index += data.length;
533 if (_remainingContent == 0) { 542 if (_remainingContent == 0) {
534 if (!_chunked) { 543 if (!_chunked) {
535 _bodyEnd(); 544 _bodyEnd();
536 _reset(); 545 _reset();
537 } else { 546 } else {
538 _state = _State.CHUNK_SIZE_STARTING_CR; 547 _state = _State.CHUNK_SIZE_STARTING_CR;
539 } 548 }
540 } 549 }
541 break; 550 break;
542 551
543 case _State.FAILURE: 552 case _State.FAILURE:
544 // Should be unreachable. 553 // Should be unreachable.
545 assert(false); 554 assert(false);
546 break; 555 break;
547 556
548 default: 557 default:
549 // Should be unreachable. 558 // Should be unreachable.
550 assert(false); 559 assert(false);
551 break; 560 break;
552 } 561 }
553 } 562 }
554 } catch (e) { 563 } catch (e) {
555 // Report the error through the error callback if any. Otherwise 564 _state = _State.FAILURE;
556 // throw the error. 565 error(e);
557 if (error != null) {
558 error(e);
559 _state = _State.FAILURE;
560 } else {
561 throw e;
562 }
563 } 566 }
564 567
565 // If all data is parsed or not needed due to failure there is no 568 // If all data is parsed or not needed due to failure there is no
566 // need to hold on to the buffer. 569 // need to hold on to the buffer.
567 if (_state != _State.UPGRADED) _releaseBuffer(); 570 if (_state != _State.UPGRADED) _releaseBuffer();
568 } 571 }
569 572
570 void writeList(List<int> buffer, int offset, int count) { 573 void streamData(List<int> buffer) {
571 assert(_buffer == null); 574 assert(_buffer == null);
572 _buffer = buffer; 575 _buffer = buffer;
573 _index = offset; 576 _index = 0;
574 _lastIndex = offset + count; 577 _lastIndex = buffer.length;
575 _parse(); 578 _parse();
576 } 579 }
577 580
578 void connectionClosed() { 581 void streamDone() {
582 // If the connection is idle the HTTP stream is closed.
583 if (_state == _State.START) {
584 if (_requestParser) {
585 closed();
586 } else {
587 error(
588 new HttpParserException(
589 "Connection closed before full header was received"));
590 }
591 return;
592 }
593
579 if (_state < _State.FIRST_BODY_STATE) { 594 if (_state < _State.FIRST_BODY_STATE) {
580 _state = _State.FAILURE; 595 _state = _State.FAILURE;
581 // Report the error through the error callback if any. Otherwise 596 // Report the error through the error callback if any. Otherwise
582 // throw the error. 597 // throw the error.
583 var e = new HttpParserException( 598 error(
584 "Connection closed before full header was received"); 599 new HttpParserException(
585 if (error != null) { 600 "Connection closed before full header was received"));
586 error(e); 601 return;
587 return;
588 }
589 throw e;
590 } 602 }
591 603
592 if (!_chunked && _contentLength == -1) { 604 if (!_chunked && _contentLength == -1) {
593 if (_state != _State.START) { 605 dataEnd(true);
594 if (dataEnd != null) dataEnd(true);
595 }
596 _state = _State.CLOSED; 606 _state = _State.CLOSED;
607 closed();
597 } else { 608 } else {
598 _state = _State.FAILURE; 609 _state = _State.FAILURE;
599 // Report the error through the error callback if any. Otherwise 610 // Report the error through the error callback if any. Otherwise
600 // throw the error. 611 // throw the error.
601 var e = new HttpParserException( 612 error(
602 "Connection closed before full body was received"); 613 new HttpParserException(
603 if (error != null) { 614 "Connection closed before full body was received"));
604 error(e);
605 return;
606 }
607 throw e;
608 } 615 }
609 } 616 }
610 617
618 void streamError(e) {
619 // Don't report errors when HTTP parser is in idle state. Clients
620 // can close the connection and cause a connection reset by peer
621 // error which is OK.
622 if (_state == _State.START) {
623 closed();
624 return;
625 }
626 error(e);
627 }
628
611 String get version { 629 String get version {
612 switch (_httpVersion) { 630 switch (_httpVersion) {
613 case _HttpVersion.HTTP10: 631 case _HttpVersion.HTTP10:
614 return "1.0"; 632 return "1.0";
615 case _HttpVersion.HTTP11: 633 case _HttpVersion.HTTP11:
616 return "1.1"; 634 return "1.1";
617 } 635 }
618 return null; 636 return null;
619 } 637 }
620 638
621 int get messageType => _messageType; 639 int get messageType => _messageType;
622 int get contentLength => _contentLength; 640 int get contentLength => _contentLength;
623 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; 641 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED;
624 bool get persistentConnection => _persistentConnection; 642 bool get persistentConnection => _persistentConnection;
625 643
626 void set responseToMethod(String method) { _responseToMethod = method; } 644 void set responseToMethod(String method) { _responseToMethod = method; }
627 645
628 bool get isIdle => _state == _State.START;
629
630 List<int> readUnparsedData() { 646 List<int> readUnparsedData() {
631 if (_buffer == null) return []; 647 if (_buffer == null) return [];
632 if (_index == _lastIndex) return []; 648 if (_index == _lastIndex) return [];
633 var result = _buffer.getRange(_index, _lastIndex - _index); 649 var result = _buffer.getRange(_index, _lastIndex - _index);
634 _releaseBuffer(); 650 _releaseBuffer();
635 return result; 651 return result;
636 } 652 }
637 653
638 void _bodyEnd() { 654 void _bodyEnd() {
639 if (dataEnd != null) { 655 dataEnd(_messageType == _MessageType.RESPONSE && !_persistentConnection);
640 dataEnd(_messageType == _MessageType.RESPONSE && !_persistentConnection);
641 }
642 } 656 }
643 657
644 _reset() { 658 _reset() {
645 _state = _State.START; 659 _state = _State.START;
646 _messageType = _MessageType.UNDETERMINED; 660 _messageType = _MessageType.UNDETERMINED;
647 _headerField = new StringBuffer(); 661 _headerField = new StringBuffer();
648 _headerValue = new StringBuffer(); 662 _headerValue = new StringBuffer();
649 _method_or_status_code = new StringBuffer(); 663 _method_or_status_code = new StringBuffer();
650 _uri_or_reason_phrase = new StringBuffer(); 664 _uri_or_reason_phrase = new StringBuffer();
651 665
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 } else { 724 } else {
711 throw new HttpParserException("Failed to parse HTTP"); 725 throw new HttpParserException("Failed to parse HTTP");
712 } 726 }
713 } 727 }
714 728
715 // The data that is currently being parsed. 729 // The data that is currently being parsed.
716 List<int> _buffer; 730 List<int> _buffer;
717 int _index; 731 int _index;
718 int _lastIndex; 732 int _lastIndex;
719 733
734 bool _requestParser;
720 int _state; 735 int _state;
721 int _httpVersionIndex; 736 int _httpVersionIndex;
722 int _messageType; 737 int _messageType;
723 StringBuffer _method_or_status_code; 738 StringBuffer _method_or_status_code;
724 StringBuffer _uri_or_reason_phrase; 739 StringBuffer _uri_or_reason_phrase;
725 StringBuffer _headerField; 740 StringBuffer _headerField;
726 StringBuffer _headerValue; 741 StringBuffer _headerValue;
727 742
728 int _httpVersion; 743 int _httpVersion;
729 int _contentLength; 744 int _contentLength;
730 bool _persistentConnection; 745 bool _persistentConnection;
731 bool _connectionUpgrade; 746 bool _connectionUpgrade;
732 bool _chunked; 747 bool _chunked;
733 748
734 bool _noMessageBody; 749 bool _noMessageBody;
735 String _responseToMethod; // Indicates the method used for the request. 750 String _responseToMethod; // Indicates the method used for the request.
736 int _remainingContent; 751 int _remainingContent;
737 752
738 // Callbacks. 753 // Callbacks.
739 Function requestStart; 754 Function requestStart;
740 Function responseStart; 755 Function responseStart;
741 Function headerReceived; 756 Function headerReceived;
742 Function headersComplete; 757 Function headersComplete;
743 Function dataReceived; 758 Function dataReceived;
744 Function dataEnd; 759 Function dataEnd;
745 Function error; 760 Function error;
761 Function closed;
746 } 762 }
747 763
748 764
749 class HttpParserException implements Exception { 765 class HttpParserException implements Exception {
750 const HttpParserException([String this.message = ""]); 766 const HttpParserException([String this.message = ""]);
751 String toString() => "HttpParserException: $message"; 767 String toString() => "HttpParserException: $message";
752 final String message; 768 final String message;
753 } 769 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_connection_close_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698