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
21Contains arguments for single HTTP call
22
23Must be used in THttpEngine to process incoming http requests
24*/
25
26
27
28////////////////////////////////////////////////////////////////////////////////
29/// destructor
30
34
35////////////////////////////////////////////////////////////////////////////////
36/// method used to get or set http header in the string buffer
37///
38/// Header has following format:
39///
40/// field1 : value1\\r\\n
41/// field2 : value2\\r\\n
42///
43/// Such format corresponds to header format in HTTP requests
44
46{
47 if (name == 0)
48 return TString();
49
50 Int_t curr = 0;
51
52 while (curr < buf.Length() - 2) {
53
54 Int_t next = buf.Index("\r\n", curr);
55 if (next == kNPOS)
56 break; // should never happen
57
58 if (buf.Index(name, curr) != curr) {
59 curr = next + 2;
60 continue;
61 }
62
63 if ((value == 0) && doing_set) {
64 // special case - empty value means that field must be removed completely
65 buf.Remove(curr, next - curr + 2);
66 return TString();
67 }
68
69 curr += strlen(name);
70 while ((curr < next) && (buf[curr] != ':'))
71 curr++;
72 curr++;
73 while ((curr < next) && (buf[curr] == ' '))
74 curr++;
75
76 if (value == 0)
77 return buf(curr, next - curr);
78 buf.Remove(curr, next - curr);
79 buf.Insert(curr, value);
80 return TString(value);
81 }
82
83 if (value == 0)
84 return TString();
85
86 buf.Append(TString::Format("%s: %s\r\n", name, value));
87 return TString(value);
88}
89
90////////////////////////////////////////////////////////////////////////////////
91/// method used to counter number of headers or returns name of specified header
92
94{
95 Int_t curr = 0, cnt = 0;
96
97 while (curr < buf.Length() - 2) {
98
99 Int_t next = buf.Index("\r\n", curr);
100 if (next == kNPOS)
101 break; // should never happen
102
103 if (cnt == number) {
104 // we should extract name of header
105 Int_t separ = curr + 1;
106 while ((separ < next) && (buf[separ] != ':'))
107 separ++;
108 return buf(curr, separ - curr);
109 }
110
111 curr = next + 2;
112 cnt++;
113 }
114
115 // return total number of headers
116 if (number == -1111)
117 return TString::Format("%d", cnt);
118 return TString();
119}
120
121
122////////////////////////////////////////////////////////////////////////////////
123/// Set content as text.
124///
125/// Content will be copied by THttpCallArg
126
128{
129 if (cont)
130 fContent = cont;
131 else
132 fContent.clear();
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Set text or binary content directly
137/// After method call argument cont will be in undefined state
138
140{
141 fContent = cont;
142}
143
144////////////////////////////////////////////////////////////////////////////////
145/// Set content type as "text/plain"
146
148{
149 SetContentType("text/plain");
150}
151
152////////////////////////////////////////////////////////////////////////////////
153/// Set content type as "text/plain" and also assigns content
154///
155/// @param txt will be in undefined state after method call
156
158{
159 SetText();
160 fContent = txt;
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Set content type as "text/xml"
165
167{
168 SetContentType("text/xml");
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// Set content type as "text/xml" and also assigns content
173///
174/// @param xml will be in undefined state after method call
175
177{
178 SetXml();
179 fContent = xml;
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Set content type as "application/json"
184
186{
187 SetContentType("application/json");
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// Set content type as "application/json" and also assigns content
192///
193/// @param json will be in undefined state after method call
194
196{
197 SetJson();
198 fContent = json;
199}
200
201////////////////////////////////////////////////////////////////////////////////
202/// Set content type as "application/x-binary"
203
205{
206 SetContentType("application/x-binary");
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Set content type as "application/x-binary" and also assigns content
211///
212/// @param bin will be in undefined state after method call
213
215{
216 SetBinary();
217 fContent = bin;
218}
219
220////////////////////////////////////////////////////////////////////////////////
221/// Set data, posted with the request
222///
223/// If make_copy==kFALSE, data will be released with free(data) call
224/// @deprecated Use signature with std::string
225
227{
228 fPostData.resize(length);
229
230 if (data && length) {
231 std::copy((const char *)data, (const char *)data + length, fPostData.begin());
232 if (!make_copy) free(data); // it supposed to get ownership over the buffer
233 }
234}
235
236////////////////////////////////////////////////////////////////////////////////
237/// Set data, which is posted with the request
238///
239/// Although std::string is used, not only text data can be assigned -
240/// std::string can contain any sequence of symbols
241
243{
244 fPostData = data;
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Assign websocket identifier from the engine
249
251{
252 SetWSId(fWSEngine->GetId());
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Takeout websocket handle with HTTP call
257///
258/// can be done only once
259
260std::shared_ptr<THttpWSEngine> THttpCallArg::TakeWSEngine()
261{
262 auto res = fWSEngine;
263 fWSEngine.reset();
264 return res;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Replace all occurrences of string in content
269///
270/// @param from that to replace
271/// @param to new content
272/// @param once set to true to stop after first occurrence is replaced
273
274/// Normally used only internally
275
276void THttpCallArg::ReplaceAllinContent(const std::string &from, const std::string &to, bool once)
277{
278 std::size_t start_pos = 0;
279 while((start_pos = fContent.find(from, start_pos)) != std::string::npos) {
280 fContent.replace(start_pos, from.length(), to);
281 if (once) return;
282 start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
283 }
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// Set complete path of requested http element
288///
289/// For instance, it could be "/folder/subfolder/get.bin"
290/// Here "/folder/subfolder/" is element path and "get.bin" requested file.
291/// One could set path and file name separately
292
294{
297
298 if (fullpath == 0)
299 return;
300
301 const char *rslash = strrchr(fullpath, '/');
302 if (rslash == 0) {
304 } else {
305 while ((fullpath != rslash) && (*fullpath == '/'))
306 fullpath++;
308 if (fPathName == "/")
310 fFileName = rslash + 1;
311 }
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Return specified header
316
318{
319 if ((name == 0) || (*name == 0))
320 return TString();
321
322 if (strcmp(name, "Content-Type") == 0)
323 return fContentType;
324 if (strcmp(name, "Content-Length") == 0)
325 return TString::Format("%ld", GetContentLength());
326
327 return AccessHeader(fHeader, name);
328}
329
330////////////////////////////////////////////////////////////////////////////////
331/// Set `name: value` pair to reply header
332///
333/// Content-Type field handled separately - one should use SetContentType() method
334/// Content-Length field cannot be set at all;
335
336void THttpCallArg::AddHeader(const char *name, const char *value)
337{
338 if ((name == 0) || (*name == 0) || (strcmp(name, "Content-Length") == 0))
339 return;
340
341 if (strcmp(name, "Content-Type") == 0)
343 else
345}
346
347////////////////////////////////////////////////////////////////////////////////
348/// Set CacheControl http header to disable browser caching
349
351{
352 AddHeader("Cache-Control", "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
353}
354
355////////////////////////////////////////////////////////////////////////////////
356/// Mark as chunked
357///
358/// Data to the client transferred in chunks.
359/// So many ProcessRequests will be invoked and produced data will be send as next chunk
360/// - until empty conent will be returned or chunked flag is cleared
361
363{
364 AccessHeader(fHeader, "Transfer-Encoding", on ? "chunked" : nullptr, kTRUE);
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// If marked as chunked
369
371{
372 return AccessHeader(fHeader, "Transfer-Encoding") == "chunked";
373}
374
375////////////////////////////////////////////////////////////////////////////////
376/// Fills HTTP header, which can be send at the beginning of reply on the http request
377///
378/// @param name is HTTP protocol name (default "HTTP/1.1")
379
380std::string THttpCallArg::FillHttpHeader(const char *name)
381{
382 std::string hdr(name ? name : "HTTP/1.1");
383
384 if ((fContentType.Length() == 0) || Is404())
385 hdr.append(" 404 Not Found\r\n"
386 "Content-Length: 0\r\n"
387 "Connection: close\r\n\r\n");
388 else if (IsChunked())
389 hdr.append(TString::Format(" 200 OK\r\n"
390 "Content-Type: %s\r\n"
391 "Connection: keep-alive\r\n"
392 "%s\r\n",
394 .Data());
395 else
396 hdr.append(TString::Format(" 200 OK\r\n"
397 "Content-Type: %s\r\n"
398 "Connection: keep-alive\r\n"
399 "Content-Length: %ld\r\n"
400 "%s\r\n",
402 .Data());
403
404 return hdr;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408/// Compress reply data with gzip compression
409
411{
412 char *objbuf = (char *)GetContent();
414
415 unsigned long objcrc = R__crc32(0, NULL, 0);
416 objcrc = R__crc32(objcrc, (const unsigned char *)objbuf, objlen);
417
418 // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
419 Int_t buflen = 10 + objlen + 8;
420 if (buflen < 512)
421 buflen = 512;
422
423 std::string buffer;
424 buffer.resize(buflen);
425
426 char *bufcur = (char *)buffer.data();
427
428 *bufcur++ = 0x1f; // first byte of ZIP identifier
429 *bufcur++ = 0x8b; // second byte of ZIP identifier
430 *bufcur++ = 0x08; // compression method
431 *bufcur++ = 0x00; // FLAG - empty, no any file names
432 *bufcur++ = 0; // empty timestamp
433 *bufcur++ = 0; //
434 *bufcur++ = 0; //
435 *bufcur++ = 0; //
436 *bufcur++ = 0; // XFL (eXtra FLags)
437 *bufcur++ = 3; // OS 3 means Unix
438 // strcpy(bufcur, "item.json");
439 // bufcur += strlen("item.json")+1;
440
441 char dummy[8];
442 memcpy(dummy, bufcur - 6, 6);
443
444 // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
445 unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, objbuf, objlen);
446
447 memcpy(bufcur - 6, dummy, 6);
448
449 bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
450
451 // write CRC32
452 *bufcur++ = objcrc & 0xff;
453 *bufcur++ = (objcrc >> 8) & 0xff;
454 *bufcur++ = (objcrc >> 16) & 0xff;
455 *bufcur++ = (objcrc >> 24) & 0xff;
456
457 // write original data length
458 *bufcur++ = objlen & 0xff;
459 *bufcur++ = (objlen >> 8) & 0xff;
460 *bufcur++ = (objlen >> 16) & 0xff;
461 *bufcur++ = (objlen >> 24) & 0xff;
462
463 buffer.resize(bufcur - (char *)buffer.data());
464
465 SetContent(std::move(buffer));
466
467 SetEncoding("gzip");
468
469 return kTRUE;
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Method used to notify condition which waiting when operation will complete
474///
475/// Condition notified only if not-postponed state is set
476
478{
479 if (!fNotifyFlag && !IsPostponed()) {
481 HttpReplied();
482 }
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// virtual method to inform object that http request is processed
487///
488/// Normally condition is notified and waiting thread will be awaked
489/// One could reimplement this method in sub-class
490
492{
493 fCond.notify_one();
494}
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:148
#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:670
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:694
TString & Append(const char *cs)
Definition TString.h:581
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:660