Differences From Artifact [2088c9d68e]:
- File src/OFHTTPServer.m — part of check-in [cb0ac3f868] at 2018-01-18 23:28:31 on branch trunk — OFHTTPServer: Fix missing cast (user: js, size: 17175) [annotate] [blame] [check-ins using]
To Artifact [b47d8bb3a2]:
- File
src/OFHTTPServer.m
— part of check-in
[f756fb2ff6]
at
2018-02-25 02:38:40
on branch trunk
— OFHTTPServer: Move the body out of the request
Instead, provide a stream for the body to the callback. (user: js, size: 17177) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | @interface OFHTTPServer () - (bool)of_socket: (OFTCPSocket *)sock didAcceptSocket: (OFTCPSocket *)clientSocket context: (id)context exception: (id)exception; @end static const char * statusCodeToString(short code) { switch (code) { case 100: return "Continue"; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | @interface OFHTTPServer () - (bool)of_socket: (OFTCPSocket *)sock didAcceptSocket: (OFTCPSocket *)clientSocket context: (id)context exception: (id)exception; @end @interface OFHTTPServerResponse: OFHTTPResponse <OFReadyForWritingObserving> { OFTCPSocket *_socket; OFHTTPServer *_server; OFHTTPRequest *_request; bool _chunked, _headersSent; } - (instancetype)initWithSocket: (OFTCPSocket *)sock server: (OFHTTPServer *)server request: (OFHTTPRequest *)request; @end @interface OFHTTPServer_Connection: OFObject { @public OFTCPSocket *_socket; OFHTTPServer *_server; OFTimer *_timer; enum { AWAITING_PROLOG, PARSING_HEADERS, SEND_RESPONSE } _state; uint8_t _HTTPMinorVersion; of_http_request_method_t _method; OFString *_host, *_path; uint16_t _port; OFMutableDictionary *_headers; size_t _contentLength; OFStream *_body; } - (instancetype)initWithSocket: (OFTCPSocket *)sock server: (OFHTTPServer *)server; - (bool)socket: (OFTCPSocket *)sock didReadLine: (OFString *)line context: (id)context exception: (id)exception; - (bool)parseProlog: (OFString *)line; - (bool)parseHeaders: (OFString *)line; - (bool)sendErrorAndClose: (short)statusCode; - (void)createResponse; @end @interface OFHTTPServerRequestBodyStream: OFStream <OFReadyForReadingObserving> { OFTCPSocket *_socket; uintmax_t _toRead; bool _atEndOfStream; } - (instancetype)initWithSocket: (OFTCPSocket *)sock contentLength: (uintmax_t)contentLength; @end static const char * statusCodeToString(short code) { switch (code) { case 100: return "Continue"; |
︙ | ︙ | |||
170 171 172 173 174 175 176 | tmp++; } return [OFString stringWithUTF8StringNoCopy: cString freeWhenDone: true]; } | < < < < < < < < < < < < < | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | tmp++; } return [OFString stringWithUTF8StringNoCopy: cString freeWhenDone: true]; } @implementation OFHTTPServerResponse - (instancetype)initWithSocket: (OFTCPSocket *)sock server: (OFHTTPServer *)server request: (OFHTTPRequest *)request { self = [super init]; |
︙ | ︙ | |||
320 321 322 323 324 325 326 | if (_socket == nil) return -1; return [_socket fileDescriptorForWriting]; } @end | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | if (_socket == nil) return -1; return [_socket fileDescriptorForWriting]; } @end @implementation OFHTTPServer_Connection - (instancetype)initWithSocket: (OFTCPSocket *)sock server: (OFHTTPServer *)server { self = [super init]; @try { |
︙ | ︙ | |||
409 410 411 412 413 414 415 | return false; @try { switch (_state) { case AWAITING_PROLOG: return [self parseProlog: line]; case PARSING_HEADERS: | | < < < < < < < < | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | return false; @try { switch (_state) { case AWAITING_PROLOG: return [self parseProlog: line]; case PARSING_HEADERS: return [self parseHeaders: line]; default: return false; } } @catch (OFWriteFailedException *e) { return false; } |
︙ | ︙ | |||
491 492 493 494 495 496 497 | - (bool)parseHeaders: (OFString *)line { OFString *key, *value, *old; size_t pos; if ([line length] == 0) { | > > > > | | | | > | | | | < | < < < < > | > > | < < < < < < | < | < | < > > | | 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | - (bool)parseHeaders: (OFString *)line { OFString *key, *value, *old; size_t pos; if ([line length] == 0) { OFString *contentLengthString; if ((contentLengthString = [_headers objectForKey: @"Content-Length"]) != nil) { intmax_t contentLength; @try { contentLength = [contentLengthString decimalValue]; } @catch (OFInvalidFormatException *e) { return [self sendErrorAndClose: 400]; } if (contentLength < 0) return [self sendErrorAndClose: 400]; [_body release]; _body = nil; _body = [[OFHTTPServerRequestBodyStream alloc] initWithSocket: _socket contentLength: contentLength]; [_timer invalidate]; [_timer release]; _timer = nil; } _state = SEND_RESPONSE; [self createResponse]; return false; } pos = [line rangeOfString: @":"].location; if (pos == OF_NOT_FOUND) return [self sendErrorAndClose: 400]; key = [line substringWithRange: of_range(0, pos)]; |
︙ | ︙ | |||
580 581 582 583 584 585 586 | _port = 80; } } return true; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | _port = 80; } } return true; } - (bool)sendErrorAndClose: (short)statusCode { OFString *date = [[OFDate date] dateStringWithFormat: @"%a, %d %b %Y %H:%M:%S GMT"]; [_socket writeFormat: @"HTTP/1.1 %d %s\r\n" @"Date: %@\r\n" @"Server: %@\r\n" @"\r\n", statusCode, statusCodeToString(statusCode), date, [_server name]]; return false; } - (void)createResponse { void *pool = objc_autoreleasePoolPush(); OFMutableURL *URL; OFHTTPRequest *request; OFHTTPServerResponse *response; size_t pos; [_timer invalidate]; [_timer release]; |
︙ | ︙ | |||
679 680 681 682 683 684 685 | [URL makeImmutable]; request = [OFHTTPRequest requestWithURL: URL]; [request setMethod: _method]; [request setProtocolVersion: (of_http_request_protocol_version_t){ 1, _HTTPMinorVersion }]; [request setHeaders: _headers]; | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | [URL makeImmutable]; request = [OFHTTPRequest requestWithURL: URL]; [request setMethod: _method]; [request setProtocolVersion: (of_http_request_protocol_version_t){ 1, _HTTPMinorVersion }]; [request setHeaders: _headers]; [request setRemoteAddress: [_socket remoteAddress]]; response = [[[OFHTTPServerResponse alloc] initWithSocket: _socket server: _server request: request] autorelease]; [[_server delegate] server: _server didReceiveRequest: request body: _body response: response]; objc_autoreleasePoolPop(pool); } @end @implementation OFHTTPServerRequestBodyStream - (instancetype)initWithSocket: (OFTCPSocket *)sock contentLength: (uintmax_t)contentLength { self = [super init]; @try { _socket = [sock retain]; _toRead = contentLength; } @catch (id e) { [self release]; @throw e; } return self; } - (void)dealloc { [self close]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream { return _atEndOfStream; } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { size_t ret; if (_toRead == 0) { _atEndOfStream = true; return 0; } if (length > _toRead) length = (size_t)_toRead; ret = [_socket readIntoBuffer: buffer length: length]; _toRead -= ret; return ret; } - (bool)hasDataInReadBuffer { return ([super hasDataInReadBuffer] || [_socket hasDataInReadBuffer]); } - (int)fileDescriptorForReading { return [_socket fileDescriptorForReading]; } - (void)close { [_socket release]; _socket = nil; } @end @implementation OFHTTPServer @synthesize host = _host, port = _port, delegate = _delegate, name = _name; + (instancetype)server |
︙ | ︙ |