mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-09 16:52:52 +07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00afaaed6a | ||
|
|
e803f5e413 | ||
|
|
57b8aca6da | ||
|
|
213029685a |
@@ -230,7 +230,7 @@ cpp-httplib automatically integrates with the OS certificate store on macOS and
|
|||||||
| Platform | Behavior | Disable (compile time) |
|
| Platform | Behavior | Disable (compile time) |
|
||||||
| :------- | :------- | :--------------------- |
|
| :------- | :------- | :--------------------- |
|
||||||
| macOS | Loads system certs from Keychain (link `CoreFoundation` and `Security` with `-framework`). Requires Apple Clang; GCC is not supported for this feature. | `CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES` |
|
| macOS | Loads system certs from Keychain (link `CoreFoundation` and `Security` with `-framework`). Requires Apple Clang; GCC is not supported for this feature. | `CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES` |
|
||||||
| Windows | Verifies the certificate chain with CryptoAPI (`CertGetCertificateChain` / `CertVerifyCertificateChainPolicy`) instead of the TLS backend, with revocation checking. Windows fetches missing roots and intermediates on demand. With a custom CA, the TLS backend verifies the chain instead; with `set_server_certificate_verifier()`, both do. | `CPPHTTPLIB_DISABLE_WINDOWS_AUTOMATIC_ROOT_CERTIFICATES_UPDATE` |
|
| Windows | Verifies the certificate chain with CryptoAPI (`CertGetCertificateChain` / `CertVerifyCertificateChainPolicy`) instead of the TLS backend. Revocation checking is best-effort: a revoked server certificate is rejected, while one whose revocation status cannot be determined is accepted. Windows fetches missing roots and intermediates on demand. With a custom CA, the TLS backend verifies the chain instead; with `set_server_certificate_verifier()`, both do. | `CPPHTTPLIB_DISABLE_WINDOWS_AUTOMATIC_ROOT_CERTIFICATES_UPDATE` |
|
||||||
|
|
||||||
On Windows, verification can also be disabled at runtime:
|
On Windows, verification can also be disabled at runtime:
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ langs = ["en", "ja"]
|
|||||||
|
|
||||||
[site]
|
[site]
|
||||||
title = "cpp-httplib"
|
title = "cpp-httplib"
|
||||||
version = "0.60.0"
|
version = "0.60.1"
|
||||||
hostname = "https://yhirose.github.io"
|
hostname = "https://yhirose.github.io"
|
||||||
base_path = "/cpp-httplib"
|
base_path = "/cpp-httplib"
|
||||||
footer_message = "© 2026 Yuji Hirose. All rights reserved."
|
footer_message = "© 2026 Yuji Hirose. All rights reserved."
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
#ifndef CPPHTTPLIB_HTTPLIB_H
|
#ifndef CPPHTTPLIB_HTTPLIB_H
|
||||||
#define CPPHTTPLIB_HTTPLIB_H
|
#define CPPHTTPLIB_HTTPLIB_H
|
||||||
|
|
||||||
#define CPPHTTPLIB_VERSION "0.60.0"
|
#define CPPHTTPLIB_VERSION "0.60.1"
|
||||||
#define CPPHTTPLIB_VERSION_NUM "0x003c00"
|
#define CPPHTTPLIB_VERSION_NUM "0x003c01"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
|
||||||
@@ -4412,6 +4412,8 @@ private:
|
|||||||
|
|
||||||
namespace ws {
|
namespace ws {
|
||||||
|
|
||||||
|
class WebSocketClient;
|
||||||
|
|
||||||
enum class Opcode : uint8_t {
|
enum class Opcode : uint8_t {
|
||||||
Continuation = 0x0,
|
Continuation = 0x0,
|
||||||
Text = 0x1,
|
Text = 0x1,
|
||||||
@@ -4513,7 +4515,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class httplib::Server;
|
friend class httplib::Server;
|
||||||
friend class WebSocketClient;
|
friend class httplib::ws::WebSocketClient;
|
||||||
|
|
||||||
WebSocket(
|
WebSocket(
|
||||||
Stream &strm, const Request &req, bool is_server,
|
Stream &strm, const Request &req, bool is_server,
|
||||||
@@ -9910,8 +9912,10 @@ inline bool range_error(Request &req, Response &res) {
|
|||||||
last_pos = content_len;
|
last_pos = content_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RFC 9110 14.1.2: a suffix-length longer than the representation
|
||||||
|
// selects the entire representation.
|
||||||
if (first_pos == -1) {
|
if (first_pos == -1) {
|
||||||
first_pos = content_len - last_pos;
|
first_pos = (std::max)(static_cast<ssize_t>(0), content_len - last_pos);
|
||||||
last_pos = content_len - 1;
|
last_pos = content_len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10854,12 +10858,6 @@ inline bool verify_cert_with_windows_schannel(
|
|||||||
auto chain_guard =
|
auto chain_guard =
|
||||||
scope_exit([&] { CertFreeCertificateChain(chain_context); });
|
scope_exit([&] { CertFreeCertificateChain(chain_context); });
|
||||||
|
|
||||||
// Check if chain has errors
|
|
||||||
if (chain_context->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) {
|
|
||||||
out_error = chain_context->TrustStatus.dwErrorStatus;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify SSL policy
|
// Verify SSL policy
|
||||||
SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para = {};
|
SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para = {};
|
||||||
extra_policy_para.cbSize = sizeof(extra_policy_para);
|
extra_policy_para.cbSize = sizeof(extra_policy_para);
|
||||||
|
|||||||
+17
-6
@@ -7242,8 +7242,21 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
|
TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
|
||||||
|
// RFC 9110 14.1.2: a suffix-length longer than the representation selects
|
||||||
|
// the entire representation.
|
||||||
|
for (auto range : {"bytes=-8", "bytes=-9999"}) {
|
||||||
|
auto res = cli_.Get("/streamed-with-range", Headers{{"Range", range}});
|
||||||
|
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
||||||
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status) << range;
|
||||||
|
EXPECT_EQ("7", res->get_header_value("Content-Length")) << range;
|
||||||
|
EXPECT_EQ("bytes 0-6/7", res->get_header_value("Content-Range")) << range;
|
||||||
|
EXPECT_EQ(std::string("abcdefg"), res->body) << range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTest, GetStreamedWithRangeSuffixZero) {
|
||||||
auto res =
|
auto res =
|
||||||
cli_.Get("/streamed-with-range?error", Headers{{"Range", "bytes=-9999"}});
|
cli_.Get("/streamed-with-range?error", Headers{{"Range", "bytes=-0"}});
|
||||||
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
||||||
@@ -14176,9 +14189,8 @@ TEST(SSLClientTest, WindowsCertificateVerification_ServerIntermediates_Online) {
|
|||||||
<< " ssl_backend_error=" << res.ssl_backend_error();
|
<< " ssl_backend_error=" << res.ssl_backend_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows, not the backend, decides on the chain: the error carries a
|
// Windows, not the backend, decides on the chain: the error is a CryptoAPI
|
||||||
// CryptoAPI trust status, which no backend error for a self-signed
|
// policy status, which no backend reports for a self-signed certificate.
|
||||||
// certificate has.
|
|
||||||
TEST(SSLClientTest, WindowsCertificateVerification_RejectsUntrustedRoot) {
|
TEST(SSLClientTest, WindowsCertificateVerification_RejectsUntrustedRoot) {
|
||||||
SSLServer svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
|
SSLServer svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||||
ASSERT_TRUE(svr.is_valid());
|
ASSERT_TRUE(svr.is_valid());
|
||||||
@@ -14198,8 +14210,7 @@ TEST(SSLClientTest, WindowsCertificateVerification_RejectsUntrustedRoot) {
|
|||||||
auto res = cli.Get("/");
|
auto res = cli.Get("/");
|
||||||
ASSERT_FALSE(res);
|
ASSERT_FALSE(res);
|
||||||
EXPECT_EQ(Error::SSLServerVerification, res.error());
|
EXPECT_EQ(Error::SSLServerVerification, res.error());
|
||||||
EXPECT_NE(0u, res.ssl_backend_error() & CERT_TRUST_IS_UNTRUSTED_ROOT)
|
EXPECT_EQ(static_cast<DWORD>(CERT_E_UNTRUSTEDROOT), res.ssl_backend_error());
|
||||||
<< "ssl_backend_error=" << res.ssl_backend_error();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user