Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THttpCallArg.cxx
Go to the documentation of this file.
1// $Id$
2// Author: Sergey Linev 21/05/2015
3
4/*************************************************************************
5 * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "THttpCallArg.h"
13
14#include <cstring>
15
16#include "RZip.h"
17#include "THttpWSEngine.h"
18
19/** \class THttpCallArg
20\ingroup http
21
22Contains arguments for single HTTP call
23
24Must be used in THttpEngine to process incoming http requests
25*/
26
27
28
29////////////////////////////////////////////////////////////////////////////////
30/// destructor
31
35
36////////////////////////////////////////////////////////////////////////////////
37/// method used to get or set http header in the string buffer
38///
39/// Header has following format:
40///
41/// field1 : value1\\r\\n
42/// field2 : value2\\r\\n
43///
44/// Such format corresponds to header format in HTTP requests
45
47{
48 if (name == 0)
49 return TString();
50
51 Int_t curr = 0;
52
53 while (curr < buf.Length() - 2) {
54
55 Int_t next = buf.Index("\r\n", curr);
56 if (next == kNPOS)
57 break; // should never happen
58
59 if (buf.Index(name, curr) != curr) {
60 curr = next + 2;
61 continue;
62 }
63
64 if ((value == 0) && doing_set) {
65 // special case - empty value means that field must be removed completely
66 buf.Remove(curr, next - curr + 2);
67 return TString();
68 }
69
70 curr += strlen(name);
71 while ((curr < next) && (buf[curr] != ':'))
72 curr++;
73 curr++;
74 while ((curr < next) && (buf[curr] == ' '))
75 curr++;
76
77 if (value == 0)
78 return buf(curr, next - curr);
79 buf.Remove(curr, next - curr);
80 buf.Insert(curr, value);
81 return TString(value);
82 }
83
84 if (value == 0)
85 return TString();
86
87 buf.Append(TString::Format("%s: %s\r\n", name, value));
88 return TString(value);
89}
90
91////////////////////////////////////////////////////////////////////////////////
92/// method used to counter number of headers or returns name of specified header
93
95{
96 Int_t curr = 0, cnt = 0;
97
98 while (curr < buf.Length() - 2) {
99
100 Int_t next = buf.Index("\r\n", curr);
101 if (next == kNPOS)
102 break; // should never happen
103
104 if (cnt == number) {
105 // we should extract name of header
106 Int_t separ = curr + 1;
107 while ((separ < next) && (buf[separ] != ':'))
108 separ++;
109 return buf(curr, separ - curr);
110 }
111
112 curr = next + 2;
113 cnt++;
114 }
115
116 // return total number of headers
117 if (number == -1111)
118 return TString::Format("%d", cnt);
119 return TString();
120}
121
122
123////////////////////////////////////////////////////////////////////////////////
124/// Set content as text.
125///
126/// Content will be copied by THttpCallArg
127
129{
130 if (cont)
131 fContent = cont;
132 else
133 fContent.clear();
134}
135
136////////////////////////////////////////////////////////////////////////////////
137/// Set text or binary content directly
138/// After method call argument cont will be in undefined state
139
141{
142 fContent = cont;
143}
144
145////////////////////////////////////////////////////////////////////////////////
146/// Set content type as "text/plain"
147
149{
150 SetContentType("text/plain");
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Set content type as "text/plain" and also assigns content
155///
156/// @param txt will be in undefined state after method call
157
159{
160 SetText();
161 fContent = txt;
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// Set content type as "text/xml"
166
168{
169 SetContentType("text/xml");
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Set content type as "text/xml" and also assigns content
174///
175/// @param xml will be in undefined state after method call
176
178{
179 SetXml();
180 fContent = xml;
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// Set content type as "application/json"
185
187{
188 SetContentType("application/json");
189}
190
191////////////////////////////////////////////////////////////////////////////////
192/// Set content type as "application/json" and also assigns content
193///
194/// @param json will be in undefined state after method call
195
197{
198 SetJson();
199 fContent = json;
200}
201
202////////////////////////////////////////////////////////////////////////////////
203/// Set content type as "application/x-binary"
204
206{
207 SetContentType("application/x-binary");
208}
209
210////////////////////////////////////////////////////////////////////////////////
211/// Set content type as "application/x-binary" and also assigns content
212///
213/// @param bin will be in undefined state after method call
214
215void THttpCallArg::SetBinaryContent(std::string &&bin)
216{
217 SetBinary();
218 fContent = bin;
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// Set data, posted with the request
223///
224/// If make_copy==kFALSE, data will be released with free(data) call
225/// @deprecated Use signature with std::string
226
228{
229 fPostData.resize(length);
230
231 if (data && length) {
232 std::copy((const char *)data, (const char *)data + length, fPostData.begin());
233 if (!make_copy) free(data); // it supposed to get ownership over the buffer
234 }
235}
236
237////////////////////////////////////////////////////////////////////////////////
238/// Set data, which is posted with the request
239///
240/// Although std::string is used, not only text data can be assigned -
241/// std::string can contain any sequence of symbols
242
244{
245 fPostData = data;
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// Assign websocket identifier from the engine
250
252{
253 SetWSId(fWSEngine->GetId());
254}
255
256////////////////////////////////////////////////////////////////////////////////
257/// Takeout websocket handle with HTTP call
258///
259/// can be done only once
260
261std::shared_ptr<THttpWSEngine> THttpCallArg::TakeWSEngine()
262{
263 auto res = fWSEngine;
264 fWSEngine.reset();
265 return res;
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Replace all occurrences of string in content
270///
271/// @param from that to replace
272/// @param to new content
273/// @param once set to true to stop after first occurrence is replaced
274
275/// Normally used only internally
276
277void THttpCallArg::ReplaceAllinContent(const std::string &from, const std::string &to, bool once)
278{
279 std::size_t start_pos = 0;
280 while((start_pos = fContent.find(from, start_pos)) != std::string::npos) {
281 fContent.replace(start_pos, from.length(), to);
282 if (once) return;
283 start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
284 }
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// Set complete path of requested http element
289///
290/// For instance, it could be "/folder/subfolder/get.bin"
291/// Here "/folder/subfolder/" is element path and "get.bin" requested file.
292/// One could set path and file name separately
293
295{
298
299 if (fullpath == 0)
300 return;
301
302 const char *rslash = strrchr(fullpath, '/');
303 if (rslash == 0) {
305 } else {
306 while ((fullpath != rslash) && (*fullpath == '/'))
307 fullpath++;
309 if (fPathName == "/")
311 fFileName = rslash + 1;
312 }
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Return specified header
317
319{
320 if ((name == 0) || (*name == 0))
321 return TString();
322
323 if (strcmp(name, "Content-Type") == 0)
324 return fContentType;
325 if (strcmp(name, "Content-Length") == 0)
326 return TString::Format("%ld", GetContentLength());
327
328 return AccessHeader(fHeader, name);
329}
330
331////////////////////////////////////////////////////////////////////////////////
332/// Set `name: value` pair to reply header
333///
334/// Content-Type field handled separately - one should use SetContentType() method
335/// Content-Length field cannot be set at all;
336
337void THttpCallArg::AddHeader(const char *name, const char *value)
338{
339 if ((name == 0) || (*name == 0) || (strcmp(name, "Content-Length") == 0))
340 return;
341
342 if (strcmp(name, "Content-Type") == 0)
344 else
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Set CacheControl http header to disable browser caching
350
352{
353 AddHeader("Cache-Control", "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Mark as chunked
358///
359/// Data to the client transferred in chunks.
360/// So many ProcessRequests will be invoked and produced data will be send as next chunk
361/// - until empty conent will be returned or chunked flag is cleared
362
364{
365 AccessHeader(fHeader, "Transfer-Encoding", on ? "chunked" : nullptr, kTRUE);
366}
367
368////////////////////////////////////////////////////////////////////////////////
369/// If marked as chunked
370
372{
373 return AccessHeader(fHeader, "Transfer-Encoding") == "chunked";
374}
375
376////////////////////////////////////////////////////////////////////////////////
377/// Fills HTTP header, which can be send at the beginning of reply on the http request
378///
379/// @param name is HTTP protocol name (default "HTTP/1.1")
380
381std::string THttpCallArg::FillHttpHeader(const char *name)
382{
383 std::string hdr(name ? name : "HTTP/1.1");
384
385 if ((fContentType.Length() == 0) || Is404())
386 hdr.append(" 404 Not Found\r\n"
387 "Content-Length: 0\r\n"
388 "Connection: close\r\n\r\n");
389 else if (IsChunked())
390 hdr.append(TString::Format(" 200 OK\r\n"
391 "Content-Type: %s\r\n"
392 "Connection: keep-alive\r\n"
393 "%s\r\n",
395 .Data());
396 else
397 hdr.append(TString::Format(" 200 OK\r\n"
398 "Content-Type: %s\r\n"
399 "Connection: keep-alive\r\n"
400 "Content-Length: %ld\r\n"
401 "%s\r\n",
403 .Data());
404
405 return hdr;
406}
407
408////////////////////////////////////////////////////////////////////////////////
409/// Compress reply data with gzip compression
410
412{
413 char *objbuf = (char *)GetContent();
415
416 unsigned long objcrc = R__crc32(0, NULL, 0);
417 objcrc = R__crc32(objcrc, (const unsigned char *)objbuf, objlen);
418
419 // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
420 Int_t buflen = 10 + objlen + 8;
421 if (buflen < 512)
422 buflen = 512;
423
424 std::string buffer;
425 buffer.resize(buflen);
426
427 char *bufcur = (char *)buffer.data();
428
429 *bufcur++ = 0x1f; // first byte of ZIP identifier
430 *bufcur++ = 0x8b; // second byte of ZIP identifier
431 *bufcur++ = 0x08; // compression method
432 *bufcur++ = 0x00; // FLAG - empty, no any file names
433 *bufcur++ = 0; // empty timestamp
434 *bufcur++ = 0; //
435 *bufcur++ = 0; //
436 *bufcur++ = 0; //
437 *bufcur++ = 0; // XFL (eXtra FLags)
438 *bufcur++ = 3; // OS 3 means Unix
439 // strcpy(bufcur, "item.json");
440 // bufcur += strlen("item.json")+1;
441
442 char dummy[8];
443 memcpy(dummy, bufcur - 6, 6);
444
445 // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
446 unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, objbuf, objlen);
447
448 memcpy(bufcur - 6, dummy, 6);
449
450 bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
451
452 // write CRC32
453 *bufcur++ = objcrc & 0xff;
454 *bufcur++ = (objcrc >> 8) & 0xff;
455 *bufcur++ = (objcrc >> 16) & 0xff;
456 *bufcur++ = (objcrc >> 24) & 0xff;
457
458 // write original data length
459 *bufcur++ = objlen & 0xff;
460 *bufcur++ = (objlen >> 8) & 0xff;
461 *bufcur++ = (objlen >> 16) & 0xff;
462 *bufcur++ = (objlen >> 24) & 0xff;
463
464 buffer.resize(bufcur - (char *)buffer.data());
465
466 SetContent(std::move(buffer));
467
468 SetEncoding("gzip");
469
470 return kTRUE;
471}
472
473////////////////////////////////////////////////////////////////////////////////
474/// Method used to notify condition which waiting when operation will complete
475///
476/// Condition notified only if not-postponed state is set
477
479{
480 if (!fNotifyFlag && !IsPostponed()) {
482 HttpReplied();
483 }
484}
485
486////////////////////////////////////////////////////////////////////////////////
487/// virtual method to inform object that http request is processed
488///
489/// Normally condition is notified and waiting thread will be awaked
490/// One could reimplement this method in sub-class
491
493{
494 fCond.notify_one();
495}
nlohmann::json json
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
#define free
Definition civetweb.c:1578
std::string fPostData
! data received with post request - text - or binary
Bool_t fNotifyFlag
! indicate that notification called
Bool_t CompressWithGzip()
Compress reply data with gzip compression.
void SetJson()
Set content type as "application/json".
TString GetHeader(const char *name)
Return specified header.
std::condition_variable fCond
! condition used to wait for processing
void SetPostData(void *data, Long_t length, Bool_t make_copy=kFALSE)
Set data, posted with the request.
std::shared_ptr< THttpWSEngine > TakeWSEngine()
Takeout websocket handle with HTTP call.
void AddHeader(const char *name, const char *value)
Set name: value pair to reply header.
void SetText()
Set content type as "text/plain".
void SetTextContent(std::string &&txt)
Set content type as "text/plain" and also assigns content.
virtual void HttpReplied()
virtual method to inform object that http request is processed
void ReplaceAllinContent(const std::string &from, const std::string &to, bool once=false)
Replace all occurrences of string in content.
TString fPathName
! item path
std::shared_ptr< THttpWSEngine > fWSEngine
! web-socket engine, which supplied to run created web socket
void NotifyCondition()
Method used to notify condition which waiting when operation will complete.
void SetPathAndFileName(const char *fullpath)
Set complete path of requested http element.
TString fContentType
! type of content
Long_t GetContentLength() const
Bool_t Is404() const
virtual ~THttpCallArg()
destructor
TString CountHeader(const TString &buf, Int_t number=-1111) const
method used to counter number of headers or returns name of specified header
const void * GetContent() const
void SetBinary()
Set content type as "application/x-binary".
void AddNoCacheHeader()
Set CacheControl http header to disable browser caching.
TString AccessHeader(TString &buf, const char *name, const char *value=nullptr, Bool_t doing_set=kFALSE)
method used to get or set http header in the string buffer
void SetXml()
Set content type as "text/xml".
void SetContent(const char *cont)
Set content as text.
Bool_t IsPostponed() const
void SetWSId(UInt_t id)
set web-socket id
TString fFileName
! file name
std::string fContent
! content - text or binary
void SetBinaryContent(std::string &&bin)
Set content type as "application/x-binary" and also assigns content.
void SetContentType(const char *typ)
set content type like "text/xml" or "application/json"
void SetChunked(Bool_t on=kTRUE)
Mark as chunked.
void SetEncoding(const char *typ)
Set Content-Encoding header like gzip.
void SetJsonContent(std::string &&json)
Set content type as "application/json" and also assigns content.
const char * GetContentType() const
void AssignWSId()
Assign websocket identifier from the engine.
void SetXmlContent(std::string &&xml)
Set content type as "text/xml" and also assigns content.
std::string FillHttpHeader(const char *header=nullptr)
Fills HTTP header, which can be send at the beginning of reply on the http request.
Bool_t IsChunked()
If marked as chunked.
TString fHeader
! response header like ContentEncoding, Cache-Control and so on
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:669
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1241
const char * Data() const
Definition TString.h:384
TString & Remove(Ssiz_t pos)
Definition TString.h:693
TString & Append(const char *cs)
Definition TString.h:580
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659