Mercurial > hg > orthanc
diff Core/HttpServer/HttpOutput.cpp @ 1430:ad94a3583b07
Plugins can send answers as multipart messages
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 29 Jun 2015 17:47:34 +0200 |
parents | 6e7e5ed91c2d |
children | f967bdf8534e |
line wrap: on
line diff
--- a/Core/HttpServer/HttpOutput.cpp Mon Jun 29 14:43:08 2015 +0200 +++ b/Core/HttpServer/HttpOutput.cpp Mon Jun 29 17:47:34 2015 +0200 @@ -151,6 +151,11 @@ } } + if (state_ == State_WritingMultipart) + { + throw OrthancException(ErrorCode_InternalError); + } + if (state_ == State_WritingHeader) { // Send the HTTP header before writing the body @@ -270,4 +275,109 @@ { stateMachine_.SendBody(NULL, 0); } + + + void HttpOutput::StateMachine::StartMultipart(const std::string& subType, + const std::string& contentType) + { + if (subType != "mixed" && + subType != "related") + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + if (keepAlive_) + { + LOG(ERROR) << "Multipart answers are not implemented together with keep-alive connections"; + throw OrthancException(ErrorCode_NotImplemented); + } + + if (state_ != State_WritingHeader) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + if (status_ != HttpStatus_200_Ok) + { + SendBody(NULL, 0); + return; + } + + stream_.OnHttpStatusReceived(status_); + + std::string header = "HTTP/1.1 200 OK\r\n"; + + // Possibly add the cookies + for (std::list<std::string>::const_iterator + it = headers_.begin(); it != headers_.end(); ++it) + { + if (!Toolbox::StartsWith(*it, "Set-Cookie: ")) + { + LOG(ERROR) << "The only headers that can be set in multipart answers are Set-Cookie (here: " << *it << " is set)"; + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + header += *it; + } + + multipartBoundary_ = Toolbox::GenerateUuid(); + multipartContentType_ = contentType; + header += "Content-Type: multipart/related; type=multipart/" + subType + "; boundary=" + multipartBoundary_ + "\r\n\r\n"; + + stream_.Send(true, header.c_str(), header.size()); + state_ = State_WritingMultipart; + } + + + void HttpOutput::StateMachine::SendMultipartItem(const void* item, size_t length) + { + std::string header = "--" + multipartBoundary_ + "\n"; + header += "Content-Type: " + multipartContentType_ + "\n"; + header += "Content-Length: " + boost::lexical_cast<std::string>(length) + "\n"; + header += "MIME-Version: 1.0\n\n"; + + stream_.Send(false, header.c_str(), header.size()); + + if (length > 0) + { + stream_.Send(false, item, length); + } + + stream_.Send(false, "\n", 1); + } + + + void HttpOutput::StateMachine::CloseMultipart() + { + if (state_ != State_WritingMultipart) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + // The two lines below might throw an exception, if the client has + // closed the connection. Such an error is ignored. + try + { + std::string header = "--" + multipartBoundary_ + "--\n"; + stream_.Send(false, header.c_str(), header.size()); + } + catch (OrthancException&) + { + } + + state_ = State_Done; + } + + + void HttpOutput::SendMultipartItem(const std::string& item) + { + if (item.size() > 0) + { + stateMachine_.SendMultipartItem(item.c_str(), item.size()); + } + else + { + stateMachine_.SendMultipartItem(NULL, 0); + } + } }