ATLAS Offline Software
CrestRequest.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 #include <iostream>
7 #include "nlohmann/json.hpp"
8 
9 #include <boost/uuid/uuid.hpp> // uuid class
10 #include <boost/uuid/uuid_generators.hpp> // generators
11 #include <boost/uuid/uuid_io.hpp>
12 #include <boost/asio.hpp>
13 #include <fstream>
14 
15 #include <string>
16 #include <map>
18 
19 namespace Crest
20 {
21 
23  {
24  curl_global_init(CURL_GLOBAL_ALL);
26  }
27 
29  {
30  curl_global_cleanup();
31  }
32 
33  void CrestRequest::setHost(const std::string &host)
34  {
35  m_host = host;
36  }
37 
38  void CrestRequest::setPort(const std::string &port)
39  {
40  m_port = port;
41  }
42 
43  void CrestRequest::setPrefix(const std::string &prefix)
44  {
45  m_prefix = prefix;
46  }
47 
48  std::string CrestRequest::make_url(const std::string &address) const
49  {
50  std::string str = m_prefix;
51  str += m_host;
52  str += ':';
53  str += m_port;
54  str += address;
55  return str;
56  }
57 
58  size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::vector<char> *output)
59  {
60  size_t total_size = size * nmemb;
61  output->insert(output->end(), reinterpret_cast<char *>(contents), reinterpret_cast<char *>(contents) + total_size);
62  return total_size;
63  }
64 
65  size_t curlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
66  {
67  size_t newLength = size * nmemb;
68 
69  try
70  {
71  s->append((char *)contents, newLength);
72  }
73  catch (std::bad_alloc &e)
74  {
75  std::cout << "Not enough memory to allocate "<<newLength<<" bytes "<< std::endl;
76  return 0;
77  }
78  return newLength;
79  }
80 
81  // Callback function to provide data for the request
82  size_t ReadCallback(void *contents, size_t size, size_t nmemb, std::string *input)
83  {
84  size_t totalSize = size * nmemb;
85  if (!input->empty())
86  {
87  // Copy data from the input string to the buffer
88  size_t toCopy = std::min(totalSize, input->size());
89  std::memcpy(contents, input->c_str(), toCopy);
90  input->erase(0, toCopy);
91  return toCopy;
92  }
93  return 0;
94  }
95 
96  std::string CrestRequest::performRequest(const std::string &current_path, Action action, nlohmann::json &js,
97  const char *method_name, const std::string& header_params)
98  {
99  CURL *curl;
100  CURLcode res;
101 
102  /* Enable tracing of ascii data */
103  // sanitise the current path
104  std::string sanitisedPath(current_path);
105  auto caretPosition = sanitisedPath.find('^');
106  if (caretPosition != std::string::npos)
107  sanitisedPath.replace(caretPosition, 1, "%5E");
108  /* get a curl handle */
109  curl = curl_easy_init();
110  std::string stt;
111  struct curl_slist *headers = NULL;
112  if (curl)
113  {
114  std::string url = make_url(sanitisedPath);
115  std::string s;
116  std::cout << "cURL request to " << url << std::endl;
117 
118  if (m_CREST_PROXY)
119  {
120  // Set the proxy type (replace with your proxy type details)
121  curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
122 
123  // Set the proxy address and port (replace with your SOCKS proxy details)
124  curl_easy_setopt(curl, CURLOPT_PROXY, m_CREST_PROXY);
125  }
126 
127  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
128  if (js.is_null())
129  {
130  if (action == Action::DELETE)
131  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
132  if (header_params != "")
133  {
134  headers = curl_slist_append(headers, header_params.c_str());
135  }
136  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
137  }
138  else
139  {
140  stt = js.dump();
141 
142  if (action == Action::PUT)
143  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
144  headers = curl_slist_append(headers, "Accept: */*");
145  headers = curl_slist_append(headers, "Content-Type: application/json");
146 
147  if (header_params != "")
148  {
149  headers = curl_slist_append(headers, header_params.c_str());
150  }
151  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
152  curl_easy_setopt(curl, CURLOPT_POST, 1L);
153 
154  /* set where to read from (on Windows you need to use READFUNCTION too) */
155  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, stt.c_str());
156  }
157 
158  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWrite_CallbackFunc_StdString);
159  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
160 
161  /* Perform the request, res will get the return code */
162  res = curl_easy_perform(curl);
163 
164  // data to check the errors in the server response:
165  long response_code;
166  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
167 
168  /* always cleanup */
169  curl_easy_cleanup(curl);
170  curl_slist_free_all(headers);
171 
172  curl_global_cleanup();
173 
174  // error checking in the server response:
175  checkResult(res, response_code, s, method_name);
176 
177  return s;
178  }
179 
180  throw CrestException(std::string("ERROR in ") + std::string(method_name) + " | CURL not init");
181  }
182 
183  std::vector<char> CrestRequest::getPayloadRequest(const std::string &current_path)
184  {
185  // Initialize libcurl
186  CURL *curl;
187  CURLcode res;
188 
189  curl_global_init(CURL_GLOBAL_DEFAULT);
190  curl = curl_easy_init();
191 
192  if (curl)
193  {
194  std::string url = make_url(current_path);
195  std::string response;
196 
197  std::string content_type = "application/octet-stream";
198 
199  if (m_CREST_PROXY)
200  {
201  // Set the proxy type (replace with your proxy type details)
202  curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
203 
204  // Set the proxy address and port (replace with your SOCKS proxy details)
205  curl_easy_setopt(curl, CURLOPT_PROXY, m_CREST_PROXY);
206  }
207  else
208  {
209  // The environment variable does not exist
210  std::cerr << "SOCKS_PROXY environment variable not found." << std::endl;
211  }
212  //
213 
214  // First set the URL that is about to receive the GET. This URL can
215  // just as well be a https:
216  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
217 
218  // Set the write callback function to handle the response
219  std::vector<char> response_data;
220  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
221  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
222  // Perform the request
223  res = curl_easy_perform(curl);
224 
225  // data to check the errors in the server response:
226  long response_code;
227  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
228 
229  curl_easy_cleanup(curl);
230 
231  // error checking in the server response:
232  const char *method_name = "CrestRequest::getPayloadRequest";
233  checkResult(res, response_code, response, method_name);
234 
235  return response_data;
236  }
237  throw CrestException(std::string("ERROR in ") + "getPayloadRequest CURL not init");
238  }
239 
240 
241  std::string CrestRequest::uploadPayload(const std::string &current_path, const std::string &tag, uint64_t endtime, const nlohmann::json &js,
242  const std::string& objectType, const std::string& compressionType, const std::string& version,
243  const std::vector<std::string> &files)
244  {
245 
246  CURL *curl;
247 
248  curl_global_init(CURL_GLOBAL_DEFAULT);
249  curl = curl_easy_init();
250 
251  struct curl_slist *headers = NULL;
252 
253  if (curl)
254  {
255  std::string url = make_url(current_path);
256  std::string response;
257 
258  std::string content_type = "application/octet-stream";
259 
260  if (m_CREST_PROXY)
261  {
262  // Set the proxy type (replace with your proxy type details)
263  curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
264 
265  // Set the proxy address and port (replace with your SOCKS proxy details)
266  curl_easy_setopt(curl, CURLOPT_PROXY, m_CREST_PROXY);
267  }
268 
269  //
270 
271  // First set the URL that is about to receive our POST. This URL can
272  // just as well be a https:
273  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
274  std::string js_str = js.dump();
275 
276  // Enable verbose mode
277  // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
278 
279  std::string format = "X-Crest-PayloadFormat: ";
280  if (files.size() > 0)
281  {
282  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
283  format += "FILE";
284  content_type = "application/form-data";
285  }
286  else
287  {
288  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
289  format += "JSON";
290  }
291  headers = curl_slist_append(headers, format.c_str());
292  headers = curl_slist_append(headers, "Accept: application/json");
293  headers = curl_slist_append(headers, "Content-Type: multipart/form-data");
294 
295  // Create the form for new version
296 #if LIBCURL_VERSION_MAJOR < 8
297  struct curl_httppost *formpost = NULL;
298  struct curl_httppost *lastptr = NULL;
299  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "tag", CURLFORM_COPYCONTENTS, tag.c_str(), CURLFORM_END);
300  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "endtime", CURLFORM_COPYCONTENTS, std::to_string(endtime).c_str(), CURLFORM_END);
301  // Set the read callback function
302  // Add the "storeset" field with the JSON data directly
303  curl_formadd(&formpost, &lastptr,
304  CURLFORM_COPYNAME, "storeset",
305  CURLFORM_BUFFER, "json_data",
306  CURLFORM_BUFFERPTR, js_str.c_str(),
307  CURLFORM_BUFFERLENGTH, js_str.size(),
308  CURLFORM_CONTENTTYPE, content_type.c_str(),
309  CURLFORM_END);
310 
311  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "version", CURLFORM_COPYCONTENTS, version.c_str(), CURLFORM_END);
312  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "objectType", CURLFORM_COPYCONTENTS, objectType.c_str(), CURLFORM_END);
313  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "compressionType", CURLFORM_COPYCONTENTS, compressionType.c_str(), CURLFORM_END);
314 
315  for (auto &file : files)
316  {
317  curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "files", CURLFORM_FILE, file.c_str(), CURLFORM_END);
318  }
319  curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
320 
321 #else
322 
323  curl_mime *mime = curl_mime_init(curl);
324  {
325  curl_mimepart *part = curl_mime_addpart(mime);
326  curl_mime_name(part, "tag");
327  curl_mime_data(part, tag.c_str(), tag.size());
328 
329  part = curl_mime_addpart(mime);
330  std::string endtime_s = std::to_string(endtime);
331  curl_mime_name(part, "endtime");
332  curl_mime_data(part, endtime_s.c_str(), endtime_s.size());
333 
334  part = curl_mime_addpart(mime);
335  curl_mime_name(part, "version");
336  curl_mime_data(part, version.c_str(), version.size());
337 
338  part = curl_mime_addpart(mime);
339  curl_mime_name(part, "objectType");
340  curl_mime_data(part, objectType.c_str(), objectType.size());
341 
342  part = curl_mime_addpart(mime);
343  curl_mime_name(part, "compressionType");
344  curl_mime_data(part, compressionType.c_str(), compressionType.size());
345 
346  part = curl_mime_addpart(mime);
347  curl_mime_name(part, "storeset");
348  curl_mime_type(part, content_type.c_str());
349  curl_mime_data(part, js.dump().c_str(), js.dump().size());
350 
351  for (auto &file : files)
352  {
353  curl_mimepart *part = curl_mime_addpart(mime);
354  curl_mime_name(part, "files");
355  curl_mime_filedata(part, file.c_str());
356  }
357  }
358  curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
359 #endif
360  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
361 
362  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWrite_CallbackFunc_StdString);
363  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
364 
365  // Perform the request
366  CURLcode res = curl_easy_perform(curl);
367 
368  // data to check the errors in the server response:
369  long response_code;
370  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
371  const char *method_name = "CrestRequest::uploadPayload";
372 
373  /* always cleanup */
374  curl_easy_cleanup(curl);
375 #if LIBCURL_VERSION_MAJOR < 8
376  curl_formfree(formpost);
377 #else
378  curl_mime_free(mime);
379 #endif
380  curl_slist_free_all(headers);
381  curl_global_cleanup();
382 
383  // error checking in the server response:
384  checkResult(res, response_code, response, method_name);
385 
386  return response;
387  }
388  std::string mes = "ERROR in CrestRequest::uploadPayload";
389  throw CrestException(mes + " | CURL not init");
390  }
391  // end of REQUEST METHODS
392 
393  // The auxillary method to remove XML/HTML tags from a std::string
394 
395  std::string CrestRequest::parseXMLOutput(std::string_view xmlBuffer)
396  {
397  bool copy = true;
398 
399  std::string plainString = "";
400 
401  // remove all xml tags
402  for (long unsigned int i = 0; i < xmlBuffer.length(); i++)
403  {
404  char convertc = xmlBuffer[i];
405 
406  if (convertc == '<')
407  copy = false;
408  else if (convertc == '>')
409  {
410  copy = true;
411  continue;
412  }
413 
414  if (copy)
415  plainString += convertc;
416  }
417 
418  return plainString;
419  }
420 
421  std::string CrestRequest::removeCR(const std::string &str)
422  {
423  std::string str2 = str;
424  std::replace(str2.begin(), str2.end(), '\n', '|');
425  char needle = '\r';
426  size_t pos;
427  while ((pos = str2.find(needle)) != str2.npos)
428  {
429  str2.erase(pos, 1);
430  }
431  return str2;
432  }
433 
434  bool CrestRequest::isJson(const std::string &str)
435  {
436  try
437  {
439  return true;
440  }
441  catch (nlohmann::json::parse_error &e)
442  {
443  return false;
444  }
445  }
446 
447  void CrestRequest::checkResult(CURLcode res, const long response_code, const std::string &st,
448  const char *method_name)
449  {
450  // Bad HTTP response:
451 
452  if (res != CURLE_OK)
453  {
454  std::string mes = "ERROR in ";
455  mes += method_name;
456  mes += " | ";
457  throw CrestException(mes + std::to_string(response_code));
458  }
459 
460  // Errors, decoded from JSON CREST Server messages:
461 
462  if (isJson(st))
463  {
464  nlohmann::json respond = getJson(st);
465  checkErrors(respond, method_name);
466  }
467 
468  // HTTP response code error interval:
469 
470  if (response_code >= 400 || response_code == 303)
471  {
472  std::string s = parseXMLOutput(st); // to remove HTML tags
473  s = removeCR(s); // to remove end lines and carridge returns
474  std::string mes = "ERROR in ";
475  mes += method_name;
476  mes += " | ";
477  throw CrestException(mes + "CREST Server response : " + s);
478  }
479  }
480 
481  nlohmann::json CrestRequest::getJson(const std::string &str, const char *method)
482  {
483  try
484  {
486  return js;
487  }
488  catch (nlohmann::json::parse_error &e)
489  {
490  if (method == nullptr || *method == '\0')
491  {
492  // method name is undefined
493 
494  std::string wh = e.what();
495  throw CrestException("ERROR in JSON conversion: " + wh + " | In string: " + str);
496  }
497  else
498  {
499  std::string str2 = parseXMLOutput(str); // to remove HTML tags use this function
500  std::string str3 = removeCR(str2); // to remove carridge return
501  throw CrestException("ERROR in " + std::string(method) + " | CREST Server response : " + str3);
502  }
503  }
504  }
505 
507  {
508  return getJson(str, "");
509  }
510 
511  int CrestRequest::checkErrors(const nlohmann::json &js, const char *method)
512  {
513  int result = 0;
514  auto res = js.find("type");
515 
516  // Old format parsing:
517 
518  if (res != js.end())
519  {
520  std::string type = js.value("type", " unknown type ");
521  if (type == "error" || type == "info")
522  {
523  std::string message = js.value("message", " unknown message ");
524  throw CrestException("ERROR in " + std::string(method) + " | CREST response: " + message);
525  }
526  }
527 
528  // New format parsing:
529 
530  auto r1 = js.find("error");
531  auto r2 = js.find("message");
532 
533  if (r1 != js.end())
534  {
535  std::string error = js.value("error", " unknown error ");
536  if (r2 != js.end())
537  {
538  std::string message = js.value("message", "");
539  throw CrestException("ERROR in " + std::string(method) + " | CREST response: " + (message.empty() ?error : message));
540  }
541  }
542  return result;
543  }
544 
545 }
RunTileTBRec.method
method
Definition: RunTileTBRec.py:73
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
Crest::WriteCallback
size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::vector< char > *output)
Definition: CrestRequest.cxx:58
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
covarianceTool.headers
headers
Definition: covarianceTool.py:537
Crest::CrestRequest::m_prefix
std::string m_prefix
Definition: CrestRequest.h:66
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Crest::CrestRequest::make_url
std::string make_url(const std::string &address) const
Definition: CrestRequest.cxx:48
get_generator_info.result
result
Definition: get_generator_info.py:21
vtune_athena.format
format
Definition: vtune_athena.py:14
Crest::ReadCallback
size_t ReadCallback(void *contents, size_t size, size_t nmemb, std::string *input)
Definition: CrestRequest.cxx:82
json
nlohmann::json json
Definition: HistogramDef.cxx:9
response
MDT_Response response
Definition: MDT_ResponseTest.cxx:28
CrestException.h
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Crest::CrestRequest::~CrestRequest
~CrestRequest()
Definition: CrestRequest.cxx:28
Crest::CrestRequest::parseXMLOutput
std::string parseXMLOutput(const std::string_view xmlBuffer)
Definition: CrestRequest.cxx:395
parse
std::map< std::string, std::string > parse(const std::string &list)
Definition: egammaLayerRecalibTool.cxx:1054
Crest::Action::DELETE
@ DELETE
Crest::CrestRequest::performRequest
std::string performRequest(const std::string &current_path, Action action, nlohmann::json &js, const std::string &header_params="")
General auxiliary method to make request to the CREST Server.
Crest::CrestRequest::uploadPayload
std::string uploadPayload(const std::string &current_path, const std::string &tag, uint64_t endtime, const nlohmann::json &js, const std::string &objectType, const std::string &compressionType, const std::string &version, const std::vector< std::string > &files)
Definition: CrestRequest.cxx:241
Crest::CrestRequest::m_CREST_PROXY
char * m_CREST_PROXY
Definition: CrestRequest.h:71
Crest::CrestRequest::setPrefix
void setPrefix(const std::string &prefix)
Definition: CrestRequest.cxx:43
Crest::CrestRequest::CrestRequest
CrestRequest()
Definition: CrestRequest.cxx:22
Crest::CrestRequest::checkResult
void checkResult(CURLcode res, long response_code, const std::string &st, const char *method_name)
Definition: CrestRequest.cxx:447
Crest
Definition: CrestApi.h:30
ReweightUtils.message
message
Definition: ReweightUtils.py:15
physics_parameters.url
string url
Definition: physics_parameters.py:27
hotSpotInTAG.objectType
objectType
Definition: hotSpotInTAG.py:107
Crest::CrestRequest::getJson
nlohmann::json getJson(const std::string &str, const char *method)
Definition: CrestRequest.cxx:481
Crest::CrestRequest::setHost
void setHost(const std::string &host)
Definition: CrestRequest.cxx:33
Crest::CrestRequest::removeCR
std::string removeCR(const std::string &str)
Definition: CrestRequest.cxx:421
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
lumiFormat.i
int i
Definition: lumiFormat.py:85
CrestRequest.h
Crest::CrestRequest::isJson
bool isJson(const std::string &str)
Definition: CrestRequest.cxx:434
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
Crest::curlWrite_CallbackFunc_StdString
size_t curlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
Definition: CrestRequest.cxx:65
generateReferenceFile.files
files
Definition: generateReferenceFile.py:12
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
file
TFile * file
Definition: tile_monitor.h:29
parseDir.wh
wh
Definition: parseDir.py:46
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
Crest::CrestRequest::m_port
std::string m_port
Definition: CrestRequest.h:68
contents
void contents(std::vector< std::string > &keys, TDirectory *td, const std::string &directory, const std::string &pattern, const std::string &path)
Definition: computils.cxx:320
Crest::CrestRequest::getPayloadRequest
std::vector< char > getPayloadRequest(const std::string &current_path)
Definition: CrestRequest.cxx:183
merge.output
output
Definition: merge.py:17
Crest::Action::PUT
@ PUT
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
Crest::CrestRequest::checkErrors
int checkErrors(const nlohmann::json &js, const char *method)
Definition: CrestRequest.cxx:511
RTTAlgmain.address
address
Definition: RTTAlgmain.py:55
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Crest::Action
Action
Definition: CrestRequest.h:21
get_generator_info.version
version
Definition: get_generator_info.py:33
SCT_ConditionsAlgorithms::CoveritySafe::getenv
std::string getenv(const std::string &variableName)
get an environment variable
Definition: SCT_ConditionsUtilities.cxx:17
Crest::CrestRequest::m_CREST_PROXY_VAR
const char * m_CREST_PROXY_VAR
Definition: CrestRequest.h:72
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
python.CaloScaleNoiseConfig.action
action
Definition: CaloScaleNoiseConfig.py:77
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
str
Definition: BTagTrackIpAccessor.cxx:11
python.copyTCTOutput.totalSize
totalSize
Definition: copyTCTOutput.py:93
calibdata.copy
bool copy
Definition: calibdata.py:27
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:24
error
Definition: IImpactPoint3dEstimator.h:70
Crest::CrestRequest::setPort
void setPort(const std::string &port)
Definition: CrestRequest.cxx:38
Crest::CrestException
Definition: CrestException.h:9
Crest::CrestRequest::m_host
std::string m_host
Definition: CrestRequest.h:67