Mercurial > hg > orthanc
annotate OrthancFramework/Sources/HttpServer/HttpOutput.cpp @ 4544:ae63b301d522 Orthanc-1.7.4
close branch
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 02 Mar 2021 16:52:26 +0100 |
parents | 2d5209153b32 |
children | db3932f9660d |
rev | line source |
---|---|
0 | 1 /** |
59 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
1900 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
1288
6e7e5ed91c2d
upgrade to year 2015
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1200
diff
changeset
|
4 * Department, University Hospital of Liege, Belgium |
3640
94f4a18a79cc
upgrade to year 2020
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3616
diff
changeset
|
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
8 * modify it under the terms of the GNU Lesser General Public License |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
9 * as published by the Free Software Foundation, either version 3 of |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
10 * the License, or (at your option) any later version. |
136 | 11 * |
0 | 12 * This program is distributed in the hope that it will be useful, but |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
15 * Lesser General Public License for more details. |
0 | 16 * |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
17 * You should have received a copy of the GNU Lesser General Public |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
18 * License along with this program. If not, see |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
19 * <http://www.gnu.org/licenses/>. |
0 | 20 **/ |
21 | |
22 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
689
diff
changeset
|
23 #include "../PrecompiledHeaders.h" |
0 | 24 #include "HttpOutput.h" |
25 | |
3380
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
26 #include "../ChunkedBuffer.h" |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
27 #include "../Compression/GzipCompressor.h" |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
28 #include "../Compression/ZlibCompressor.h" |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
29 #include "../Logging.h" |
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
30 #include "../OrthancException.h" |
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
31 #include "../Toolbox.h" |
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
32 |
324 | 33 #include <iostream> |
0 | 34 #include <vector> |
35 #include <stdio.h> | |
36 #include <boost/lexical_cast.hpp> | |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
37 |
0 | 38 |
3178
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
39 #if ORTHANC_ENABLE_CIVETWEB == 1 |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
40 # if !defined(CIVETWEB_HAS_DISABLE_KEEP_ALIVE) |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
41 # error Macro CIVETWEB_HAS_DISABLE_KEEP_ALIVE must be defined |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
42 # endif |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
43 #endif |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
44 |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
45 |
59 | 46 namespace Orthanc |
0 | 47 { |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
48 HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream, |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
49 bool isKeepAlive) : |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
50 stream_(stream), |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
51 state_(State_WritingHeader), |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
52 status_(HttpStatus_200_Ok), |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
53 hasContentLength_(false), |
4201 | 54 contentLength_(0), |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
55 contentPosition_(0), |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
56 keepAlive_(isKeepAlive) |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
57 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
58 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
59 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
60 HttpOutput::StateMachine::~StateMachine() |
910 | 61 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
62 if (state_ != State_Done) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
63 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
64 //asm volatile ("int3;"); |
1200 | 65 //LOG(ERROR) << "This HTTP answer does not contain any body"; |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
66 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
67 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
68 if (hasContentLength_ && contentPosition_ != contentLength_) |
910 | 69 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
70 LOG(ERROR) << "This HTTP answer has not sent the proper number of bytes in its body"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
71 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
72 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
73 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
74 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
75 void HttpOutput::StateMachine::SetHttpStatus(HttpStatus status) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
76 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
77 if (state_ != State_WritingHeader) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
78 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
79 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
910 | 80 } |
81 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
82 status_ = status; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
83 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
84 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
85 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
86 void HttpOutput::StateMachine::SetContentLength(uint64_t length) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
87 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
88 if (state_ != State_WritingHeader) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
89 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
90 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
91 } |
910 | 92 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
93 hasContentLength_ = true; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
94 contentLength_ = length; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
95 } |
910 | 96 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
97 void HttpOutput::StateMachine::SetContentType(const char* contentType) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
98 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
99 AddHeader("Content-Type", contentType); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
100 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
101 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
102 void HttpOutput::StateMachine::SetContentFilename(const char* filename) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
103 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
104 // TODO Escape double quotes |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
105 AddHeader("Content-Disposition", "filename=\"" + std::string(filename) + "\""); |
910 | 106 } |
107 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
108 void HttpOutput::StateMachine::SetCookie(const std::string& cookie, |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
109 const std::string& value) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
110 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
111 if (state_ != State_WritingHeader) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
112 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
113 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
114 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
115 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
116 // TODO Escape "=" characters |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
117 AddHeader("Set-Cookie", cookie + "=" + value); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
118 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
119 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
120 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
121 void HttpOutput::StateMachine::AddHeader(const std::string& header, |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
122 const std::string& value) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
123 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
124 if (state_ != State_WritingHeader) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
125 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
126 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
127 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
128 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
129 headers_.push_back(header + ": " + value + "\r\n"); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
130 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
131 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
132 void HttpOutput::StateMachine::ClearHeaders() |
910 | 133 { |
134 if (state_ != State_WritingHeader) | |
135 { | |
136 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
137 } | |
138 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
139 headers_.clear(); |
910 | 140 } |
141 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
142 void HttpOutput::StateMachine::SendBody(const void* buffer, size_t length) |
910 | 143 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
144 if (state_ == State_Done) |
910 | 145 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
146 if (length == 0) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
147 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
148 return; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
149 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
150 else |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
151 { |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
152 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
153 "Because of keep-alive connections, the entire body must " |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
154 "be sent at once or Content-Length must be given"); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
155 } |
910 | 156 } |
157 | |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
158 if (state_ == State_WritingMultipart) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
159 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
160 throw OrthancException(ErrorCode_InternalError); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
161 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
162 |
910 | 163 if (state_ == State_WritingHeader) |
164 { | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
165 // Send the HTTP header before writing the body |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
166 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
167 stream_.OnHttpStatusReceived(status_); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
168 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
169 std::string s = "HTTP/1.1 " + |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
170 boost::lexical_cast<std::string>(status_) + |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
171 " " + std::string(EnumerationToString(status_)) + |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
172 "\r\n"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
173 |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
174 if (keepAlive_) |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
175 { |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
176 s += "Connection: keep-alive\r\n"; |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
177 } |
3171
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
178 else |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
179 { |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
180 s += "Connection: close\r\n"; |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
181 } |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
182 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
183 for (std::list<std::string>::const_iterator |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
184 it = headers_.begin(); it != headers_.end(); ++it) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
185 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
186 s += *it; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
187 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
188 |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
189 if (status_ != HttpStatus_200_Ok) |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
190 { |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
191 hasContentLength_ = false; |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
192 } |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
193 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
194 uint64_t contentLength = (hasContentLength_ ? contentLength_ : length); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
195 s += "Content-Length: " + boost::lexical_cast<std::string>(contentLength) + "\r\n\r\n"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
196 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
197 stream_.Send(true, s.c_str(), s.size()); |
910 | 198 state_ = State_WritingBody; |
199 } | |
200 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
201 if (hasContentLength_ && |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
202 contentPosition_ + length > contentLength_) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
203 { |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
204 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
205 "The body size exceeds what was declared with SetContentSize()"); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
206 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
207 |
910 | 208 if (length > 0) |
209 { | |
911 | 210 stream_.Send(false, buffer, length); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
211 contentPosition_ += length; |
330 | 212 } |
213 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
214 if (!hasContentLength_ || |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
215 contentPosition_ == contentLength_) |
330 | 216 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
217 state_ = State_Done; |
330 | 218 } |
219 } | |
220 | |
207 | 221 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
222 void HttpOutput::StateMachine::CloseBody() |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
223 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
224 switch (state_) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
225 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
226 case State_WritingHeader: |
1522 | 227 SetContentLength(0); |
228 SendBody(NULL, 0); | |
229 break; | |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
230 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
231 case State_WritingBody: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
232 if (!hasContentLength_ || |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
233 contentPosition_ == contentLength_) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
234 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
235 state_ = State_Done; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
236 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
237 else |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
238 { |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
239 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
240 "The body size has not reached what was declared with SetContentSize()"); |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
241 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
242 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
243 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
244 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
245 case State_WritingMultipart: |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
246 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
247 "Cannot invoke CloseBody() with multipart outputs"); |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
248 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
249 case State_Done: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
250 return; // Ignore |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
251 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
252 default: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
253 throw OrthancException(ErrorCode_InternalError); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
254 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
255 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
256 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
257 |
1517 | 258 HttpCompression HttpOutput::GetPreferredCompression(size_t bodySize) const |
259 { | |
260 #if 0 | |
261 // TODO Do not compress small files? | |
262 if (bodySize < 512) | |
263 { | |
264 return HttpCompression_None; | |
265 } | |
266 #endif | |
267 | |
268 // Prefer "gzip" over "deflate" if the choice is offered | |
269 | |
270 if (isGzipAllowed_) | |
271 { | |
272 return HttpCompression_Gzip; | |
273 } | |
274 else if (isDeflateAllowed_) | |
275 { | |
276 return HttpCompression_Deflate; | |
277 } | |
278 else | |
279 { | |
280 return HttpCompression_None; | |
281 } | |
282 } | |
283 | |
284 | |
1042
8d1845feb277
set cookies, not allowed methods, unauthorized in plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
911
diff
changeset
|
285 void HttpOutput::SendMethodNotAllowed(const std::string& allowed) |
0 | 286 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
287 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
288 stateMachine_.SetHttpStatus(HttpStatus_405_MethodNotAllowed); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
289 stateMachine_.AddHeader("Allow", allowed); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
290 stateMachine_.SendBody(NULL, 0); |
0 | 291 } |
292 | |
293 | |
1567
9c5d93510414
If error while calling the REST API, the answer body contains an error description
jodogne
parents:
1523
diff
changeset
|
294 void HttpOutput::SendStatus(HttpStatus status, |
9c5d93510414
If error while calling the REST API, the answer body contains an error description
jodogne
parents:
1523
diff
changeset
|
295 const char* message, |
9c5d93510414
If error while calling the REST API, the answer body contains an error description
jodogne
parents:
1523
diff
changeset
|
296 size_t messageSize) |
0 | 297 { |
1954 | 298 if (status == HttpStatus_301_MovedPermanently || |
3425 | 299 //status == HttpStatus_401_Unauthorized || |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
398
diff
changeset
|
300 status == HttpStatus_405_MethodNotAllowed) |
0 | 301 { |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
302 throw OrthancException(ErrorCode_ParameterOutOfRange, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2908
diff
changeset
|
303 "Please use the dedicated methods to this HTTP status code in HttpOutput"); |
0 | 304 } |
305 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
306 stateMachine_.SetHttpStatus(status); |
1645
1558b3226b18
IHttpExceptionFormatter
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1592
diff
changeset
|
307 stateMachine_.SendBody(message, messageSize); |
339 | 308 } |
309 | |
310 | |
0 | 311 void HttpOutput::Redirect(const std::string& path) |
312 { | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
313 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
314 stateMachine_.SetHttpStatus(HttpStatus_301_MovedPermanently); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
315 stateMachine_.AddHeader("Location", path); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
316 stateMachine_.SendBody(NULL, 0); |
0 | 317 } |
908
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
318 |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
319 |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
320 void HttpOutput::SendUnauthorized(const std::string& realm) |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
321 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
322 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
323 stateMachine_.SetHttpStatus(HttpStatus_401_Unauthorized); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
324 stateMachine_.AddHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\""); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
325 stateMachine_.SendBody(NULL, 0); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
326 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
327 |
2908
9d277f8ad698
new enumeration: MimeType
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2905
diff
changeset
|
328 |
1521 | 329 void HttpOutput::Answer(const void* buffer, |
330 size_t length) | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
331 { |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
332 if (length == 0) |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
333 { |
1521 | 334 AnswerEmpty(); |
335 return; | |
336 } | |
337 | |
338 HttpCompression compression = GetPreferredCompression(length); | |
339 | |
340 if (compression == HttpCompression_None) | |
341 { | |
342 stateMachine_.SetContentLength(length); | |
343 stateMachine_.SendBody(buffer, length); | |
344 return; | |
345 } | |
346 | |
347 std::string compressed, encoding; | |
348 | |
349 switch (compression) | |
350 { | |
351 case HttpCompression_Deflate: | |
352 { | |
353 encoding = "deflate"; | |
354 ZlibCompressor compressor; | |
355 // Do not prefix the buffer with its uncompressed size, to be compatible with "deflate" | |
356 compressor.SetPrefixWithUncompressedSize(false); | |
357 compressor.Compress(compressed, buffer, length); | |
358 break; | |
359 } | |
360 | |
361 case HttpCompression_Gzip: | |
362 { | |
363 encoding = "gzip"; | |
364 GzipCompressor compressor; | |
365 compressor.Compress(compressed, buffer, length); | |
366 break; | |
367 } | |
368 | |
369 default: | |
370 throw OrthancException(ErrorCode_InternalError); | |
371 } | |
372 | |
373 LOG(TRACE) << "Compressing a HTTP answer using " << encoding; | |
374 | |
375 // The body is empty, do not use HTTP compression | |
376 if (compressed.size() == 0) | |
377 { | |
378 AnswerEmpty(); | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
379 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
380 else |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
381 { |
1521 | 382 stateMachine_.AddHeader("Content-Encoding", encoding); |
383 stateMachine_.SetContentLength(compressed.size()); | |
384 stateMachine_.SendBody(compressed.c_str(), compressed.size()); | |
385 } | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
386 |
1521 | 387 stateMachine_.CloseBody(); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
388 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
389 |
1521 | 390 |
391 void HttpOutput::Answer(const std::string& str) | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
392 { |
1521 | 393 Answer(str.size() == 0 ? NULL : str.c_str(), str.size()); |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
394 } |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
395 |
1521 | 396 |
397 void HttpOutput::AnswerEmpty() | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
398 { |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
399 stateMachine_.CloseBody(); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
400 } |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
401 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
402 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
403 void HttpOutput::StateMachine::CheckHeadersCompatibilityWithMultipart() const |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
404 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
405 for (std::list<std::string>::const_iterator |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
406 it = headers_.begin(); it != headers_.end(); ++it) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
407 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
408 if (!Toolbox::StartsWith(*it, "Set-Cookie: ")) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
409 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
410 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
411 "The only headers that can be set in multipart answers " |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
412 "are Set-Cookie (here: " + *it + " is set)"); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
413 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
414 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
415 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
416 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
417 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
418 static void PrepareMultipartMainHeader(std::string& boundary, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
419 std::string& contentTypeHeader, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
420 const std::string& subType, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
421 const std::string& contentType) |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
422 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
423 if (subType != "mixed" && |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
424 subType != "related") |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
425 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
426 throw OrthancException(ErrorCode_ParameterOutOfRange); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
427 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
428 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
429 /** |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
430 * Fix for issue 54 ("Decide what to do wrt. quoting of multipart |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
431 * answers"). The "type" parameter in the "Content-Type" HTTP |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
432 * header must be quoted if it contains a forward slash "/". This |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
433 * is necessary for DICOMweb compatibility with OsiriX, but breaks |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
434 * compatibility with old releases of the client in the Orthanc |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
435 * DICOMweb plugin <= 0.3 (releases >= 0.4 work fine). |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
436 * |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
437 * Full history is available at the following locations: |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
438 * - In changeset 2248:69b0f4e8a49b: |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
439 * # hg history -v -r 2248 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
440 * - https://bitbucket.org/sjodogne/orthanc/issues/54/ |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
441 * - https://groups.google.com/d/msg/orthanc-users/65zhIM5xbKI/TU5Q1_LhAwAJ |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
442 **/ |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
443 std::string tmp; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
444 if (contentType.find('/') == std::string::npos) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
445 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
446 // No forward slash in the content type |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
447 tmp = contentType; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
448 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
449 else |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
450 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
451 // Quote the content type because of the forward slash |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
452 tmp = "\"" + contentType + "\""; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
453 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
454 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
455 boundary = Toolbox::GenerateUuid() + "-" + Toolbox::GenerateUuid(); |
3616 | 456 |
457 /** | |
458 * Fix for issue #165: "Encapsulation boundaries must not appear | |
459 * within the encapsulations, and must be no longer than 70 | |
460 * characters, not counting the two leading hyphens." | |
461 * https://tools.ietf.org/html/rfc1521 | |
462 * https://bitbucket.org/sjodogne/orthanc/issues/165/ | |
463 **/ | |
464 if (boundary.size() != 36 + 1 + 36) // one UUID contains 36 characters | |
465 { | |
466 throw OrthancException(ErrorCode_InternalError); | |
467 } | |
468 | |
469 boundary = boundary.substr(0, 70); | |
470 | |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
471 contentTypeHeader = ("multipart/" + subType + "; type=" + tmp + "; boundary=" + boundary); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
472 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
473 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
474 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
475 void HttpOutput::StateMachine::StartMultipart(const std::string& subType, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
476 const std::string& contentType) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
477 { |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
478 if (state_ != State_WritingHeader) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
479 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
480 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
481 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
482 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
483 if (status_ != HttpStatus_200_Ok) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
484 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
485 SendBody(NULL, 0); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
486 return; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
487 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
488 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
489 stream_.OnHttpStatusReceived(status_); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
490 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
491 std::string header = "HTTP/1.1 200 OK\r\n"; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
492 |
3154
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
493 if (keepAlive_) |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
494 { |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
495 #if ORTHANC_ENABLE_MONGOOSE == 1 |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
496 throw OrthancException(ErrorCode_NotImplemented, |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
497 "Multipart answers are not implemented together " |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
498 "with keep-alive connections if using Mongoose"); |
3178
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
499 |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
500 #elif ORTHANC_ENABLE_CIVETWEB == 1 |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
501 # if CIVETWEB_HAS_DISABLE_KEEP_ALIVE == 1 |
3154
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
502 // Turn off Keep-Alive for multipart answers |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
503 // https://github.com/civetweb/civetweb/issues/727 |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
504 stream_.DisableKeepAlive(); |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
505 header += "Connection: close\r\n"; |
3178
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
506 # else |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
507 // The function "mg_disable_keep_alive()" is not available, |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
508 // let's continue with Keep-Alive. Performance of WADO-RS will |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
509 // decrease. |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
510 header += "Connection: keep-alive\r\n"; |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
511 # endif |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
512 |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
513 #else |
6d558598d713
Fix build with unpatched versions of Civetweb (missing "mg_disable_keep_alive()")
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3171
diff
changeset
|
514 # error Please support your embedded Web server here |
3154
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
515 #endif |
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
516 } |
3171
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
517 else |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
518 { |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
519 header += "Connection: close\r\n"; |
81cd9a4f3018
always add HTTP header "Connection: close" if keep-alive is disabled
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3154
diff
changeset
|
520 } |
3154
6e8822be2f08
Fix compatibility with DICOMweb plugin (allow multipart answers over HTTP Keep-Alive)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
521 |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
522 // Possibly add the cookies |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
523 CheckHeadersCompatibilityWithMultipart(); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
524 |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
525 for (std::list<std::string>::const_iterator |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
526 it = headers_.begin(); it != headers_.end(); ++it) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
527 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
528 header += *it; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
529 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
530 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
531 std::string contentTypeHeader; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
532 PrepareMultipartMainHeader(multipartBoundary_, contentTypeHeader, subType, contentType); |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
533 multipartContentType_ = contentType; |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
534 header += ("Content-Type: " + contentTypeHeader + "\r\n\r\n"); |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
535 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
536 stream_.Send(true, header.c_str(), header.size()); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
537 state_ = State_WritingMultipart; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
538 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
539 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
540 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
541 static void PrepareMultipartItemHeader(std::string& target, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
542 size_t length, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
543 const std::map<std::string, std::string>& headers, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
544 const std::string& boundary, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
545 const std::string& contentType) |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
546 { |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
547 target = "--" + boundary + "\r\n"; |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
548 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
549 bool hasContentType = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
550 bool hasContentLength = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
551 bool hasMimeVersion = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
552 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
553 for (std::map<std::string, std::string>::const_iterator |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
554 it = headers.begin(); it != headers.end(); ++it) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
555 { |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
556 target += it->first + ": " + it->second + "\r\n"; |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
557 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
558 std::string tmp; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
559 Toolbox::ToLowerCase(tmp, it->first); |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
560 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
561 if (tmp == "content-type") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
562 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
563 hasContentType = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
564 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
565 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
566 if (tmp == "content-length") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
567 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
568 hasContentLength = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
569 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
570 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
571 if (tmp == "mime-version") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
572 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
573 hasMimeVersion = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
574 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
575 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
576 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
577 if (!hasContentType) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
578 { |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
579 target += "Content-Type: " + contentType + "\r\n"; |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
580 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
581 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
582 if (!hasContentLength) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
583 { |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
584 target += "Content-Length: " + boost::lexical_cast<std::string>(length) + "\r\n"; |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
585 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
586 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
587 if (!hasMimeVersion) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
588 { |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
589 target += "MIME-Version: 1.0\r\n\r\n"; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
590 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
591 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
592 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
593 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
594 void HttpOutput::StateMachine::SendMultipartItem(const void* item, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
595 size_t length, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
596 const std::map<std::string, std::string>& headers) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
597 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
598 if (state_ != State_WritingMultipart) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
599 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
600 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
601 } |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
602 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
603 std::string header; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
604 PrepareMultipartItemHeader(header, length, headers, multipartBoundary_, multipartContentType_); |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
605 stream_.Send(false, header.c_str(), header.size()); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
606 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
607 if (length > 0) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
608 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
609 stream_.Send(false, item, length); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
610 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
611 |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
612 stream_.Send(false, "\r\n", 2); |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
613 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
614 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
615 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
616 void HttpOutput::StateMachine::CloseMultipart() |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
617 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
618 if (state_ != State_WritingMultipart) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
619 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
620 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
621 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
622 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
623 // The two lines below might throw an exception, if the client has |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
624 // closed the connection. Such an error is ignored. |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
625 try |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
626 { |
1832
b7da58699f92
Fix formatting of multipart HTTP answers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1645
diff
changeset
|
627 std::string header = "--" + multipartBoundary_ + "--\r\n"; |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
628 stream_.Send(false, header.c_str(), header.size()); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
629 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
630 catch (OrthancException&) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
631 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
632 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
633 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
634 state_ = State_Done; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
635 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
636 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
637 |
3380
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
638 static void AnswerStreamAsBuffer(HttpOutput& output, |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
639 IHttpStreamAnswer& stream) |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
640 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
641 ChunkedBuffer buffer; |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
642 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
643 while (stream.ReadNextChunk()) |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
644 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
645 if (stream.GetChunkSize() > 0) |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
646 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
647 buffer.AddChunk(stream.GetChunkContent(), stream.GetChunkSize()); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
648 } |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
649 } |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
650 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
651 std::string s; |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
652 buffer.Flatten(s); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
653 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
654 output.SetContentType(stream.GetContentType()); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
655 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
656 std::string filename; |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
657 if (stream.HasContentFilename(filename)) |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
658 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
659 output.SetContentFilename(filename.c_str()); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
660 } |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
661 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
662 output.Answer(s); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
663 } |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
664 |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
665 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
666 void HttpOutput::Answer(IHttpStreamAnswer& stream) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
667 { |
1523
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
668 HttpCompression compression = stream.SetupHttpCompression(isGzipAllowed_, isDeflateAllowed_); |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
669 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
670 switch (compression) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
671 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
672 case HttpCompression_None: |
3380
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
673 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
674 if (isGzipAllowed_ || isDeflateAllowed_) |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
675 { |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
676 // New in Orthanc 1.5.7: Compress streams without built-in |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
677 // compression, if requested by the "Accept-Encoding" HTTP |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
678 // header |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
679 AnswerStreamAsBuffer(*this, stream); |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
680 return; |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
681 } |
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
682 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
683 break; |
3380
0528a6c36f3d
HTTP header "Accept-Encoding" is honored for streams without built-in support for compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3178
diff
changeset
|
684 } |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
685 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
686 case HttpCompression_Gzip: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
687 stateMachine_.AddHeader("Content-Encoding", "gzip"); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
688 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
689 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
690 case HttpCompression_Deflate: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
691 stateMachine_.AddHeader("Content-Encoding", "deflate"); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
692 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
693 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
694 default: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
695 throw OrthancException(ErrorCode_ParameterOutOfRange); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
696 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
697 |
1523
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
698 stateMachine_.SetContentLength(stream.GetContentLength()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
699 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
700 std::string contentType = stream.GetContentType(); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
701 if (contentType.empty()) |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
702 { |
2905
ae20fccdd867
refactoring mime types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2805
diff
changeset
|
703 contentType = MIME_BINARY; |
1523
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
704 } |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
705 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
706 stateMachine_.SetContentType(contentType.c_str()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
707 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
708 std::string filename; |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
709 if (stream.HasContentFilename(filename)) |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
710 { |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
711 SetContentFilename(filename.c_str()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
712 } |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
713 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
714 while (stream.ReadNextChunk()) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
715 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
716 stateMachine_.SendBody(stream.GetChunkContent(), |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
717 stream.GetChunkSize()); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
718 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
719 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
720 stateMachine_.CloseBody(); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
721 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
722 |
3528
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
723 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
724 void HttpOutput::AnswerMultipartWithoutChunkedTransfer( |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
725 const std::string& subType, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
726 const std::string& contentType, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
727 const std::vector<const void*>& parts, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
728 const std::vector<size_t>& sizes, |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
729 const std::vector<const std::map<std::string, std::string>*>& headers) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
730 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
731 if (parts.size() != sizes.size()) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
732 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
733 throw OrthancException(ErrorCode_ParameterOutOfRange); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
734 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
735 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
736 stateMachine_.CheckHeadersCompatibilityWithMultipart(); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
737 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
738 std::string boundary, contentTypeHeader; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
739 PrepareMultipartMainHeader(boundary, contentTypeHeader, subType, contentType); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
740 SetContentType(contentTypeHeader); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
741 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
742 std::map<std::string, std::string> empty; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
743 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
744 ChunkedBuffer chunked; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
745 for (size_t i = 0; i < parts.size(); i++) |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
746 { |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
747 std::string partHeader; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
748 PrepareMultipartItemHeader(partHeader, sizes[i], headers[i] == NULL ? empty : *headers[i], |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
749 boundary, contentType); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
750 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
751 chunked.AddChunk(partHeader); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
752 chunked.AddChunk(parts[i], sizes[i]); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
753 chunked.AddChunk("\r\n"); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
754 } |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
755 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
756 chunked.AddChunk("--" + boundary + "--\r\n"); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
757 |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
758 std::string body; |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
759 chunked.Flatten(body); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
760 Answer(body); |
f6fe095f7130
don't open a multipart stream if plugin only sends one part
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3425
diff
changeset
|
761 } |
0 | 762 } |