Overview
Comment: | OFHTTPClient: Support for sending chunked body |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
aac504a7bcea53ce5c069997aaa53413 |
User & Date: | js on 2020-03-25 21:26:09 |
Other Links: | manifest | tags |
Context
2020-03-28
| ||
14:35 | OFHTTPServer: Support for chunked request bodies check-in: 8faade8d19 user: js tags: trunk | |
2020-03-25
| ||
21:26 | OFHTTPClient: Support for sending chunked body check-in: aac504a7bc user: js tags: trunk | |
2020-03-23
| ||
01:03 | of_dns_record_type_parse(): Allow ALL check-in: 103f04241c user: js tags: trunk | |
Changes
Modified src/OFHTTPClient.m from [36ad6829ee] to [6a00e9f50f].
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | - (void)closeAndReconnect; @end @interface OFHTTPClientRequestBodyStream: OFStream <OFReadyForWritingObserving> { OFHTTPClientRequestHandler *_handler; OFTCPSocket *_socket; uintmax_t _toWrite; bool _atEndOfStream; } - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler socket: (OFTCPSocket *)sock; @end | > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | - (void)closeAndReconnect; @end @interface OFHTTPClientRequestBodyStream: OFStream <OFReadyForWritingObserving> { OFHTTPClientRequestHandler *_handler; OFTCPSocket *_socket; bool _chunked; uintmax_t _toWrite; bool _atEndOfStream; } - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler socket: (OFTCPSocket *)sock; @end |
︙ | ︙ | |||
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | - (OFString *)stream: (OFStream *)stream didWriteString: (OFString *)string encoding: (of_string_encoding_t)encoding bytesWritten: (size_t)bytesWritten exception: (id)exception { if (exception != nil) { if ([exception isKindOfClass: [OFWriteFailedException class]] && ([exception errNo] == ECONNRESET || [exception errNo] == EPIPE)) { /* In case a keep-alive connection timed out */ [self closeAndReconnect]; return nil; } [self raiseException: exception]; return nil; } _firstLine = true; | > > > > > > > | | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | - (OFString *)stream: (OFStream *)stream didWriteString: (OFString *)string encoding: (of_string_encoding_t)encoding bytesWritten: (size_t)bytesWritten exception: (id)exception { OFDictionary OF_GENERIC(OFString *, OFString *) *headers; OFString *transferEncoding; if (exception != nil) { if ([exception isKindOfClass: [OFWriteFailedException class]] && ([exception errNo] == ECONNRESET || [exception errNo] == EPIPE)) { /* In case a keep-alive connection timed out */ [self closeAndReconnect]; return nil; } [self raiseException: exception]; return nil; } _firstLine = true; headers = _request.headers; transferEncoding = [headers objectForKey: @"Transfer-Encoding"]; if ([transferEncoding isEqual: @"chunked"] || [headers objectForKey: @"Content-Length"] != nil) { stream.delegate = nil; OFStream *requestBody = [[[OFHTTPClientRequestBodyStream alloc] initWithHandler: self socket: (OFTCPSocket *)stream] autorelease]; if ([_client->_delegate respondsToSelector: |
︙ | ︙ | |||
700 701 702 703 704 705 706 | socket: (OFTCPSocket *)sock { self = [super init]; @try { OFDictionary OF_GENERIC(OFString *, OFString *) *headers; intmax_t contentLength; | | > > > | > | > | | | | | < | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | socket: (OFTCPSocket *)sock { self = [super init]; @try { OFDictionary OF_GENERIC(OFString *, OFString *) *headers; intmax_t contentLength; OFString *transferEncoding, *contentLengthString; _handler = [handler retain]; _socket = [sock retain]; headers = _handler->_request.headers; transferEncoding = [headers objectForKey: @"Transfer-Encoding"]; _chunked = [transferEncoding isEqual: @"chunked"]; contentLengthString = [headers objectForKey: @"Content-Length"]; if (contentLengthString != nil) { if (_chunked) @throw [OFInvalidArgumentException exception]; contentLength = contentLengthString.decimalValue; if (contentLength < 0) @throw [OFOutOfRangeException exception]; _toWrite = contentLength; } else if (!_chunked) @throw [OFInvalidArgumentException exception]; } @catch (id e) { [self release]; @throw e; } return self; |
︙ | ︙ | |||
746 747 748 749 750 751 752 753 754 755 756 757 758 759 | { size_t requestedLength = length; size_t ret; if (_socket == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: requestedLength bytesWritten: 0 errNo: 0]; | > > > > > > > > > > | > | | | > | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | { size_t requestedLength = length; size_t ret; if (_socket == nil) @throw [OFNotOpenException exceptionWithObject: self]; /* * We must not send a chunk of size 0, as that would end the body. We * always ignore writing 0 bytes to still allow writing 0 bytes after * the end of stream. */ if (length == 0) return 0; if (_atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: requestedLength bytesWritten: 0 errNo: 0]; if (_chunked) [_socket writeFormat: @"%zX\r\n", length]; else if (length > _toWrite) length = (size_t)_toWrite; ret = [_socket writeBuffer: buffer length: length]; if (ret > length) @throw [OFOutOfRangeException exception]; if (!_chunked) { _toWrite -= ret; if (_toWrite == 0) _atEndOfStream = true; } if (requestedLength > length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: requestedLength bytesWritten: ret errNo: 0]; |
︙ | ︙ | |||
787 788 789 790 791 792 793 | } - (void)close { if (_socket == nil) @throw [OFNotOpenException exceptionWithObject: self]; | > > | | 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | } - (void)close { if (_socket == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_chunked) [_socket writeString: @"0\r\n"]; else if (_toWrite > 0) @throw [OFTruncatedDataException exception]; _socket.delegate = _handler; [_socket asyncReadLine]; [_socket release]; _socket = nil; |
︙ | ︙ | |||
836 837 838 839 840 841 842 843 844 845 846 847 848 849 | super.headers = headers; _chunked = [[headers objectForKey: @"Transfer-Encoding"] isEqual: @"chunked"]; contentLength = [headers objectForKey: @"Content-Length"]; if (contentLength != nil) { _hasContentLength = true; @try { intmax_t toRead = contentLength.decimalValue; if (toRead < 0) @throw [OFInvalidServerReplyException | > > > | 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | super.headers = headers; _chunked = [[headers objectForKey: @"Transfer-Encoding"] isEqual: @"chunked"]; contentLength = [headers objectForKey: @"Content-Length"]; if (contentLength != nil) { if (_chunked) @throw [OFInvalidServerReplyException exception]; _hasContentLength = true; @try { intmax_t toRead = contentLength.decimalValue; if (toRead < 0) @throw [OFInvalidServerReplyException |
︙ | ︙ |
Modified utils/ofhttp/OFHTTP.m from [7982cd7599] to [cb6f1d9fe7].
︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 | if (full) { [stream writeString: @"\n"]; [stream writeLine: OF_LOCALIZED(@"full_usage", @"Options:\n " @"-b --body " @" Specify the file to send as body\n " @"-c --continue " @" Continue download of existing file\n " @"-f --force " @" Force / overwrite existing file\n " @"-h --help " @" Show this help\n " @"-H --header " | > > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | if (full) { [stream writeString: @"\n"]; [stream writeLine: OF_LOCALIZED(@"full_usage", @"Options:\n " @"-b --body " @" Specify the file to send as body\n " @" " @" (- for standard input)\n " @"-c --continue " @" Continue download of existing file\n " @"-f --force " @" Force / overwrite existing file\n " @"-h --help " @" Show this help\n " @"-H --header " |
︙ | ︙ | |||
316 317 318 319 320 321 322 | [_clientHeaders setObject: value forKey: name]; } - (void)setBody: (OFString *)path { | | > > > > > | | > | | > > > | | > > > > > > > | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | [_clientHeaders setObject: value forKey: name]; } - (void)setBody: (OFString *)path { OFString *contentLength = nil; [_body release]; _body = nil; if ([path isEqual: @"-"]) _body = [of_stdin copy]; else { _body = [[OFFile alloc] initWithPath: path mode: @"r"]; @try { uintmax_t fileSize = [[OFFileManager defaultManager] attributesOfItemAtPath: path].fileSize; contentLength = [OFString stringWithFormat: @"%ju", fileSize]; [_clientHeaders setObject: contentLength forKey: @"Content-Length"]; } @catch (OFRetrieveItemAttributesFailedException *e) { } } if (contentLength == nil) [_clientHeaders setObject: @"chunked" forKey: @"Transfer-Encoding"]; } - (void)setMethod: (OFString *)method { void *pool = objc_autoreleasePoolPush(); method = method.uppercaseString; |
︙ | ︙ |
Modified utils/ofhttp/lang/de.json from [ed88980c09] to [9f2302952b].
1 2 3 4 5 6 7 8 9 10 11 12 | { "usage": "Benutzung: %[prog] -[cehHmoOPqv] url1 [url2 ...]", "full_usage": [ "Optionen:\n", " -b --body Angegebene Datei als Body übergeben\n", " -c --continue Download von existierender Datei ", "fortsetzen\n", " -f --force Existierende Datei überschreiben\n", " -h --help Diese Hilfe anzeigen\n", " -H --header Einen Header (z.B. X-Foo:Bar) hinzufügen\n", " -m --method HTTP Request-Methode setzen\n", " -o --output Ausgabe-Dateiname angeben\n", | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | { "usage": "Benutzung: %[prog] -[cehHmoOPqv] url1 [url2 ...]", "full_usage": [ "Optionen:\n", " -b --body Angegebene Datei als Body übergeben\n", " (- für Standard-Eingabe)\n", " -c --continue Download von existierender Datei ", "fortsetzen\n", " -f --force Existierende Datei überschreiben\n", " -h --help Diese Hilfe anzeigen\n", " -H --header Einen Header (z.B. X-Foo:Bar) hinzufügen\n", " -m --method HTTP Request-Methode setzen\n", " -o --output Ausgabe-Dateiname angeben\n", |
︙ | ︙ |