XRootD
Loading...
Searching...
No Matches
XrdHttpReq Class Reference

#include <XrdHttpReq.hh>

Inheritance diagram for XrdHttpReq:
Collaboration diagram for XrdHttpReq:

Public Types

enum  ReqType {
  rtUnset = -1 ,
  rtUnknown = 0 ,
  rtMalformed ,
  rtGET ,
  rtHEAD ,
  rtPUT ,
  rtOPTIONS ,
  rtPATCH ,
  rtDELETE ,
  rtPROPFIND ,
  rtMKCOL ,
  rtMOVE ,
  rtPOST
}
 These are the HTTP/DAV requests that we support. More...

Public Member Functions

 XrdHttpReq (XrdHttpProtocol *protinstance, const XrdHttpReadRangeHandler::Configuration &rcfg)
virtual ~XrdHttpReq ()
void addCgi (const std::string &key, const std::string &value)
void appendOpaque (XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow)
std::string buildPartialHdr (long long bytestart, long long byteend, long long filesize, char *token)
 Build a partial header for a multipart response.
std::string buildPartialHdrEnd (char *token)
 Build the closing part for a multipart response.
virtual bool Data (XrdXrootd::Bridge::Context &info, const struct iovec *iovP, int iovN, int iovL, bool final)
virtual bool Done (XrdXrootd::Bridge::Context &info)
 the result context
virtual bool Error (XrdXrootd::Bridge::Context &info, int ecode, const char *etext)
virtual int File (XrdXrootd::Bridge::Context &info, int dlen)
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.
int parseFirstLine (char *line, int len)
 Parse the first line of the header.
int parseLine (char *line, int len)
 Parse the header.
int ProcessHTTPReq ()
virtual bool Redir (XrdXrootd::Bridge::Context &info, int port, const char *hname)
int ReqReadV (const XrdHttpIOList &cl)
 Prepare the buffers for sending a readv request.
virtual void reset ()
const std::string & userAgent () const
Public Member Functions inherited from XrdXrootd::Bridge::Result
 Result ()
 Constructor & Destructor.
virtual ~Result ()
virtual void Free (Bridge::Context &info, char *buffP, int buffL)
virtual bool Wait (Bridge::Context &info, int wtime, const char *wtext)
virtual Bridge::ResultWaitResp (Bridge::Context &info, int wtime, const char *wtext)

Public Attributes

std::map< std::string, std::string > allheaders
int depth
std::string destination
 The destination field specified in the req.
std::string etext
char fhandle [4]
long filectime
long fileflags
long filemodtime
long long filesize
bool final
 true -> final result
bool fopened
std::string hdr2cgistr
 Additional opaque info that may come from the hdr2cgi directive.
bool headerok
 Tells if we have finished reading the header.
std::string host
 The host field specified in the req.
int iovL
 byte count
int iovN
 array count
const struct iovec * iovP
 The latest data chunks got from the xrd layer. These are valid only inside the callbacks!
bool keepalive
long long length
bool m_appended_asize {false}
 Track whether we already appended the oss.asize argument for PUTs.
bool m_appended_hdr2cgistr
std::string m_digest_header
 The computed digest for the HTTP response header.
XrdHttpChecksumHandler::XrdHttpChecksumRawPtr m_req_cksum = nullptr
 The checksum that was ran for this request.
std::string m_req_digest
 The requested digest type.
XrdOucString m_resource_with_digest
int mScitag
XrdOucEnvopaque
 The opaque data, after parsing.
std::vector< readahead_listralist
bool readClosing
XrdHttpReadRangeHandler readRangeHandler
 Tracking the next ranges of data to read during GET.
XrdOucString redirdest
int reqstate
 State machine to talk to the bridge.
ReqType request
 The request we got.
std::string requestverb
XrdOucString resource
 The resource specified by the request, stripped of opaque data.
XrdOucString resourceplusopaque
 The resource specified by the request, including all the opaque data.
unsigned int rwOpDone
 To coordinate multipart responses across multiple calls.
unsigned int rwOpPartialDone
bool sendcontinue
std::string stringresp
 If we want to give a string as a response, we compose it here.
long long writtenbytes
 In a long write, we track where we have arrived.
XErrorCode xrderrcode
ClientRequest xrdreq
 The last issued xrd request, often pending.
XResponseType xrdresp
 The last response data we got.

Detailed Description

Definition at line 71 of file XrdHttpReq.hh.

Member Enumeration Documentation

◆ ReqType

These are the HTTP/DAV requests that we support.

Enumerator
rtUnset 
rtUnknown 
rtMalformed 
rtGET 
rtHEAD 
rtPUT 
rtOPTIONS 
rtPATCH 
rtDELETE 
rtPROPFIND 
rtMKCOL 
rtMOVE 
rtPOST 

Definition at line 219 of file XrdHttpReq.hh.

Constructor & Destructor Documentation

◆ XrdHttpReq()

XrdHttpReq::XrdHttpReq ( XrdHttpProtocol * protinstance,
const XrdHttpReadRangeHandler::Configuration & rcfg )
inline

Definition at line 166 of file XrdHttpReq.hh.

166 :
167 readRangeHandler(rcfg), keepalive(true) {
168
169 prot = protinstance;
170 length = 0;
171 //xmlbody = 0;
172 depth = 0;
173 opaque = 0;
174 writtenbytes = 0;
175 fopened = false;
176 headerok = false;
177 mScitag = -1;
178 };
long long length
bool headerok
Tells if we have finished reading the header.
long long writtenbytes
In a long write, we track where we have arrived.
XrdOucEnv * opaque
The opaque data, after parsing.
XrdHttpReadRangeHandler readRangeHandler
Tracking the next ranges of data to read during GET.

References depth, fopened, headerok, keepalive, length, mScitag, opaque, readRangeHandler, and writtenbytes.

◆ ~XrdHttpReq()

XrdHttpReq::~XrdHttpReq ( )
virtual

Definition at line 110 of file XrdHttpReq.cc.

110 {
111 //if (xmlbody) xmlFreeDoc(xmlbody);
112
113 reset();
114}
virtual void reset()

References reset().

Here is the call graph for this function:

Member Function Documentation

◆ addCgi()

void XrdHttpReq::addCgi ( const std::string & key,
const std::string & value )

Definition at line 786 of file XrdHttpReq.cc.

786 {
787 if (hdr2cgistr.length() > 0) {
788 hdr2cgistr.append("&");
789 }
790 hdr2cgistr.append(key);
791 hdr2cgistr.append("=");
792 hdr2cgistr.append(value);
793}
std::string hdr2cgistr
Additional opaque info that may come from the hdr2cgi directive.

References hdr2cgistr.

Referenced by parseLine().

Here is the caller graph for this function:

◆ appendOpaque()

void XrdHttpReq::appendOpaque ( XrdOucString & s,
XrdSecEntity * secent,
char * hash,
time_t tnow )

Definition at line 629 of file XrdHttpReq.cc.

629 {
630
631 int l = 0;
632 char * p = 0;
633 if (opaque)
634 p = opaque->Env(l);
635
636 if (hdr2cgistr.empty() && (l < 2) && !hash) return;
637
638 // this works in most cases, except if the url already contains the xrdhttp tokens
639 s = s + "?";
640 if (!hdr2cgistr.empty()) {
641 char *s1 = quote(hdr2cgistr.c_str());
642 if (s1) {
643 s += s1;
644 free(s1);
645 }
646 }
647 if (p && (l > 1)) {
648 char *s1 = quote(p+1);
649 if (s1) {
650 if (!hdr2cgistr.empty()) {
651 s = s + "&";
652 }
653 s = s + s1;
654 free(s1);
655 }
656 }
657
658
659
660 if (hash) {
661 if (l > 1) s += "&";
662 s += "xrdhttptk=";
663 s += hash;
664
665 s += "&xrdhttptime=";
666 char buf[256];
667 sprintf(buf, "%lld", (long long) tnow);
668 s += buf;
669
670 if (secent) {
671 if (secent->name) {
672 s += "&xrdhttpname=";
673 char *s1 = quote(secent->name);
674 if (s1) {
675 s += s1;
676 free(s1);
677 }
678 }
679
680 if (secent->vorg) {
681 s += "&xrdhttpvorg=";
682 char *s1 = quote(secent->vorg);
683 if (s1) {
684 s += s1;
685 free(s1);
686 }
687 }
688
689 if (secent->host) {
690 s += "&xrdhttphost=";
691 char *s1 = quote(secent->host);
692 if (s1) {
693 s += s1;
694 free(s1);
695 }
696 }
697
698 if (secent->moninfo) {
699 s += "&xrdhttpdn=";
700 char *s1 = quote(secent->moninfo);
701 if (s1) {
702 s += s1;
703 free(s1);
704 }
705 }
706
707 if (secent->role) {
708 s += "&xrdhttprole=";
709 char *s1 = quote(secent->role);
710 if (s1) {
711 s += s1;
712 free(s1);
713 }
714 }
715
716 if (secent->grps) {
717 s += "&xrdhttpgrps=";
718 char *s1 = quote(secent->grps);
719 if (s1) {
720 s += s1;
721 free(s1);
722 }
723 }
724
725 if (secent->endorsements) {
726 s += "&xrdhttpendorsements=";
727 char *s1 = quote(secent->endorsements);
728 if (s1) {
729 s += s1;
730 free(s1);
731 }
732 }
733
734 if (secent->credslen) {
735 s += "&xrdhttpcredslen=";
736 char buf[16];
737 sprintf(buf, "%d", secent->credslen);
738 char *s1 = quote(buf);
739 if (s1) {
740 s += s1;
741 free(s1);
742 }
743 }
744
745 if (secent->credslen) {
746 if (secent->creds) {
747 s += "&xrdhttpcreds=";
748 // Apparently this string might be not 0-terminated (!)
749 char *zerocreds = strndup(secent->creds, secent->credslen);
750 if (zerocreds) {
751 char *s1 = quote(zerocreds);
752 if (s1) {
753 s += s1;
754 free(s1);
755 }
756 free(zerocreds);
757 }
758 }
759 }
760
761 }
762 }
763
764}
char * quote(const char *str)
char * vorg
Entity's virtual organization(s)
int credslen
Length of the 'creds' data.
char * creds
Raw entity credentials or cert.
char * grps
Entity's group name(s)
char * name
Entity's name.
char * role
Entity's role(s)
char * endorsements
Protocol specific endorsements.
char * moninfo
Information for monitoring.
char * host
Entity's host name dnr dependent.

References XrdSecEntity::creds, XrdSecEntity::credslen, XrdSecEntity::endorsements, XrdSecEntity::grps, hdr2cgistr, XrdSecEntity::host, XrdSecEntity::moninfo, XrdSecEntity::name, opaque, quote(), XrdSecEntity::role, and XrdSecEntity::vorg.

Referenced by ProcessHTTPReq(), and Redir().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ buildPartialHdr()

std::string XrdHttpReq::buildPartialHdr ( long long bytestart,
long long byteend,
long long filesize,
char * token )

Build a partial header for a multipart response.

Definition at line 425 of file XrdHttpReq.cc.

425 {
426 std::ostringstream s;
427
428 s << "\r\n--" << token << "\r\n";
429 s << "Content-type: text/plain; charset=UTF-8\r\n";
430 s << "Content-range: bytes " << bytestart << "-" << byteend << "/" << fsz << "\r\n\r\n";
431
432 return s.str();
433}

◆ buildPartialHdrEnd()

std::string XrdHttpReq::buildPartialHdrEnd ( char * token)

Build the closing part for a multipart response.

Definition at line 435 of file XrdHttpReq.cc.

435 {
436 std::ostringstream s;
437
438 s << "\r\n--" << token << "--\r\n";
439
440 return s.str();
441}

◆ Data()

bool XrdHttpReq::Data ( XrdXrootd::Bridge::Context & info,
const struct iovec * iovP,
int iovN,
int iovL,
bool final )
virtual

Effect a client data response.

The Data() method is called when Run() resulted in a successful data response. The method should rewrite the data and send it to the client using the associated XrdLink object. As an example, 1) Result::Data(info, iovP, iovN, iovL) is called. 2) Inspect iovP, rewrite the data. 3) Send the response: info->linkP->Send(new_iovP, new_iovN, new_iovL); 4) Handle send errors and cleanup(e.g. deallocate storage). 5) Return, the exchange is now complete.

Parameters
infothe context associated with the result.
iovPa pointer to the iovec structure containing the xrootd data response about to be sent to the client. The request header is not included in the iovec structure. The elements of this structure must not be modified by the method.
iovNthe number of elements in the iovec structure array.
iovLtotal number of data bytes that would be sent to the client. This is simply the sum of all the lengths in the iovec.
finalTrue is this is the final result. Otherwise, this is a partial result (i.e. kXR_oksofar) and more data will result causing additional callbacks.
Returns
true continue normal processing. false terminate the bridge and close the link.
Parameters
infothe result context
iovPpointer to data array
iovNarray count
iovLbyte count
finaltrue -> final result

Implements XrdXrootd::Bridge::Result.

Definition at line 443 of file XrdHttpReq.cc.

449 {
450
451 TRACE(REQ, " XrdHttpReq::Data! final=" << final);
452
453 this->xrdresp = kXR_ok;
454 this->iovP = iovP_;
455 this->iovN = iovN_;
456 this->iovL = iovL_;
457 this->final = final_;
458
459 if (PostProcessHTTPReq(final_)) reset();
460
461 return true;
462
463};
@ kXR_ok
Definition XProtocol.hh:899
#define TRACE(act, x)
Definition XrdTrace.hh:63
XResponseType xrdresp
The last response data we got.
int iovL
byte count
const struct iovec * iovP
The latest data chunks got from the xrd layer. These are valid only inside the callbacks!
int iovN
array count

References iovL, iovN, iovP, kXR_ok, reset(), TRACE, and xrdresp.

Here is the call graph for this function:

◆ Done()

bool XrdHttpReq::Done ( XrdXrootd::Bridge::Context & info)
virtual

the result context

Effect a client acknowledgement.

The Done() method is called when Run() resulted in success and there is no associated data for the client (equivalent to a simple kXR_ok response).

Parameters
infothe context associated with the result.
Returns
true continue normal processing. false terminate the bridge and close the link.

Implements XrdXrootd::Bridge::Result.

Definition at line 489 of file XrdHttpReq.cc.

489 {
490
491 TRACE(REQ, " XrdHttpReq::Done");
492
493 xrdresp = kXR_ok;
494
495 this->iovN = 0;
496
497 int r = PostProcessHTTPReq(true);
498 // Beware, we don't have to reset() if the result is 0
499 if (r) reset();
500 if (r < 0) return false;
501
502
503 return true;
504};

References iovN, kXR_ok, reset(), TRACE, and xrdresp.

Here is the call graph for this function:

◆ Error()

bool XrdHttpReq::Error ( XrdXrootd::Bridge::Context & info,
int ecode,
const char * etext )
virtual

Effect a client error response.

The Error() method is called when an error was encountered while processing the Run() request. The error should be reflected to the client.

Parameters
infothe context associated with the result.
ecodethe "kXR" error code describing the nature of the error. The code is in host byte format.
etexta null terminated string describing the error in human terms
Returns
true continue normal processing. false terminate the bridge and close the link.
Parameters
infothe result context
ecodethe "kXR" error code
etextassociated error message

Implements XrdXrootd::Bridge::Result.

Definition at line 506 of file XrdHttpReq.cc.

509 {
510
511 TRACE(REQ, " XrdHttpReq::Error");
512
514 xrderrcode = (XErrorCode) ecode;
515
516 if (etext_) {
517 char *s = escapeXML(etext_);
518 this->etext = s;
519 free(s);
520 }
521
522 if (PostProcessHTTPReq()) reset();
523
524 // If we are servicing a GET on a directory, it'll generate an error for the default
525 // OSS (we don't assume this is always true). Catch and suppress the error so we can instead
526 // generate a directory listing (if configured).
527 if ((request == rtGET) && (xrdreq.header.requestid == ntohs(kXR_open)) && (xrderrcode == kXR_isDirectory))
528 return true;
529
530 return false;
531};
XErrorCode
Definition XProtocol.hh:989
@ kXR_isDirectory
@ kXR_error
Definition XProtocol.hh:903
@ kXR_open
Definition XProtocol.hh:122
char * escapeXML(const char *str)
std::string etext
ReqType request
The request we got.
XErrorCode xrderrcode
ClientRequest xrdreq
The last issued xrd request, often pending.

References escapeXML(), etext, kXR_error, kXR_isDirectory, kXR_open, request, reset(), rtGET, TRACE, xrderrcode, xrdreq, and xrdresp.

Here is the call graph for this function:

◆ File()

int XrdHttpReq::File ( XrdXrootd::Bridge::Context & info,
int dlen )
virtual

Notify callback that a sendfile() request is pending.

The File() method is called when Run() resulted in a sendfile response (i.e. sendfile() would have been used to send data to the client). This allows the callback to reframe the sendfile() data using the Send() method in the passed context object (see class Context above).

Parameters
infothe context associated with the result.
dlentotal number of data bytes that would be sent to the client.
Returns
true continue normal processing. false terminate the bridge and close the link.
Parameters
infothe result context
dlenbyte count

Implements XrdXrootd::Bridge::Result.

Definition at line 465 of file XrdHttpReq.cc.

467 {
468
469 // sendfile about to be sent by bridge for fetching data for GET:
470 // no https, no chunked+trailer, no multirange
471
472 //prot->SendSimpleResp(200, NULL, NULL, NULL, dlen);
473 int rc = info.Send(0, 0, 0, 0);
474 TRACE(REQ, " XrdHttpReq::File dlen:" << dlen << " send rc:" << rc);
475 bool start, finish;
476 // short read will be classed as error
477 if (rc) {
478 readRangeHandler.NotifyError();
479 return false;
480 }
481
482 if (readRangeHandler.NotifyReadResult(dlen, nullptr, start, finish) < 0)
483 return false;
484
485
486 return true;
487};
virtual int Send(const struct iovec *headP, int headN, const struct iovec *tailP, int tailN)

References readRangeHandler, XrdXrootd::Bridge::Context::Send(), and TRACE.

Here is the call graph for this function:

◆ parseBody()

int XrdHttpReq::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 at line 94 of file XrdHttpReq.cc.

94 {
95 /*
96 * The document being in memory, it has no base per RFC 2396,
97 * and the "noname.xml" argument will serve as its base.
98 */
99 //xmlbody = xmlReadMemory(body, len, "noname.xml", NULL, 0);
100 //if (xmlbody == NULL) {
101 // fprintf(stderr, "Failed to parse document\n");
102 // return 1;
103 //}
104
105
106
107 return 1;
108}

Referenced by ProcessHTTPReq().

Here is the caller graph for this function:

◆ parseFirstLine()

int XrdHttpReq::parseFirstLine ( char * line,
int len )

Parse the first line of the header.

Definition at line 256 of file XrdHttpReq.cc.

256 {
257
258 char *key = line;
259
260 int pos;
261
262 // Do the naive parsing
263 if (!line) return -1;
264
265 // Look for the first space-delimited token
266 char *p = strchr((char *) line, (int) ' ');
267 if (!p) {
269 return -1;
270 }
271
272
273 pos = p - line;
274 // The first token cannot be too long
275 if (pos > MAX_TK_LEN - 1) {
277 return -2;
278 }
279
280 // The first space-delimited char cannot be the first one
281 // this allows to deal with the case when a client sends a first line that starts with a space " GET / HTTP/1.1"
282 if(pos == 0) {
284 return -4;
285 }
286
287 // the first token must be non empty
288 if (pos > 0) {
289 line[pos] = 0;
290 char *val = line + pos + 1;
291
292 // Here we are supposed to initialize whatever flag or variable that is needed
293 // by looking at the first token of the line
294
295 // The token is key
296 // The remainder is val, look for the resource
297 p = strchr((char *) val, (int) ' ');
298
299 if (!p) {
301 line[pos] = ' ';
302 return -3;
303 }
304
305 *p = '\0';
306 parseResource(val);
307
308 *p = ' ';
309
310 // Xlate the known header lines
311 if (!strcmp(key, "GET")) {
312 request = rtGET;
313 } else if (!strcmp(key, "HEAD")) {
314 request = rtHEAD;
315 } else if (!strcmp(key, "PUT")) {
316 request = rtPUT;
317 } else if (!strcmp(key, "POST")) {
318 request = rtPOST;
319 } else if (!strcmp(key, "PATCH")) {
321 } else if (!strcmp(key, "OPTIONS")) {
323 } else if (!strcmp(key, "DELETE")) {
325 } else if (!strcmp(key, "PROPFIND")) {
327
328 } else if (!strcmp(key, "MKCOL")) {
330
331 } else if (!strcmp(key, "MOVE")) {
332 request = rtMOVE;
333 } else {
335 }
336
337 requestverb = key;
338
339 // The last token should be the protocol. If it is HTTP/1.0, then
340 // keepalive is disabled by default.
341 if (!strcmp(p+1, "HTTP/1.0\r\n")) {
342 keepalive = false;
343 }
344 line[pos] = ' ';
345 }
346
347 return 0;
348}
#define MAX_TK_LEN
Definition XrdHttpReq.cc:65
std::string requestverb

References keepalive, MAX_TK_LEN, request, requestverb, rtDELETE, rtGET, rtHEAD, rtMalformed, rtMKCOL, rtMOVE, rtOPTIONS, rtPATCH, rtPOST, rtPROPFIND, rtPUT, and rtUnknown.

◆ parseLine()

int XrdHttpReq::parseLine ( char * line,
int len )

Parse the header.

Definition at line 116 of file XrdHttpReq.cc.

116 {
117
118 char *key = line;
119 int pos;
120
121 // Do the parsing
122 if (!line) return -1;
123
124
125 char *p = strchr((char *) line, (int) ':');
126 if (!p) {
127
129 return -1;
130 }
131
132 pos = (p - line);
133 if (pos > (MAX_TK_LEN - 1)) {
134
136 return -2;
137 }
138
139 if (pos > 0) {
140 line[pos] = 0;
141 char *val = line + pos + 1;
142
143 // Trim left
144 while ( (!isgraph(*val) || (!*val)) && (val < line+len)) val++;
145
146 // We memorize the headers also as a string
147 // because external plugins may need to process it differently
148 std::string ss = val;
149 if(ss.length() >= 2 && ss.substr(ss.length() - 2, 2) != "\r\n") {
151 return -3;
152 }
153 trim(ss);
154 allheaders[key] = ss;
155
156 // Here we are supposed to initialize whatever flag or variable that is needed
157 // by looking at the first token of the line
158 // The token is key
159 // The value is val
160
161 // Screen out the needed header lines
162 if (!strcasecmp(key, "connection")) {
163
164 if (!strcasecmp(val, "Keep-Alive\r\n")) {
165 keepalive = true;
166 } else if (!strcasecmp(val, "close\r\n")) {
167 keepalive = false;
168 }
169
170 } else if (!strcasecmp(key, "host")) {
171 parseHost(val);
172 } else if (!strcasecmp(key, "range")) {
173 // (rfc2616 14.35.1) says if Range header contains any range
174 // which is syntactically invalid the Range header should be ignored.
175 // Therefore no need for the range handler to report an error.
176 readRangeHandler.ParseContentRange(val);
177 } else if (!strcasecmp(key, "content-length")) {
178 length = atoll(val);
179
180 } else if (!strcasecmp(key, "destination")) {
181 destination.assign(val, line+len-val);
183 } else if (!strcasecmp(key, "want-digest")) {
184 m_req_digest.assign(val, line + len - val);
186 //Transform the user requests' want-digest to lowercase
187 std::transform(m_req_digest.begin(),m_req_digest.end(),m_req_digest.begin(),::tolower);
188 } else if (!strcasecmp(key, "depth")) {
189 depth = -1;
190 if (strcmp(val, "infinity"))
191 depth = atoll(val);
192
193 } else if (!strcasecmp(key, "expect") && strstr(val, "100-continue")) {
194 sendcontinue = true;
195 } else if (!strcasecmp(key, "te") && strstr(val, "trailers")) {
196 m_trailer_headers = true;
197 } else if (!strcasecmp(key, "transfer-encoding") && strstr(val, "chunked")) {
198 m_transfer_encoding_chunked = true;
199 } else if (!strcasecmp(key, "x-transfer-status") && strstr(val, "true")) {
200 m_transfer_encoding_chunked = true;
201 m_status_trailer = true;
202 } else if (!strcasecmp(key, "scitag")) {
203 if(prot->pmarkHandle != nullptr) {
204 parseScitag(val);
205 }
206 } else if (!strcasecmp(key, "user-agent")) {
207 m_user_agent = val;
208 trim(m_user_agent);
209 } else {
210 // Some headers need to be translated into "local" cgi info.
211 auto it = std::find_if(prot->hdr2cgimap.begin(), prot->hdr2cgimap.end(),[key](const auto & item) {
212 return !strcasecmp(key,item.first.c_str());
213 });
214 if (it != prot->hdr2cgimap.end() && (opaque ? (0 == opaque->Get(it->second.c_str())) : true)) {
215 std::string s;
216 s.assign(val, line+len-val);
217 trim(s);
218 addCgi(it->second,s);
219 }
220 }
221
222
223 line[pos] = ':';
224 }
225
226 return 0;
227}
void trim(std::string &str)
Definition XrdHttpReq.cc:76
std::string destination
The destination field specified in the req.
std::string m_req_digest
The requested digest type.
std::map< std::string, std::string > allheaders
void addCgi(const std::string &key, const std::string &value)
bool sendcontinue

References addCgi(), allheaders, depth, destination, keepalive, length, m_req_digest, MAX_TK_LEN, opaque, readRangeHandler, request, rtMalformed, sendcontinue, and trim().

Here is the call graph for this function:

◆ ProcessHTTPReq()

int XrdHttpReq::ProcessHTTPReq ( )

Crunch an http request. Return values: 0->call Process again 1->request processed -1->error

If we have to add extra header information, add it here.

Definition at line 928 of file XrdHttpReq.cc.

928 {
929
930 kXR_int32 l;
931
932 // State variable for tracking the query parameter search
933 // - 0: Indicates we've not yet searched the URL for '?'
934 // - 1: Indicates we have a '?' and hence query parameters
935 // - 2: Indicates we do *not* have '?' present -- no query parameters
936 int query_param_status = 0;
937 if (!m_appended_asize) {
938 m_appended_asize = true;
939 if (request == rtPUT && length) {
940 if (query_param_status == 0) {
941 query_param_status = strchr(resourceplusopaque.c_str(), '?') ? 1 : 2;
942 }
943 resourceplusopaque.append((query_param_status == 1) ? '&' : '?');
944 query_param_status = 1;
945 auto length_str = std::to_string(length);
946 resourceplusopaque.append("oss.asize=");
947 resourceplusopaque.append(length_str.c_str());
948 if (!opaque) {
949 opaque = new XrdOucEnv();
950 }
951 opaque->Put("oss.asize", length_str.c_str());
952 }
953 }
954
956 if (!m_appended_hdr2cgistr && !hdr2cgistr.empty()) {
957 if (query_param_status == 0) {
958 query_param_status = strchr(resourceplusopaque.c_str(), '?') ? 1 : 2;
959 }
960 resourceplusopaque.append((query_param_status == 1) ? '&' : '?');
961
962 char *q = quote(hdr2cgistr.c_str());
963 resourceplusopaque.append(q);
964 if (TRACING(TRACE_DEBUG)) {
965 // The obfuscation of "authz" will only be done if the server http.header2cgi config contains something that maps a header to this "authz" cgi.
966 // Unfortunately the obfuscation code will be called no matter what is configured in http.header2cgi.
967 std::string header2cgistrObf = obfuscateAuth(hdr2cgistr);
968
969 TRACEI(DEBUG, "Appended header fields to opaque info: '"
970 << header2cgistrObf.c_str() << "'");
971
972 }
973 // We assume that anything appended to the CGI str should also
974 // apply to the destination in case of a MOVE.
975 if (strchr(destination.c_str(), '?')) destination.append("&");
976 else destination.append("?");
977 destination.append(q);
978
979 free(q);
981 }
982
983 // Verify if we have an external handler for this request
984 if (reqstate == 0) {
985 XrdHttpExtHandler *exthandler = prot->FindMatchingExtHandler(*this);
986 if (exthandler) {
987 XrdHttpExtReq xreq(this, prot);
988 int r = exthandler->ProcessReq(xreq);
989 reset();
990 if (!r) return 1; // All went fine, response sent
991 if (r < 0) return -1; // There was a hard error... close the connection
992
993 return 1; // There was an error and a response was sent
994 }
995 }
996
997 //
998 // Here we process the request locally
999 //
1000
1001 switch (request) {
1004 {
1005 prot->SendSimpleResp(400, NULL, NULL, (char *) "Request unknown", 0, false);
1006 reset();
1007 return -1;
1008 }
1010 {
1011 prot->SendSimpleResp(400, NULL, NULL, (char *) "Request malformed", 0, false);
1012 reset();
1013 return -1;
1014 }
1015 case XrdHttpReq::rtHEAD:
1016 {
1017 if (reqstate == 0) {
1018 // Always start with Stat; in the case of a checksum request, we'll have a follow-up query
1019 if (prot->doStat((char *) resourceplusopaque.c_str())) {
1020 prot->SendSimpleResp(404, NULL, NULL, (char *) "Could not run request.", 0, false);
1021 return -1;
1022 }
1023 return 0;
1024 } else {
1025 const char *opaque = strchr(resourceplusopaque.c_str(), '?');
1026 // Note that doChksum requires that the memory stays alive until the callback is invoked.
1028
1029 m_req_cksum = prot->cksumHandler.getChecksumToRun(m_req_digest);
1030 if(!m_req_cksum) {
1031 // No HTTP IANA checksums have been configured by the server admin, return a "METHOD_NOT_ALLOWED" error
1032 prot->SendSimpleResp(403, NULL, NULL, (char *) "No HTTP-IANA compatible checksums have been configured.", 0, false);
1033 return -1;
1034 }
1035 if (!opaque) {
1036 m_resource_with_digest += "?cks.type=";
1037 m_resource_with_digest += m_req_cksum->getXRootDConfigDigestName().c_str();
1038 } else {
1039 m_resource_with_digest += "&cks.type=";
1040 m_resource_with_digest += m_req_cksum->getXRootDConfigDigestName().c_str();
1041 }
1042 if (prot->doChksum(m_resource_with_digest) < 0) {
1043 // In this case, the Want-Digest header was set and PostProcess gave the go-ahead to do a checksum.
1044 prot->SendSimpleResp(500, NULL, NULL, (char *) "Failed to create initial checksum request.", 0, false);
1045 return -1;
1046 }
1047 return 1;
1048 }
1049 }
1050 case XrdHttpReq::rtGET:
1051 {
1052 int retval = keepalive ? 1 : -1; // reset() clears keepalive
1053
1054 if (resource.beginswith("/static/")) {
1055
1056 // This is a request for a /static resource
1057 // If we have to use the embedded ones then we return the ones in memory as constants
1058
1059 // The sysadmin can always redirect the request to another host that
1060 // contains his static resources
1061
1062 // We also allow xrootd to preread from the local disk all the files
1063 // that have to be served as static resources.
1064
1065 if (prot->embeddedstatic) {
1066
1067 // Default case: the icon and the css of the HTML rendering of XrdHttp
1068 if (resource == "/static/css/xrdhttp.css") {
1069 prot->SendSimpleResp(200, NULL, NULL, (char *) static_css_xrdhttp_css, static_css_xrdhttp_css_len, keepalive);
1070 reset();
1071 return retval;
1072 }
1073 if (resource == "/static/icons/xrdhttp.ico") {
1074 prot->SendSimpleResp(200, NULL, NULL, (char *) favicon_ico, favicon_ico_len, keepalive);
1075 reset();
1076 return retval;
1077 }
1078
1079 }
1080
1081 // If we are here then none of the embedded resources match (or they are disabled)
1082 // We may have to redirect to a host that is supposed to serve the static resources
1083 if (prot->staticredir) {
1084
1085 XrdOucString s = "Location: ";
1086 s.append(prot->staticredir);
1087
1088 if (s.endswith('/'))
1089 s.erasefromend(1);
1090
1091 s.append(resource);
1092 appendOpaque(s, 0, 0, 0);
1093
1094 prot->SendSimpleResp(302, NULL, (char *) s.c_str(), 0, 0, false);
1095 return -1;
1096
1097
1098 } else {
1099
1100 // We lookup the requested path in a hash containing the preread files
1101 if (prot->staticpreload) {
1102 XrdHttpProtocol::StaticPreloadInfo *mydata = prot->staticpreload->Find(resource.c_str());
1103 if (mydata) {
1104 prot->SendSimpleResp(200, NULL, NULL, (char *) mydata->data, mydata->len, keepalive);
1105 reset();
1106 return retval;
1107 }
1108 }
1109
1110 }
1111
1112
1113 }
1114
1115 // The reqstate parameter basically moves us through a simple state machine.
1116 // To optimize things, we start off by opening the file; if it turns out to be a directory, then
1117 // we close the file handle and switch to doing a HTML-based rendering of the directory. This
1118 // avoids needing to always to do "stat" first to determine the next step (since the file-open also
1119 // does a "stat").
1120 // - 0: Perform an open on the resource
1121 // - 1: Perform a checksum request on the resource (only if requested in header; otherwise skipped)
1122 // - 2: Perform a close (for dirlist only)
1123 // - 3: Perform a dirlist.
1124 // - 4+: Reads from file; if at end, perform a close.
1125 switch (reqstate) {
1126 case 0: // Open the path for reading.
1127 {
1128 memset(&xrdreq, 0, sizeof (ClientRequest));
1129 xrdreq.open.requestid = htons(kXR_open);
1130 l = resourceplusopaque.length() + 1;
1131 xrdreq.open.dlen = htonl(l);
1132 xrdreq.open.mode = 0;
1133 xrdreq.open.options = htons(kXR_retstat | kXR_open_read);
1134
1135 if (!prot->Bridge->Run((char *) &xrdreq, (char *) resourceplusopaque.c_str(), l)) {
1136 prot->SendSimpleResp(404, NULL, NULL, (char *) "Could not run request.", 0, false);
1137 return -1;
1138 }
1139
1140 // Prepare to chunk up the request
1141 writtenbytes = 0;
1142
1143 // We want to be invoked again after this request is finished
1144 return 0;
1145 }
1146 case 1: // Checksum request
1147 if (!(fileflags & kXR_isDir) && !m_req_digest.empty()) {
1148 // In this case, the Want-Digest header was set.
1149 bool has_opaque = strchr(resourceplusopaque.c_str(), '?');
1150 // Note that doChksum requires that the memory stays alive until the callback is invoked.
1151 m_req_cksum = prot->cksumHandler.getChecksumToRun(m_req_digest);
1152 if(!m_req_cksum) {
1153 // No HTTP IANA checksums have been configured by the server admin, return a "METHOD_NOT_ALLOWED" error
1154 prot->SendSimpleResp(403, NULL, NULL, (char *) "No HTTP-IANA compatible checksums have been configured.", 0, false);
1155 return -1;
1156 }
1158 if (has_opaque) {
1159 m_resource_with_digest += "&cks.type=";
1160 m_resource_with_digest += m_req_cksum->getXRootDConfigDigestName().c_str();
1161 } else {
1162 m_resource_with_digest += "?cks.type=";
1163 m_resource_with_digest += m_req_cksum->getXRootDConfigDigestName().c_str();
1164 }
1165 if (prot->doChksum(m_resource_with_digest) < 0) {
1166 prot->SendSimpleResp(500, NULL, NULL, (char *) "Failed to start internal checksum request to satisfy Want-Digest header.", 0, false);
1167 return -1;
1168 }
1169 return 0;
1170 } else {
1171 TRACEI(DEBUG, "No checksum requested; skipping to request state 2");
1172 reqstate += 1;
1173 }
1174 // fallthrough
1175 case 2: // Close file handle for directory
1176 if ((fileflags & kXR_isDir) && fopened) {
1177 memset(&xrdreq, 0, sizeof (ClientRequest));
1178 xrdreq.close.requestid = htons(kXR_close);
1179 memcpy(xrdreq.close.fhandle, fhandle, 4);
1180
1181 if (!prot->Bridge->Run((char *) &xrdreq, 0, 0)) {
1182 mapXrdErrorToHttpStatus();
1183 sendFooterError("Could not run close request on the bridge");
1184 return -1;
1185 }
1186 return 0;
1187 } else {
1188 reqstate += 1;
1189 }
1190 // fallthrough
1191 case 3: // List directory
1192 if (fileflags & kXR_isDir) {
1193 if (prot->listdeny) {
1194 prot->SendSimpleResp(503, NULL, NULL, (char *) "Listings are disabled.", 0, false);
1195 return -1;
1196 }
1197
1198 if (prot->listredir) {
1199 XrdOucString s = "Location: ";
1200 s.append(prot->listredir);
1201
1202 if (s.endswith('/'))
1203 s.erasefromend(1);
1204
1205 s.append(resource);
1206 appendOpaque(s, 0, 0, 0);
1207
1208 prot->SendSimpleResp(302, NULL, (char *) s.c_str(), 0, 0, false);
1209 return -1;
1210 }
1211
1212 std::string res;
1213 res = resourceplusopaque.c_str();
1214
1215 // --------- DIRLIST
1216 memset(&xrdreq, 0, sizeof (ClientRequest));
1217 xrdreq.dirlist.requestid = htons(kXR_dirlist);
1218 xrdreq.dirlist.options[0] = kXR_dstat;
1219 l = res.length() + 1;
1220 xrdreq.dirlist.dlen = htonl(l);
1221
1222 if (!prot->Bridge->Run((char *) &xrdreq, (char *) res.c_str(), l)) {
1223 mapXrdErrorToHttpStatus();
1224 prot->SendSimpleResp(httpStatusCode, NULL, NULL, httpStatusText.c_str(), httpStatusText.length(), false);
1225 sendFooterError("Could not run listing request on the bridge");
1226 return -1;
1227 }
1228
1229 // We don't want to be invoked again after this request is finished
1230 return 1;
1231 }
1232 else {
1233 reqstate += 1;
1234 }
1235 // fallthrough
1236 case 4:
1237 {
1238 auto retval = ReturnGetHeaders();
1239 if (retval) {
1240 return retval;
1241 }
1242 }
1243 // fallthrough
1244 default: // Read() or Close(); reqstate is 4+
1245 {
1246 const XrdHttpIOList &readChunkList = readRangeHandler.NextReadList();
1247
1248 // Close() if we have finished, otherwise read the next chunk
1249
1250 // --------- CLOSE
1251 if ( readChunkList.empty() )
1252 {
1253
1254 memset(&xrdreq, 0, sizeof (ClientRequest));
1255 xrdreq.close.requestid = htons(kXR_close);
1256 memcpy(xrdreq.close.fhandle, fhandle, 4);
1257
1258 if (!prot->Bridge->Run((char *) &xrdreq, 0, 0)) {
1259 TRACEI(REQ, " Failed to run close request on the bridge.");
1260 // Note: we have already completed the request and sent the data to the client.
1261 // Hence, there's no need to send an error. However, since the bridge is potentially
1262 // in a bad state, we close the TCP socket to force the client to reconnect.
1263 return -1;
1264 }
1265
1266 // We have finished
1267 readClosing = true;
1268 return 1;
1269
1270 }
1271 // --------- READ or READV
1272
1273 if ( readChunkList.size() == 1 ) {
1274 // Use a read request for single range
1275
1276 long l;
1277 long long offs;
1278
1279 // --------- READ
1280 memset(&xrdreq, 0, sizeof (xrdreq));
1281 xrdreq.read.requestid = htons(kXR_read);
1282 memcpy(xrdreq.read.fhandle, fhandle, 4);
1283 xrdreq.read.dlen = 0;
1284
1285 offs = readChunkList[0].offset;
1286 l = readChunkList[0].size;
1287
1288 xrdreq.read.offset = htonll(offs);
1289 xrdreq.read.rlen = htonl(l);
1290
1291 // If we are using HTTPS or if the client requested trailers, or if the
1292 // read concerns a multirange reponse, disable sendfile
1293 // (in the latter two cases, the extra framing is only done in PostProcessHTTPReq)
1294 if (prot->ishttps || (m_transfer_encoding_chunked && m_trailer_headers) ||
1295 !readRangeHandler.isSingleRange()) {
1296 if (!prot->Bridge->setSF((kXR_char *) fhandle, false)) {
1297 TRACE(REQ, " XrdBridge::SetSF(false) failed.");
1298
1299 }
1300 }
1301
1302
1303
1304 if (l <= 0) {
1305 if (l < 0) {
1306 TRACE(ALL, " Data sizes mismatch.");
1307 return -1;
1308 }
1309 else {
1310 TRACE(ALL, " No more bytes to send.");
1311 reset();
1312 return 1;
1313 }
1314 }
1315
1316 if ((offs >= filesize) || (offs+l > filesize)) {
1317 httpStatusCode = 416;
1318 httpStatusText = "Range Not Satisfiable";
1319 std::stringstream ss;
1320 ss << "Requested range " << l << "@" << offs << " is past the end of file (" << filesize << ")";
1321 sendFooterError(ss.str());
1322 return -1;
1323 }
1324
1325 if (!prot->Bridge->Run((char *) &xrdreq, 0, 0)) {
1326 mapXrdErrorToHttpStatus();
1327 sendFooterError("Could not run read request on the bridge");
1328 return -1;
1329 }
1330 } else {
1331 // --------- READV
1332
1333 length = ReqReadV(readChunkList);
1334
1335 if (!prot->Bridge->Run((char *) &xrdreq, (char *) &ralist[0], length)) {
1336 mapXrdErrorToHttpStatus();
1337 sendFooterError("Could not run ReadV request on the bridge");
1338 return -1;
1339 }
1340
1341 }
1342
1343 // We want to be invoked again after this request is finished
1344 return 0;
1345 } // case 3+
1346
1347 } // switch (reqstate)
1348
1349
1350 } // case XrdHttpReq::rtGET
1351
1352 case XrdHttpReq::rtPUT:
1353 {
1354 //if (prot->ishttps) {
1355 //prot->SendSimpleResp(501, NULL, NULL, (char *) "HTTPS not supported yet for direct writing. Sorry.", 0);
1356 //return -1;
1357 //}
1358
1359 if (!fopened) {
1360
1361 // --------- OPEN for write!
1362 memset(&xrdreq, 0, sizeof (ClientRequest));
1363 xrdreq.open.requestid = htons(kXR_open);
1364 l = resourceplusopaque.length() + 1;
1365 xrdreq.open.dlen = htonl(l);
1366 xrdreq.open.mode = htons(kXR_ur | kXR_uw | kXR_gw | kXR_gr | kXR_or);
1367 if (! XrdHttpProtocol::usingEC)
1368 xrdreq.open.options = htons(kXR_mkpath | kXR_open_wrto | kXR_delete);
1369 else
1370 xrdreq.open.options = htons(kXR_mkpath | kXR_open_wrto | kXR_new);
1371
1372 if (!prot->Bridge->Run((char *) &xrdreq, (char *) resourceplusopaque.c_str(), l)) {
1373 prot->SendSimpleResp(404, NULL, NULL, (char *) "Could not run request.", 0, keepalive);
1374 return -1;
1375 }
1376
1377
1378 // We want to be invoked again after this request is finished
1379 // Only if there is data to fetch from the socket or there will
1380 // never be more data
1381 if (prot->BuffUsed() > 0 || (length == 0 && !sendcontinue))
1382 return 0;
1383
1384 return 1;
1385
1386 } else {
1387
1388 if (m_transfer_encoding_chunked) {
1389 if (m_current_chunk_size == m_current_chunk_offset) {
1390 // Chunk has been consumed; we now must process the CRLF.
1391 // Note that we don't support trailer headers.
1392 if (prot->BuffUsed() < 2) return 1;
1393 if (prot->myBuffStart[0] != '\r' || prot->myBuffStart[1] != '\n') {
1394 prot->SendSimpleResp(400, NULL, NULL, (char *) "Invalid trailing chunk encoding.", 0, keepalive);
1395 return -1;
1396 }
1397 prot->BuffConsume(2);
1398 if (m_current_chunk_size == 0) {
1399 // All data has been sent. Turn off chunk processing and
1400 // set the bytes written and length appropriately; on next callback,
1401 // we will hit the close() block below.
1402 m_transfer_encoding_chunked = false;
1404 return ProcessHTTPReq();
1405 }
1406 m_current_chunk_size = -1;
1407 m_current_chunk_offset = 0;
1408 // If there is more data, we try to process the next chunk; otherwise, return
1409 if (!prot->BuffUsed()) return 1;
1410 }
1411 if (-1 == m_current_chunk_size) {
1412
1413 // Parse out the next chunk size.
1414 long long idx = 0;
1415 bool found_newline = false;
1416 // Set a maximum size of chunk we will allow
1417 // Nginx sets this to "NGX_MAX_OFF_T_VALUE", which is 9223372036854775807 (a some crazy number)
1418 // We set it to 1TB, which is 1099511627776
1419 // This is to prevent a malicious client from sending a very large chunk size
1420 // or a malformed chunk request.
1421 // 1TB in base-16 is 0x40000000000, so only allow 11 characters, plus the CRLF
1422 long long max_chunk_size_chars = std::min(static_cast<long long>(prot->BuffUsed()), static_cast<long long>(13));
1423 for (; idx < max_chunk_size_chars; idx++) {
1424 if (prot->myBuffStart[idx] == '\n') {
1425 found_newline = true;
1426 break;
1427 }
1428 }
1429 // If we found a new line, but it is the first character in the buffer (no chunk length)
1430 // or if the previous character is not a CR.
1431 if (found_newline && ((idx == 0) || prot->myBuffStart[idx-1] != '\r')) {
1432 prot->SendSimpleResp(400, NULL, NULL, (char *)"Invalid chunked encoding", 0, false);
1433 TRACE(REQ, "XrdHTTP PUT: Sending invalid chunk encoding. Start of chunk should have had a length, followed by a CRLF.");
1434 return -1;
1435 }
1436 if (found_newline) {
1437 char *endptr = NULL;
1438 std::string line_contents(prot->myBuffStart, idx);
1439 long long chunk_contents = strtol(line_contents.c_str(), &endptr, 16);
1440 // Chunk sizes can be followed by trailer information or CRLF
1441 if (*endptr != ';' && *endptr != '\r') {
1442 prot->SendSimpleResp(400, NULL, NULL, (char *)"Invalid chunked encoding", 0, false);
1443 TRACE(REQ, "XrdHTTP PUT: Sending invalid chunk encoding. Chunk size was not followed by a ';' or CR." << __LINE__);
1444 return -1;
1445 }
1446 m_current_chunk_size = chunk_contents;
1447 m_current_chunk_offset = 0;
1448 prot->BuffConsume(idx + 1);
1449 TRACE(REQ, "XrdHTTP PUT: next chunk from client will be " << m_current_chunk_size << " bytes");
1450 } else {
1451 // Need more data!
1452 return 1;
1453 }
1454 }
1455
1456 if (m_current_chunk_size == 0) {
1457 // All data has been sent. Invoke this routine again immediately to process CRLF
1458 return ProcessHTTPReq();
1459 } else {
1460 // At this point, we have a chunk size defined and should consume payload data
1461 memset(&xrdreq, 0, sizeof (xrdreq));
1462 xrdreq.write.requestid = htons(kXR_write);
1463 memcpy(xrdreq.write.fhandle, fhandle, 4);
1464
1465 long long chunk_bytes_remaining = m_current_chunk_size - m_current_chunk_offset;
1466 long long bytes_to_write = std::min(static_cast<long long>(prot->BuffUsed()),
1467 chunk_bytes_remaining);
1468
1469 xrdreq.write.offset = htonll(writtenbytes);
1470 xrdreq.write.dlen = htonl(bytes_to_write);
1471
1472 TRACEI(REQ, "XrdHTTP PUT: Writing chunk of size " << bytes_to_write << " starting with '" << *(prot->myBuffStart) << "'" << " with " << chunk_bytes_remaining << " bytes remaining in the chunk");
1473 if (!prot->Bridge->Run((char *) &xrdreq, prot->myBuffStart, bytes_to_write)) {
1474 mapXrdErrorToHttpStatus();
1475 sendFooterError("Could not run write request on the bridge");
1476 return -1;
1477 }
1478 // If there are more bytes in the buffer, then immediately call us after the
1479 // write is finished; otherwise, wait for data.
1480 return (prot->BuffUsed() > chunk_bytes_remaining) ? 0 : 1;
1481 }
1482 } else if (writtenbytes < length) {
1483
1484
1485 // --------- WRITE
1486 memset(&xrdreq, 0, sizeof (xrdreq));
1487 xrdreq.write.requestid = htons(kXR_write);
1488 memcpy(xrdreq.write.fhandle, fhandle, 4);
1489
1490 long long bytes_to_read = std::min(static_cast<long long>(prot->BuffUsed()),
1492
1493 xrdreq.write.offset = htonll(writtenbytes);
1494 xrdreq.write.dlen = htonl(bytes_to_read);
1495
1496 TRACEI(REQ, "Writing " << bytes_to_read);
1497 if (!prot->Bridge->Run((char *) &xrdreq, prot->myBuffStart, bytes_to_read)) {
1498 mapXrdErrorToHttpStatus();
1499 sendFooterError("Could not run write request on the bridge");
1500 return -1;
1501 }
1502
1503 if (writtenbytes + prot->BuffUsed() >= length)
1504 // Trigger an immediate recall after this request has finished
1505 return 0;
1506 else
1507 // We want to be invoked again after this request is finished
1508 // only if there is pending data
1509 return 1;
1510
1511
1512
1513 } else {
1514
1515 // --------- CLOSE
1516 memset(&xrdreq, 0, sizeof (ClientRequest));
1517 xrdreq.close.requestid = htons(kXR_close);
1518 memcpy(xrdreq.close.fhandle, fhandle, 4);
1519
1520
1521 if (!prot->Bridge->Run((char *) &xrdreq, 0, 0)) {
1522 mapXrdErrorToHttpStatus();
1523 sendFooterError("Could not run close request on the bridge");
1524 return -1;
1525 }
1526
1527 // We have finished
1528 return 1;
1529
1530 }
1531
1532 }
1533
1534 break;
1535
1536 }
1538 {
1539 prot->SendSimpleResp(200, NULL, (char *) "DAV: 1\r\nDAV: <http://apache.org/dav/propset/fs/1>\r\nAllow: HEAD,GET,PUT,PROPFIND,DELETE,OPTIONS", NULL, 0, keepalive);
1540 bool ret_keepalive = keepalive; // reset() clears keepalive
1541 reset();
1542 return ret_keepalive ? 1 : -1;
1543 }
1545 {
1546
1547
1548 switch (reqstate) {
1549
1550 case 0: // Stat()
1551 {
1552
1553
1554 // --------- STAT is always the first step
1555 memset(&xrdreq, 0, sizeof (ClientRequest));
1556 xrdreq.stat.requestid = htons(kXR_stat);
1557 std::string s = resourceplusopaque.c_str();
1558
1559
1560 l = resourceplusopaque.length() + 1;
1561 xrdreq.stat.dlen = htonl(l);
1562
1563 if (!prot->Bridge->Run((char *) &xrdreq, (char *) resourceplusopaque.c_str(), l)) {
1564 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run request.", 0, false);
1565 return -1;
1566 }
1567
1568 // We need to be invoked again to complete the request
1569 return 0;
1570 }
1571 default:
1572
1573 if (fileflags & kXR_isDir) {
1574 // --------- RMDIR
1575 memset(&xrdreq, 0, sizeof (ClientRequest));
1576 xrdreq.rmdir.requestid = htons(kXR_rmdir);
1577
1578 std::string s = resourceplusopaque.c_str();
1579
1580 l = s.length() + 1;
1581 xrdreq.rmdir.dlen = htonl(l);
1582
1583 if (!prot->Bridge->Run((char *) &xrdreq, (char *) s.c_str(), l)) {
1584 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run rmdir request.", 0, false);
1585 return -1;
1586 }
1587 } else {
1588 // --------- DELETE
1589 memset(&xrdreq, 0, sizeof (ClientRequest));
1590 xrdreq.rm.requestid = htons(kXR_rm);
1591
1592 std::string s = resourceplusopaque.c_str();
1593
1594 l = s.length() + 1;
1595 xrdreq.rm.dlen = htonl(l);
1596
1597 if (!prot->Bridge->Run((char *) &xrdreq, (char *) s.c_str(), l)) {
1598 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run rm request.", 0, false);
1599 return -1;
1600 }
1601 }
1602
1603
1604 // We don't want to be invoked again after this request is finished
1605 return 1;
1606
1607 }
1608
1609
1610
1611 }
1613 {
1614 prot->SendSimpleResp(501, NULL, NULL, (char *) "Request not supported yet.", 0, false);
1615
1616 return -1;
1617 }
1619 {
1620
1621
1622
1623 switch (reqstate) {
1624
1625 case 0: // Stat() and add the current item to the list of the things to send
1626 {
1627
1628 if (length > 0) {
1629 TRACE(REQ, "Reading request body " << length << " bytes.");
1630 char *p = 0;
1631 // We have to specifically read all the request body
1632
1633 if (prot->BuffgetData(length, &p, true) < length) {
1634 prot->SendSimpleResp(501, NULL, NULL, (char *) "Error in getting the PROPFIND request body.", 0, false);
1635 return -1;
1636 }
1637
1638 if ((depth > 1) || (depth < 0)) {
1639 prot->SendSimpleResp(501, NULL, NULL, (char *) "Invalid depth value.", 0, false);
1640 return -1;
1641 }
1642
1643
1644 parseBody(p, length);
1645 }
1646
1647
1648 // --------- STAT is always the first step
1649 memset(&xrdreq, 0, sizeof (ClientRequest));
1650 xrdreq.stat.requestid = htons(kXR_stat);
1651 std::string s = resourceplusopaque.c_str();
1652
1653
1654 l = resourceplusopaque.length() + 1;
1655 xrdreq.stat.dlen = htonl(l);
1656
1657 if (!prot->Bridge->Run((char *) &xrdreq, (char *) resourceplusopaque.c_str(), l)) {
1658 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run request.", 0, false);
1659 return -1;
1660 }
1661
1662
1663 if (depth == 0) {
1664 // We don't need to be invoked again
1665 return 1;
1666 } else
1667 // We need to be invoked again to complete the request
1668 return 0;
1669
1670
1671
1672 break;
1673 }
1674
1675 default: // Dirlist()
1676 {
1677
1678 // --------- DIRLIST
1679 memset(&xrdreq, 0, sizeof (ClientRequest));
1680 xrdreq.dirlist.requestid = htons(kXR_dirlist);
1681
1682 std::string s = resourceplusopaque.c_str();
1683 xrdreq.dirlist.options[0] = kXR_dstat;
1684 //s += "?xrd.dirstat=1";
1685
1686 l = s.length() + 1;
1687 xrdreq.dirlist.dlen = htonl(l);
1688
1689 if (!prot->Bridge->Run((char *) &xrdreq, (char *) s.c_str(), l)) {
1690 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run request.", 0, false);
1691 return -1;
1692 }
1693
1694 // We don't want to be invoked again after this request is finished
1695 return 1;
1696 }
1697 }
1698
1699
1700 break;
1701 }
1703 {
1704
1705 // --------- MKDIR
1706 memset(&xrdreq, 0, sizeof (ClientRequest));
1707 xrdreq.mkdir.requestid = htons(kXR_mkdir);
1708
1709 std::string s = resourceplusopaque.c_str();
1710 xrdreq.mkdir.options[0] = (kXR_char) kXR_mkdirpath;
1711
1712 l = s.length() + 1;
1713 xrdreq.mkdir.dlen = htonl(l);
1714
1715 if (!prot->Bridge->Run((char *) &xrdreq, (char *) s.c_str(), l)) {
1716 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run request.", 0, false);
1717 return -1;
1718 }
1719
1720 // We don't want to be invoked again after this request is finished
1721 return 1;
1722 }
1723 case XrdHttpReq::rtMOVE:
1724 {
1725
1726 // --------- MOVE
1727 memset(&xrdreq, 0, sizeof (ClientRequest));
1728 xrdreq.mv.requestid = htons(kXR_mv);
1729
1730 std::string s = resourceplusopaque.c_str();
1731 s += " ";
1732
1733 char buf[256];
1734 char *ppath;
1735 int port = 0;
1736 if (parseURL((char *) destination.c_str(), buf, port, &ppath)) {
1737 prot->SendSimpleResp(501, NULL, NULL, (char *) "Cannot parse destination url.", 0, false);
1738 return -1;
1739 }
1740
1741 char buf2[256];
1742 strcpy(buf2, host.c_str());
1743 char *pos = strchr(buf2, ':');
1744 if (pos) *pos = '\0';
1745
1746 // If we are a redirector we enforce that the host field is equal to
1747 // whatever was written in the destination url
1748 //
1749 // If we are a data server instead we cannot enforce anything, we will
1750 // just ignore the host part of the destination
1751 if ((prot->myRole == kXR_isManager) && strcmp(buf, buf2)) {
1752 prot->SendSimpleResp(501, NULL, NULL, (char *) "Only in-place renaming is supported for MOVE.", 0, false);
1753 return -1;
1754 }
1755
1756
1757
1758
1759 s += ppath;
1760
1761 l = s.length() + 1;
1762 xrdreq.mv.dlen = htonl(l);
1763 xrdreq.mv.arg1len = htons(resourceplusopaque.length());
1764
1765 if (!prot->Bridge->Run((char *) &xrdreq, (char *) s.c_str(), l)) {
1766 prot->SendSimpleResp(501, NULL, NULL, (char *) "Could not run request.", 0, false);
1767 return -1;
1768 }
1769
1770 // We don't want to be invoked again after this request is finished
1771 return 1;
1772
1773 }
1774 default:
1775 {
1776 prot->SendSimpleResp(501, NULL, NULL, (char *) "Request not supported.", 0, false);
1777 return -1;
1778 }
1779
1780 }
1781
1782 return 1;
1783}
#define kXR_isManager
@ kXR_open_wrto
Definition XProtocol.hh:469
@ kXR_delete
Definition XProtocol.hh:453
@ kXR_open_read
Definition XProtocol.hh:456
@ kXR_mkpath
Definition XProtocol.hh:460
@ kXR_new
Definition XProtocol.hh:455
@ kXR_retstat
Definition XProtocol.hh:463
@ kXR_dstat
Definition XProtocol.hh:240
@ kXR_read
Definition XProtocol.hh:125
@ kXR_mkdir
Definition XProtocol.hh:120
@ kXR_dirlist
Definition XProtocol.hh:116
@ kXR_rm
Definition XProtocol.hh:126
@ kXR_write
Definition XProtocol.hh:131
@ kXR_rmdir
Definition XProtocol.hh:127
@ kXR_mv
Definition XProtocol.hh:121
@ kXR_stat
Definition XProtocol.hh:129
@ kXR_close
Definition XProtocol.hh:115
@ kXR_mkdirpath
Definition XProtocol.hh:410
@ kXR_gw
Definition XProtocol.hh:444
@ kXR_ur
Definition XProtocol.hh:440
@ kXR_uw
Definition XProtocol.hh:441
@ kXR_gr
Definition XProtocol.hh:443
@ kXR_or
Definition XProtocol.hh:446
@ kXR_isDir
int kXR_int32
Definition XPtypes.hh:89
unsigned char kXR_char
Definition XPtypes.hh:65
#define DEBUG(x)
int parseURL(char *url, char *host, int &port, char **path)
std::vector< XrdOucIOVec2 > XrdHttpIOList
std::string obfuscateAuth(const std::string &input)
#define TRACE_DEBUG
Definition XrdTrace.hh:36
#define TRACING(x)
Definition XrdTrace.hh:70
#define TRACEI(act, x)
Definition XrdTrace.hh:66
virtual int ProcessReq(XrdHttpExtReq &)=0
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 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:94
std::vector< readahead_list > ralist
XrdOucString resource
The resource specified by the request, stripped of opaque data.
int ProcessHTTPReq()
XrdOucString resourceplusopaque
The resource specified by the request, including all the opaque data.
std::string host
The host field specified in the req.
XrdHttpChecksumHandler::XrdHttpChecksumRawPtr m_req_cksum
The checksum that was ran for this request.
bool m_appended_hdr2cgistr
void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow)
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
int erasefromend(int sz=0)
bool endswith(char c)
void append(const int i)
const char * c_str() const

References XrdOucString::append(), appendOpaque(), XrdOucString::c_str(), XrdHttpProtocol::StaticPreloadInfo::data, DEBUG, depth, destination, XrdOucString::endswith(), XrdOucString::erasefromend(), fhandle, fileflags, filesize, fopened, hdr2cgistr, host, keepalive, kXR_close, kXR_delete, kXR_dirlist, kXR_dstat, kXR_gr, kXR_gw, kXR_isDir, kXR_isManager, kXR_mkdir, kXR_mkdirpath, kXR_mkpath, kXR_mv, kXR_new, kXR_open, kXR_open_read, kXR_open_wrto, kXR_or, kXR_read, kXR_retstat, kXR_rm, kXR_rmdir, kXR_stat, kXR_ur, kXR_uw, kXR_write, XrdHttpProtocol::StaticPreloadInfo::len, length, m_appended_asize, m_appended_hdr2cgistr, m_req_cksum, m_req_digest, m_resource_with_digest, obfuscateAuth(), opaque, parseBody(), parseURL(), ProcessHTTPReq(), XrdHttpExtHandler::ProcessReq(), quote(), ralist, readClosing, readRangeHandler, ReqReadV(), reqstate, request, reset(), resource, resourceplusopaque, rtDELETE, rtGET, rtHEAD, rtMalformed, rtMKCOL, rtMOVE, rtOPTIONS, rtPATCH, rtPROPFIND, rtPUT, rtUnknown, rtUnset, sendcontinue, TRACE, TRACE_DEBUG, TRACEI, TRACING, writtenbytes, and xrdreq.

Referenced by ProcessHTTPReq().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Redir()

bool XrdHttpReq::Redir ( XrdXrootd::Bridge::Context & info,
int port,
const char * hname )
virtual

Redirect the client to another host:port.

The Redir() method is called when the client must be redirected to another host.

Parameters
infothe context associated with the result.
portthe port number in host byte format.
hnamethe DNS name of the host or IP address is IPV4 or IPV6 format (i.e. "n.n.n.n" or "[ipv6_addr]").
Returns
true continue normal processing. false terminate the bridge and close the link.
Parameters
infothe result context
portthe port number
hnamethe destination host

Implements XrdXrootd::Bridge::Result.

Definition at line 533 of file XrdHttpReq.cc.

536 {
537
538
539
540 char buf[512];
541 char hash[512];
542 hash[0] = '\0';
543
544 if (prot->isdesthttps)
545 redirdest = "Location: https://";
546 else
547 redirdest = "Location: http://";
548
549 // port < 0 signals switch to full URL
550 if (port < 0)
551 {
552 if (strncmp(hname, "file://", 7) == 0)
553 {
554 TRACE(REQ, " XrdHttpReq::Redir Switching to file:// ");
555 redirdest = "Location: "; // "file://" already contained in hname
556 }
557 }
558 // Beware, certain Ofs implementations (e.g. EOS) add opaque data directly to the host name
559 // This must be correctly treated here and appended to the opaque info
560 // that we may already have
561 char *pp = strchr((char *)hname, '?');
562 char *vardata = 0;
563 if (pp) {
564 *pp = '\0';
565 redirdest += hname;
566 vardata = pp+1;
567 int varlen = strlen(vardata);
568
569 //Now extract the remaining, vardata points to it
570 while(*vardata == '&' && varlen) {vardata++; varlen--;}
571
572 // Put the question mark back where it was
573 *pp = '?';
574 }
575 else
576 redirdest += hname;
577
578 if (port > 0) {
579 sprintf(buf, ":%d", port);
580 redirdest += buf;
581 }
582
583 redirdest += resource.c_str();
584
585 // Here we put back the opaque info, if any
586 if (vardata) {
587 char *newvardata = quote(vardata);
588 redirdest += "?&";
589 redirdest += newvardata;
590 free(newvardata);
591 }
592
593 // Shall we put also the opaque data of the request? Maybe not
594 //int l;
595 //if (opaque && opaque->Env(l))
596 // redirdest += opaque->Env(l);
597
598
599 time_t timenow = 0;
600 if (!prot->isdesthttps && prot->ishttps) {
601 // If the destination is not https, then we suppose that it
602 // will need this token to fill its authorization info
603 timenow = time(0);
604 calcHashes(hash, this->resource.c_str(), (kXR_int16) request,
605 &prot->SecEntity,
606 timenow,
607 prot->secretkey);
608 }
609
610 if (hash[0]) {
611 appendOpaque(redirdest, &prot->SecEntity, hash, timenow);
612 } else
613 appendOpaque(redirdest, 0, 0, 0);
614
615
616 TRACE(REQ, " XrdHttpReq::Redir Redirecting to " << obfuscateAuth(redirdest.c_str()).c_str());
617
618 if (request != rtGET)
619 prot->SendSimpleResp(307, NULL, (char *) redirdest.c_str(), 0, 0, keepalive);
620 else
621 prot->SendSimpleResp(302, NULL, (char *) redirdest.c_str(), 0, 0, keepalive);
622
623 bool ret_keepalive = keepalive; // reset() clears keepalive
624 reset();
625 return ret_keepalive;
626};
short kXR_int16
Definition XPtypes.hh:66
void calcHashes(char *hash, const char *fn, kXR_int16 request, XrdSecEntity *secent, time_t tim, const char *key)
XrdOucString redirdest

References appendOpaque(), calcHashes(), keepalive, obfuscateAuth(), quote(), redirdest, request, reset(), resource, rtGET, and TRACE.

Here is the call graph for this function:

◆ ReqReadV()

int XrdHttpReq::ReqReadV ( const XrdHttpIOList & cl)

Prepare the buffers for sending a readv request.

Definition at line 388 of file XrdHttpReq.cc.

388 {
389
390
391 // Now we build the protocol-ready read ahead list
392 // and also put the correct placeholders inside the cache
393 int n = cl.size();
394 ralist.clear();
395 ralist.reserve(n);
396
397 int j = 0;
398 for (const auto &c: cl) {
399 ralist.emplace_back();
400 auto &ra = ralist.back();
401 memcpy(&ra.fhandle, this->fhandle, 4);
402
403 ra.offset = c.offset;
404 ra.rlen = c.size;
405 j++;
406 }
407
408 if (j > 0) {
409
410 // Prepare a request header
411
412 memset(&xrdreq, 0, sizeof (xrdreq));
413
414 xrdreq.header.requestid = htons(kXR_readv);
415 xrdreq.readv.dlen = htonl(j * sizeof (struct readahead_list));
416
417 clientMarshallReadAheadList(j);
418
419
420 }
421
422 return (j * sizeof (struct readahead_list));
423}
@ kXR_readv
Definition XProtocol.hh:137

References kXR_readv, ralist, and xrdreq.

Referenced by ProcessHTTPReq().

Here is the caller graph for this function:

◆ reset()

void XrdHttpReq::reset ( )
virtual

State machine to talk to the bridge

Definition at line 2756 of file XrdHttpReq.cc.

2756 {
2757
2758 TRACE(REQ, " XrdHttpReq request ended.");
2759
2760 //if (xmlbody) xmlFreeDoc(xmlbody);
2761 readRangeHandler.reset();
2762 readClosing = false;
2763 writtenbytes = 0;
2764 etext.clear();
2765 redirdest = "";
2766
2767 // // Here we should deallocate this
2768 // const struct iovec *iovP //!< pointer to data array
2769 // int iovN, //!< array count
2770 // int iovL, //!< byte count
2771 // bool final //!< true -> final result
2772
2773
2774 //xmlbody = 0;
2775 depth = 0;
2778 ralist.clear();
2779 ralist.shrink_to_fit();
2780
2781 request = rtUnset;
2782 resource = "";
2783 allheaders.clear();
2784
2785 // Reset the state of the request's digest request.
2786 m_req_digest.clear();
2787 m_digest_header.clear();
2788 m_req_cksum = nullptr;
2789
2791 m_user_agent = "";
2792
2793 headerok = false;
2794 keepalive = true;
2795 length = 0;
2796 filesize = 0;
2797 depth = 0;
2798 sendcontinue = false;
2799
2800 m_transfer_encoding_chunked = false;
2801 m_current_chunk_size = -1;
2802 m_current_chunk_offset = 0;
2803
2804 m_trailer_headers = false;
2805 m_status_trailer = false;
2806
2808 reqstate = 0;
2809
2810 memset(&xrdreq, 0, sizeof (xrdreq));
2811 memset(&xrdresp, 0, sizeof (xrdresp));
2813
2814 etext.clear();
2815 redirdest = "";
2816
2817 stringresp = "";
2818
2819 host = "";
2820 destination = "";
2821 hdr2cgistr = "";
2822 m_appended_hdr2cgistr = false;
2823 m_appended_asize = false;
2824
2825 iovP = 0;
2826 iovN = 0;
2827 iovL = 0;
2828
2829
2830 if (opaque) delete(opaque);
2831 opaque = 0;
2832
2833 fopened = false;
2834
2835 final = false;
2836
2837 mScitag = -1;
2838}
@ kXR_noErrorYet
@ kXR_noResponsesYet
Definition XProtocol.hh:908
std::string m_digest_header
The computed digest for the HTTP response header.
std::string stringresp
If we want to give a string as a response, we compose it here.

References allheaders, depth, destination, etext, filesize, fopened, hdr2cgistr, headerok, host, iovL, iovN, iovP, keepalive, kXR_noErrorYet, kXR_noResponsesYet, length, m_appended_asize, m_appended_hdr2cgistr, m_digest_header, m_req_cksum, m_req_digest, m_resource_with_digest, mScitag, opaque, ralist, readClosing, readRangeHandler, redirdest, reqstate, request, resource, rtUnset, sendcontinue, stringresp, TRACE, writtenbytes, xrderrcode, xrdreq, and xrdresp.

Referenced by ~XrdHttpReq(), Data(), Done(), Error(), ProcessHTTPReq(), and Redir().

Here is the caller graph for this function:

◆ userAgent()

const std::string & XrdHttpReq::userAgent ( ) const
inline

Definition at line 210 of file XrdHttpReq.hh.

210{return m_user_agent;}

Member Data Documentation

◆ allheaders

std::map<std::string, std::string> XrdHttpReq::allheaders

Definition at line 241 of file XrdHttpReq.hh.

Referenced by parseLine(), and reset().

◆ depth

int XrdHttpReq::depth

Definition at line 260 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), parseLine(), ProcessHTTPReq(), and reset().

◆ destination

std::string XrdHttpReq::destination

The destination field specified in the req.

Definition at line 266 of file XrdHttpReq.hh.

Referenced by parseLine(), ProcessHTTPReq(), and reset().

◆ etext

std::string XrdHttpReq::etext

Definition at line 301 of file XrdHttpReq.hh.

Referenced by Error(), and reset().

◆ fhandle

char XrdHttpReq::fhandle[4]

Definition at line 315 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq().

◆ filectime

long XrdHttpReq::filectime

Definition at line 314 of file XrdHttpReq.hh.

◆ fileflags

long XrdHttpReq::fileflags

Definition at line 312 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq().

◆ filemodtime

long XrdHttpReq::filemodtime

Definition at line 313 of file XrdHttpReq.hh.

◆ filesize

long long XrdHttpReq::filesize

Definition at line 311 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ final

bool XrdHttpReq::final

true -> final result

Definition at line 308 of file XrdHttpReq.hh.

◆ fopened

bool XrdHttpReq::fopened

Definition at line 316 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), ProcessHTTPReq(), and reset().

◆ hdr2cgistr

std::string XrdHttpReq::hdr2cgistr

Additional opaque info that may come from the hdr2cgi directive.

Definition at line 282 of file XrdHttpReq.hh.

Referenced by addCgi(), appendOpaque(), ProcessHTTPReq(), and reset().

◆ headerok

bool XrdHttpReq::headerok

Tells if we have finished reading the header.

Definition at line 252 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), and reset().

◆ host

std::string XrdHttpReq::host

The host field specified in the req.

Definition at line 264 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ iovL

int XrdHttpReq::iovL

byte count

Definition at line 307 of file XrdHttpReq.hh.

Referenced by Data(), and reset().

◆ iovN

int XrdHttpReq::iovN

array count

Definition at line 306 of file XrdHttpReq.hh.

Referenced by Data(), Done(), and reset().

◆ iovP

const struct iovec* XrdHttpReq::iovP

The latest data chunks got from the xrd layer. These are valid only inside the callbacks!

pointer to data array

Definition at line 305 of file XrdHttpReq.hh.

Referenced by Data(), and reset().

◆ keepalive

bool XrdHttpReq::keepalive

Definition at line 258 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), parseFirstLine(), parseLine(), ProcessHTTPReq(), Redir(), and reset().

◆ length

long long XrdHttpReq::length

◆ m_appended_asize

bool XrdHttpReq::m_appended_asize {false}

Track whether we already appended the oss.asize argument for PUTs.

Definition at line 285 of file XrdHttpReq.hh.

285{false};

Referenced by ProcessHTTPReq(), and reset().

◆ m_appended_hdr2cgistr

bool XrdHttpReq::m_appended_hdr2cgistr

Definition at line 283 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ m_digest_header

std::string XrdHttpReq::m_digest_header

The computed digest for the HTTP response header.

Definition at line 279 of file XrdHttpReq.hh.

Referenced by reset().

◆ m_req_cksum

XrdHttpChecksumHandler::XrdHttpChecksumRawPtr XrdHttpReq::m_req_cksum = nullptr

The checksum that was ran for this request.

Definition at line 272 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ m_req_digest

std::string XrdHttpReq::m_req_digest

The requested digest type.

Definition at line 269 of file XrdHttpReq.hh.

Referenced by parseLine(), ProcessHTTPReq(), and reset().

◆ m_resource_with_digest

XrdOucString XrdHttpReq::m_resource_with_digest

The checksum algorithm is specified as part of the opaque data in the URL. Hence, when a digest is generated to satisfy a request, we cache the tweaked URL in this data member.

Definition at line 277 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ mScitag

int XrdHttpReq::mScitag

Definition at line 327 of file XrdHttpReq.hh.

Referenced by XrdHttpExtReq::XrdHttpExtReq(), XrdHttpReq(), and reset().

◆ opaque

XrdOucEnv* XrdHttpReq::opaque

The opaque data, after parsing.

Definition at line 246 of file XrdHttpReq.hh.

Referenced by XrdHttpExtReq::XrdHttpExtReq(), XrdHttpReq(), appendOpaque(), parseLine(), ProcessHTTPReq(), and reset().

◆ ralist

std::vector<readahead_list> XrdHttpReq::ralist

Definition at line 195 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), ReqReadV(), and reset().

◆ readClosing

bool XrdHttpReq::readClosing

Definition at line 256 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ readRangeHandler

XrdHttpReadRangeHandler XrdHttpReq::readRangeHandler

Tracking the next ranges of data to read during GET.

Definition at line 255 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), File(), parseLine(), ProcessHTTPReq(), and reset().

◆ redirdest

XrdOucString XrdHttpReq::redirdest

Definition at line 302 of file XrdHttpReq.hh.

Referenced by Redir(), and reset().

◆ reqstate

int XrdHttpReq::reqstate

State machine to talk to the bridge.

Definition at line 322 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ request

ReqType XrdHttpReq::request

The request we got.

Definition at line 236 of file XrdHttpReq.hh.

Referenced by Error(), parseFirstLine(), parseLine(), ProcessHTTPReq(), Redir(), and reset().

◆ requestverb

std::string XrdHttpReq::requestverb

Definition at line 237 of file XrdHttpReq.hh.

Referenced by parseFirstLine().

◆ resource

XrdOucString XrdHttpReq::resource

The resource specified by the request, stripped of opaque data.

Definition at line 244 of file XrdHttpReq.hh.

Referenced by XrdHttpExtReq::XrdHttpExtReq(), ProcessHTTPReq(), Redir(), and reset().

◆ resourceplusopaque

XrdOucString XrdHttpReq::resourceplusopaque

The resource specified by the request, including all the opaque data.

Definition at line 248 of file XrdHttpReq.hh.

Referenced by XrdHttpExtReq::XrdHttpExtReq(), and ProcessHTTPReq().

◆ rwOpDone

unsigned int XrdHttpReq::rwOpDone

To coordinate multipart responses across multiple calls.

Definition at line 293 of file XrdHttpReq.hh.

◆ rwOpPartialDone

unsigned int XrdHttpReq::rwOpPartialDone

Definition at line 293 of file XrdHttpReq.hh.

◆ sendcontinue

bool XrdHttpReq::sendcontinue

Definition at line 261 of file XrdHttpReq.hh.

Referenced by parseLine(), ProcessHTTPReq(), and reset().

◆ stringresp

std::string XrdHttpReq::stringresp

If we want to give a string as a response, we compose it here.

Definition at line 319 of file XrdHttpReq.hh.

Referenced by reset().

◆ writtenbytes

long long XrdHttpReq::writtenbytes

In a long write, we track where we have arrived.

Definition at line 325 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), ProcessHTTPReq(), and reset().

◆ xrderrcode

XErrorCode XrdHttpReq::xrderrcode

Definition at line 300 of file XrdHttpReq.hh.

Referenced by Error(), and reset().

◆ xrdreq

ClientRequest XrdHttpReq::xrdreq

The last issued xrd request, often pending.

Definition at line 296 of file XrdHttpReq.hh.

Referenced by Error(), ProcessHTTPReq(), ReqReadV(), and reset().

◆ xrdresp

XResponseType XrdHttpReq::xrdresp

The last response data we got.

Definition at line 299 of file XrdHttpReq.hh.

Referenced by Data(), Done(), Error(), and reset().


The documentation for this class was generated from the following files: