comparison OrthancFramework/Sources/HttpServer/HttpOutput.cpp @ 4672:d9942d48fea7

ZipWriter::CancelStream(), ZipWriter::GetArchiveSize() and HttpOutput::AnswerWithoutBuffering()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 02 Jun 2021 17:35:39 +0200
parents c1f36fd13730
children 7053502fbf97
comparison
equal deleted inserted replaced
4671:42e1f5bde40b 4672:d9942d48fea7
571 571
572 contentTypeHeader = ("multipart/" + subType + "; type=" + tmp + "; boundary=" + boundary); 572 contentTypeHeader = ("multipart/" + subType + "; type=" + tmp + "; boundary=" + boundary);
573 } 573 }
574 574
575 575
576 void HttpOutput::StateMachine::StartMultipart(const std::string& subType, 576 void HttpOutput::StateMachine::StartStreamInternal(const std::string& contentType)
577 const std::string& contentType)
578 { 577 {
579 if (state_ != State_WritingHeader) 578 if (state_ != State_WritingHeader)
580 { 579 {
581 throw OrthancException(ErrorCode_BadSequenceOfCalls); 580 throw OrthancException(ErrorCode_BadSequenceOfCalls);
582 } 581 }
618 else 617 else
619 { 618 {
620 header += "Connection: close\r\n"; 619 header += "Connection: close\r\n";
621 } 620 }
622 621
623 // Possibly add the cookies
624 CheckHeadersCompatibilityWithMultipart();
625
626 for (std::list<std::string>::const_iterator 622 for (std::list<std::string>::const_iterator
627 it = headers_.begin(); it != headers_.end(); ++it) 623 it = headers_.begin(); it != headers_.end(); ++it)
628 { 624 {
629 header += *it; 625 header += *it;
630 } 626 }
627
628 header += ("Content-Type: " + contentType + "\r\n\r\n");
629
630 stream_.Send(true, header.c_str(), header.size());
631 }
632
633
634 void HttpOutput::StateMachine::StartMultipart(const std::string& subType,
635 const std::string& contentType)
636 {
637 CheckHeadersCompatibilityWithMultipart();
631 638
632 std::string contentTypeHeader; 639 std::string contentTypeHeader;
633 PrepareMultipartMainHeader(multipartBoundary_, contentTypeHeader, subType, contentType); 640 PrepareMultipartMainHeader(multipartBoundary_, contentTypeHeader, subType, contentType);
634 multipartContentType_ = contentType; 641 multipartContentType_ = contentType;
635 header += ("Content-Type: " + contentTypeHeader + "\r\n\r\n"); 642
636 643 StartStreamInternal(contentTypeHeader);
637 stream_.Send(true, header.c_str(), header.size()); 644
638 state_ = State_WritingMultipart; 645 state_ = State_WritingMultipart;
646 }
647
648
649 void HttpOutput::StateMachine::StartStream(const std::string& contentType)
650 {
651 StartStreamInternal(contentType);
652 state_ = State_WritingStream;
639 } 653 }
640 654
641 655
642 static void PrepareMultipartItemHeader(std::string& target, 656 static void PrepareMultipartItemHeader(std::string& target,
643 size_t length, 657 size_t length,
731 catch (OrthancException&) 745 catch (OrthancException&)
732 { 746 {
733 } 747 }
734 748
735 state_ = State_Done; 749 state_ = State_Done;
750 }
751
752
753 void HttpOutput::StateMachine::SendStreamItem(const void* data,
754 size_t size)
755 {
756 if (state_ != State_WritingStream)
757 {
758 throw OrthancException(ErrorCode_BadSequenceOfCalls);
759 }
760 else
761 {
762 if (size > 0)
763 {
764 stream_.Send(false, data, size);
765 }
766 }
767 }
768
769
770 void HttpOutput::StateMachine::CloseStream()
771 {
772 if (state_ != State_WritingStream)
773 {
774 throw OrthancException(ErrorCode_BadSequenceOfCalls);
775 }
776 else
777 {
778 state_ = State_Done;
779 }
736 } 780 }
737 781
738 782
739 static void AnswerStreamAsBuffer(HttpOutput& output, 783 static void AnswerStreamAsBuffer(HttpOutput& output,
740 IHttpStreamAnswer& stream) 784 IHttpStreamAnswer& stream)
858 902
859 std::string body; 903 std::string body;
860 chunked.Flatten(body); 904 chunked.Flatten(body);
861 Answer(body); 905 Answer(body);
862 } 906 }
907
908
909 void HttpOutput::AnswerWithoutBuffering(IHttpStreamAnswer& stream)
910 {
911 std::string contentType = stream.GetContentType();
912 if (contentType.empty())
913 {
914 contentType = MIME_BINARY;
915 }
916
917 std::string filename;
918 if (stream.HasContentFilename(filename))
919 {
920 stateMachine_.AddHeader("Content-Disposition", "filename=\"" + std::string(filename) + "\"");
921 }
922
923 stateMachine_.StartStream(contentType.c_str());
924
925 while (stream.ReadNextChunk())
926 {
927 stateMachine_.SendStreamItem(stream.GetChunkContent(), stream.GetChunkSize());
928 }
929
930 stateMachine_.CloseStream();
931 }
863 } 932 }