diff --git a/Userland/Libraries/LibHTTP/HttpResponse.cpp b/Userland/Libraries/LibHTTP/HttpResponse.cpp index b6245263b4..c93f296ed0 100644 --- a/Userland/Libraries/LibHTTP/HttpResponse.cpp +++ b/Userland/Libraries/LibHTTP/HttpResponse.cpp @@ -18,4 +18,63 @@ HttpResponse::~HttpResponse() { } +StringView HttpResponse::reason_phrase_for_code(int code) +{ + VERIFY(code >= 100 && code <= 599); + + static HashMap s_reason_phrases = { + { 100, "Continue"sv }, + { 101, "Switching Protocols"sv }, + { 200, "OK"sv }, + { 201, "Created"sv }, + { 202, "Accepted"sv }, + { 203, "Non-Authoritative Information"sv }, + { 204, "No Content"sv }, + { 205, "Reset Content"sv }, + { 206, "Partial Content"sv }, + { 300, "Multiple Choices"sv }, + { 301, "Moved Permanently"sv }, + { 302, "Found"sv }, + { 303, "See Other"sv }, + { 304, "Not Modified"sv }, + { 305, "Use Proxy"sv }, + { 307, "Temporary Redirect"sv }, + { 400, "Bad Request"sv }, + { 401, "Unauthorized"sv }, + { 402, "Payment Required"sv }, + { 403, "Forbidden"sv }, + { 404, "Not Found"sv }, + { 405, "Method Not Allowed"sv }, + { 406, "Not Acceptable"sv }, + { 407, "Proxy Authentication Required"sv }, + { 408, "Request Timeout"sv }, + { 409, "Conflict"sv }, + { 410, "Gone"sv }, + { 411, "Length Required"sv }, + { 412, "Precondition Failed"sv }, + { 413, "Payload Too Large"sv }, + { 414, "URI Too Long"sv }, + { 415, "Unsupported Media Type"sv }, + { 416, "Range Not Satisfiable"sv }, + { 417, "Expectation Failed"sv }, + { 426, "Upgrade Required"sv }, + { 500, "Internal Server Error"sv }, + { 501, "Not Implemented"sv }, + { 502, "Bad Gateway"sv }, + { 503, "Service Unavailable"sv }, + { 504, "Gateway Timeout"sv }, + { 505, "HTTP Version Not Supported"sv } + }; + + if (s_reason_phrases.contains(code)) + return s_reason_phrases.ensure(code); + + // NOTE: "A client MUST understand the class of any status code, as indicated by the first + // digit, and treat an unrecognized status code as being equivalent to the x00 status + // code of that class." (RFC 7231, section 6) + auto generic_code = (code / 100) * 100; + VERIFY(s_reason_phrases.contains(generic_code)); + return s_reason_phrases.ensure(generic_code); +} + } diff --git a/Userland/Libraries/LibHTTP/HttpResponse.h b/Userland/Libraries/LibHTTP/HttpResponse.h index 897e013684..d6e31eed03 100644 --- a/Userland/Libraries/LibHTTP/HttpResponse.h +++ b/Userland/Libraries/LibHTTP/HttpResponse.h @@ -21,7 +21,10 @@ public: } int code() const { return m_code; } - const HashMap& headers() const { return m_headers; } + StringView reason_phrase() const { return reason_phrase_for_code(m_code); } + HashMap const& headers() const { return m_headers; } + + static StringView reason_phrase_for_code(int code); private: HttpResponse(int code, HashMap&&);