XRootD
XrdHttpReq.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // This file is part of XrdHTTP: A pragmatic implementation of the
3 // HTTP/WebDAV protocol for the Xrootd framework
4 //
5 // Copyright (c) 2013 by European Organization for Nuclear Research (CERN)
6 // Author: Fabrizio Furano <furano@cern.ch>
7 // File Date: Nov 2012
8 //------------------------------------------------------------------------------
9 // XRootD is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // XRootD is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
21 //------------------------------------------------------------------------------
22 
23 
24 
25 
26 
27 
28 
38 #ifndef XRDHTTPREQ_HH
39 #define XRDHTTPREQ_HH
40 
41 
42 #include "XrdOuc/XrdOucString.hh"
43 
44 #include "XProtocol/XProtocol.hh"
48 
49 #include <vector>
50 #include <string>
51 #include <map>
52 
53 //#include <libxml/parser.h>
54 //#include <libxml/tree.h>
55 
56 
57 
58 
59 struct DirListInfo {
60  std::string path;
61  long long size;
62  long id;
63  long flags;
64  long modtime;
65 };
66 
67 
68 class XrdHttpProtocol;
69 class XrdOucEnv;
70 
72 
73 public:
74  // ----------------
75  // Description of the request. The header/body parsing
76  // is supposed to populate these fields, for fast access while
77  // processing the request
78 
80 
81  enum ReqType: int {
82  rtUnset = -1,
83  rtUnknown = 0,
94  rtPOST
95  };
96 
97 private:
98  // HTTP response parameters to be sent back to the user
99  int httpStatusCode;
100  // HTTP Error code for the response
101  // e.g. 8.1, 8.3.1, etc.
102  // https://twiki.cern.ch/twiki/bin/view/LCG/WebdavErrorImprovement
103  std::string httpErrorCode;
104  // HTTP response text with following format:
105  // Severity: ErrorCode: free-style text message
106  // Severity being OK, WARNING, or ERROR
107  // ErrorCode being a decimal numeric plus dot string, i.e. n or n.m or n.m.l,
108  // etc. free-style text message any UTF-8 string
109  // Optionally, it also contains the trailer headers whereever applicable
110  // e.g. X-Transfer-Status: 200: OK
111  // or X-Transfer-Status: 500: ERROR: <error message>: <additional text>
112  std::string httpErrorBody;
113 
114 
115  // The value of the user agent, if specified
116  std::string m_user_agent;
117 
118  // Whether transfer encoding was requested.
119  bool m_transfer_encoding_chunked;
120  long long m_current_chunk_offset;
121  long long m_current_chunk_size;
122 
123  // Whether trailer headers were enabled
124  bool m_trailer_headers{false};
125 
126  // Whether the client understands our special status trailer.
127  // The status trailer allows us to report when an IO error occurred
128  // after a response body has started
129  bool m_status_trailer{false};
130 
131  int parseHost(char *);
132 
133  void parseScitag(const std::string & val);
134 
135  //xmlDocPtr xmlbody; /* the resulting document tree */
136  XrdHttpProtocol *prot;
137 
138  void clientMarshallReadAheadList(int nitems);
139  void clientUnMarshallReadAheadList(int nitems);
140 
141 
142  void getfhandle();
143 
144  // Process the checksum response and return a header that should
145  // be included in the response.
146  int PostProcessChecksum(std::string &digest_header);
147 
148  // Process the listing request of a GET request against a directory
149  // - final_: True if this is the last entry in the listing.
150  int PostProcessListing(bool final_);
151 
152  // Send the response for a GET request for a file read (i.e., not a directory)
153  // Invoked after the open is successful but before the first read is issued.
154  int ReturnGetHeaders();
155 
161  int PostProcessHTTPReq(bool final = false);
162 
163  // Parse a resource string, typically a filename, setting the resource field and the opaque data
164  void parseResource(char *url);
165 
166  // Set Webdav Error messages
167  void generateWebdavErrMsg();
168 
169  // Sanitize the resource from http[s]://[host]/ questionable prefix
170  void sanitizeResourcePfx();
171 
172  // parses the iovN data pointers elements as either a kXR_read or kXR_readv
173  // response and fills out a XrdHttpIOList with the corresponding length and
174  // buffer pointers. File offsets from kXR_readv responses are not recorded.
175  void getReadResponse(XrdHttpIOList &received);
176 
177  // notifies the range handler of receipt of bytes and sends the client
178  // the data.
179  int sendReadResponseSingleRange(const XrdHttpIOList &received);
180 
181  // notifies the range handler of receipt of bytes and sends the client
182  // the data and necessary headers, assuming multipart/byteranges content type.
183  int sendReadResponsesMultiRanges(const XrdHttpIOList &received);
184 
185  // If requested by the client, sends any I/O errors that occur during the transfer
186  // into a footer.
187  int sendFooterError(const std::string &);
188 
189  // Set the age header from the file modification time
190  void addAgeHeader(std::string & headers);
196  static void extractChecksumFromList(const std::string & checksumList, std::vector<std::string> & extractedChecksum);
197 
204  static void determineXRootDChecksumFromUserDigest(const std::string & userDigest, std::vector<std::string> & xrootdChecksums);
205 
206 public:
208  readRangeHandler(rcfg), closeAfterError(false), keepalive(true) {
209 
210  prot = protinstance;
211  length = 0;
212  //xmlbody = 0;
213  depth = 0;
214  opaque = 0;
215  writtenbytes = 0;
216  fopened = false;
217  headerok = false;
218  mScitag = -1;
219  };
220 
221  virtual ~XrdHttpReq();
222 
223  virtual void reset();
224 
226  int parseLine(char *line, int len);
227 
229  int parseFirstLine(char *line, int len);
230 
232  int parseBody(char *body, long long len);
233 
235  int ReqReadV(const XrdHttpIOList &cl);
236  std::vector<readahead_list> ralist;
237 
239  std::string buildPartialHdr(long long bytestart, long long byteend, long long filesize, char *token);
240 
242  std::string buildPartialHdrEnd(char *token);
243 
244  // Appends the opaque info that we have
245  // NOTE: this function assumes that the strings are unquoted, and will quote them
246  void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow);
247 
248  void addCgi(const std::string & key, const std::string & value);
249 
250  // Set the transfer status header, if requested by the client
251  void setTransferStatusHeader(std::string &header);
252 
253  // Return the current user agent; if none has been specified, returns an empty string
254  const std::string &userAgent() const {return m_user_agent;}
255 
256 
259  std::string requestverb;
260 
261  // We have to keep the headers for possible further processing
262  // by external plugins
263  std::map<std::string, std::string> allheaders;
264 
271 
272 
274  bool headerok;
275 
279 
280  // Indication that there was a read error and the next
281  // request processing state should cleanly close the file.
283 
284  bool keepalive;
285  long long length; // Total size from client for PUT; total length of response TO client for GET.
286  int depth;
288 
290  std::string host;
292  std::string destination;
293 
295  std::string m_req_digest;
296 
299 
305  std::string m_digest_header;
306 
308  std::string hdr2cgistr;
311  bool m_appended_asize{false};
312 
313  //
314  // Area for coordinating request and responses to/from the bridge
315  //
316 
317 
319  unsigned int rwOpDone, rwOpPartialDone;
320 
323 
327  std::string etext;
329 
331  const struct iovec *iovP;
332  int iovN;
333  int iovL;
334  bool final;
335 
336  // The latest stat info got from the xrd layer
337  long long filesize;
338  long fileflags;
340  long filectime;
341  char fhandle[4];
342  bool fopened;
343 
345  std::string stringresp;
346 
348  int reqstate;
349 
351  long long writtenbytes;
352 
353  int mScitag;
354 
355  std::string m_origin;
356 
357 
358 
359 
360 
366  int ProcessHTTPReq();
367 
368 
369  // ------------
370  // Items inherited from the Bridge class
371  //
372 
373  //-----------------------------------------------------------------------------
399  //-----------------------------------------------------------------------------
400 
401  virtual bool Data(XrdXrootd::Bridge::Context &info,
402  const
403  struct iovec *iovP,
404  int iovN,
405  int iovL,
406  bool final
407  );
408 
409  //-----------------------------------------------------------------------------
419  //-----------------------------------------------------------------------------
420 
421  virtual bool Done(XrdXrootd::Bridge::Context &info);
422 
423 
424  //-----------------------------------------------------------------------------
437  //-----------------------------------------------------------------------------
438 
439  virtual bool Error(XrdXrootd::Bridge::Context &info,
440  int ecode,
441  const char *etext
442  );
443 
444  //-----------------------------------------------------------------------------
457  //-----------------------------------------------------------------------------
458 
459  virtual int File(XrdXrootd::Bridge::Context &info,
460  int dlen
461  );
462 
463  //-----------------------------------------------------------------------------
476  //-----------------------------------------------------------------------------
477 
478  virtual bool Redir(XrdXrootd::Bridge::Context &info,
479  int port,
480  const char *hname
481  );
482 
483 };
484 
485 
486 
487 void trim(std::string &str);
488 
489 #endif /* XRDHTTPREQ_HH */
490 
XErrorCode
Definition: XProtocol.hh:989
XResponseType
Definition: XProtocol.hh:898
long long size
Definition: XrdHttpReq.hh:61
void trim(std::string &str)
Definition: XrdHttpReq.cc:77
std::string path
Definition: XrdHttpReq.hh:60
long modtime
Definition: XrdHttpReq.hh:64
std::vector< XrdOucIOVec2 > XrdHttpIOList
int reqstate
State machine to talk to the bridge.
Definition: XrdHttpReq.hh:348
char fhandle[4]
Definition: XrdHttpReq.hh:341
int ReqReadV(const XrdHttpIOList &cl)
Prepare the buffers for sending a readv request.
Definition: XrdHttpReq.cc:397
bool keepalive
Definition: XrdHttpReq.hh:284
unsigned int rwOpPartialDone
Definition: XrdHttpReq.hh:319
int parseBody(char *body, long long len)
Parse the body of a request, assuming that it's XML and that it's entirely in memory.
Definition: XrdHttpReq.cc:95
std::vector< readahead_list > ralist
Definition: XrdHttpReq.hh:236
long long length
Definition: XrdHttpReq.hh:285
std::string destination
The destination field specified in the req.
Definition: XrdHttpReq.hh:292
XrdOucString resource
The resource specified by the request, stripped of opaque data.
Definition: XrdHttpReq.hh:266
bool headerok
Tells if we have finished reading the header.
Definition: XrdHttpReq.hh:274
std::string m_digest_header
The computed digest for the HTTP response header.
Definition: XrdHttpReq.hh:305
std::string etext
Definition: XrdHttpReq.hh:327
std::string stringresp
If we want to give a string as a response, we compose it here.
Definition: XrdHttpReq.hh:345
XResponseType xrdresp
The last response data we got.
Definition: XrdHttpReq.hh:325
std::string requestverb
Definition: XrdHttpReq.hh:259
ReqType request
The request we got.
Definition: XrdHttpReq.hh:258
int ProcessHTTPReq()
Definition: XrdHttpReq.cc:839
bool closeAfterError
Definition: XrdHttpReq.hh:282
long long writtenbytes
In a long write, we track where we have arrived.
Definition: XrdHttpReq.hh:351
XrdOucEnv * opaque
The opaque data, after parsing.
Definition: XrdHttpReq.hh:268
long fileflags
Definition: XrdHttpReq.hh:338
int iovL
byte count
Definition: XrdHttpReq.hh:333
bool fopened
Definition: XrdHttpReq.hh:342
const struct iovec * iovP
The latest data chunks got from the xrd layer. These are valid only inside the callbacks!
Definition: XrdHttpReq.hh:331
virtual ~XrdHttpReq()
Definition: XrdHttpReq.cc:111
std::string m_req_digest
The requested digest type.
Definition: XrdHttpReq.hh:295
XrdOucString resourceplusopaque
The resource specified by the request, including all the opaque data.
Definition: XrdHttpReq.hh:270
virtual bool Data(XrdXrootd::Bridge::Context &info, const struct iovec *iovP, int iovN, int iovL, bool final)
Definition: XrdHttpReq.cc:452
long filectime
Definition: XrdHttpReq.hh:340
std::string hdr2cgistr
Additional opaque info that may come from the hdr2cgi directive.
Definition: XrdHttpReq.hh:308
virtual bool Done(XrdXrootd::Bridge::Context &info)
the result context
Definition: XrdHttpReq.cc:498
std::string host
The host field specified in the req.
Definition: XrdHttpReq.hh:290
long filemodtime
Definition: XrdHttpReq.hh:339
int parseFirstLine(char *line, int len)
Parse the first line of the header.
Definition: XrdHttpReq.cc:265
XrdOucString redirdest
Definition: XrdHttpReq.hh:328
std::string m_origin
Definition: XrdHttpReq.hh:355
ReqType
These are the HTTP/DAV requests that we support.
Definition: XrdHttpReq.hh:81
int parseLine(char *line, int len)
Parse the header.
Definition: XrdHttpReq.cc:117
std::string buildPartialHdrEnd(char *token)
Build the closing part for a multipart response.
Definition: XrdHttpReq.cc:444
XrdHttpChecksumHandler::XrdHttpChecksumRawPtr m_req_cksum
The checksum that was ran for this request.
Definition: XrdHttpReq.hh:298
void setTransferStatusHeader(std::string &header)
Definition: XrdHttpReq.cc:2002
bool m_appended_hdr2cgistr
Definition: XrdHttpReq.hh:309
void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow)
Definition: XrdHttpReq.cc:639
int iovN
array count
Definition: XrdHttpReq.hh:332
XrdHttpReq(XrdHttpProtocol *protinstance, const XrdHttpReadRangeHandler::Configuration &rcfg)
Definition: XrdHttpReq.hh:207
bool m_appended_asize
Track whether we already appended the oss.asize argument for PUTs.
Definition: XrdHttpReq.hh:311
XrdOucString m_resource_with_digest
Definition: XrdHttpReq.hh:303
long long filesize
Definition: XrdHttpReq.hh:337
bool readClosing
Definition: XrdHttpReq.hh:278
virtual bool Redir(XrdXrootd::Bridge::Context &info, int port, const char *hname)
Definition: XrdHttpReq.cc:545
XErrorCode xrderrcode
Definition: XrdHttpReq.hh:326
virtual int File(XrdXrootd::Bridge::Context &info, int dlen)
Definition: XrdHttpReq.cc:474
std::map< std::string, std::string > allheaders
Definition: XrdHttpReq.hh:263
unsigned int rwOpDone
To coordinate multipart responses across multiple calls.
Definition: XrdHttpReq.hh:319
void addCgi(const std::string &key, const std::string &value)
Definition: XrdHttpReq.cc:747
bool sendcontinue
Definition: XrdHttpReq.hh:287
ClientRequest xrdreq
The last issued xrd request, often pending.
Definition: XrdHttpReq.hh:322
const std::string & userAgent() const
Definition: XrdHttpReq.hh:254
std::string buildPartialHdr(long long bytestart, long long byteend, long long filesize, char *token)
Build a partial header for a multipart response.
Definition: XrdHttpReq.cc:434
XrdHttpReadRangeHandler readRangeHandler
Tracking the next ranges of data to read during GET.
Definition: XrdHttpReq.hh:277
virtual void reset()
Definition: XrdHttpReq.cc:2700
virtual bool Error(XrdXrootd::Bridge::Context &info, int ecode, const char *etext)
Definition: XrdHttpReq.cc:515