aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/include
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2025-09-29 10:36:32 +0200
committerGitHub Enterprise <[email protected]>2025-09-29 10:36:32 +0200
commit2f0efec7ab0430f4f4858db87b7eecfbccc0f47c (patch)
tree80ce35992a220260cf070fac739626f555de738a /src/zenhttp/include
parentfixed race condition in zen::logging::Get (#519) (diff)
downloadzen-2f0efec7ab0430f4f4858db87b7eecfbccc0f47c.tar.xz
zen-2f0efec7ab0430f4f4858db87b7eecfbccc0f47c.zip
make cpr a HttpClient implementation detail (#517)
these changes remove cpr from anything which is not `HttpClient` internals. The goal is to eventually replace cpr with a more direct curl interface to eliminate cpr since it's proven problematic due to their development practices which frequently breaks APIs and prevents us from updating vcpkg. But this PR is limited to refactoring existing cpr code to use `HttpClient` instead.
Diffstat (limited to 'src/zenhttp/include')
-rw-r--r--src/zenhttp/include/zenhttp/cprutils.h86
-rw-r--r--src/zenhttp/include/zenhttp/formatters.h71
-rw-r--r--src/zenhttp/include/zenhttp/httpclient.h28
3 files changed, 114 insertions, 71 deletions
diff --git a/src/zenhttp/include/zenhttp/cprutils.h b/src/zenhttp/include/zenhttp/cprutils.h
new file mode 100644
index 000000000..a3b870c0f
--- /dev/null
+++ b/src/zenhttp/include/zenhttp/cprutils.h
@@ -0,0 +1,86 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/compactbinary.h>
+#include <zencore/compactbinaryvalidation.h>
+#include <zencore/iobuffer.h>
+#include <zencore/string.h>
+#include <zenhttp/formatters.h>
+#include <zenhttp/httpclient.h>
+#include <zenhttp/httpcommon.h>
+
+ZEN_THIRD_PARTY_INCLUDES_START
+#include <cpr/response.h>
+#include <fmt/format.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+
+template<>
+struct fmt::formatter<cpr::Response>
+{
+ constexpr auto parse(format_parse_context& Ctx) -> decltype(Ctx.begin()) { return Ctx.end(); }
+
+ template<typename FormatContext>
+ auto format(const cpr::Response& Response, FormatContext& Ctx) const -> decltype(Ctx.out())
+ {
+ using namespace std::literals;
+
+ zen::NiceTimeSpanMs NiceResponseTime(uint64_t(Response.elapsed * 1000));
+
+ if (zen::IsHttpSuccessCode(Response.status_code))
+ {
+ return fmt::format_to(Ctx.out(),
+ "Url: {}, Status: {}, Error: '{}' ({}), Bytes: {}/{} (Up/Down), Elapsed: {}",
+ Response.url.str(),
+ Response.status_code,
+ Response.error.message,
+ int(Response.error.code),
+ Response.uploaded_bytes,
+ Response.downloaded_bytes,
+ NiceResponseTime.c_str());
+ }
+ else
+ {
+ const auto It = Response.header.find("Content-Type");
+ const std::string_view ContentType = It != Response.header.end() ? It->second : "<None>"sv;
+
+ if (ContentType == "application/x-ue-cb"sv)
+ {
+ zen::IoBuffer Body(zen::IoBuffer::Wrap, Response.text.data(), Response.text.size());
+ zen::CbObjectView Obj(Body.Data());
+ zen::ExtendableStringBuilder<256> Sb;
+ std::string_view Json = Obj.ToJson(Sb).ToView();
+
+ return fmt::format_to(
+ Ctx.out(),
+ "Url: {}, Status: {}, Error: '{}' ({}). Bytes: {}/{} (Up/Down), Elapsed: {}, Response: '{}', Reason: '{}'",
+ Response.url.str(),
+ Response.status_code,
+ Response.error.message,
+ int(Response.error.code),
+ Response.uploaded_bytes,
+ Response.downloaded_bytes,
+ NiceResponseTime.c_str(),
+ Json,
+ Response.reason);
+ }
+ else
+ {
+ zen::BodyLogFormatter Body(Response.text);
+
+ return fmt::format_to(
+ Ctx.out(),
+ "Url: {}, Status: {}, Error: '{}' ({}), Bytes: {}/{} (Up/Down), Elapsed: {}, Response: '{}', Reason: '{}'",
+ Response.url.str(),
+ Response.status_code,
+ Response.error.message,
+ int(Response.error.code),
+ Response.uploaded_bytes,
+ Response.downloaded_bytes,
+ NiceResponseTime.c_str(),
+ Body.GetText(),
+ Response.reason);
+ }
+ }
+ }
+};
diff --git a/src/zenhttp/include/zenhttp/formatters.h b/src/zenhttp/include/zenhttp/formatters.h
index 05a23d675..0af31fa30 100644
--- a/src/zenhttp/include/zenhttp/formatters.h
+++ b/src/zenhttp/include/zenhttp/formatters.h
@@ -10,7 +10,6 @@
#include <zenhttp/httpcommon.h>
ZEN_THIRD_PARTY_INCLUDES_START
-#include <cpr/cpr.h>
#include <fmt/format.h>
ZEN_THIRD_PARTY_INCLUDES_END
@@ -59,76 +58,6 @@ public:
} // namespace zen
template<>
-struct fmt::formatter<cpr::Response>
-{
- constexpr auto parse(format_parse_context& Ctx) -> decltype(Ctx.begin()) { return Ctx.end(); }
-
- template<typename FormatContext>
- auto format(const cpr::Response& Response, FormatContext& Ctx) const -> decltype(Ctx.out())
- {
- using namespace std::literals;
-
- zen::NiceTimeSpanMs NiceResponseTime(uint64_t(Response.elapsed * 1000));
-
- if (zen::IsHttpSuccessCode(Response.status_code))
- {
- return fmt::format_to(Ctx.out(),
- "Url: {}, Status: {}, Error: '{}' ({}), Bytes: {}/{} (Up/Down), Elapsed: {}",
- Response.url.str(),
- Response.status_code,
- Response.error.message,
- int(Response.error.code),
- Response.uploaded_bytes,
- Response.downloaded_bytes,
- NiceResponseTime.c_str());
- }
- else
- {
- const auto It = Response.header.find("Content-Type");
- const std::string_view ContentType = It != Response.header.end() ? It->second : "<None>"sv;
-
- if (ContentType == "application/x-ue-cb"sv)
- {
- zen::IoBuffer Body(zen::IoBuffer::Wrap, Response.text.data(), Response.text.size());
- zen::CbObjectView Obj(Body.Data());
- zen::ExtendableStringBuilder<256> Sb;
- std::string_view Json = Obj.ToJson(Sb).ToView();
-
- return fmt::format_to(
- Ctx.out(),
- "Url: {}, Status: {}, Error: '{}' ({}). Bytes: {}/{} (Up/Down), Elapsed: {}, Response: '{}', Reason: '{}'",
- Response.url.str(),
- Response.status_code,
- Response.error.message,
- int(Response.error.code),
- Response.uploaded_bytes,
- Response.downloaded_bytes,
- NiceResponseTime.c_str(),
- Json,
- Response.reason);
- }
- else
- {
- zen::BodyLogFormatter Body(Response.text);
-
- return fmt::format_to(
- Ctx.out(),
- "Url: {}, Status: {}, Error: '{}' ({}), Bytes: {}/{} (Up/Down), Elapsed: {}, Response: '{}', Reason: '{}'",
- Response.url.str(),
- Response.status_code,
- Response.error.message,
- int(Response.error.code),
- Response.uploaded_bytes,
- Response.downloaded_bytes,
- NiceResponseTime.c_str(),
- Body.GetText(),
- Response.reason);
- }
- }
- }
-};
-
-template<>
struct fmt::formatter<zen::HttpClient::Response>
{
constexpr auto parse(format_parse_context& Ctx) -> decltype(Ctx.begin()) { return Ctx.end(); }
diff --git a/src/zenhttp/include/zenhttp/httpclient.h b/src/zenhttp/include/zenhttp/httpclient.h
index 50bd5b53a..ec06aa229 100644
--- a/src/zenhttp/include/zenhttp/httpclient.h
+++ b/src/zenhttp/include/zenhttp/httpclient.h
@@ -76,6 +76,34 @@ public:
{
}
+ inline int GetInternalErrorCode() const { return m_Error; }
+ inline HttpResponseCode GetHttpResponseCode() const { return m_ResponseCode; }
+
+ enum class ResponseClass : std::int8_t
+ {
+ kSuccess = 0,
+
+ kHttpOtherClientError = 80,
+ kHttpCantConnectError = 81, // CONNECTION_FAILURE
+ kHttpNotFound = 66, // NotFound(404)
+ kHttpUnauthorized = 77, // Unauthorized(401),
+ kHttpSLLError =
+ 82, // SSL_CONNECT_ERROR, SSL_LOCAL_CERTIFICATE_ERROR, SSL_REMOTE_CERTIFICATE_ERROR, SSL_CACERT_ERROR, GENERIC_SSL_ERROR
+ kHttpForbidden = 83, // Forbidden(403)
+ kHttpTimeout = 84, // NETWORK_RECEIVE_ERROR, NETWORK_SEND_FAILURE, OPERATION_TIMEDOUT, RequestTimeout(408)
+ kHttpConflict = 85, // Conflict(409)
+ kHttpNoHost = 86, // HOST_RESOLUTION_FAILURE, PROXY_RESOLUTION_FAILURE
+
+ kHttpOtherServerError = 90,
+ kHttpInternalServerError = 91, // InternalServerError(500)
+ kHttpServiceUnavailable = 69, // ServiceUnavailable(503)
+ kHttpBadGateway = 92, // BadGateway(502)
+ kHttpGatewayTimeout = 93, // GatewayTimeout(504)
+ };
+
+ ResponseClass GetResponseClass() const;
+
+private:
const int m_Error = 0;
const HttpResponseCode m_ResponseCode = HttpResponseCode::ImATeapot;
};