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#include <sys/types.h>
53
55 std::string path;
56 long long size;
57 long id;
58 long flags;
59 long modtime;
60};
61
62
63class XrdHttpProtocol;
64class XrdOucEnv;
65
67
68public:
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
94
95private:
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
207public:
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
286
290
291 // Indication that there was a read error and the next
292 // request processing state should cleanly close the file.
294
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
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;
354 char fhandle[4];
356
358 std::string stringresp;
359
362
364 long long writtenbytes;
365
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
507void trim(std::string &str);
508
509#endif /* XRDHTTPREQ_HH */
510
XErrorCode
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
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
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
ssize_t length
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.
bool length_seen
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:77
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()