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 bool Data (Bridge::Context &info, const struct iovec *iovP, int iovN, int iovL, bool final)=0
 
virtual bool Done (Bridge::Context &info)=0
 the result context
 
virtual bool Error (Bridge::Context &info, int ecode, const char *etext)=0
 
virtual int File (Bridge::Context &info, int dlen)=0
 
virtual void Free (Bridge::Context &info, char *buffP, int buffL)
 
virtual bool Redir (Bridge::Context &info, int port, const char *hname)=0
 
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_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 207 of file XrdHttpReq.hh.

Constructor & Destructor Documentation

◆ XrdHttpReq()

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

Definition at line 154 of file XrdHttpReq.hh.

154 :
155 readRangeHandler(rcfg), keepalive(true) {
156
157 prot = protinstance;
158 length = 0;
159 //xmlbody = 0;
160 depth = 0;
161 opaque = 0;
162 writtenbytes = 0;
163 fopened = false;
164 headerok = false;
165 mScitag = -1;
166 };
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, length, mScitag, opaque, and writtenbytes.

◆ ~XrdHttpReq()

XrdHttpReq::~XrdHttpReq ( )
virtual

Definition at line 109 of file XrdHttpReq.cc.

109 {
110 //if (xmlbody) xmlFreeDoc(xmlbody);
111
112 reset();
113}
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 782 of file XrdHttpReq.cc.

782 {
783 if (hdr2cgistr.length() > 0) {
784 hdr2cgistr.append("&");
785 }
786 hdr2cgistr.append(key);
787 hdr2cgistr.append("=");
788 hdr2cgistr.append(value);
789}
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 625 of file XrdHttpReq.cc.

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

Referenced by XrdHttpProtocol::Process(), 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 424 of file XrdHttpReq.cc.

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

◆ buildPartialHdrEnd()

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

Build the closing part for a multipart response.

Definition at line 434 of file XrdHttpReq.cc.

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

◆ 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 442 of file XrdHttpReq.cc.

448 {
449
450 TRACE(REQ, " XrdHttpReq::Data! final=" << final);
451
452 this->xrdresp = kXR_ok;
453 this->iovP = iovP_;
454 this->iovN = iovN_;
455 this->iovL = iovL_;
456 this->final = final_;
457
458 if (PostProcessHTTPReq(final_)) reset();
459
460 return true;
461
462};
@ kXR_ok
Definition XProtocol.hh:897
#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 488 of file XrdHttpReq.cc.

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

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 505 of file XrdHttpReq.cc.

508 {
509
510 TRACE(REQ, " XrdHttpReq::Error");
511
513 xrderrcode = (XErrorCode) ecode;
514
515 if (etext_) {
516 char *s = escapeXML(etext_);
517 this->etext = s;
518 free(s);
519 }
520
521 if (PostProcessHTTPReq()) reset();
522
523 // Second part of the ugly hack on stat()
524 if ((request == rtGET) && (xrdreq.header.requestid == ntohs(kXR_stat)))
525 return true;
526
527 return false;
528};
XErrorCode
Definition XProtocol.hh:987
@ kXR_error
Definition XProtocol.hh:901
struct ClientRequestHdr header
Definition XProtocol.hh:844
kXR_unt16 requestid
Definition XProtocol.hh:157
@ kXR_stat
Definition XProtocol.hh:129
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, ClientRequest::header, kXR_error, kXR_stat, request, ClientRequestHdr::requestid, 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 464 of file XrdHttpReq.cc.

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

References XrdHttpReadRangeHandler::NotifyError(), XrdHttpReadRangeHandler::NotifyReadResult(), 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 93 of file XrdHttpReq.cc.

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

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 255 of file XrdHttpReq.cc.

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

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

Referenced by XrdHttpProtocol::Process().

+ Here is the caller graph for this function:

◆ parseLine()

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

Parse the header.

Definition at line 115 of file XrdHttpReq.cc.

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

References addCgi(), allheaders, depth, destination, XrdOucEnv::Get(), XrdHttpProtocol::hdr2cgimap, keepalive, length, m_req_digest, MAX_TK_LEN, opaque, XrdHttpReadRangeHandler::ParseContentRange(), XrdHttpProtocol::pmarkHandle, readRangeHandler, request, rtMalformed, sendcontinue, and trim().

Referenced by XrdHttpProtocol::Process().

+ Here is the call graph for this function:
+ Here is the caller 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 924 of file XrdHttpReq.cc.

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

References XrdOucString::append(), appendOpaque(), ClientMvRequest::arg1len, XrdOucString::beginswith(), XrdHttpProtocol::Bridge, XrdOucString::c_str(), XrdHttpProtocol::cksumHandler, ClientRequest::close, XrdHttpProtocol::StaticPreloadInfo::data, DEBUG, depth, destination, ClientRequest::dirlist, ClientDirlistRequest::dlen, ClientMkdirRequest::dlen, ClientMvRequest::dlen, ClientOpenRequest::dlen, ClientReadRequest::dlen, ClientRmRequest::dlen, ClientRmdirRequest::dlen, ClientStatRequest::dlen, ClientWriteRequest::dlen, XrdHttpProtocol::doChksum(), XrdHttpProtocol::doStat(), XrdHttpProtocol::embeddedstatic, XrdOucString::endswith(), XrdOucString::erasefromend(), ClientCloseRequest::fhandle, ClientReadRequest::fhandle, ClientWriteRequest::fhandle, fhandle, fileflags, filesize, fopened, XrdHttpChecksumHandler::getChecksumToRun(), XrdHttpChecksum::getXRootDConfigDigestName(), hdr2cgistr, host, XrdHttpReadRangeHandler::isSingleRange(), 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, XrdOucString::length(), XrdHttpProtocol::listdeny, XrdHttpProtocol::listredir, m_appended_hdr2cgistr, m_req_cksum, m_req_digest, m_resource_with_digest, ClientRequest::mkdir, ClientOpenRequest::mode, ClientRequest::mv, XrdHttpProtocol::myRole, XrdHttpReadRangeHandler::NextReadList(), XrdOucUtils::obfuscate(), ClientReadRequest::offset, ClientWriteRequest::offset, opaque, ClientRequest::open, ClientDirlistRequest::options, ClientMkdirRequest::options, ClientOpenRequest::options, parseBody(), parseURL(), ProcessHTTPReq(), XrdHttpExtHandler::ProcessReq(), quote(), ralist, ClientRequest::read, readClosing, readRangeHandler, ReqReadV(), reqstate, request, ClientCloseRequest::requestid, ClientDirlistRequest::requestid, ClientMkdirRequest::requestid, ClientMvRequest::requestid, ClientOpenRequest::requestid, ClientReadRequest::requestid, ClientRmRequest::requestid, ClientRmdirRequest::requestid, ClientStatRequest::requestid, ClientWriteRequest::requestid, reset(), resource, resourceplusopaque, ClientReadRequest::rlen, ClientRequest::rm, ClientRequest::rmdir, rtDELETE, rtGET, rtHEAD, rtMalformed, rtMKCOL, rtMOVE, rtOPTIONS, rtPATCH, rtPROPFIND, rtPUT, rtUnknown, rtUnset, XrdXrootd::Bridge::Run(), sendcontinue, XrdXrootd::Bridge::setSF(), ClientRequest::stat, XrdHttpProtocol::staticpreload, XrdHttpProtocol::staticredir, TRACE, TRACE_DEBUG, TRACEI, TRACING, ClientRequest::write, writtenbytes, and xrdreq.

Referenced by XrdHttpProtocol::Process(), and 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 530 of file XrdHttpReq.cc.

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

References appendOpaque(), XrdOucString::c_str(), calcHashes(), XrdHttpProtocol::isdesthttps, keepalive, quote(), redirdest, request, reset(), resource, rtGET, XrdHttpProtocol::SecEntity, XrdHttpProtocol::secretkey, 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 387 of file XrdHttpReq.cc.

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

References ClientReadVRequest::dlen, ClientRequest::header, kXR_readv, ralist, ClientRequest::readv, ClientRequestHdr::requestid, 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 2745 of file XrdHttpReq.cc.

2745 {
2746
2747 TRACE(REQ, " XrdHttpReq request ended.");
2748
2749 //if (xmlbody) xmlFreeDoc(xmlbody);
2751 readClosing = false;
2752 writtenbytes = 0;
2753 etext.clear();
2754 redirdest = "";
2755
2756 // // Here we should deallocate this
2757 // const struct iovec *iovP //!< pointer to data array
2758 // int iovN, //!< array count
2759 // int iovL, //!< byte count
2760 // bool final //!< true -> final result
2761
2762
2763 //xmlbody = 0;
2764 depth = 0;
2767 ralist.clear();
2768 ralist.shrink_to_fit();
2769
2770 request = rtUnset;
2771 resource = "";
2772 allheaders.clear();
2773
2774 // Reset the state of the request's digest request.
2775 m_req_digest.clear();
2776 m_digest_header.clear();
2777 m_req_cksum = nullptr;
2778
2780 m_user_agent = "";
2781
2782 headerok = false;
2783 keepalive = true;
2784 length = 0;
2785 filesize = 0;
2786 depth = 0;
2787 sendcontinue = false;
2788
2789 m_transfer_encoding_chunked = false;
2790 m_current_chunk_size = -1;
2791 m_current_chunk_offset = 0;
2792
2793 m_trailer_headers = false;
2794 m_status_trailer = false;
2795
2797 reqstate = 0;
2798
2799 memset(&xrdreq, 0, sizeof (xrdreq));
2800 memset(&xrdresp, 0, sizeof (xrdresp));
2802
2803 etext.clear();
2804 redirdest = "";
2805
2806 stringresp = "";
2807
2808 host = "";
2809 destination = "";
2810 hdr2cgistr = "";
2811 m_appended_hdr2cgistr = false;
2812
2813 iovP = 0;
2814 iovN = 0;
2815 iovL = 0;
2816
2817
2818 if (opaque) delete(opaque);
2819 opaque = 0;
2820
2821 fopened = false;
2822
2823 final = false;
2824
2825 mScitag = -1;
2826}
@ kXR_noErrorYet
@ kXR_noResponsesYet
Definition XProtocol.hh:906
void reset()
resets this handler
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_hdr2cgistr, m_digest_header, m_req_cksum, m_req_digest, m_resource_with_digest, mScitag, opaque, ralist, readClosing, readRangeHandler, redirdest, reqstate, request, XrdHttpReadRangeHandler::reset(), resource, rtUnset, sendcontinue, stringresp, TRACE, writtenbytes, xrderrcode, xrdreq, and xrdresp.

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

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

◆ userAgent()

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

Definition at line 198 of file XrdHttpReq.hh.

198{return m_user_agent;}

Referenced by XrdHttpProtocol::Process().

+ Here is the caller graph for this function:

Member Data Documentation

◆ allheaders

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

Definition at line 229 of file XrdHttpReq.hh.

Referenced by parseLine(), and reset().

◆ depth

int XrdHttpReq::depth

Definition at line 248 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 254 of file XrdHttpReq.hh.

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

◆ etext

std::string XrdHttpReq::etext

Definition at line 287 of file XrdHttpReq.hh.

Referenced by Error(), and reset().

◆ fhandle

char XrdHttpReq::fhandle[4]

Definition at line 301 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq().

◆ filectime

long XrdHttpReq::filectime

Definition at line 300 of file XrdHttpReq.hh.

◆ fileflags

long XrdHttpReq::fileflags

Definition at line 298 of file XrdHttpReq.hh.

Referenced by XrdHttpProtocol::doStat(), and ProcessHTTPReq().

◆ filemodtime

long XrdHttpReq::filemodtime

Definition at line 299 of file XrdHttpReq.hh.

Referenced by XrdHttpProtocol::doStat().

◆ filesize

long long XrdHttpReq::filesize

Definition at line 297 of file XrdHttpReq.hh.

Referenced by XrdHttpProtocol::doStat(), ProcessHTTPReq(), and reset().

◆ final

bool XrdHttpReq::final

true -> final result

Definition at line 294 of file XrdHttpReq.hh.

◆ fopened

bool XrdHttpReq::fopened

Definition at line 302 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 270 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 240 of file XrdHttpReq.hh.

Referenced by XrdHttpReq(), XrdHttpProtocol::Process(), and reset().

◆ host

std::string XrdHttpReq::host

The host field specified in the req.

Definition at line 252 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ iovL

int XrdHttpReq::iovL

byte count

Definition at line 293 of file XrdHttpReq.hh.

Referenced by Data(), and reset().

◆ iovN

int XrdHttpReq::iovN

array count

Definition at line 292 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 291 of file XrdHttpReq.hh.

Referenced by Data(), and reset().

◆ keepalive

bool XrdHttpReq::keepalive

Definition at line 246 of file XrdHttpReq.hh.

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

◆ length

long long XrdHttpReq::length

◆ m_appended_hdr2cgistr

bool XrdHttpReq::m_appended_hdr2cgistr

Definition at line 271 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 267 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 260 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 257 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 265 of file XrdHttpReq.hh.

Referenced by ProcessHTTPReq(), and reset().

◆ mScitag

int XrdHttpReq::mScitag

Definition at line 313 of file XrdHttpReq.hh.

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

◆ opaque

XrdOucEnv* XrdHttpReq::opaque

The opaque data, after parsing.

Definition at line 234 of file XrdHttpReq.hh.

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

◆ ralist

std::vector<readahead_list> XrdHttpReq::ralist

Definition at line 183 of file XrdHttpReq.hh.

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

◆ readClosing

bool XrdHttpReq::readClosing

Definition at line 244 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 243 of file XrdHttpReq.hh.

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

◆ redirdest

XrdOucString XrdHttpReq::redirdest

Definition at line 288 of file XrdHttpReq.hh.

Referenced by Redir(), and reset().

◆ reqstate

int XrdHttpReq::reqstate

State machine to talk to the bridge.

Definition at line 308 of file XrdHttpReq.hh.

Referenced by XrdHttpProtocol::Process(), ProcessHTTPReq(), and reset().

◆ request

ReqType XrdHttpReq::request

The request we got.

Definition at line 224 of file XrdHttpReq.hh.

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

◆ requestverb

std::string XrdHttpReq::requestverb

Definition at line 225 of file XrdHttpReq.hh.

Referenced by parseFirstLine().

◆ resource

XrdOucString XrdHttpReq::resource

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

Definition at line 232 of file XrdHttpReq.hh.

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

◆ resourceplusopaque

XrdOucString XrdHttpReq::resourceplusopaque

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

Definition at line 236 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 279 of file XrdHttpReq.hh.

◆ rwOpPartialDone

unsigned int XrdHttpReq::rwOpPartialDone

Definition at line 279 of file XrdHttpReq.hh.

◆ sendcontinue

bool XrdHttpReq::sendcontinue

Definition at line 249 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 305 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 311 of file XrdHttpReq.hh.

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

◆ xrderrcode

XErrorCode XrdHttpReq::xrderrcode

Definition at line 286 of file XrdHttpReq.hh.

Referenced by Error(), and reset().

◆ xrdreq

ClientRequest XrdHttpReq::xrdreq

The last issued xrd request, often pending.

Definition at line 282 of file XrdHttpReq.hh.

Referenced by XrdHttpProtocol::doChksum(), XrdHttpProtocol::doStat(), Error(), XrdHttpProtocol::Process(), ProcessHTTPReq(), ReqReadV(), and reset().

◆ xrdresp

XResponseType XrdHttpReq::xrdresp

The last response data we got.

Definition at line 285 of file XrdHttpReq.hh.

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


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