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

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

Issue 11783034: Re-implement support for client redirects. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2_io/dart
Patch Set: Review fixes Created 7 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_basic_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 part of dart.io; 5 part of dart.io;
6 6
7 // Global constants. 7 // Global constants.
8 class _Const { 8 class _Const {
9 // Bytes for "HTTP". 9 // Bytes for "HTTP".
10 static const HTTP = const [72, 84, 84, 80]; 10 static const HTTP = const [72, 84, 84, 80];
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 // 2616 section 4.3). 443 // 2616 section 4.3).
444 if (_messageType == _MessageType.REQUEST && 444 if (_messageType == _MessageType.REQUEST &&
445 _contentLength < 0 && 445 _contentLength < 0 &&
446 _chunked == false) { 446 _chunked == false) {
447 _contentLength = 0; 447 _contentLength = 0;
448 } 448 }
449 if (_connectionUpgrade) { 449 if (_connectionUpgrade) {
450 _state = _State.UPGRADED; 450 _state = _State.UPGRADED;
451 } 451 }
452 _createIncomingConnection(); 452 _createIncomingConnection();
453 _incomingConnection.headers = _headers;
454 _incomingConnection.contentLength = _contentLength;
455 if (_requestParser) { 453 if (_requestParser) {
456 _incomingConnection.method = 454 _incomingConnection.method =
457 new String.fromCharCodes(_method_or_status_code); 455 new String.fromCharCodes(_method_or_status_code);
458 _incomingConnection.uri = 456 _incomingConnection.uri =
459 new Uri.fromString( 457 new Uri.fromString(
460 new String.fromCharCodes(_uri_or_reason_phrase)); 458 new String.fromCharCodes(_uri_or_reason_phrase));
461 } else { 459 } else {
462 _incomingConnection.statusCode = _statusCode; 460 _incomingConnection.statusCode = _statusCode;
463 _incomingConnection.reasonPhrase = 461 _incomingConnection.reasonPhrase =
464 new String.fromCharCodes(_uri_or_reason_phrase); 462 new String.fromCharCodes(_uri_or_reason_phrase);
465 } 463 }
466 _method_or_status_code.clear(); 464 _method_or_status_code.clear();
467 _uri_or_reason_phrase.clear(); 465 _uri_or_reason_phrase.clear();
468 if (_connectionUpgrade) { 466 if (_connectionUpgrade) {
469 _incomingConnection.upgraded = true; 467 _incomingConnection.upgraded = true;
470 add(_incomingConnection); 468 add(_incomingConnection);
471 return; 469 break;
472 } 470 }
473 if (_chunked) { 471 if (_chunked) {
474 _state = _State.CHUNK_SIZE; 472 _state = _State.CHUNK_SIZE;
475 _remainingContent = 0; 473 _remainingContent = 0;
476 } else if (_contentLength == 0 || 474 } else if (_contentLength == 0 ||
477 (_messageType == _MessageType.RESPONSE && 475 (_messageType == _MessageType.RESPONSE &&
478 (_noMessageBody || _responseToMethod == "HEAD"))) { 476 (_noMessageBody || _responseToMethod == "HEAD"))) {
479 _state = _State.DONE; 477 _state = _State.DONE;
480 add(_incomingConnection); 478 add(_incomingConnection);
481 _incomingConnection.close(); 479 _closeIncomingConnection();
482 _incomingConnection = null;
483 break; 480 break;
484 } else if (_contentLength > 0) { 481 } else if (_contentLength > 0) {
485 _remainingContent = _contentLength; 482 _remainingContent = _contentLength;
486 _state = _State.BODY; 483 _state = _State.BODY;
487 } else { 484 } else {
488 // Neither chunked nor content length. End of body 485 // Neither chunked nor content length. End of body
489 // indicated by close. 486 // indicated by close.
490 _state = _State.BODY; 487 _state = _State.BODY;
491 } 488 }
492 add(_incomingConnection); 489 add(_incomingConnection);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 break; 526 break;
530 527
531 case _State.CHUNKED_BODY_DONE_CR: 528 case _State.CHUNKED_BODY_DONE_CR:
532 _expect(byte, _CharCode.CR); 529 _expect(byte, _CharCode.CR);
533 _state = _State.CHUNKED_BODY_DONE_LF; 530 _state = _State.CHUNKED_BODY_DONE_LF;
534 break; 531 break;
535 532
536 case _State.CHUNKED_BODY_DONE_LF: 533 case _State.CHUNKED_BODY_DONE_LF:
537 _expect(byte, _CharCode.LF); 534 _expect(byte, _CharCode.LF);
538 _state = _State.DONE; 535 _state = _State.DONE;
539 _incomingConnection.close(); 536 _closeIncomingConnection();
540 _incomingConnection = null;
541 break; 537 break;
542 538
543 case _State.BODY: 539 case _State.BODY:
544 // The body is not handled one byte at a time but in blocks. 540 // The body is not handled one byte at a time but in blocks.
545 _index--; 541 _index--;
546 int dataAvailable = _lastIndex - _index; 542 int dataAvailable = _lastIndex - _index;
547 List<int> data; 543 List<int> data;
548 if (_remainingContent == null || 544 if (_remainingContent == null ||
549 dataAvailable <= _remainingContent) { 545 dataAvailable <= _remainingContent) {
550 data = new Uint8List(dataAvailable); 546 data = new Uint8List(dataAvailable);
551 data.setRange(0, dataAvailable, _buffer, _index); 547 data.setRange(0, dataAvailable, _buffer, _index);
552 } else { 548 } else {
553 data = new Uint8List(_remainingContent); 549 data = new Uint8List(_remainingContent);
554 data.setRange(0, _remainingContent, _buffer, _index); 550 data.setRange(0, _remainingContent, _buffer, _index);
555 } 551 }
556 552
557 _incomingConnection.add(data); 553 _incomingConnection.add(data);
558 if (_remainingContent != null) { 554 if (_remainingContent != null) {
559 _remainingContent -= data.length; 555 _remainingContent -= data.length;
560 } 556 }
561 _index += data.length; 557 _index += data.length;
562 if (_remainingContent == 0) { 558 if (_remainingContent == 0) {
563 if (!_chunked) { 559 if (!_chunked) {
564 _state = _State.DONE; 560 _state = _State.DONE;
565 _incomingConnection.close(); 561 _closeIncomingConnection();
566 _incomingConnection = null;
567 } else { 562 } else {
568 _state = _State.CHUNK_SIZE_STARTING_CR; 563 _state = _State.CHUNK_SIZE_STARTING_CR;
569 } 564 }
570 } 565 }
571 break; 566 break;
572 567
573 case _State.FAILURE: 568 case _State.FAILURE:
574 // Should be unreachable. 569 // Should be unreachable.
575 assert(false); 570 assert(false);
576 break; 571 break;
(...skipping 22 matching lines...) Expand all
599 _parse(); 594 _parse();
600 } 595 }
601 596
602 void _onDone() { 597 void _onDone() {
603 if (_state == _State.CLOSED || _state == _State.FAILURE) return; 598 if (_state == _State.CLOSED || _state == _State.FAILURE) return;
604 599
605 if (_incomingConnection != null) { 600 if (_incomingConnection != null) {
606 // Redirect to _parseObject, if present. 601 // Redirect to _parseObject, if present.
607 if (_state != _State.DONE && 602 if (_state != _State.DONE &&
608 _state != _State.UPGRADED && 603 _state != _State.UPGRADED &&
604 !(_state == _State.START && !_requestParser) &&
609 !(_state == _State.BODY && !_chunked && _contentLength == -1)) { 605 !(_state == _State.BODY && !_chunked && _contentLength == -1)) {
610 _incomingConnection.signalError( 606 _incomingConnection.signalError(
611 new AsyncError( 607 new AsyncError(
612 new HttpParserException( 608 new HttpParserException(
613 "Connection closed while receiving data"))); 609 "Connection closed while receiving data")));
614 } 610 }
615 _incomingConnection.close(); 611 _closeIncomingConnection();
616 _incomingConnection = null;
617 close(); 612 close();
618 return; 613 return;
619 } 614 }
620 // If the connection is idle the HTTP stream is closed. 615 // If the connection is idle the HTTP stream is closed.
621 if (_state == _State.START) { 616 if (_state == _State.START) {
622 if (!_requestParser) { 617 if (!_requestParser) {
623 error( 618 error(
624 new AsyncError( 619 new AsyncError(
625 new HttpParserException( 620 new HttpParserException(
626 "Connection closed before full header was received"))); 621 "Connection closed before full header was received")));
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 return byte - 0x41 + 10; // A - F 769 return byte - 0x41 + 10; // A - F
775 } else if (0x61 <= byte && byte <= 0x66) { 770 } else if (0x61 <= byte && byte <= 0x66) {
776 return byte - 0x61 + 10; // a - f 771 return byte - 0x61 + 10; // a - f
777 } else { 772 } else {
778 throw new HttpParserException("Failed to parse HTTP"); 773 throw new HttpParserException("Failed to parse HTTP");
779 } 774 }
780 } 775 }
781 776
782 void _createIncomingConnection() { 777 void _createIncomingConnection() {
783 assert(_incomingConnection == null); 778 assert(_incomingConnection == null);
784 _incomingConnection = new _HttpIncomingConnection(_pauseData, _resumeData); 779 _incomingConnection = new _HttpIncomingConnection(_headers,
780 _pauseData,
781 _resumeData);
785 _incomingConnection.messageHandled.then(() { 782 _incomingConnection.messageHandled.then(() {
786 _paused = false;
787 _reset(); 783 _reset();
784 // Use _resumeData to ensure we start with the current chunk, and not
785 // accepting any more, unless we have an empty buffer.
786 _resumeData();
788 }); 787 });
789 } 788 }
790 789
790 void _closeIncomingConnection() {
791 assert(_incomingConnection != null);
792 var tmp = _incomingConnection;
793 _incomingConnection = null;
794 tmp.close();
795 }
796
791 void _pauseData() { 797 void _pauseData() {
792 if (_pauseCompleter == null) { 798 if (_pauseCompleter == null) {
793 _pauseCompleter = new SignalCompleter(); 799 _pauseCompleter = new SignalCompleter();
794 _subscription.pause(_pauseCompleter.signal); 800 _subscription.pause(_pauseCompleter.signal);
795 } 801 }
796 _paused = true; 802 _paused = true;
797 } 803 }
798 804
799 void _resumeData() { 805 void _resumeData() {
800 _paused = false; 806 _paused = false;
801 if (_buffer != null) { 807 if (_buffer != null) {
802 _parse(); 808 _parse();
803 if (_paused) return; 809 if (_paused) return;
804 } 810 }
805 _pauseCompleter.complete(); 811 if (_pauseCompleter != null) {
806 _pauseCompleter = null; 812 _pauseCompleter.complete();
813 _pauseCompleter = null;
814 }
807 } 815 }
808 816
809 void error(error) { 817 void error(error) {
810 _subscription.cancel(); 818 _subscription.cancel();
811 _state = _State.FAILURE; 819 _state = _State.FAILURE;
812 signalError(error); 820 signalError(error);
813 close(); 821 close();
814 } 822 }
815 823
816 // The data that is currently being parsed. 824 // The data that is currently being parsed.
(...skipping 29 matching lines...) Expand all
846 bool _paused = false; 854 bool _paused = false;
847 SignalCompleter _pauseCompleter; 855 SignalCompleter _pauseCompleter;
848 } 856 }
849 857
850 858
851 class HttpParserException implements Exception { 859 class HttpParserException implements Exception {
852 const HttpParserException([String this.message = ""]); 860 const HttpParserException([String this.message = ""]);
853 String toString() => "HttpParserException: $message"; 861 String toString() => "HttpParserException: $message";
854 final String message; 862 final String message;
855 } 863 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_impl.dart ('k') | tests/standalone/io/http_basic_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698