Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 // 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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 | 327 |
| 328 void _parse() { | 328 void _parse() { |
| 329 try { | 329 try { |
| 330 _doParse(); | 330 _doParse(); |
| 331 } catch (e, s) { | 331 } catch (e, s) { |
| 332 _state = _State.FAILURE; | 332 _state = _State.FAILURE; |
| 333 _reportError(e, s); | 333 _reportError(e, s); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 | 336 |
| 337 // Process end of headers. Returns true if the parser should stop | |
| 338 // parsing and return. This will be in case of either an upgrade | |
| 339 // request or a request or response with an empty body. | |
| 340 bool _headersEnd() { | |
|
Søren Gjesse
2015/04/09 10:53:28
This is a copy of the inlined code removed below w
| |
| 341 _headers._mutable = false; | |
| 342 | |
| 343 _transferLength = _headers.contentLength; | |
| 344 // Ignore the Content-Length header if Transfer-Encoding | |
| 345 // is chunked (RFC 2616 section 4.4) | |
| 346 if (_chunked) _transferLength = -1; | |
| 347 | |
| 348 // If a request message has neither Content-Length nor | |
| 349 // Transfer-Encoding the message must not have a body (RFC | |
| 350 // 2616 section 4.3). | |
| 351 if (_messageType == _MessageType.REQUEST && | |
| 352 _transferLength < 0 && | |
| 353 _chunked == false) { | |
| 354 _transferLength = 0; | |
| 355 } | |
| 356 if (_connectionUpgrade) { | |
| 357 _state = _State.UPGRADED; | |
| 358 _transferLength = 0; | |
| 359 } | |
| 360 _createIncoming(_transferLength); | |
| 361 if (_requestParser) { | |
| 362 _incoming.method = | |
| 363 new String.fromCharCodes(_method); | |
| 364 _incoming.uri = | |
| 365 Uri.parse( | |
| 366 new String.fromCharCodes(_uri_or_reason_phrase)); | |
| 367 } else { | |
| 368 _incoming.statusCode = _statusCode; | |
| 369 _incoming.reasonPhrase = | |
| 370 new String.fromCharCodes(_uri_or_reason_phrase); | |
| 371 } | |
| 372 _method.clear(); | |
| 373 _uri_or_reason_phrase.clear(); | |
| 374 if (_connectionUpgrade) { | |
| 375 _incoming.upgraded = true; | |
| 376 _parserCalled = false; | |
| 377 var tmp = _incoming; | |
| 378 _closeIncoming(); | |
| 379 _controller.add(tmp); | |
| 380 return true; | |
| 381 } | |
| 382 if (_transferLength == 0 || | |
| 383 (_messageType == _MessageType.RESPONSE && _noMessageBody)) { | |
| 384 _reset(); | |
| 385 var tmp = _incoming; | |
| 386 _closeIncoming(); | |
| 387 _controller.add(tmp); | |
| 388 return false; | |
| 389 } else if (_chunked) { | |
| 390 _state = _State.CHUNK_SIZE; | |
| 391 _remainingContent = 0; | |
| 392 } else if (_transferLength > 0) { | |
| 393 _remainingContent = _transferLength; | |
| 394 _state = _State.BODY; | |
| 395 } else { | |
| 396 // Neither chunked nor content length. End of body | |
| 397 // indicated by close. | |
| 398 _state = _State.BODY; | |
| 399 } | |
| 400 _parserCalled = false; | |
| 401 _controller.add(_incoming); | |
| 402 return true; | |
| 403 } | |
| 404 | |
| 337 // From RFC 2616. | 405 // From RFC 2616. |
| 338 // generic-message = start-line | 406 // generic-message = start-line |
| 339 // *(message-header CRLF) | 407 // *(message-header CRLF) |
| 340 // CRLF | 408 // CRLF |
| 341 // [ message-body ] | 409 // [ message-body ] |
| 342 // start-line = Request-Line | Status-Line | 410 // start-line = Request-Line | Status-Line |
| 343 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF | 411 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF |
| 344 // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF | 412 // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF |
| 345 // message-header = field-name ":" [ field-value ] | 413 // message-header = field-name ":" [ field-value ] |
| 346 void _doParse() { | 414 void _doParse() { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 _httpVersionIndex++; | 548 _httpVersionIndex++; |
| 481 } else if (byte == _CharCode.ZERO) { | 549 } else if (byte == _CharCode.ZERO) { |
| 482 // HTTP/1.0 parsed. | 550 // HTTP/1.0 parsed. |
| 483 _httpVersion = _HttpVersion.HTTP10; | 551 _httpVersion = _HttpVersion.HTTP10; |
| 484 _persistentConnection = false; | 552 _persistentConnection = false; |
| 485 _httpVersionIndex++; | 553 _httpVersionIndex++; |
| 486 } else { | 554 } else { |
| 487 throw new HttpException("Invalid response line"); | 555 throw new HttpException("Invalid response line"); |
| 488 } | 556 } |
| 489 } else { | 557 } else { |
| 490 _expect(byte, _CharCode.CR); | 558 if (byte == _CharCode.CR) { |
| 491 _state = _State.REQUEST_LINE_ENDING; | 559 _state = _State.REQUEST_LINE_ENDING; |
| 560 } else { | |
| 561 _expect(byte, _CharCode.LF); | |
| 562 _messageType = _MessageType.REQUEST; | |
| 563 _state = _State.HEADER_START; | |
| 564 } | |
| 492 } | 565 } |
| 493 break; | 566 break; |
| 494 | 567 |
| 495 case _State.REQUEST_LINE_ENDING: | 568 case _State.REQUEST_LINE_ENDING: |
| 496 _expect(byte, _CharCode.LF); | 569 _expect(byte, _CharCode.LF); |
| 497 _messageType = _MessageType.REQUEST; | 570 _messageType = _MessageType.REQUEST; |
| 498 _state = _State.HEADER_START; | 571 _state = _State.HEADER_START; |
| 499 break; | 572 break; |
| 500 | 573 |
| 501 case _State.RESPONSE_LINE_STATUS_CODE: | 574 case _State.RESPONSE_LINE_STATUS_CODE: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 _noMessageBody = true; | 611 _noMessageBody = true; |
| 539 } | 612 } |
| 540 } | 613 } |
| 541 _state = _State.HEADER_START; | 614 _state = _State.HEADER_START; |
| 542 break; | 615 break; |
| 543 | 616 |
| 544 case _State.HEADER_START: | 617 case _State.HEADER_START: |
| 545 _headers = new _HttpHeaders(version); | 618 _headers = new _HttpHeaders(version); |
| 546 if (byte == _CharCode.CR) { | 619 if (byte == _CharCode.CR) { |
| 547 _state = _State.HEADER_ENDING; | 620 _state = _State.HEADER_ENDING; |
| 621 } else if (byte == _CharCode.LF) { | |
| 622 if (_headersEnd()) { | |
| 623 return; | |
| 624 } else { | |
| 625 break; | |
| 626 } | |
| 548 } else { | 627 } else { |
| 549 // Start of new header field. | 628 // Start of new header field. |
| 550 _headerField.add(_toLowerCaseByte(byte)); | 629 _headerField.add(_toLowerCaseByte(byte)); |
| 551 _state = _State.HEADER_FIELD; | 630 _state = _State.HEADER_FIELD; |
| 552 } | 631 } |
| 553 break; | 632 break; |
| 554 | 633 |
| 555 case _State.HEADER_FIELD: | 634 case _State.HEADER_FIELD: |
| 556 if (byte == _CharCode.COLON) { | 635 if (byte == _CharCode.COLON) { |
| 557 _state = _State.HEADER_VALUE_START; | 636 _state = _State.HEADER_VALUE_START; |
| 558 } else { | 637 } else { |
| 559 if (!_isTokenChar(byte)) { | 638 if (!_isTokenChar(byte)) { |
| 560 throw new HttpException("Invalid header field name"); | 639 throw new HttpException("Invalid header field name"); |
| 561 } | 640 } |
| 562 _headerField.add(_toLowerCaseByte(byte)); | 641 _headerField.add(_toLowerCaseByte(byte)); |
| 563 } | 642 } |
| 564 break; | 643 break; |
| 565 | 644 |
| 566 case _State.HEADER_VALUE_START: | 645 case _State.HEADER_VALUE_START: |
| 567 if (byte == _CharCode.CR) { | 646 if (byte == _CharCode.CR) { |
| 568 _state = _State.HEADER_VALUE_FOLDING_OR_ENDING; | 647 _state = _State.HEADER_VALUE_FOLDING_OR_ENDING; |
| 648 } else if (byte == _CharCode.LF) { | |
| 649 _state = _State.HEADER_VALUE_FOLD_OR_END; | |
| 569 } else if (byte != _CharCode.SP && byte != _CharCode.HT) { | 650 } else if (byte != _CharCode.SP && byte != _CharCode.HT) { |
| 570 // Start of new header value. | 651 // Start of new header value. |
| 571 _headerValue.add(byte); | 652 _headerValue.add(byte); |
| 572 _state = _State.HEADER_VALUE; | 653 _state = _State.HEADER_VALUE; |
| 573 } | 654 } |
| 574 break; | 655 break; |
| 575 | 656 |
| 576 case _State.HEADER_VALUE: | 657 case _State.HEADER_VALUE: |
| 577 if (byte == _CharCode.CR) { | 658 if (byte == _CharCode.CR) { |
| 578 _state = _State.HEADER_VALUE_FOLDING_OR_ENDING; | 659 _state = _State.HEADER_VALUE_FOLDING_OR_ENDING; |
| 660 } else if (byte == _CharCode.LF) { | |
| 661 _state = _State.HEADER_VALUE_FOLD_OR_END; | |
| 579 } else { | 662 } else { |
| 580 _headerValue.add(byte); | 663 _headerValue.add(byte); |
| 581 } | 664 } |
| 582 break; | 665 break; |
| 583 | 666 |
| 584 case _State.HEADER_VALUE_FOLDING_OR_ENDING: | 667 case _State.HEADER_VALUE_FOLDING_OR_ENDING: |
| 585 _expect(byte, _CharCode.LF); | 668 _expect(byte, _CharCode.LF); |
| 586 _state = _State.HEADER_VALUE_FOLD_OR_END; | 669 _state = _State.HEADER_VALUE_FOLD_OR_END; |
| 587 break; | 670 break; |
| 588 | 671 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 606 _headers._add(headerField, tokens[i]); | 689 _headers._add(headerField, tokens[i]); |
| 607 } | 690 } |
| 608 } else { | 691 } else { |
| 609 _headers._add(headerField, headerValue); | 692 _headers._add(headerField, headerValue); |
| 610 } | 693 } |
| 611 _headerField.clear(); | 694 _headerField.clear(); |
| 612 _headerValue.clear(); | 695 _headerValue.clear(); |
| 613 | 696 |
| 614 if (byte == _CharCode.CR) { | 697 if (byte == _CharCode.CR) { |
| 615 _state = _State.HEADER_ENDING; | 698 _state = _State.HEADER_ENDING; |
| 699 } else if (byte == _CharCode.LF) { | |
| 700 if (_headersEnd()) { | |
| 701 return; | |
| 702 } else { | |
| 703 break; | |
| 704 } | |
| 616 } else { | 705 } else { |
| 617 // Start of new header field. | 706 // Start of new header field. |
| 618 _headerField.add(_toLowerCaseByte(byte)); | 707 _headerField.add(_toLowerCaseByte(byte)); |
| 619 _state = _State.HEADER_FIELD; | 708 _state = _State.HEADER_FIELD; |
| 620 } | 709 } |
| 621 } | 710 } |
| 622 break; | 711 break; |
| 623 | 712 |
| 624 case _State.HEADER_ENDING: | 713 case _State.HEADER_ENDING: |
| 625 _expect(byte, _CharCode.LF); | 714 _expect(byte, _CharCode.LF); |
| 626 _headers._mutable = false; | 715 if (_headersEnd()) { |
| 627 | 716 return; |
| 628 _transferLength = _headers.contentLength; | 717 } else { |
| 629 // Ignore the Content-Length header if Transfer-Encoding | 718 break; |
| 630 // is chunked (RFC 2616 section 4.4) | |
| 631 if (_chunked) _transferLength = -1; | |
| 632 | |
| 633 // If a request message has neither Content-Length nor | |
| 634 // Transfer-Encoding the message must not have a body (RFC | |
| 635 // 2616 section 4.3). | |
| 636 if (_messageType == _MessageType.REQUEST && | |
| 637 _transferLength < 0 && | |
| 638 _chunked == false) { | |
| 639 _transferLength = 0; | |
| 640 } | 719 } |
| 641 if (_connectionUpgrade) { | |
| 642 _state = _State.UPGRADED; | |
| 643 _transferLength = 0; | |
| 644 } | |
| 645 _createIncoming(_transferLength); | |
| 646 if (_requestParser) { | |
| 647 _incoming.method = | |
| 648 new String.fromCharCodes(_method); | |
| 649 _incoming.uri = | |
| 650 Uri.parse( | |
| 651 new String.fromCharCodes(_uri_or_reason_phrase)); | |
| 652 } else { | |
| 653 _incoming.statusCode = _statusCode; | |
| 654 _incoming.reasonPhrase = | |
| 655 new String.fromCharCodes(_uri_or_reason_phrase); | |
| 656 } | |
| 657 _method.clear(); | |
| 658 _uri_or_reason_phrase.clear(); | |
| 659 if (_connectionUpgrade) { | |
| 660 _incoming.upgraded = true; | |
| 661 _parserCalled = false; | |
| 662 var tmp = _incoming; | |
| 663 _closeIncoming(); | |
| 664 _controller.add(tmp); | |
| 665 return; | |
| 666 } | |
| 667 if (_transferLength == 0 || | |
| 668 (_messageType == _MessageType.RESPONSE && _noMessageBody)) { | |
| 669 _reset(); | |
| 670 var tmp = _incoming; | |
| 671 _closeIncoming(); | |
| 672 _controller.add(tmp); | |
| 673 break; | |
| 674 } else if (_chunked) { | |
| 675 _state = _State.CHUNK_SIZE; | |
| 676 _remainingContent = 0; | |
| 677 } else if (_transferLength > 0) { | |
| 678 _remainingContent = _transferLength; | |
| 679 _state = _State.BODY; | |
| 680 } else { | |
| 681 // Neither chunked nor content length. End of body | |
| 682 // indicated by close. | |
| 683 _state = _State.BODY; | |
| 684 } | |
| 685 _parserCalled = false; | |
| 686 _controller.add(_incoming); | |
| 687 return; | 720 return; |
| 688 | 721 |
| 689 case _State.CHUNK_SIZE_STARTING_CR: | 722 case _State.CHUNK_SIZE_STARTING_CR: |
| 690 _expect(byte, _CharCode.CR); | 723 _expect(byte, _CharCode.CR); |
| 691 _state = _State.CHUNK_SIZE_STARTING_LF; | 724 _state = _State.CHUNK_SIZE_STARTING_LF; |
| 692 break; | 725 break; |
| 693 | 726 |
| 694 case _State.CHUNK_SIZE_STARTING_LF: | 727 case _State.CHUNK_SIZE_STARTING_LF: |
| 695 _expect(byte, _CharCode.LF); | 728 _expect(byte, _CharCode.LF); |
| 696 _state = _State.CHUNK_SIZE; | 729 _state = _State.CHUNK_SIZE; |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 } | 1068 } |
| 1036 } | 1069 } |
| 1037 | 1070 |
| 1038 void _reportError(error, [stackTrace]) { | 1071 void _reportError(error, [stackTrace]) { |
| 1039 if (_socketSubscription != null) _socketSubscription.cancel(); | 1072 if (_socketSubscription != null) _socketSubscription.cancel(); |
| 1040 _state = _State.FAILURE; | 1073 _state = _State.FAILURE; |
| 1041 _controller.addError(error, stackTrace); | 1074 _controller.addError(error, stackTrace); |
| 1042 _controller.close(); | 1075 _controller.close(); |
| 1043 } | 1076 } |
| 1044 } | 1077 } |
| OLD | NEW |