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