ROOT  6.06/09
Reference Guide
THttpCallArg.cxx
Go to the documentation of this file.
1 // $Id$
2 // Author: Sergey Linev 21/05/2015
3 
4 #include "THttpCallArg.h"
5 
6 #include <string.h>
7 #include "RZip.h"
8 
9 //////////////////////////////////////////////////////////////////////////
10 // //
11 // THttpCallArg //
12 // //
13 // Contains arguments for single HTTP call //
14 // Must be used in THttpEngine to process incoming http requests //
15 // //
16 //////////////////////////////////////////////////////////////////////////
17 
19 
20 ////////////////////////////////////////////////////////////////////////////////
21 /// constructor
22 
24  TObject(),
25  fTopName(),
26  fMethod(),
27  fPathName(),
28  fFileName(),
29  fUserName(),
30  fQuery(),
31  fPostData(0),
32  fPostDataLength(0),
33  fCond(),
34  fContentType(),
35  fRequestHeader(),
36  fHeader(),
37  fContent(),
38  fZipping(0),
39  fBinData(0),
40  fBinDataLength(0)
41 {
42 }
43 
44 ////////////////////////////////////////////////////////////////////////////////
45 /// destructor
46 
48 {
49  if (fPostData) {
50  free(fPostData);
51  fPostData = 0;
52  }
53 
54  if (fBinData) {
55  free(fBinData);
56  fBinData = 0;
57  }
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// method used to get or set http header in the string buffer
62 /// Header has following format:
63 /// field1 : value1\r\n
64 /// field2 : value2\r\n
65 /// Such format corresponds to header format in HTTP requests
66 
67 TString THttpCallArg::AccessHeader(TString& buf, const char* name, const char* value, Bool_t doing_set)
68 {
69  if (name==0) return TString();
70 
71  Int_t curr = 0;
72 
73  while (curr < buf.Length()-2) {
74 
75  Int_t next = buf.Index("\r\n", curr);
76  if (next == kNPOS) break; // should never happen
77 
78  if (buf.Index(name, curr) != curr) {
79  curr = next + 2;
80  continue;
81  }
82 
83  if ((value==0) && doing_set) {
84  // special case - empty value means that field must be removed completely
85  buf.Remove(curr, next-curr+2);
86  return TString();
87  }
88 
89  curr += strlen(name);
90  while ((curr < next) && (buf[curr] != ':')) curr++;
91  curr++;
92  while ((curr < next) && (buf[curr] == ' ')) curr++;
93 
94  if (value==0) return buf(curr, next-curr);
95  buf.Remove(curr, next-curr);
96  buf.Insert(curr, value);
97  return TString(value);
98  }
99 
100  if (value==0) return TString();
101 
102  buf.Append(TString::Format("%s: %s\r\n", name, value));
103  return TString(value);
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// method used to counter number of headers or returns name of specified header
108 
110 {
111  Int_t curr(0), cnt(0);
112 
113  while (curr < buf.Length()-2) {
114 
115  Int_t next = buf.Index("\r\n", curr);
116  if (next == kNPOS) break; // should never happen
117 
118  if (cnt == number) {
119  // we should extract name of header
120  Int_t separ = curr + 1;
121  while ((separ < next) && (buf[separ] != ':')) separ++;
122  return buf(curr, separ-curr);
123  }
124 
125  curr = next + 2;
126  cnt++;
127  }
128 
129  // return total number of headers
130  if (number == -1111) return TString::Format("%d", cnt);
131  return TString();
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// set data, posted with the request
136 /// buffer should be allocated with malloc(length+1) call,
137 /// while last byte will be set to 0
138 /// Than one could use post data as null-terminated string
139 
141 {
142  if (fPostData) free(fPostData);
143  if (data!=0) *(((char*) data) + length) = 0;
144  fPostData = data;
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// set binary data, which will be returned as reply body
150 
152 {
153  if (fBinData) free(fBinData);
154  fBinData = data;
156 
157  // string content must be cleared in any case
158  fContent.Clear();
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// set complete path of requested http element
163 /// For instance, it could be "/folder/subfolder/get.bin"
164 /// Here "/folder/subfolder/" is element path and "get.bin" requested file.
165 /// One could set path and file name separately
166 
167 void THttpCallArg::SetPathAndFileName(const char *fullpath)
168 {
169  fPathName.Clear();
170  fFileName.Clear();
171 
172  if (fullpath == 0) return;
173 
174  const char *rslash = strrchr(fullpath, '/');
175  if (rslash == 0) {
176  fFileName = fullpath;
177  } else {
178  while ((fullpath != rslash) && (*fullpath == '/')) fullpath++;
179  fPathName.Append(fullpath, rslash - fullpath);
180  if (fPathName == "/") fPathName.Clear();
181  fFileName = rslash + 1;
182  }
183 }
184 
185 ////////////////////////////////////////////////////////////////////////////////
186 /// return specified header
187 
189 {
190  if ((name == 0) || (*name == 0)) return TString();
191 
192  if (strcmp(name,"Content-Type") == 0) return fContentType;
193  if (strcmp(name,"Content-Length") == 0) return TString::Format("%ld", GetContentLength());
194 
195  return AccessHeader(fHeader, name);
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// Set name: value pair to reply header
200 /// Content-Type field handled separately - one should use SetContentType() method
201 /// Content-Length field cannot be set at all;
202 
203 void THttpCallArg::AddHeader(const char *name, const char *value)
204 {
205  if ((name == 0) || (*name == 0) || (strcmp(name,"Content-Length") == 0)) return;
206 
207  if (strcmp(name,"Content-Type") == 0)
208  SetContentType(value);
209  else
210  AccessHeader(fHeader, name, value, kTRUE);
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// fill HTTP header
215 
216 void THttpCallArg::FillHttpHeader(TString &hdr, const char *kind)
217 {
218  if (kind == 0) kind = "HTTP/1.1";
219 
220  if ((fContentType.Length() == 0) || Is404()) {
221  hdr.Form("%s 404 Not Found\r\n"
222  "Content-Length: 0\r\n"
223  "Connection: close\r\n\r\n", kind);
224  } else {
225  hdr.Form("%s 200 OK\r\n"
226  "Content-Type: %s\r\n"
227  "Connection: keep-alive\r\n"
228  "Content-Length: %ld\r\n"
229  "%s\r\n",
230  kind,
231  GetContentType(),
233  fHeader.Data());
234  }
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// compress reply data with gzip compression
239 
241 {
242  char *objbuf = (char *) GetContent();
243  Long_t objlen = GetContentLength();
244 
245  unsigned long objcrc = R__crc32(0, NULL, 0);
246  objcrc = R__crc32(objcrc, (const unsigned char *) objbuf, objlen);
247 
248  // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
249  Int_t buflen = 10 + objlen + 8;
250  if (buflen < 512) buflen = 512;
251 
252  void *buffer = malloc(buflen);
253 
254  char *bufcur = (char *) buffer;
255 
256  *bufcur++ = 0x1f; // first byte of ZIP identifier
257  *bufcur++ = 0x8b; // second byte of ZIP identifier
258  *bufcur++ = 0x08; // compression method
259  *bufcur++ = 0x00; // FLAG - empty, no any file names
260  *bufcur++ = 0; // empty timestamp
261  *bufcur++ = 0; //
262  *bufcur++ = 0; //
263  *bufcur++ = 0; //
264  *bufcur++ = 0; // XFL (eXtra FLags)
265  *bufcur++ = 3; // OS 3 means Unix
266  //strcpy(bufcur, "item.json");
267  //bufcur += strlen("item.json")+1;
268 
269  char dummy[8];
270  memcpy(dummy, bufcur - 6, 6);
271 
272  // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
273  unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, objbuf, objlen);
274 
275  memcpy(bufcur - 6, dummy, 6);
276 
277  bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
278 
279  *bufcur++ = objcrc & 0xff; // CRC32
280  *bufcur++ = (objcrc >> 8) & 0xff;
281  *bufcur++ = (objcrc >> 16) & 0xff;
282  *bufcur++ = (objcrc >> 24) & 0xff;
283 
284  *bufcur++ = objlen & 0xff; // original data length
285  *bufcur++ = (objlen >> 8) & 0xff; // original data length
286  *bufcur++ = (objlen >> 16) & 0xff; // original data length
287  *bufcur++ = (objlen >> 24) & 0xff; // original data length
288 
289  SetBinData(buffer, bufcur - (char *) buffer);
290 
291  SetEncoding("gzip");
292 
293  return kTRUE;
294 }
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Ssiz_t Length() const
Definition: TString.h:390
Long_t GetContentLength() const
Definition: THttpCallArg.h:323
Bool_t Is404() const
Definition: THttpCallArg.h:306
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void * fBinData
indicate if content should be zipped
Definition: THttpCallArg.h:45
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:592
void SetContentType(const char *typ)
Definition: THttpCallArg.h:203
const void * GetContent() const
Definition: THttpCallArg.h:328
const char * Data() const
Definition: TString.h:349
void SetEncoding(const char *typ)
Definition: THttpCallArg.h:257
ClassImp(THttpCallArg) THttpCallArg
constructor
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:2334
Vc_ALWAYS_INLINE void free(T *p)
Frees memory that was allocated with Vc::malloc.
Definition: memory.h:94
void SetPostData(void *data, Long_t length)
set data, posted with the request buffer should be allocated with malloc(length+1) call...
void SetPathAndFileName(const char *fullpath)
set complete path of requested http element For instance, it could be "/folder/subfolder/get.bin" Here "/folder/subfolder/" is element path and "get.bin" requested file.
TString fContentType
condition used to wait for processing
Definition: THttpCallArg.h:39
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1139
TString fPathName
request method like GET or POST
Definition: THttpCallArg.h:29
TString & Append(const char *cs)
Definition: TString.h:492
Long_t fPostDataLength
binary data received with post request
Definition: THttpCallArg.h:35
Long_t fBinDataLength
binary data, assigned with http call
Definition: THttpCallArg.h:46
void SetBinData(void *data, Long_t length)
set binary data, which will be returned as reply body
Double_t length(const TVector2 &v)
Definition: CsgOps.cxx:347
TString AccessHeader(TString &buf, const char *name, const char *value=0, Bool_t doing_set=kFALSE)
method used to get or set http header in the string buffer Header has following format: field1 : valu...
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
void * fPostData
additional arguments
Definition: THttpCallArg.h:34
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
long Long_t
Definition: RtypesCore.h:50
TString CountHeader(const TString &buf, Int_t number=-1111) const
method used to counter number of headers or returns name of specified header
TString fHeader
complete header, provided with request
Definition: THttpCallArg.h:41
static RooMathCoreReg dummy
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
TString fContent
response header like ContentEncoding, Cache-Control and so on
Definition: THttpCallArg.h:42
void AddHeader(const char *name, const char *value)
Set name: value pair to reply header Content-Type field handled separately - one should use SetConten...
const Ssiz_t kNPOS
Definition: Rtypes.h:115
#define NULL
Definition: Rtypes.h:82
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
const Bool_t kTRUE
Definition: Rtypes.h:91
float value
Definition: math.cpp:443
Vc_ALWAYS_INLINE_L T *Vc_ALWAYS_INLINE_R malloc(size_t n)
Allocates memory on the Heap with alignment and padding suitable for vectorized access.
Definition: memory.h:67
~THttpCallArg()
destructor
TString fFileName
item path
Definition: THttpCallArg.h:30
const char * cnt
Definition: TXMLSetup.cxx:75
Bool_t CompressWithGzip()
compress reply data with gzip compression
TString GetHeader(const char *name)
return specified header
void FillHttpHeader(TString &buf, const char *header=0)
fill HTTP header
const char * GetContentType() const
Definition: THttpCallArg.h:316