Mercurial > hg > orthanc
annotate Core/HttpServer/HttpOutput.cpp @ 2018:300599489cab
USE_BOOST_LOCALE_BACKENDS
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 14 Jun 2016 15:51:00 +0200 |
parents | 1845512f8914 |
children | 84d1d392a9ab |
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 |
0 | 5 * |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
136 | 10 * |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
0 | 22 * |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
689
diff
changeset
|
33 #include "../PrecompiledHeaders.h" |
0 | 34 #include "HttpOutput.h" |
35 | |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
36 #include "../Logging.h" |
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
37 #include "../OrthancException.h" |
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
38 #include "../Toolbox.h" |
1514
d73a2178b319
support of deflate and gzip content-types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1511
diff
changeset
|
39 #include "../Compression/GzipCompressor.h" |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
40 #include "../Compression/ZlibCompressor.h" |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
41 |
324 | 42 #include <iostream> |
0 | 43 #include <vector> |
44 #include <stdio.h> | |
45 #include <boost/lexical_cast.hpp> | |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1430
diff
changeset
|
46 |
0 | 47 |
59 | 48 namespace Orthanc |
0 | 49 { |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
50 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
|
51 bool isKeepAlive) : |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
52 stream_(stream), |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
53 state_(State_WritingHeader), |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
54 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
|
55 hasContentLength_(false), |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
56 contentPosition_(0), |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
57 keepAlive_(isKeepAlive) |
1113
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 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
61 HttpOutput::StateMachine::~StateMachine() |
910 | 62 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
63 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
|
64 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
65 //asm volatile ("int3;"); |
1200 | 66 //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
|
67 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
68 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
69 if (hasContentLength_ && contentPosition_ != contentLength_) |
910 | 70 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
71 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
|
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 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
76 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
|
77 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
78 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
|
79 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
80 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
910 | 81 } |
82 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
83 status_ = status; |
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 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
87 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
|
88 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
89 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
|
90 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
91 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
|
92 } |
910 | 93 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
94 hasContentLength_ = true; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
95 contentLength_ = length; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
96 } |
910 | 97 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
98 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
|
99 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
100 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
|
101 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
102 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
103 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
|
104 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
105 // 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
|
106 AddHeader("Content-Disposition", "filename=\"" + std::string(filename) + "\""); |
910 | 107 } |
108 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
109 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
|
110 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
|
111 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
112 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
|
113 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
114 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
|
115 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
116 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
117 // TODO Escape "=" characters |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
118 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
|
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 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
122 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
|
123 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
|
124 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
125 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
|
126 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
127 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
|
128 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
129 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
130 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
|
131 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
132 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
133 void HttpOutput::StateMachine::ClearHeaders() |
910 | 134 { |
135 if (state_ != State_WritingHeader) | |
136 { | |
137 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
138 } | |
139 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
140 headers_.clear(); |
910 | 141 } |
142 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
143 void HttpOutput::StateMachine::SendBody(const void* buffer, size_t length) |
910 | 144 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
145 if (state_ == State_Done) |
910 | 146 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
147 if (length == 0) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
148 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
149 return; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
150 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
151 else |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
152 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
153 LOG(ERROR) << "Because of keep-alive connections, the entire body must be sent at once or Content-Length must be given"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
154 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
|
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 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
178 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
179 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
|
180 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
|
181 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
182 s += *it; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
183 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
184 |
1115
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
185 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
|
186 { |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
187 hasContentLength_ = false; |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
188 } |
da56a7916e8a
Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1113
diff
changeset
|
189 |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
190 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
|
191 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
|
192 |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
193 stream_.Send(true, s.c_str(), s.size()); |
910 | 194 state_ = State_WritingBody; |
195 } | |
196 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
197 if (hasContentLength_ && |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
198 contentPosition_ + length > contentLength_) |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
199 { |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
200 LOG(ERROR) << "The body size exceeds what was declared with SetContentSize()"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
201 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
|
202 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
203 |
910 | 204 if (length > 0) |
205 { | |
911 | 206 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
|
207 contentPosition_ += length; |
330 | 208 } |
209 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
210 if (!hasContentLength_ || |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
211 contentPosition_ == contentLength_) |
330 | 212 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
213 state_ = State_Done; |
330 | 214 } |
215 } | |
216 | |
207 | 217 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
218 void HttpOutput::StateMachine::CloseBody() |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
219 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
220 switch (state_) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
221 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
222 case State_WritingHeader: |
1522 | 223 SetContentLength(0); |
224 SendBody(NULL, 0); | |
225 break; | |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
226 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
227 case State_WritingBody: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
228 if (!hasContentLength_ || |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
229 contentPosition_ == contentLength_) |
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 state_ = State_Done; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
232 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
233 else |
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 LOG(ERROR) << "The body size has not reached what was declared with SetContentSize()"; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
236 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
237 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
238 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
239 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
240 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
241 case State_WritingMultipart: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
242 LOG(ERROR) << "Cannot invoke CloseBody() with multipart outputs"; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
243 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
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_Done: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
246 return; // Ignore |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
247 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
248 default: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
249 throw OrthancException(ErrorCode_InternalError); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
250 } |
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 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
253 |
1517 | 254 HttpCompression HttpOutput::GetPreferredCompression(size_t bodySize) const |
255 { | |
256 #if 0 | |
257 // TODO Do not compress small files? | |
258 if (bodySize < 512) | |
259 { | |
260 return HttpCompression_None; | |
261 } | |
262 #endif | |
263 | |
264 // Prefer "gzip" over "deflate" if the choice is offered | |
265 | |
266 if (isGzipAllowed_) | |
267 { | |
268 return HttpCompression_Gzip; | |
269 } | |
270 else if (isDeflateAllowed_) | |
271 { | |
272 return HttpCompression_Deflate; | |
273 } | |
274 else | |
275 { | |
276 return HttpCompression_None; | |
277 } | |
278 } | |
279 | |
280 | |
1042
8d1845feb277
set cookies, not allowed methods, unauthorized in plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
911
diff
changeset
|
281 void HttpOutput::SendMethodNotAllowed(const std::string& allowed) |
0 | 282 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
283 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
284 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
|
285 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
|
286 stateMachine_.SendBody(NULL, 0); |
0 | 287 } |
288 | |
289 | |
1567
9c5d93510414
If error while calling the REST API, the answer body contains an error description
jodogne
parents:
1523
diff
changeset
|
290 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
|
291 const char* message, |
9c5d93510414
If error while calling the REST API, the answer body contains an error description
jodogne
parents:
1523
diff
changeset
|
292 size_t messageSize) |
0 | 293 { |
1954 | 294 if (status == HttpStatus_301_MovedPermanently || |
908
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
295 status == HttpStatus_401_Unauthorized || |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
398
diff
changeset
|
296 status == HttpStatus_405_MethodNotAllowed) |
0 | 297 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
298 LOG(ERROR) << "Please use the dedicated methods to this HTTP status code in HttpOutput"; |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
299 throw OrthancException(ErrorCode_ParameterOutOfRange); |
0 | 300 } |
301 | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
302 stateMachine_.SetHttpStatus(status); |
1645
1558b3226b18
IHttpExceptionFormatter
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1592
diff
changeset
|
303 stateMachine_.SendBody(message, messageSize); |
339 | 304 } |
305 | |
306 | |
0 | 307 void HttpOutput::Redirect(const std::string& path) |
308 { | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
309 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
310 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
|
311 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
|
312 stateMachine_.SendBody(NULL, 0); |
0 | 313 } |
908
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
314 |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
315 |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
316 void HttpOutput::SendUnauthorized(const std::string& realm) |
e078ea944089
refactoring HttpOutput
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
317 { |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
318 stateMachine_.ClearHeaders(); |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
319 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
|
320 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
|
321 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
|
322 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
323 |
1521 | 324 void HttpOutput::Answer(const void* buffer, |
325 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
|
326 { |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
327 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
|
328 { |
1521 | 329 AnswerEmpty(); |
330 return; | |
331 } | |
332 | |
333 HttpCompression compression = GetPreferredCompression(length); | |
334 | |
335 if (compression == HttpCompression_None) | |
336 { | |
337 stateMachine_.SetContentLength(length); | |
338 stateMachine_.SendBody(buffer, length); | |
339 return; | |
340 } | |
341 | |
342 std::string compressed, encoding; | |
343 | |
344 switch (compression) | |
345 { | |
346 case HttpCompression_Deflate: | |
347 { | |
348 encoding = "deflate"; | |
349 ZlibCompressor compressor; | |
350 // Do not prefix the buffer with its uncompressed size, to be compatible with "deflate" | |
351 compressor.SetPrefixWithUncompressedSize(false); | |
352 compressor.Compress(compressed, buffer, length); | |
353 break; | |
354 } | |
355 | |
356 case HttpCompression_Gzip: | |
357 { | |
358 encoding = "gzip"; | |
359 GzipCompressor compressor; | |
360 compressor.Compress(compressed, buffer, length); | |
361 break; | |
362 } | |
363 | |
364 default: | |
365 throw OrthancException(ErrorCode_InternalError); | |
366 } | |
367 | |
368 LOG(TRACE) << "Compressing a HTTP answer using " << encoding; | |
369 | |
370 // The body is empty, do not use HTTP compression | |
371 if (compressed.size() == 0) | |
372 { | |
373 AnswerEmpty(); | |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
374 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
375 else |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
376 { |
1521 | 377 stateMachine_.AddHeader("Content-Encoding", encoding); |
378 stateMachine_.SetContentLength(compressed.size()); | |
379 stateMachine_.SendBody(compressed.c_str(), compressed.size()); | |
380 } | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
381 |
1521 | 382 stateMachine_.CloseBody(); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
383 } |
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
384 |
1521 | 385 |
386 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
|
387 { |
1521 | 388 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
|
389 } |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1486
diff
changeset
|
390 |
1521 | 391 |
392 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
|
393 { |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
394 stateMachine_.CloseBody(); |
1113
ba5c0908600c
Refactoring of HttpOutput ("Content-Length" header is now always sent)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1042
diff
changeset
|
395 } |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
396 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
397 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
398 void HttpOutput::StateMachine::StartMultipart(const std::string& subType, |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
399 const std::string& contentType) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
400 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
401 if (subType != "mixed" && |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
402 subType != "related") |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
403 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
404 throw OrthancException(ErrorCode_ParameterOutOfRange); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
405 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
406 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
407 if (keepAlive_) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
408 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
409 LOG(ERROR) << "Multipart answers are not implemented together with keep-alive connections"; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
410 throw OrthancException(ErrorCode_NotImplemented); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
411 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
412 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
413 if (state_ != State_WritingHeader) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
414 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
415 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
416 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
417 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
418 if (status_ != HttpStatus_200_Ok) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
419 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
420 SendBody(NULL, 0); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
421 return; |
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 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
424 stream_.OnHttpStatusReceived(status_); |
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 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
|
427 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
428 // Possibly add the cookies |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
429 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
|
430 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
|
431 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
432 if (!Toolbox::StartsWith(*it, "Set-Cookie: ")) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
433 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
434 LOG(ERROR) << "The only headers that can be set in multipart answers are Set-Cookie (here: " << *it << " is set)"; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
435 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
436 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
437 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
438 header += *it; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
439 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
440 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
441 multipartBoundary_ = Toolbox::GenerateUuid(); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
442 multipartContentType_ = contentType; |
1855
aa95aea0a352
Fix formatting of multipart HTTP answers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1832
diff
changeset
|
443 header += "Content-Type: multipart/" + subType + "; type=" + contentType + "; boundary=" + multipartBoundary_ + "\r\n\r\n"; |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
444 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
445 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
|
446 state_ = State_WritingMultipart; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
447 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
448 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
449 |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
450 void HttpOutput::StateMachine::SendMultipartItem(const void* item, |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
451 size_t length, |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
452 const std::map<std::string, std::string>& headers) |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
453 { |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
454 if (state_ != State_WritingMultipart) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
455 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
456 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
457 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
458 |
1832
b7da58699f92
Fix formatting of multipart HTTP answers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1645
diff
changeset
|
459 std::string header = "--" + multipartBoundary_ + "\r\n"; |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
460 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
461 bool hasContentType = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
462 bool hasContentLength = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
463 bool hasMimeVersion = false; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
464 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
465 for (std::map<std::string, std::string>::const_iterator |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
466 it = headers.begin(); it != headers.end(); ++it) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
467 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
468 header += it->first + ": " + it->second + "\r\n"; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
469 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
470 std::string tmp; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
471 Toolbox::ToLowerCase(tmp, it->first); |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
472 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
473 if (tmp == "content-type") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
474 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
475 hasContentType = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
476 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
477 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
478 if (tmp == "content-length") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
479 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
480 hasContentLength = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
481 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
482 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
483 if (tmp == "mime-version") |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
484 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
485 hasMimeVersion = true; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
486 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
487 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
488 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
489 if (!hasContentType) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
490 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
491 header += "Content-Type: " + multipartContentType_ + "\r\n"; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
492 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
493 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
494 if (!hasContentLength) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
495 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
496 header += "Content-Length: " + boost::lexical_cast<std::string>(length) + "\r\n"; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
497 } |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
498 |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
499 if (!hasMimeVersion) |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
500 { |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
501 header += "MIME-Version: 1.0\r\n\r\n"; |
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
502 } |
1430
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
503 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
504 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
|
505 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
506 if (length > 0) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
507 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
508 stream_.Send(false, item, length); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
509 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
510 |
1882
5cf2bd0abfa2
OrthancPluginSendMultipartItem2 for DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1875
diff
changeset
|
511 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
|
512 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
513 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
514 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
515 void HttpOutput::StateMachine::CloseMultipart() |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
516 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
517 if (state_ != State_WritingMultipart) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
518 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
519 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
520 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
521 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
522 // 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
|
523 // 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
|
524 try |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
525 { |
1832
b7da58699f92
Fix formatting of multipart HTTP answers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1645
diff
changeset
|
526 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
|
527 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
|
528 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
529 catch (OrthancException&) |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
530 { |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
531 } |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
532 |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
533 state_ = State_Done; |
ad94a3583b07
Plugins can send answers as multipart messages
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
534 } |
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 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
537 void HttpOutput::Answer(IHttpStreamAnswer& stream) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
538 { |
1523
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
539 HttpCompression compression = stream.SetupHttpCompression(isGzipAllowed_, isDeflateAllowed_); |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
540 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
541 switch (compression) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
542 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
543 case HttpCompression_None: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
544 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
545 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
546 case HttpCompression_Gzip: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
547 stateMachine_.AddHeader("Content-Encoding", "gzip"); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
548 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
549 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
550 case HttpCompression_Deflate: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
551 stateMachine_.AddHeader("Content-Encoding", "deflate"); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
552 break; |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
553 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
554 default: |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
555 throw OrthancException(ErrorCode_ParameterOutOfRange); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
556 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
557 |
1523
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
558 stateMachine_.SetContentLength(stream.GetContentLength()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
559 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
560 std::string contentType = stream.GetContentType(); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
561 if (contentType.empty()) |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
562 { |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
563 contentType = "application/octet-stream"; |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
564 } |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
565 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
566 stateMachine_.SetContentType(contentType.c_str()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
567 |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
568 std::string filename; |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
569 if (stream.HasContentFilename(filename)) |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
570 { |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
571 SetContentFilename(filename.c_str()); |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
572 } |
c388502a066d
testing FilesystemHttpSender
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1522
diff
changeset
|
573 |
1519
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
574 while (stream.ReadNextChunk()) |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
575 { |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
576 stateMachine_.SendBody(stream.GetChunkContent(), |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
577 stream.GetChunkSize()); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
578 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
579 |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
580 stateMachine_.CloseBody(); |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
581 } |
8bd0d897763f
refactoring: IHttpStreamAnswer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1517
diff
changeset
|
582 |
0 | 583 } |