From fd1ea9a9454c60bf00b68f1bbc37178c831ae474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20R=C4=99bacz?= Date: Mon, 8 Apr 2024 21:59:37 +0200 Subject: [PATCH] Core: Added all well known http status codes (#195) --- tutorial/Network02/Network02.cpp | 13 ++++--- uppsrc/Core/Core.upp | 1 + uppsrc/Core/Http.cpp | 10 +++++ uppsrc/Core/HttpStatusCode.i | 67 ++++++++++++++++++++++++++++++++ uppsrc/Core/Inet.h | 11 +++++- uppsrc/Core/InetUtil.cpp | 3 +- 6 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 uppsrc/Core/HttpStatusCode.i diff --git a/tutorial/Network02/Network02.cpp b/tutorial/Network02/Network02.cpp index 799a75dfa..0cdeed7b1 100644 --- a/tutorial/Network02/Network02.cpp +++ b/tutorial/Network02/Network02.cpp @@ -9,7 +9,7 @@ void ProcessHttpRequest(TcpSocket& client) HttpHeader header; if(!header.Read(client)) { Cerr() << "Failed to read HttpHeader.\n"; - HttpResponse(client, false, 400, "Invalid request"); + HttpResponse(client, false, HttpStatus::BAD_REQUEST); return; } @@ -21,12 +21,15 @@ void ProcessHttpRequest(TcpSocket& client) << "Indonesia" << "Brazil" << "France"; - - HttpResponse(client, false, 200, "OK", "application/json", ja.ToString()); + + auto code = HttpStatus::OK; + HttpResponse(client, false, code, HttpStatus::ToString(code), "application/json", + ja.ToString()); + return; } } - - HttpResponse(client, false, 404, "Not found"); + + HttpResponse(client, false, HttpStatus::NOT_FOUND); } void RunServerLoop(TcpSocket& server) diff --git a/uppsrc/Core/Core.upp b/uppsrc/Core/Core.upp index d3269cb37..0cc8202fb 100644 --- a/uppsrc/Core/Core.upp +++ b/uppsrc/Core/Core.upp @@ -183,6 +183,7 @@ file xxHsh.cpp, Web readonly separator, Inet.h, + HttpStatusCode.i, InetUtil.cpp, MIME.cpp, Socket.cpp, diff --git a/uppsrc/Core/Http.cpp b/uppsrc/Core/Http.cpp index b97c4c95f..5fe5b23c3 100644 --- a/uppsrc/Core/Http.cpp +++ b/uppsrc/Core/Http.cpp @@ -922,4 +922,14 @@ String HttpRequest::GetPhaseName() const return phase >= 0 && phase <= FAILED ? m[phase] : ""; } +String HttpStatus::ToString(int status) +{ + switch (status) { + #define CODE_(id, code, str) case id: return #str; + #include "HttpStatusCode.i" + #undef CODE_ + default: return ""; + } +} + } diff --git a/uppsrc/Core/HttpStatusCode.i b/uppsrc/Core/HttpStatusCode.i new file mode 100644 index 000000000..cb378d924 --- /dev/null +++ b/uppsrc/Core/HttpStatusCode.i @@ -0,0 +1,67 @@ +CODE_(CONTINUE, 100, "Continue") +CODE_(SWITCHING_PROTOCOLS, 101, "Switching Protocols") +CODE_(PROCESSING, 102, "Processing") +CODE_(EARLY_HINTS, 103, "Early Hints") + +CODE_(OK, 200, "OK") +CODE_(CREATED, 201, "Created") +CODE_(ACCEPTED, 202, "Accepted") +CODE_(NON_AUTHORITATIVE_INFO, 203, "Non Authoritative Info") +CODE_(NO_CONTENT, 204, "No Content") +CODE_(RESET_CONTENT, 205, "Reset Content") +CODE_(PARTIAL_CONTENT, 206, "Partial Content") +CODE_(MULTI_STATUS, 207, "Multi Status") +CODE_(ALREADY_REPORTED, 208, "Already Reported") +CODE_(IM_USED, 226, "IM Used") + +CODE_(MULTIPLE_CHOICES, 300, "Multiple Choices") +CODE_(MOVED_PERMANENTLY, 301, "Moved Permanently") +CODE_(FOUND, 302, "Found") +CODE_(SEE_OTHER, 303, "See Other") +CODE_(NOT_MODIFIED, 304, "Not Modified") +CODE_(USE_PROXY, 305, "Use Proxy") +CODE_(_, 306, "_") +CODE_(TEMPORARY_REDIRECT, 307, "Temporary Redirect") +CODE_(PERMANENT_REDIRECT, 308, "Permanent Redirect") + +CODE_(BAD_REQUEST, 400, "Bad Request") +CODE_(UNAUTHORIZED, 401, "Unauthorized") +CODE_(PAYMENT_REQUIRED, 402, "Payment Required") +CODE_(FORBIDDEN, 403, "Forbidden") +CODE_(NOT_FOUND, 404, "Not Found") +CODE_(METHOD_NOT_ALLOWED, 405, "Method Not Allowed") +CODE_(NOT_ACCEPTABLE, 406, "Not Acceptable") +CODE_(PROXY_AUTH_REQUIRED, 407, "Proxy Auth Required") +CODE_(REQUEST_TIEMOUT, 408, "Request Timeout") +CODE_(CONFLICT, 409, "Conflict") +CODE_(GONE, 410, "Gone") +CODE_(LENGTH_REQUIRED, 411, "Length Required") +CODE_(PRECONDITION_FAILED, 412, "Precondition Failed") +CODE_(REQUEST_ENTITY_TOO_LARGE, 413, "Request Entity Too Large") +CODE_(REQUEST_URI_TOO_LONG, 414, "Request URI Too Long") +CODE_(UNSUPPORTED_MEDIA_TYPE, 415, "Unsupported Media Type") +CODE_(REQUEST_RANGE_NOT_SATISFIABLE, 416, "Request Range Not Satisfiable") +CODE_(EXPECTATION_FAILED, 417, "Expectation Failed") +CODE_(TEAPOT, 418, "Teapot") +CODE_(MISDIRECTED_REQUEST, 421, "Misdirected Request") +CODE_(UNPROCESSABLE_ENTITY, 422, "Unprocessable Entity") +CODE_(LOCKED, 423, "Locked") +CODE_(FAILED_DEPENDENCY, 424, "Failed Dependency") +CODE_(TOO_EARLY, 425, "Too Early") +CODE_(UPGRADE_REQUIRED, 426, "Upgrade Required") +CODE_(PRECONDITION_REQUIRED, 428, "Precondition Required") +CODE_(TOO_MANY_REQUESTS, 429, "Too Many Requests") +CODE_(REQUEST_HEADER_FIELDS_TOO_LARGE, 431, "Request Header Fields Too Large") +CODE_(UNAVAILABLE_FOR_LEGAL_REASONS, 451, "Unavailable For Legal Reasons") + +CODE_(INTERNAL_SERVER_ERROR, 500, "Internal Server Error") +CODE_(NOT_IMPLEMENTED, 501, "Not Implemented") +CODE_(BAD_GATEWAY, 502, "Bad Gateway") +CODE_(SERVICE_UNAVAILABLE, 503, "Service Unavailable") +CODE_(GATEWAY_TIMEOUT, 504, "Gateway Timeout") +CODE_(HTTP_VERSION_NOT_SUPPORTED, 505, "HTTP Version Not Supported") +CODE_(VARIANT_ALSO_NEGOTIATES, 506, "Variant Also Negotiates") +CODE_(INSUFFICIENT_STORAGE, 507, "Insufficient Storage") +CODE_(LOOP_DETECTED, 508, "Loop Detected") +CODE_(NOT_EXTENDED, 510, "Not Extended") +CODE_(NETWORK_AUTHENTICATION_REQUIRED, 511, "Network Authentication Required") diff --git a/uppsrc/Core/Inet.h b/uppsrc/Core/Inet.h index 3ba7d4205..df51b30fd 100644 --- a/uppsrc/Core/Inet.h +++ b/uppsrc/Core/Inet.h @@ -297,6 +297,15 @@ struct UrlInfo { UrlInfo(const String& url) { Parse(url); } }; +namespace HttpStatus +{ + #define CODE_(id, code, str) constexpr int id = code; + #include "HttpStatusCode.i" + #undef CODE_ + + String ToString(int code); +} + struct HttpCookie : Moveable { String id; String value; @@ -596,7 +605,7 @@ public: static void TraceShort(bool b = true); }; -bool HttpResponse(TcpSocket& socket, bool scgi, int code, const char *phrase, +bool HttpResponse(TcpSocket& socket, bool scgi, int code, const char *phrase = NULL, const char *content_type = NULL, const String& data = Null, const char *server = NULL, bool gzip = false); diff --git a/uppsrc/Core/InetUtil.cpp b/uppsrc/Core/InetUtil.cpp index a1553c010..e52e39e18 100644 --- a/uppsrc/Core/InetUtil.cpp +++ b/uppsrc/Core/InetUtil.cpp @@ -632,7 +632,8 @@ bool HttpResponse(TcpSocket& socket, bool scgi, int code, const char *phrase, bool gzip) { String r; - r << (scgi ? "Status: " : "HTTP/1.1 ") << code << ' ' << phrase << "\r\n" + r << (scgi ? "Status: " : "HTTP/1.1 ") << + code << ' ' << (phrase ? String(phrase) : HttpStatus::ToString(code)) << "\r\n" "Date: " << WwwFormat(GetUtcTime()) << "\r\n" "Server: " << (server ? server : "U++ based server") << "\r\n" "Connection: close\r\n";