@@ -817,124 +817,23 @@ void XrdHttpReq::parseResource(char *res) {
817817 resourceplusopaque.append (' ?' );
818818 resourceplusopaque.append (p + 1 );
819819 }
820-
821-
822-
823820}
824821
825- void XrdHttpReq::sendWebdavErrorMessage (
826- XResponseType xrdresp, XErrorCode xrderrcode, XrdHttpReq::ReqType httpVerb,
827- XRequestTypes xrdOperation, std::string etext, const char *desc,
828- const char *header_to_add, bool keepalive) {
829- int code{0 };
830- std::string errCode{" Unknown" };
831- std::string statusText;
822+ void XrdHttpReq::generateWebdavErrMsg () {
832823
833- switch (httpVerb) {
834- case XrdHttpReq::rtPUT:
835- if (xrdOperation == kXR_open ) {
836- if (xrderrcode == kXR_isDirectory ) {
837- code = 409 ;
838- errCode = " 8.1" ;
839- } else if (xrderrcode == kXR_NoSpace ) {
840- code = 507 ;
841- errCode = " 8.3.1" ;
842- } else if (xrderrcode == kXR_overQuota ) {
843- code = 507 ;
844- errCode = " 8.3.2" ;
845- } else if (xrderrcode == kXR_NotAuthorized ) {
846- code = 403 ;
847- errCode = " 9.3" ;
848- }
849- } else if (xrdOperation == kXR_write ) {
850- if (xrderrcode == kXR_NoSpace ) {
851- code = 507 ;
852- errCode = " 8.4.1" ;
853- } else if (xrderrcode == kXR_overQuota ) {
854- code = 507 ;
855- errCode = " 8.4.2" ;
856- }
857- }
858- break ;
859- default :
860- break ;
824+ // This block is only used when sending an "X-Transfer-Status" trailer response.
825+ // We set the body to "OK" so that the trailer becomes "X-Transfer-Status: 200 OK",
826+ // indicating a successful transfer.
827+ if (xrdresp == kXR_ok ) {
828+ httpStatusCode = 200 ;
829+ httpErrorBody = " OK" ;
830+ return ;
861831 }
862832
863- // Remove the if at the end of project completion
864- // Till then status text defaults to as set by mapXrdResponseToHttpStatus
865- if (code != 0 ) {
866- httpStatusCode = code;
867- httpErrorCode = errCode;
868- httpErrorBody = " ERROR: " + errCode + " : " + etext + " \n " ;
833+ // default error
834+ httpStatusCode = mapXrdErrToHttp (xrderrcode);
835+ httpErrorBody = etext + " \n " ;
869836
870- prot->SendSimpleResp (httpStatusCode, desc, header_to_add,
871- httpErrorBody.c_str (), httpErrorBody.length (),
872- keepalive);
873- }
874- }
875-
876- // Map an XRootD error code to an appropriate HTTP status code and message
877- // The variables httpStatusCode and httpErrorBody will be populated
878-
879- void XrdHttpReq::mapXrdErrorToHttpStatus () {
880- // Set default HTTP status values for an error case
881- httpStatusCode = 500 ;
882- httpErrorBody = " Unrecognized error" ;
883-
884- // Do error mapping
885- if (xrdresp == kXR_error ) {
886- switch (xrderrcode) {
887- case kXR_AuthFailed :
888- httpStatusCode = 401 ; httpErrorBody = " Unauthorized" ;
889- break ;
890- case kXR_NotAuthorized :
891- httpStatusCode = 403 ; httpErrorBody = " Operation not permitted" ;
892- break ;
893- case kXR_NotFound :
894- httpStatusCode = 404 ; httpErrorBody = " File not found" ;
895- break ;
896- case kXR_Unsupported :
897- httpStatusCode = 405 ; httpErrorBody = " Operation not supported" ;
898- break ;
899- case kXR_FileLocked :
900- httpStatusCode = 423 ; httpErrorBody = " Resource is a locked" ;
901- break ;
902- case kXR_isDirectory :
903- httpStatusCode = 409 ; httpErrorBody = " Resource is a directory" ;
904- break ;
905- case kXR_ItExists :
906- if (request != ReqType::rtDELETE) {
907- httpStatusCode = 409 ; httpErrorBody = " File already exists" ;
908- } else {
909- // In the case the XRootD layer returns a kXR_ItExists after a deletion
910- // was submitted, we return a 405 status code with the error message set by
911- // the XRootD layer
912- httpStatusCode = 405 ;
913- }
914- break ;
915- case kXR_InvalidRequest :
916- httpStatusCode = 405 ; httpErrorBody = " Method is not allowed" ;
917- break ;
918- case kXR_noserver :
919- httpStatusCode = 502 ; httpErrorBody = " Bad Gateway" ;
920- break ;
921- case kXR_TimerExpired :
922- httpStatusCode = 504 ; httpErrorBody = " Gateway timeout" ;
923- break ;
924- default :
925- break ;
926- }
927-
928- if (!etext.empty ()) httpErrorBody = etext;
929-
930- TRACEI (REQ, " PostProcessHTTPReq mapping Xrd error [" << xrderrcode
931- << " ] to status code [" << httpStatusCode << " ]" );
932-
933- httpErrorBody += " \n " ;
934- } else {
935- httpStatusCode = 200 ;
936- httpErrorBody = " OK" ;
937- }
938837}
939838
940839int XrdHttpReq::ProcessHTTPReq () {
@@ -1007,14 +906,9 @@ int XrdHttpReq::ProcessHTTPReq() {
1007906 switch (request) {
1008907 case XrdHttpReq::rtUnset:
1009908 case XrdHttpReq::rtUnknown:
1010- {
1011- prot->SendSimpleResp (400 , NULL , NULL , (char *) " Request unknown" , 0 , false );
1012- reset ();
1013- return -1 ;
1014- }
1015- case XrdHttpReq::rtMalformed:
1016- {
1017- prot->SendSimpleResp (400 , NULL , NULL , (char *) " Request malformed" , 0 , false );
909+ case XrdHttpReq::rtMalformed: {
910+ generateWebdavErrMsg ();
911+ prot->SendSimpleResp (httpStatusCode, NULL , NULL , httpErrorBody.c_str (), httpErrorBody.length (), false );
1018912 reset ();
1019913 return -1 ;
1020914 }
@@ -1035,7 +929,8 @@ int XrdHttpReq::ProcessHTTPReq() {
1035929 m_req_cksum = prot->cksumHandler .getChecksumToRun (m_req_digest);
1036930 if (!m_req_cksum) {
1037931 // No HTTP IANA checksums have been configured by the server admin, return a "METHOD_NOT_ALLOWED" error
1038- prot->SendSimpleResp (403 , NULL , NULL , (char *) " No HTTP-IANA compatible checksums have been configured." , 0 , false );
932+ // We should not send body in response to HEAD request
933+ prot->SendSimpleResp (HTTP_METHOD_NOT_ALLOWED, NULL , NULL , NULL , 0 , false );
1039934 return -1 ;
1040935 }
1041936 if (!opaque) {
@@ -1157,7 +1052,7 @@ int XrdHttpReq::ProcessHTTPReq() {
11571052 m_req_cksum = prot->cksumHandler .getChecksumToRun (m_req_digest);
11581053 if (!m_req_cksum) {
11591054 // No HTTP IANA checksums have been configured by the server admin, return a "METHOD_NOT_ALLOWED" error
1160- prot->SendSimpleResp (403 , NULL , NULL , (char *) " No HTTP-IANA compatible checksums have been configured." , 0 , false );
1055+ prot->SendSimpleResp (HTTP_METHOD_NOT_ALLOWED , NULL , NULL , (char *) " No HTTP-IANA compatible checksums have been configured." , 0 , false );
11611056 return -1 ;
11621057 }
11631058 m_resource_with_digest = resourceplusopaque;
@@ -1185,7 +1080,7 @@ int XrdHttpReq::ProcessHTTPReq() {
11851080 memcpy (xrdreq.close .fhandle , fhandle, 4 );
11861081
11871082 if (!prot->Bridge ->Run ((char *) &xrdreq, 0 , 0 )) {
1188- mapXrdErrorToHttpStatus ();
1083+ generateWebdavErrMsg ();
11891084 return sendFooterError (" Could not run close request on the bridge" );
11901085 }
11911086 return 0 ;
@@ -1225,7 +1120,7 @@ int XrdHttpReq::ProcessHTTPReq() {
12251120 xrdreq.dirlist .dlen = htonl (l);
12261121
12271122 if (!prot->Bridge ->Run ((char *) &xrdreq, (char *) res.c_str (), l)) {
1228- mapXrdErrorToHttpStatus ();
1123+ generateWebdavErrMsg ();
12291124 prot->SendSimpleResp (httpStatusCode, NULL , NULL , httpErrorBody.c_str (), httpErrorBody.length (), false );
12301125 sendFooterError (" Could not run listing request on the bridge" );
12311126 return -1 ;
@@ -1327,7 +1222,7 @@ int XrdHttpReq::ProcessHTTPReq() {
13271222 }
13281223
13291224 if (!prot->Bridge ->Run ((char *) &xrdreq, 0 , 0 )) {
1330- mapXrdErrorToHttpStatus ();
1225+ generateWebdavErrMsg ();
13311226 return sendFooterError (" Could not run read request on the bridge" );
13321227 }
13331228 } else {
@@ -1336,7 +1231,7 @@ int XrdHttpReq::ProcessHTTPReq() {
13361231 length = ReqReadV (readChunkList);
13371232
13381233 if (!prot->Bridge ->Run ((char *) &xrdreq, (char *) &ralist[0 ], length)) {
1339- mapXrdErrorToHttpStatus ();
1234+ generateWebdavErrMsg ();
13401235 return sendFooterError (" Could not run ReadV request on the bridge" );
13411236 }
13421237
@@ -1473,7 +1368,7 @@ int XrdHttpReq::ProcessHTTPReq() {
14731368
14741369 TRACEI (REQ, " XrdHTTP PUT: Writing chunk of size " << bytes_to_write << " starting with '" << *(prot->myBuffStart ) << " '" << " with " << chunk_bytes_remaining << " bytes remaining in the chunk" );
14751370 if (!prot->Bridge ->Run ((char *) &xrdreq, prot->myBuffStart , bytes_to_write)) {
1476- mapXrdErrorToHttpStatus ();
1371+ generateWebdavErrMsg ();
14771372 return sendFooterError (" Could not run write request on the bridge" );
14781373 }
14791374 // If there are more bytes in the buffer, then immediately call us after the
@@ -1496,7 +1391,7 @@ int XrdHttpReq::ProcessHTTPReq() {
14961391
14971392 TRACEI (REQ, " Writing " << bytes_to_read);
14981393 if (!prot->Bridge ->Run ((char *) &xrdreq, prot->myBuffStart , bytes_to_read)) {
1499- mapXrdErrorToHttpStatus ();
1394+ generateWebdavErrMsg ();
15001395 return sendFooterError (" Could not run write request on the bridge" );
15011396 }
15021397
@@ -1519,7 +1414,7 @@ int XrdHttpReq::ProcessHTTPReq() {
15191414
15201415
15211416 if (!prot->Bridge ->Run ((char *) &xrdreq, 0 , 0 )) {
1522- mapXrdErrorToHttpStatus ();
1417+ generateWebdavErrMsg ();
15231418 return sendFooterError (" Could not run close request on the bridge" );
15241419 }
15251420
@@ -2134,7 +2029,7 @@ void XrdHttpReq::setTransferStatusHeader(std::string &header) {
21342029int XrdHttpReq::PostProcessHTTPReq (bool final_) {
21352030
21362031 TRACEI (REQ, " PostProcessHTTPReq req: " << request << " reqstate: " << reqstate << " final_:" << final_);
2137- mapXrdErrorToHttpStatus ();
2032+ generateWebdavErrMsg ();
21382033
21392034 if (xrdreq.set .requestid == htons (kXR_set )) {
21402035 // We have set the user agent, if it fails we return a 500 error, otherwise the callback is successful --> we continue
@@ -2370,8 +2265,7 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) {
23702265 {
23712266 if (!fopened) {
23722267 if (xrdresp != kXR_ok ) {
2373- sendWebdavErrorMessage (xrdresp, xrderrcode, XrdHttpReq::rtPUT,
2374- kXR_open , etext, NULL , NULL , keepalive);
2268+ prot->SendSimpleResp (httpStatusCode, NULL , NULL , httpErrorBody.c_str (), httpErrorBody.length (), keepalive);
23752269 return -1 ;
23762270 }
23772271
@@ -2389,9 +2283,13 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) {
23892283 break ;
23902284 } else {
23912285
2392-
23932286 // If we are here it's too late to send a proper error message...
2394- if (xrdresp == kXR_error ) return -1 ;
2287+ // However, we decide to send a response anyway before we close the connection
2288+ // We are not sure if sending a final response before reading the entire request
2289+ if (xrdresp == kXR_error ) {
2290+ prot->SendSimpleResp (httpStatusCode, NULL , NULL , httpErrorBody.c_str (), httpErrorBody.length (), keepalive);
2291+ return -1 ;
2292+ }
23952293
23962294 if (ntohs (xrdreq.header .requestid ) == kXR_write ) {
23972295 int l = ntohl (xrdreq.write .dlen );
@@ -2416,8 +2314,7 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) {
24162314 prot->SendSimpleResp (201 , NULL , NULL , (char *)" :-)" , 0 , keepalive);
24172315 return keepalive ? 1 : -1 ;
24182316 } else {
2419- sendWebdavErrorMessage (xrdresp, xrderrcode, XrdHttpReq::rtPUT,
2420- kXR_close , etext, NULL , NULL , keepalive);
2317+ prot->SendSimpleResp (httpStatusCode, NULL , NULL , httpErrorBody.c_str (), httpErrorBody.length (), keepalive);
24212318 return -1 ;
24222319 }
24232320 }
0 commit comments