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 #include "XProtocol/XProtocol.hh"
44 #include "XrdOuc/XrdOucString.hh"
46 #include "XrdHttpMonState.hh"
47 
48 #include <chrono>
49 #include <map>
50 #include <string>
51 #include <vector>
52 #include <sys/types.h>
53 
54 struct DirListInfo {
55  std::string path;
56  long long size;
57  long id;
58  long flags;
59  long modtime;
60 };
61 
62 
63 class XrdHttpProtocol;
64 class XrdOucEnv;
65 
67 
68 public:
69  // ----------------
70  // Description of the request. The header/body parsing
71  // is supposed to populate these fields, for fast access while
72  // processing the request
73 
75  // Any changes here should also reflect in XrdHttpMon::verbCountersSchema to capture statistics of requests by verb
76  // The count and order or verbs listed should be consistent with the monitoring counters
77  enum ReqType : int {
78  rtUnset = -1,
79  rtUnknown = 0,
92  rtCount
93  };
94 
95 private:
96  // HTTP response parameters to be sent back to the user
97  int httpStatusCode{-1};
98 
99  // Stores the first response that was sent as part of the Response Header
100  // Used when staus code is updated after for e.g. Chunked Response + X-Transfer-Status request
101  int initialStatusCode{-1};
102 
103  // HTTP Error code for the response
104  // e.g. 8.1, 8.3.1, etc.
105  // https://twiki.cern.ch/twiki/bin/view/LCG/WebdavErrorImprovement
106  std::string httpErrorCode;
107  // HTTP response text with following format:
108  // Severity: ErrorCode: free-style text message
109  // Severity being OK, WARNING, or ERROR
110  // ErrorCode being a decimal numeric plus dot string, i.e. n or n.m or n.m.l,
111  // etc. free-style text message any UTF-8 string
112  // Optionally, it also contains the trailer headers whereever applicable
113  // e.g. X-Transfer-Status: 200: OK
114  // or X-Transfer-Status: 500: ERROR: <error message>: <additional text>
115  std::string httpErrorBody;
116 
117 
118  // The value of the user agent, if specified
119  std::string m_user_agent;
120 
121  // Whether transfer encoding was requested.
122  bool m_transfer_encoding_chunked{false};
123  long long m_current_chunk_offset;
124  long long m_current_chunk_size;
125 
126  // Whether trailer headers were enabled
127  bool m_trailer_headers{false};
128 
129  // Whether the client understands our special status trailer.
130  // The status trailer allows us to report when an IO error occurred
131  // after a response body has started
132  bool m_status_trailer{false};
133 
134  int parseHost(char *);
135 
136  void parseScitag(const std::string & val);
137 
138  //xmlDocPtr xmlbody; /* the resulting document tree */
139  XrdHttpProtocol *prot;
140 
141  void clientMarshallReadAheadList(int nitems);
142  void clientUnMarshallReadAheadList(int nitems);
143 
144 
145  void getfhandle();
146 
147  // Process the checksum response and return a header that should
148  // be included in the response.
149  int PostProcessChecksum(std::string &digest_header);
150 
151  // Process the listing request of a GET request against a directory
152  // - final_: True if this is the last entry in the listing.
153  int PostProcessListing(bool final_);
154 
155  // Send the response for a GET request for a file read (i.e., not a directory)
156  // Invoked after the open is successful but before the first read is issued.
157  int ReturnGetHeaders();
158 
164  int PostProcessHTTPReq(bool final = false);
165 
166  // Parse a resource string, typically a filename, setting the resource field and the opaque data
167  void parseResource(char *url);
168 
169  // Set Webdav Error messages
170  void generateWebdavErrMsg();
171 
172  // Sanitize the resource from http[s]://[host]/ questionable prefix
173  void sanitizeResourcePfx();
174 
175  // parses the iovN data pointers elements as either a kXR_read or kXR_readv
176  // response and fills out a XrdHttpIOList with the corresponding length and
177  // buffer pointers. File offsets from kXR_readv responses are not recorded.
178  void getReadResponse(XrdHttpIOList &received);
179 
180  // notifies the range handler of receipt of bytes and sends the client
181  // the data.
182  int sendReadResponseSingleRange(const XrdHttpIOList &received);
183 
184  // notifies the range handler of receipt of bytes and sends the client
185  // the data and necessary headers, assuming multipart/byteranges content type.
186  int sendReadResponsesMultiRanges(const XrdHttpIOList &received);
187 
188  // If requested by the client, sends any I/O errors that occur during the transfer
189  // into a footer.
190  int sendFooterError(const std::string &);
191 
192  // Set the age header from the file modification time
193  void addAgeHeader(std::string & headers);
194 
195  // Set the ETag header containing union of stat.st_ino and stat.st_dev
196  // See XrdXrootdProtocol::StatGen() for the full definition of etag value.
197  void addETagHeader(std::string & headers);
198 
205  int prepareChecksumQuery(XrdHttpChecksumHandler::XrdHttpChecksumRawPtr & outCksum, XrdOucString & outResourceDigestOpaque);
206 
207 public:
209  readRangeHandler(rcfg), closeAfterError(false), keepalive(true) {
210 
211  prot = protinstance;
212  length = 0;
213  //xmlbody = 0;
214  depth = 0;
215  opaque = 0;
216  writtenbytes = 0;
217  fopened = false;
218  headerok = false;
219  mScitag = -1;
220  };
221 
222  virtual ~XrdHttpReq();
223 
224  virtual void reset();
225 
226  int getInitialStatusCode() { return initialStatusCode;}
227  int getHttpStatusCode() { return httpStatusCode;}
228 
229  void setHttpStatusCode(int code) {
230  httpStatusCode = code;
231  if (initialStatusCode < 0 && code >= 200 ) {
232  initialStatusCode = code;
233  }
234  }
235 
237  int parseLine(char *line, int len);
238 
240  int parseFirstLine(char *line, int len);
241 
243  int parseBody(char *body, long long len);
244 
246  int ReqReadV(const XrdHttpIOList &cl);
247  std::vector<readahead_list> ralist;
248 
250  std::string buildPartialHdr(long long bytestart, long long byteend, long long filesize, char *token);
251 
253  std::string buildPartialHdrEnd(char *token);
254 
255  // Appends the opaque info that we have
256  // NOTE: this function assumes that the strings are unquoted, and will quote them
257  void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow);
258 
259  void addCgi(const std::string & key, const std::string & value);
260 
261  // Set the transfer status header, if requested by the client
262  void setTransferStatusHeader(std::string &header);
263 
264  // Return the current user agent; if none has been specified, returns an empty string
265  const std::string &userAgent() const {return m_user_agent;}
266 
267 
270  std::string requestverb;
271 
272  // We have to keep the headers for possible further processing
273  // by external plugins
274  std::map<std::string, std::string> allheaders;
275 
282 
283 
285  bool headerok;
286 
290 
291  // Indication that there was a read error and the next
292  // request processing state should cleanly close the file.
294 
295  bool keepalive;
296  ssize_t length; // Total size from client for PUT; total length of response TO client for GET.
297  bool length_seen{false}; // Set once a Content-Length header has been accepted (RFC 7230 ยง3.3.3 rule 4).
298  int depth;
300 
302  std::string host;
304  std::string destination;
305 
307  std::string m_want_digest;
308 
311 
317  std::string m_digest_header;
318 
320  std::string hdr2cgistr;
323  bool m_appended_asize{false};
324 
325  //
326  // Area for coordinating request and responses to/from the bridge
327  //
328 
329 
331  unsigned int rwOpDone, rwOpPartialDone;
332 
335 
339  std::string etext;
341 
343  const struct iovec *iovP;
344  int iovN;
345  int iovL;
346  bool final;
347 
348  // The latest stat info got from the xrd layer
349  long long etagval;
350  long long filesize;
351  long fileflags;
353  long filectime;
354  char fhandle[4];
355  bool fopened;
356 
358  std::string stringresp;
359 
361  int reqstate;
362 
364  long long writtenbytes;
365 
366  int mScitag;
367 
368  std::string m_origin;
369 
370  std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::time_point::min();
371 
373  std::map<std::string,std::string> m_repr_digest;
374 
377  std::map<std::string,uint8_t> m_want_repr_digest;
378 
380 
386  int ProcessHTTPReq();
387 
388 
389  // ------------
390  // Items inherited from the Bridge class
391  //
392 
393  //-----------------------------------------------------------------------------
419  //-----------------------------------------------------------------------------
420 
421  virtual bool Data(XrdXrootd::Bridge::Context &info,
422  const
423  struct iovec *iovP,
424  int iovN,
425  int iovL,
426  bool final
427  );
428 
429  //-----------------------------------------------------------------------------
439  //-----------------------------------------------------------------------------
440 
441  virtual bool Done(XrdXrootd::Bridge::Context &info);
442 
443 
444  //-----------------------------------------------------------------------------
457  //-----------------------------------------------------------------------------
458 
459  virtual bool Error(XrdXrootd::Bridge::Context &info,
460  int ecode,
461  const char *etext
462  );
463 
464  //-----------------------------------------------------------------------------
477  //-----------------------------------------------------------------------------
478 
479  virtual int File(XrdXrootd::Bridge::Context &info,
480  int dlen
481  );
482 
483  //-----------------------------------------------------------------------------
496  //-----------------------------------------------------------------------------
497 
498  virtual bool Redir(XrdXrootd::Bridge::Context &info,
499  int port,
500  const char *hname
501  );
502 
503 };
504 
505 
506 
507 void trim(std::string &str);
508 
509 #endif /* XRDHTTPREQ_HH */
510 
XErrorCode
Definition: XProtocol.hh:1031
XResponseType
Definition: XProtocol.hh:940
XrdHttpMonState
long long size
Definition: XrdHttpReq.hh:56
void trim(std::string &str)
Definition: XrdHttpReq.cc:78
std::string path
Definition: XrdHttpReq.hh:55
long modtime
Definition: XrdHttpReq.hh:59
std::vector< XrdOucIOVec2 > XrdHttpIOList
int reqstate
State machine to talk to the bridge.
Definition: XrdHttpReq.hh:361
char fhandle[4]
Definition: XrdHttpReq.hh:354
int ReqReadV(const XrdHttpIOList &cl)
Prepare the buffers for sending a readv request.
Definition: XrdHttpReq.cc:451
int getHttpStatusCode()
Definition: XrdHttpReq.hh:227
bool keepalive
Definition: XrdHttpReq.hh:295
unsigned int rwOpPartialDone
Definition: XrdHttpReq.hh:331
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:96
std::vector< readahead_list > ralist
Definition: XrdHttpReq.hh:247
std::string destination
The destination field specified in the req.
Definition: XrdHttpReq.hh:304
XrdOucString resource
The resource specified by the request, stripped of opaque data.
Definition: XrdHttpReq.hh:277
bool headerok
Tells if we have finished reading the header.
Definition: XrdHttpReq.hh:285
std::map< std::string, uint8_t > m_want_repr_digest
Definition: XrdHttpReq.hh:377
ssize_t length
Definition: XrdHttpReq.hh:296
std::string m_digest_header
The computed digest for the HTTP response header.
Definition: XrdHttpReq.hh:317
std::string etext
Definition: XrdHttpReq.hh:339
std::string stringresp
If we want to give a string as a response, we compose it here.
Definition: XrdHttpReq.hh:358
XResponseType xrdresp
The last response data we got.
Definition: XrdHttpReq.hh:337
std::map< std::string, std::string > m_repr_digest
Repr-Digest map where the key is the digest name and the value is the base64 encoded digest value.
Definition: XrdHttpReq.hh:373
std::string requestverb
Definition: XrdHttpReq.hh:270
ReqType request
The request we got.
Definition: XrdHttpReq.hh:269
bool length_seen
Definition: XrdHttpReq.hh:297
int ProcessHTTPReq()
Definition: XrdHttpReq.cc:940
bool closeAfterError
Definition: XrdHttpReq.hh:293
long long writtenbytes
In a long write, we track where we have arrived.
Definition: XrdHttpReq.hh:364
XrdOucEnv * opaque
The opaque data, after parsing.
Definition: XrdHttpReq.hh:279
long fileflags
Definition: XrdHttpReq.hh:351
int iovL
byte count
Definition: XrdHttpReq.hh:345
bool fopened
Definition: XrdHttpReq.hh:355
const struct iovec * iovP
The latest data chunks got from the xrd layer. These are valid only inside the callbacks!
Definition: XrdHttpReq.hh:343
virtual ~XrdHttpReq()
Definition: XrdHttpReq.cc:112
XrdOucString resourceplusopaque
The resource specified by the request, including all the opaque data.
Definition: XrdHttpReq.hh:281
virtual bool Data(XrdXrootd::Bridge::Context &info, const struct iovec *iovP, int iovN, int iovL, bool final)
Definition: XrdHttpReq.cc:506
long filectime
Definition: XrdHttpReq.hh:353
std::string hdr2cgistr
Additional opaque info that may come from the hdr2cgi directive.
Definition: XrdHttpReq.hh:320
virtual bool Done(XrdXrootd::Bridge::Context &info)
the result context
Definition: XrdHttpReq.cc:552
std::string host
The host field specified in the req.
Definition: XrdHttpReq.hh:302
long filemodtime
Definition: XrdHttpReq.hh:352
int parseFirstLine(char *line, int len)
Parse the first line of the header.
Definition: XrdHttpReq.cc:319
XrdOucString redirdest
Definition: XrdHttpReq.hh:340
void setHttpStatusCode(int code)
Definition: XrdHttpReq.hh:229
std::string m_origin
Definition: XrdHttpReq.hh:368
ReqType
These are the HTTP/DAV requests that we support.
Definition: XrdHttpReq.hh:77
int parseLine(char *line, int len)
Parse the header.
Definition: XrdHttpReq.cc:118
std::string buildPartialHdrEnd(char *token)
Build the closing part for a multipart response.
Definition: XrdHttpReq.cc:498
XrdHttpChecksumHandler::XrdHttpChecksumRawPtr m_req_cksum
The checksum that was ran for this request.
Definition: XrdHttpReq.hh:310
std::string m_want_digest
The requested digest type.
Definition: XrdHttpReq.hh:307
void setTransferStatusHeader(std::string &header)
Definition: XrdHttpReq.cc:2090
bool m_appended_hdr2cgistr
Definition: XrdHttpReq.hh:321
void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow)
Definition: XrdHttpReq.cc:711
int iovN
array count
Definition: XrdHttpReq.hh:344
XrdHttpReq(XrdHttpProtocol *protinstance, const XrdHttpReadRangeHandler::Configuration &rcfg)
Definition: XrdHttpReq.hh:208
bool m_appended_asize
Track whether we already appended the oss.asize argument for PUTs.
Definition: XrdHttpReq.hh:323
XrdOucString m_resource_with_digest
Definition: XrdHttpReq.hh:315
long long filesize
Definition: XrdHttpReq.hh:350
bool readClosing
Definition: XrdHttpReq.hh:289
std::chrono::steady_clock::time_point startTime
Definition: XrdHttpReq.hh:370
long long etagval
Definition: XrdHttpReq.hh:349
virtual bool Redir(XrdXrootd::Bridge::Context &info, int port, const char *hname)
Definition: XrdHttpReq.cc:599
XErrorCode xrderrcode
Definition: XrdHttpReq.hh:338
virtual int File(XrdXrootd::Bridge::Context &info, int dlen)
Definition: XrdHttpReq.cc:528
std::map< std::string, std::string > allheaders
Definition: XrdHttpReq.hh:274
int getInitialStatusCode()
Definition: XrdHttpReq.hh:226
unsigned int rwOpDone
To coordinate multipart responses across multiple calls.
Definition: XrdHttpReq.hh:331
void addCgi(const std::string &key, const std::string &value)
Definition: XrdHttpReq.cc:819
bool sendcontinue
Definition: XrdHttpReq.hh:299
ClientRequest xrdreq
The last issued xrd request, often pending.
Definition: XrdHttpReq.hh:334
const std::string & userAgent() const
Definition: XrdHttpReq.hh:265
XrdHttpMonState monState
Definition: XrdHttpReq.hh:379
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:488
XrdHttpReadRangeHandler readRangeHandler
Tracking the next ranges of data to read during GET.
Definition: XrdHttpReq.hh:288
virtual void reset()
Definition: XrdHttpReq.cc:2771
virtual bool Error(XrdXrootd::Bridge::Context &info, int ecode, const char *etext)
Definition: XrdHttpReq.cc:569