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

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

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

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

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

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

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