diff --git a/src/XrdHttp/XrdHttpProtocol.cc b/src/XrdHttp/XrdHttpProtocol.cc index 4cfc4a62677..0825913a69d 100644 --- a/src/XrdHttp/XrdHttpProtocol.cc +++ b/src/XrdHttp/XrdHttpProtocol.cc @@ -1426,9 +1426,12 @@ int XrdHttpProtocol::StartSimpleResp(int code, const char *desc, const char *hea ss << desc; } else { if (code == 200) ss << "OK"; - else if (code == 206) ss << "Partial content"; + else if (code == 206) ss << "Partial Content"; else if (code == 302) ss << "Redirect"; - else if (code == 404) ss << "Not found"; + else if (code == 403) ss << "Forbidden"; + else if (code == 404) ss << "Not Found"; + else if (code == 405) ss << "Method Not Allowed"; + else if (code == 500) ss << "Internal Server Error"; else ss << "Unknown"; } ss << crlf; diff --git a/src/XrdHttp/XrdHttpReq.cc b/src/XrdHttp/XrdHttpReq.cc index 233a6d4cde7..0d635adbe13 100644 --- a/src/XrdHttp/XrdHttpReq.cc +++ b/src/XrdHttp/XrdHttpReq.cc @@ -770,6 +770,38 @@ void XrdHttpReq::parseResource(char *res) { } +// Map an XRootD error code to an appropriate HTTP status code and message +// The variables httpStatusCode and httpStatusText will be populated + +void XrdHttpReq::mapXrdErrorToHttpStatus() { + // Set default HTTP status values for an error case + httpStatusCode = 500; + httpStatusText = "Unrecognized error"; + + // Do error mapping + if (xrdresp == kXR_error) { + switch (xrderrcode) { + case kXR_NotAuthorized: + httpStatusCode = 403; httpStatusText = "Operation not permitted"; + break; + case kXR_NotFound: + httpStatusCode = 404; httpStatusText = "File not found"; + break; + case kXR_Unsupported: + httpStatusCode = 405; httpStatusText = "Operation not supported"; + default: + break; + } + + if (!etext.empty()) httpStatusText = etext; + + TRACEI(REQ, "PostProcessHTTPReq mapping Xrd error [" << xrderrcode + << "] to status code [" << httpStatusCode << "]"); + + httpStatusText += "\n"; + } +} + int XrdHttpReq::ProcessHTTPReq() { kXR_int32 l; @@ -1419,6 +1451,7 @@ int XrdHttpReq::ProcessHTTPReq() { int XrdHttpReq::PostProcessHTTPReq(bool final_) { TRACEI(REQ, "PostProcessHTTPReq req: " << request << " reqstate: " << reqstate); + mapXrdErrorToHttpStatus(); switch (request) { case XrdHttpReq::rtUnknown: @@ -1452,11 +1485,13 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { return 1; } - prot->SendSimpleResp(500, NULL, NULL, NULL, 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); reset(); return 1; } else { - prot->SendSimpleResp(404, NULL, NULL, (char *) "Error man!", 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } } @@ -1467,7 +1502,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { if (xrdresp == kXR_error) { - prot->SendSimpleResp(404, NULL, NULL, (char *) etext.c_str(), 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } @@ -1695,7 +1731,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { // We are here if the request failed if (prot->myRole == kXR_isManager) { - prot->SendSimpleResp(404, NULL, NULL, (char *) "File not found.", 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } @@ -1785,8 +1822,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { // reqstate--; // return 0; //} - - prot->SendSimpleResp(404, NULL, NULL, (char *) "Error man!", 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } @@ -1796,7 +1833,7 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { } default: //read or readv { - + // Nothing to do if we are postprocessing a close if (ntohs(xrdreq.header.requestid) == kXR_close) return 1; @@ -1923,7 +1960,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { prot->SendSimpleResp(200, NULL, NULL, (char *) ":-)", 0); return 1; } else { - prot->SendSimpleResp(500, NULL, NULL, (char *) etext.c_str(), 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } } @@ -1944,7 +1982,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { { if (xrdresp != kXR_ok) { - prot->SendSimpleResp(404, NULL, NULL, (char *) etext.c_str(), 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } @@ -1976,7 +2015,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { prot->SendSimpleResp(200, NULL, NULL, (char *) ":-)", 0); return 1; } - prot->SendSimpleResp(500, NULL, NULL, (char *) "Internal Error", 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } } @@ -1988,7 +2028,8 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { { if (xrdresp == kXR_error) { - prot->SendSimpleResp(404, NULL, NULL, (char *) etext.c_str(), 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; } @@ -2226,12 +2267,10 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) { } - - - switch (xrdresp) { case kXR_error: - prot->SendSimpleResp(500, NULL, NULL, (char *) etext.c_str(), 0); + prot->SendSimpleResp(httpStatusCode, NULL, NULL, + httpStatusText.c_str(), httpStatusText.length()); return -1; break; diff --git a/src/XrdHttp/XrdHttpReq.hh b/src/XrdHttp/XrdHttpReq.hh index c364eaa6663..83f7900960f 100644 --- a/src/XrdHttp/XrdHttpReq.hh +++ b/src/XrdHttp/XrdHttpReq.hh @@ -76,6 +76,10 @@ class XrdOucEnv; class XrdHttpReq : public XrdXrootd::Bridge::Result { private: + // HTTP response parameters to be sent back to the user + int httpStatusCode; + std::string httpStatusText; + int parseContentRange(char *); int parseHost(char *); int parseRWOp(char *); @@ -93,6 +97,8 @@ private: // Parse a resource string, typically a filename, setting the resource field and the opaque data void parseResource(char *url); + // Map an XRootD error code to an appropriate HTTP status code and message + void mapXrdErrorToHttpStatus(); public: XrdHttpReq(XrdHttpProtocol *protinstance) {