aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-09-28 23:24:45 +0200
committerStefan Boberg <[email protected]>2021-09-28 23:24:45 +0200
commit46eebda16a2c3a66bb8ca48488e49d659556d745 (patch)
treec5fb2662c2cf5e3fb4efc2e263e8663d37723747
parentRemoved IsPointerToStack() (diff)
downloadzen-46eebda16a2c3a66bb8ca48488e49d659556d745.tar.xz
zen-46eebda16a2c3a66bb8ca48488e49d659556d745.zip
http: ReasonStringForHttpResultCode returns string_view to avoid strlen
-rw-r--r--zenhttp/httpserver.cpp118
-rw-r--r--zenhttp/httpsys.cpp105
-rw-r--r--zenhttp/include/zenhttp/httpcommon.h2
3 files changed, 111 insertions, 114 deletions
diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp
index 795e81ea8..78fc34984 100644
--- a/zenhttp/httpserver.cpp
+++ b/zenhttp/httpserver.cpp
@@ -152,7 +152,7 @@ ToString(HttpVerb Verb)
}
}
-const char*
+std::string_view
ReasonStringForHttpResultCode(int HttpCode)
{
switch (HttpCode)
@@ -160,132 +160,132 @@ ReasonStringForHttpResultCode(int HttpCode)
// 1xx Informational
case 100:
- return "Continue";
+ return "Continue"sv;
case 101:
- return "Switching Protocols";
+ return "Switching Protocols"sv;
// 2xx Success
case 200:
- return "OK";
+ return "OK"sv;
case 201:
- return "Created";
+ return "Created"sv;
case 202:
- return "Accepted";
+ return "Accepted"sv;
case 204:
- return "No Content";
+ return "No Content"sv;
case 205:
- return "Reset Content";
+ return "Reset Content"sv;
case 206:
- return "Partial Content";
+ return "Partial Content"sv;
// 3xx Redirection
case 300:
- return "Multiple Choices";
+ return "Multiple Choices"sv;
case 301:
- return "Moved Permanently";
+ return "Moved Permanently"sv;
case 302:
- return "Found";
+ return "Found"sv;
case 303:
- return "See Other";
+ return "See Other"sv;
case 304:
- return "Not Modified";
+ return "Not Modified"sv;
case 305:
- return "Use Proxy";
+ return "Use Proxy"sv;
case 306:
- return "Switch Proxy";
+ return "Switch Proxy"sv;
case 307:
- return "Temporary Redirect";
+ return "Temporary Redirect"sv;
case 308:
- return "Permanent Redirect";
+ return "Permanent Redirect"sv;
// 4xx Client errors
case 400:
- return "Bad Request";
+ return "Bad Request"sv;
case 401:
- return "Unauthorized";
+ return "Unauthorized"sv;
case 402:
- return "Payment Required";
+ return "Payment Required"sv;
case 403:
- return "Forbidden";
+ return "Forbidden"sv;
case 404:
- return "Not Found";
+ return "Not Found"sv;
case 405:
- return "Method Not Allowed";
+ return "Method Not Allowed"sv;
case 406:
- return "Not Acceptable";
+ return "Not Acceptable"sv;
case 407:
- return "Proxy Authentication Required";
+ return "Proxy Authentication Required"sv;
case 408:
- return "Request Timeout";
+ return "Request Timeout"sv;
case 409:
- return "Conflict";
+ return "Conflict"sv;
case 410:
- return "Gone";
+ return "Gone"sv;
case 411:
- return "Length Required";
+ return "Length Required"sv;
case 412:
- return "Precondition Failed";
+ return "Precondition Failed"sv;
case 413:
- return "Payload Too Large";
+ return "Payload Too Large"sv;
case 414:
- return "URI Too Long";
+ return "URI Too Long"sv;
case 415:
- return "Unsupported Media Type";
+ return "Unsupported Media Type"sv;
case 416:
- return "Range Not Satisifiable";
+ return "Range Not Satisifiable"sv;
case 417:
- return "Expectation Failed";
+ return "Expectation Failed"sv;
case 418:
- return "I'm a teapot";
+ return "I'm a teapot"sv;
case 421:
- return "Misdirected Request";
+ return "Misdirected Request"sv;
case 422:
- return "Unprocessable Entity";
+ return "Unprocessable Entity"sv;
case 423:
- return "Locked";
+ return "Locked"sv;
case 424:
- return "Failed Dependency";
+ return "Failed Dependency"sv;
case 425:
- return "Too Early";
+ return "Too Early"sv;
case 426:
- return "Upgrade Required";
+ return "Upgrade Required"sv;
case 428:
- return "Precondition Required";
+ return "Precondition Required"sv;
case 429:
- return "Too Many Requests";
+ return "Too Many Requests"sv;
case 431:
- return "Request Header Fields Too Large";
+ return "Request Header Fields Too Large"sv;
// 5xx Server errors
case 500:
- return "Internal Server Error";
+ return "Internal Server Error"sv;
case 501:
- return "Not Implemented";
+ return "Not Implemented"sv;
case 502:
- return "Bad Gateway";
+ return "Bad Gateway"sv;
case 503:
- return "Service Unavailable";
+ return "Service Unavailable"sv;
case 504:
- return "Gateway Timeout";
+ return "Gateway Timeout"sv;
case 505:
- return "HTTP Version Not Supported";
+ return "HTTP Version Not Supported"sv;
case 506:
- return "Variant Also Negotiates";
+ return "Variant Also Negotiates"sv;
case 507:
- return "Insufficient Storage";
+ return "Insufficient Storage"sv;
case 508:
- return "Loop Detected";
+ return "Loop Detected"sv;
case 510:
- return "Not Extended";
+ return "Not Extended"sv;
case 511:
- return "Network Authentication Required";
+ return "Network Authentication Required"sv;
default:
- return "Unknown Result";
+ return "Unknown Result"sv;
}
}
@@ -545,7 +545,7 @@ HttpRequestRouter::HandleRequest(zen::HttpServerRequest& Request)
Ref<HttpServer>
CreateHttpServer()
{
-#if 0
+#if 1
return new HttpUwsServer;
#elif ZEN_WITH_HTTPSYS
return new HttpSysServer{std::thread::hardware_concurrency()};
diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp
index bccff24ab..9b2e7f832 100644
--- a/zenhttp/httpsys.cpp
+++ b/zenhttp/httpsys.cpp
@@ -18,47 +18,43 @@
# pragma comment(lib, "httpapi.lib")
std::wstring
-UTF8_to_wstring(const char* in)
+UTF8_to_UTF16(const char* InPtr)
{
- std::wstring out;
- unsigned int codepoint;
+ std::wstring OutString;
+ unsigned int Codepoint;
- while (*in != 0)
+ while (*InPtr != 0)
{
- unsigned char ch = static_cast<unsigned char>(*in);
-
- if (ch <= 0x7f)
- codepoint = ch;
- else if (ch <= 0xbf)
- codepoint = (codepoint << 6) | (ch & 0x3f);
- else if (ch <= 0xdf)
- codepoint = ch & 0x1f;
- else if (ch <= 0xef)
- codepoint = ch & 0x0f;
+ unsigned char InChar = static_cast<unsigned char>(*InPtr);
+
+ if (InChar <= 0x7f)
+ Codepoint = InChar;
+ else if (InChar <= 0xbf)
+ Codepoint = (Codepoint << 6) | (InChar & 0x3f);
+ else if (InChar <= 0xdf)
+ Codepoint = InChar & 0x1f;
+ else if (InChar <= 0xef)
+ Codepoint = InChar & 0x0f;
else
- codepoint = ch & 0x07;
+ Codepoint = InChar & 0x07;
- ++in;
+ ++InPtr;
- if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff))
+ if (((*InPtr & 0xc0) != 0x80) && (Codepoint <= 0x10ffff))
{
- if constexpr (sizeof(wchar_t) > 2)
+ if (Codepoint > 0xffff)
{
- out.append(1, static_cast<wchar_t>(codepoint));
+ OutString.append(1, static_cast<wchar_t>(0xd800 + (Codepoint >> 10)));
+ OutString.append(1, static_cast<wchar_t>(0xdc00 + (Codepoint & 0x03ff)));
}
- else if (codepoint > 0xffff)
+ else if (Codepoint < 0xd800 || Codepoint >= 0xe000)
{
- out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
- out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
- }
- else if (codepoint < 0xd800 || codepoint >= 0xe000)
- {
- out.append(1, static_cast<wchar_t>(codepoint));
+ OutString.append(1, static_cast<wchar_t>(Codepoint));
}
}
}
- return out;
+ return OutString;
}
namespace zen {
@@ -493,6 +489,7 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
// Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
//
// Set DisableServerHeader to 1 to disable suffix, or 2 to disable the header altogether
+ // (only the latter appears to do anything in my testing, on Windows 10).
//
// (reference https://docs.microsoft.com/en-us/archive/blogs/dsnotes/wswcf-remove-server-header)
//
@@ -519,9 +516,11 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
ContentTypeHeader->pRawValue = ContentTypeString.data();
ContentTypeHeader->RawValueLength = (USHORT)ContentTypeString.size();
+ std::string_view ReasonString = ReasonStringForHttpResultCode(m_ResponseCode);
+
HttpResponse.StatusCode = m_ResponseCode;
- HttpResponse.pReason = ReasonStringForHttpResultCode(m_ResponseCode);
- HttpResponse.ReasonLength = (USHORT)strlen(HttpResponse.pReason);
+ HttpResponse.pReason = ReasonString.data();
+ HttpResponse.ReasonLength = (USHORT)ReasonString.size();
// Cache policy
@@ -823,18 +822,18 @@ HttpSysServer::RegisterService(const char* UrlPath, HttpService& Service)
++UrlPath;
}
- const std::wstring Path16 = UTF8_to_wstring(UrlPath);
- Service.SetUriPrefixLength(Path16.size() + 1 /* leading slash */);
+ const std::wstring PathUtf16 = UTF8_to_UTF16(UrlPath);
+ Service.SetUriPrefixLength(PathUtf16.size() + 1 /* leading slash */);
// Convert to wide string
- std::wstring Url16 = m_BaseUri + Path16;
+ std::wstring Url16 = m_BaseUri + PathUtf16;
ULONG Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, Url16.c_str(), HTTP_URL_CONTEXT(&Service), 0 /* Reserved */);
if (Result != NO_ERROR)
{
- ZEN_ERROR("HttpAddUrlToUrlGroup failed with result {}", Result);
+ ZEN_ERROR("HttpAddUrlToUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
return;
}
@@ -850,17 +849,17 @@ HttpSysServer::UnregisterService(const char* UrlPath, HttpService& Service)
++UrlPath;
}
- const std::wstring Path16 = UTF8_to_wstring(UrlPath);
+ const std::wstring PathUtf16 = UTF8_to_UTF16(UrlPath);
// Convert to wide string
- std::wstring Url16 = m_BaseUri + Path16;
+ std::wstring Url16 = m_BaseUri + PathUtf16;
ULONG Result = HttpRemoveUrlFromUrlGroup(m_HttpUrlGroupId, Url16.c_str(), 0);
if (Result != NO_ERROR)
{
- ZEN_ERROR("HttpRemoveUrlFromUrlGroup failed with result {}", Result);
+ ZEN_ERROR("HttpRemoveUrlFromUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
}
}
@@ -1269,7 +1268,7 @@ InitialRequestHandler::IssueRequest(std::error_code& ErrorCode)
ErrorCode = MakeErrorCode(HttpApiResult);
- ZEN_ERROR("HttpReceiveHttpRequest failed, error {}", ErrorCode.message());
+ ZEN_ERROR("HttpReceiveHttpRequest failed, error: '{}'", ErrorCode.message());
return;
}
@@ -1293,7 +1292,7 @@ InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesT
break;
}
- // Route requests
+ // Route request
try
{
@@ -1400,28 +1399,26 @@ InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesT
m_CurrentPayloadOffset += NumberOfBytesTransferred;
}
- if (m_CurrentPayloadOffset == m_ContentLength)
+ if (m_CurrentPayloadOffset != m_ContentLength)
{
- m_PayloadBuffer.MakeImmutable();
+ // Body not complete, issue another read request to receive more body data
+ return this;
+ }
- // Body received completely - call request handler
+ // Request body received completely
- HttpSysServerRequest& ThisRequest = Transaction().InvokeRequestHandler(*Service, m_PayloadBuffer);
+ m_PayloadBuffer.MakeImmutable();
- if (!ThisRequest.IsHandled())
- {
- return new HttpMessageResponseRequest(Transaction(), 404, "Not found"sv);
- }
+ HttpSysServerRequest& ThisRequest = Transaction().InvokeRequestHandler(*Service, m_PayloadBuffer);
- if (HttpMessageResponseRequest* Response = ThisRequest.m_Response)
- {
- return Response;
- }
+ if (!ThisRequest.IsHandled())
+ {
+ return new HttpMessageResponseRequest(Transaction(), 404, "Not found"sv);
}
- else
+
+ if (HttpMessageResponseRequest* Response = ThisRequest.m_Response)
{
- // Issue a read request for more body data
- return this;
+ return Response;
}
}
@@ -1430,7 +1427,7 @@ InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesT
}
catch (std::exception& ex)
{
- // TODO provide more meaningful error output
+ ZEN_ERROR("Caught exception while handling request: '{}'", ex.what());
return new HttpMessageResponseRequest(Transaction(), 500, ex.what());
}
diff --git a/zenhttp/include/zenhttp/httpcommon.h b/zenhttp/include/zenhttp/httpcommon.h
index 62070061c..3e213ece4 100644
--- a/zenhttp/include/zenhttp/httpcommon.h
+++ b/zenhttp/include/zenhttp/httpcommon.h
@@ -19,7 +19,7 @@ class StringBuilderBase;
std::string_view MapContentTypeToString(HttpContentType ContentType);
extern HttpContentType (*ParseContentType)(const std::string_view& ContentTypeString);
-const char* ReasonStringForHttpResultCode(int HttpCode);
+std::string_view ReasonStringForHttpResultCode(int HttpCode);
[[nodiscard]] inline bool
IsHttpSuccessCode(int HttpCode)