aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/httpsys.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-09-28 15:48:00 +0200
committerGitHub <[email protected]>2023-09-28 15:48:00 +0200
commit6bedc99f75d00ccf2cabaf10c95e7588e01c509f (patch)
treeb8e53e7437fc8acce9d8e97d8950dbe94ea2a6d6 /src/zenhttp/httpsys.cpp
parentprefer to handle cache RPC requests synchronously (#428) (diff)
downloadzen-6bedc99f75d00ccf2cabaf10c95e7588e01c509f.tar.xz
zen-6bedc99f75d00ccf2cabaf10c95e7588e01c509f.zip
added more context to http response error message (#430)
when a http.sys request response API call fails, we now include more information including metadata about the contents of the reponse (i.e memory/file references including file names/size and chunk offsets/size) to help track down some odd error conditions seen in production
Diffstat (limited to 'src/zenhttp/httpsys.cpp')
-rw-r--r--src/zenhttp/httpsys.cpp87
1 files changed, 77 insertions, 10 deletions
diff --git a/src/zenhttp/httpsys.cpp b/src/zenhttp/httpsys.cpp
index 886d53143..4d9a3e5b8 100644
--- a/src/zenhttp/httpsys.cpp
+++ b/src/zenhttp/httpsys.cpp
@@ -6,6 +6,8 @@
#include <zencore/compactbinarybuilder.h>
#include <zencore/compactbinarypackage.h>
#include <zencore/except.h>
+#include <zencore/filesystem.h>
+#include <zencore/fmtutils.h>
#include <zencore/logging.h>
#include <zencore/scopeguard.h>
#include <zencore/string.h>
@@ -220,7 +222,7 @@ public:
kRequestPending
};
- Status HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred);
+ [[nodiscard]] Status HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred);
static void __stdcall IoCompletionCallback(PTP_CALLBACK_INSTANCE Instance,
PVOID pContext /* HttpSysServer */,
@@ -380,8 +382,7 @@ HttpMessageResponseRequest::InitializeForPayload(uint16_t ResponseCode, std::spa
{
// Use direct file transfer
- m_HttpDataChunks.push_back({});
- auto& Chunk = m_HttpDataChunks.back();
+ auto& Chunk = m_HttpDataChunks.emplace_back();
Chunk.DataChunkType = HttpDataChunkFromFileHandle;
Chunk.FromFileHandle.FileHandle = FileRef.FileHandle;
@@ -402,8 +403,7 @@ HttpMessageResponseRequest::InitializeForPayload(uint16_t ResponseCode, std::spa
{
const ULONG ThisChunkSize = gsl::narrow<ULONG>(zen::Min(1 * 1024 * 1024 * 1024, BufferDataSize));
- m_HttpDataChunks.push_back({});
- auto& Chunk = m_HttpDataChunks.back();
+ auto& Chunk = m_HttpDataChunks.emplace_back();
Chunk.DataChunkType = HttpDataChunkFromMemory;
Chunk.FromMemory.pBuffer = (void*)WriteCursor;
@@ -593,6 +593,65 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
);
}
+ auto EmitReponseDetails = [&](StringBuilderBase& ResponseDetails) -> void {
+ for (int i = 0; i < ThisRequestChunkCount; ++i)
+ {
+ const HTTP_DATA_CHUNK Chunk = m_HttpDataChunks[ThisRequestChunkOffset + i];
+
+ if (i > 0)
+ {
+ ResponseDetails << " + ";
+ }
+
+ switch (Chunk.DataChunkType)
+ {
+ case HttpDataChunkFromMemory:
+ ResponseDetails << "mem:" << uint64_t(Chunk.FromMemory.BufferLength);
+ break;
+
+ case HttpDataChunkFromFileHandle:
+ ResponseDetails << "file:";
+ {
+ ResponseDetails << uint64_t(Chunk.FromFileHandle.ByteRange.StartingOffset.QuadPart) << ","
+ << uint64_t(Chunk.FromFileHandle.ByteRange.Length.QuadPart) << ",";
+
+ std::error_code PathEc;
+ HANDLE FileHandle = Chunk.FromFileHandle.FileHandle;
+ std::filesystem::path Path = PathFromHandle(FileHandle, PathEc);
+
+ if (PathEc)
+ {
+ ResponseDetails << "bad_file(" << PathEc.message() << ")";
+ }
+ else
+ {
+ const uint64_t FileSize = FileSizeFromHandle(FileHandle);
+ ResponseDetails << Path.u8string() << "(" << FileSize << ")";
+ }
+ }
+ break;
+
+ case HttpDataChunkFromFragmentCache:
+ ResponseDetails << "frag:???"; // We do not use these
+ break;
+
+ case HttpDataChunkFromFragmentCacheEx:
+ ResponseDetails << "frax:???"; // We do not use these
+ break;
+
+# if 0 // Not available in older Windows SDKs
+ case HttpDataChunkTrailers:
+ ResponseDetails << "trls:???"; // We do not use these
+ break;
+# endif
+
+ default:
+ ResponseDetails << "???: " << Chunk.DataChunkType;
+ break;
+ }
+ }
+ };
+
if (SendResult == NO_ERROR)
{
// Synchronous completion, but the completion event will still be posted to IOCP
@@ -607,16 +666,24 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
}
else
{
+ ErrorCode = MakeErrorCode(SendResult);
+
// An error occurred, no completion will be posted to IOCP
CancelThreadpoolIo(Iocp);
- ZEN_WARN("failed to send HTTP response (error: '{}'), request URL: '{}', request id: {}",
- GetSystemErrorAsString(SendResult),
- HttpReq->pRawUrl,
- HttpReq->RequestId);
+ // Emit diagnostics
- ErrorCode = MakeErrorCode(SendResult);
+ ExtendableStringBuilder<256> ResponseDetails;
+ EmitReponseDetails(ResponseDetails);
+
+ ZEN_WARN("failed to send HTTP response (error {}: '{}'), request URL: '{}', ({}.{}) response: {}",
+ SendResult,
+ ErrorCode.message(),
+ HttpReq->pRawUrl,
+ Tx.ServerRequest().SessionId(),
+ HttpReq->RequestId,
+ ResponseDetails);
}
}