comparison Framework/Oracle/GenericOracleRunner.cpp @ 1077:d7a18a3cd6f9 broker

IOracleRunner
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Oct 2019 16:51:41 +0200
parents
children e6d2ff8f1ab4
comparison
equal deleted inserted replaced
1076:008dbc4ceb62 1077:d7a18a3cd6f9
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
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
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "GenericOracleRunner.h"
23
24 #include "CustomOracleCommand.h"
25 #include "GetOrthancImageCommand.h"
26 #include "GetOrthancWebViewerJpegCommand.h"
27 #include "HttpCommand.h"
28 #include "OracleCommandExceptionMessage.h"
29 #include "OrthancRestApiCommand.h"
30
31 #include <Core/Compression/GzipCompressor.h>
32 #include <Core/HttpClient.h>
33 #include <Core/OrthancException.h>
34 #include <Core/Toolbox.h>
35
36 namespace OrthancStone
37 {
38 static void CopyHttpHeaders(Orthanc::HttpClient& client,
39 const Orthanc::HttpClient::HttpHeaders& headers)
40 {
41 for (Orthanc::HttpClient::HttpHeaders::const_iterator
42 it = headers.begin(); it != headers.end(); it++ )
43 {
44 client.AddHeader(it->first, it->second);
45 }
46 }
47
48
49 static void DecodeAnswer(std::string& answer,
50 const Orthanc::HttpClient::HttpHeaders& headers)
51 {
52 Orthanc::HttpCompression contentEncoding = Orthanc::HttpCompression_None;
53
54 for (Orthanc::HttpClient::HttpHeaders::const_iterator it = headers.begin();
55 it != headers.end(); ++it)
56 {
57 std::string s;
58 Orthanc::Toolbox::ToLowerCase(s, it->first);
59
60 if (s == "content-encoding")
61 {
62 if (it->second == "gzip")
63 {
64 contentEncoding = Orthanc::HttpCompression_Gzip;
65 }
66 else
67 {
68 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol,
69 "Unsupported HTTP Content-Encoding: " + it->second);
70 }
71
72 break;
73 }
74 }
75
76 if (contentEncoding == Orthanc::HttpCompression_Gzip)
77 {
78 std::string compressed;
79 answer.swap(compressed);
80
81 Orthanc::GzipCompressor compressor;
82 compressor.Uncompress(answer, compressed.c_str(), compressed.size());
83
84 LOG(INFO) << "Uncompressing gzip Encoding: from " << compressed.size()
85 << " to " << answer.size() << " bytes";
86 }
87 }
88
89
90 static void Execute(IMessageEmitter& emitter,
91 boost::weak_ptr<IObserver>& receiver,
92 const HttpCommand& command)
93 {
94 Orthanc::HttpClient client;
95 client.SetUrl(command.GetUrl());
96 client.SetMethod(command.GetMethod());
97 client.SetTimeout(command.GetTimeout());
98
99 CopyHttpHeaders(client, command.GetHttpHeaders());
100
101 if (command.GetMethod() == Orthanc::HttpMethod_Post ||
102 command.GetMethod() == Orthanc::HttpMethod_Put)
103 {
104 client.SetBody(command.GetBody());
105 }
106
107 std::string answer;
108 Orthanc::HttpClient::HttpHeaders answerHeaders;
109 client.ApplyAndThrowException(answer, answerHeaders);
110
111 DecodeAnswer(answer, answerHeaders);
112
113 HttpCommand::SuccessMessage message(command, answerHeaders, answer);
114 emitter.EmitMessage(receiver, message);
115 }
116
117
118 static void Execute(IMessageEmitter& emitter,
119 const Orthanc::WebServiceParameters& orthanc,
120 boost::weak_ptr<IObserver>& receiver,
121 const OrthancRestApiCommand& command)
122 {
123 Orthanc::HttpClient client(orthanc, command.GetUri());
124 client.SetMethod(command.GetMethod());
125 client.SetTimeout(command.GetTimeout());
126
127 CopyHttpHeaders(client, command.GetHttpHeaders());
128
129 if (command.GetMethod() == Orthanc::HttpMethod_Post ||
130 command.GetMethod() == Orthanc::HttpMethod_Put)
131 {
132 client.SetBody(command.GetBody());
133 }
134
135 std::string answer;
136 Orthanc::HttpClient::HttpHeaders answerHeaders;
137 client.ApplyAndThrowException(answer, answerHeaders);
138
139 DecodeAnswer(answer, answerHeaders);
140
141 OrthancRestApiCommand::SuccessMessage message(command, answerHeaders, answer);
142 emitter.EmitMessage(receiver, message);
143 }
144
145
146 static void Execute(IMessageEmitter& emitter,
147 const Orthanc::WebServiceParameters& orthanc,
148 boost::weak_ptr<IObserver>& receiver,
149 const GetOrthancImageCommand& command)
150 {
151 Orthanc::HttpClient client(orthanc, command.GetUri());
152 client.SetTimeout(command.GetTimeout());
153
154 CopyHttpHeaders(client, command.GetHttpHeaders());
155
156 std::string answer;
157 Orthanc::HttpClient::HttpHeaders answerHeaders;
158 client.ApplyAndThrowException(answer, answerHeaders);
159
160 DecodeAnswer(answer, answerHeaders);
161
162 command.ProcessHttpAnswer(emitter, receiver, answer, answerHeaders);
163 }
164
165
166 static void Execute(IMessageEmitter& emitter,
167 const Orthanc::WebServiceParameters& orthanc,
168 boost::weak_ptr<IObserver>& receiver,
169 const GetOrthancWebViewerJpegCommand& command)
170 {
171 Orthanc::HttpClient client(orthanc, command.GetUri());
172 client.SetTimeout(command.GetTimeout());
173
174 CopyHttpHeaders(client, command.GetHttpHeaders());
175
176 std::string answer;
177 Orthanc::HttpClient::HttpHeaders answerHeaders;
178 client.ApplyAndThrowException(answer, answerHeaders);
179
180 DecodeAnswer(answer, answerHeaders);
181
182 command.ProcessHttpAnswer(emitter, receiver, answer);
183 }
184
185
186 void GenericOracleRunner::Run(boost::weak_ptr<IObserver>& receiver,
187 IOracleCommand& command)
188 {
189 try
190 {
191 switch (command.GetType())
192 {
193 case IOracleCommand::Type_Sleep:
194 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType,
195 "Sleep command cannot be executed by the runner");
196 break;
197
198 case IOracleCommand::Type_Http:
199 Execute(emitter_, receiver,
200 dynamic_cast<const HttpCommand&>(command));
201 break;
202
203 case IOracleCommand::Type_OrthancRestApi:
204 Execute(emitter_, orthanc_, receiver, dynamic_cast<const OrthancRestApiCommand&>(command));
205 break;
206
207 case IOracleCommand::Type_GetOrthancImage:
208 Execute(emitter_, orthanc_, receiver, dynamic_cast<const GetOrthancImageCommand&>(command));
209 break;
210
211 case IOracleCommand::Type_GetOrthancWebViewerJpeg:
212 Execute(emitter_, orthanc_, receiver, dynamic_cast<const GetOrthancWebViewerJpegCommand&>(command));
213 break;
214
215 case IOracleCommand::Type_Custom:
216 dynamic_cast<CustomOracleCommand&>(command).Execute(emitter_, receiver, *this);
217 break;
218
219 default:
220 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
221 }
222 }
223 catch (Orthanc::OrthancException& e)
224 {
225 LOG(ERROR) << "Exception within the oracle: " << e.What();
226 emitter_.EmitMessage(receiver, OracleCommandExceptionMessage(command, e));
227 }
228 catch (...)
229 {
230 LOG(ERROR) << "Threaded exception within the oracle";
231 emitter_.EmitMessage(receiver, OracleCommandExceptionMessage
232 (command, Orthanc::ErrorCode_InternalError));
233 }
234 }
235 }