ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  fContentType(),
34  fRequestHeader(),
35  fHeader(),
36  fContent(),
37  fZipping(0),
38  fBinData(0),
39  fBinDataLength(0)
40 {
41 }
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// destructor
45 
47 {
48  if (fPostData) {
49  free(fPostData);
50  fPostData = 0;
51  }
52 
53  if (fBinData) {
54  free(fBinData);
55  fBinData = 0;
56  }
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// method used to get or set http header in the string buffer
61 /// Header has following format:
62 /// field1 : value1\r\n
63 /// field2 : value2\r\n
64 /// Such format corresponds to header format in HTTP requests
65 
66 TString THttpCallArg::AccessHeader(TString& buf, const char* name, const char* value, Bool_t doing_set)
67 {
68  if (name==0) return TString();
69 
70  Int_t curr = 0;
71 
72  while (curr < buf.Length()-2) {
73 
74  Int_t next = buf.Index("\r\n", curr);
75  if (next == kNPOS) break; // should never happen
76 
77  if (buf.Index(name, curr) != curr) {
78  curr = next + 2;
79  continue;
80  }
81 
82  if ((value==0) && doing_set) {
83  // special case - empty value means that field must be removed completely
84  buf.Remove(curr, next-curr+2);
85  return TString();
86  }
87 
88  curr += strlen(name);
89  while ((curr < next) && (buf[curr] != ':')) curr++;
90  curr++;
91  while ((curr < next) && (buf[curr] == ' ')) curr++;
92 
93  if (value==0) return buf(curr, next-curr);
94  buf.Remove(curr, next-curr);
95  buf.Insert(curr, value);
96  return TString(value);
97  }
98 
99  if (value==0) return TString();
100 
101  buf.Append(TString::Format("%s: %s\r\n", name, value));
102  return TString(value);
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// method used to counter number of headers or returns name of specified header
107 
109 {
110  Int_t curr(0), cnt(0);
111 
112  while (curr < buf.Length()-2) {
113 
114  Int_t next = buf.Index("\r\n", curr);
115  if (next == kNPOS) break; // should never happen
116 
117  if (cnt == number) {
118  // we should extract name of header
119  Int_t separ = curr + 1;
120  while ((separ < next) && (buf[separ] != ':')) separ++;
121  return buf(curr, separ-curr);
122  }
123 
124  curr = next + 2;
125  cnt++;
126  }
127 
128  // return total number of headers
129  if (number == -1111) return TString::Format("%d", cnt);
130  return TString();
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// set data, posted with the request
135 /// buffer should be allocated with malloc(length+1) call,
136 /// while last byte will be set to 0
137 /// Than one could use post data as null-terminated string
138 
140 {
141  if (fPostData) free(fPostData);
142  if (data!=0) *(((char*) data) + length) = 0;
143  fPostData = data;
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 /// set binary data, which will be returned as reply body
149 
151 {
152  if (fBinData) free(fBinData);
153  fBinData = data;
155 
156  // string content must be cleared in any case
157  fContent.Clear();
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// set complete path of requested http element
162 /// For instance, it could be "/folder/subfolder/get.bin"
163 /// Here "/folder/subfolder/" is element path and "get.bin" requested file.
164 /// One could set path and file name separately
165 
166 void THttpCallArg::SetPathAndFileName(const char *fullpath)
167 {
168  fPathName.Clear();
169  fFileName.Clear();
170 
171  if (fullpath == 0) return;
172 
173  const char *rslash = strrchr(fullpath, '/');
174  if (rslash == 0) {
175  fFileName = fullpath;
176  } else {
177  while ((fullpath != rslash) && (*fullpath == '/')) fullpath++;
178  fPathName.Append(fullpath, rslash - fullpath);
179  if (fPathName == "/") fPathName.Clear();
180  fFileName = rslash + 1;
181  }
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// return specified header
186 
188 {
189  if ((name == 0) || (*name == 0)) return TString();
190 
191  if (strcmp(name,"Content-Type") == 0) return fContentType;
192  if (strcmp(name,"Content-Length") == 0) return TString::Format("%ld", GetContentLength());
193 
194  return AccessHeader(fHeader, name);
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Set name: value pair to reply header
199 /// Content-Type field handled separately - one should use SetContentType() method
200 /// Content-Length field cannot be set at all;
201 
202 void THttpCallArg::AddHeader(const char *name, const char *value)
203 {
204  if ((name == 0) || (*name == 0) || (strcmp(name,"Content-Length") == 0)) return;
205 
206  if (strcmp(name,"Content-Type") == 0)
207  SetContentType(value);
208  else
209  AccessHeader(fHeader, name, value, kTRUE);
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// fill HTTP header
214 
215 void THttpCallArg::FillHttpHeader(TString &hdr, const char *kind)
216 {
217  if (kind == 0) kind = "HTTP/1.1";
218 
219  if ((fContentType.Length() == 0) || Is404()) {
220  hdr.Form("%s 404 Not Found\r\n"
221  "Content-Length: 0\r\n"
222  "Connection: close\r\n\r\n", kind);
223  } else {
224  hdr.Form("%s 200 OK\r\n"
225  "Content-Type: %s\r\n"
226  "Connection: keep-alive\r\n"
227  "Content-Length: %ld\r\n"
228  "%s\r\n",
229  kind,
230  GetContentType(),
232  fHeader.Data());
233  }
234 }
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 /// compress reply data with gzip compression
238 
240 {
241  char *objbuf = (char *) GetContent();
242  Long_t objlen = GetContentLength();
243 
244  unsigned long objcrc = R__crc32(0, NULL, 0);
245  objcrc = R__crc32(objcrc, (const unsigned char *) objbuf, objlen);
246 
247  // 10 bytes (ZIP header), compressed data, 8 bytes (CRC and original length)
248  Int_t buflen = 10 + objlen + 8;
249  if (buflen < 512) buflen = 512;
250 
251  void *buffer = malloc(buflen);
252 
253  char *bufcur = (char *) buffer;
254 
255  *bufcur++ = 0x1f; // first byte of ZIP identifier
256  *bufcur++ = 0x8b; // second byte of ZIP identifier
257  *bufcur++ = 0x08; // compression method
258  *bufcur++ = 0x00; // FLAG - empty, no any file names
259  *bufcur++ = 0; // empty timestamp
260  *bufcur++ = 0; //
261  *bufcur++ = 0; //
262  *bufcur++ = 0; //
263  *bufcur++ = 0; // XFL (eXtra FLags)
264  *bufcur++ = 3; // OS 3 means Unix
265  //strcpy(bufcur, "item.json");
266  //bufcur += strlen("item.json")+1;
267 
268  char dummy[8];
269  memcpy(dummy, bufcur - 6, 6);
270 
271  // R__memcompress fills first 6 bytes with own header, therefore just overwrite them
272  unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, objbuf, objlen);
273 
274  memcpy(bufcur - 6, dummy, 6);
275 
276  bufcur += (ziplen - 6); // jump over compressed data (6 byte is extra ROOT header)
277 
278  *bufcur++ = objcrc & 0xff; // CRC32
279  *bufcur++ = (objcrc >> 8) & 0xff;
280  *bufcur++ = (objcrc >> 16) & 0xff;
281  *bufcur++ = (objcrc >> 24) & 0xff;
282 
283  *bufcur++ = objlen & 0xff; // original data length
284  *bufcur++ = (objlen >> 8) & 0xff; // original data length
285  *bufcur++ = (objlen >> 16) & 0xff; // original data length
286  *bufcur++ = (objlen >> 24) & 0xff; // original data length
287 
288  SetBinData(buffer, bufcur - (char *) buffer);
289 
290  SetEncoding("gzip");
291 
292  return kTRUE;
293 }
tuple buffer
Definition: tree.py:99
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:321
Bool_t Is404() const
Definition: THttpCallArg.h:304
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:43
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:592
void SetContentType(const char *typ)
Definition: THttpCallArg.h:201
const void * GetContent() const
Definition: THttpCallArg.h:326
const char * Data() const
Definition: TString.h:349
void SetEncoding(const char *typ)
Definition: THttpCallArg.h:255
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:2321
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:37
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1126
TString fPathName
request method like GET or POST
Definition: THttpCallArg.h:27
TString & Append(const char *cs)
Definition: TString.h:492
Long_t fPostDataLength
binary data received with post request
Definition: THttpCallArg.h:33
Long_t fBinDataLength
binary data, assigned with http call
Definition: THttpCallArg.h:44
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:2308
void * fPostData
additional arguments
Definition: THttpCallArg.h:32
tuple free
Definition: fildir.py:30
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:39
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:40
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:28
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:314