mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-26 12:24:46 +00:00
Self-host the httpbin auth-testing backend for BaseAuthTest/DigestAuthTest
These tests exercise the squid proxies by hitting /basic-auth and /digest-auth on an external httpbin-style site. That site's identity has already moved twice (httpbin.org -> httpcan.org, per #2300) chasing uptime, and httpcan.org itself is now down (Cloudflare 502 from its origin), failing CI with no code change involved. Adds two containers to the existing squid docker-compose stack instead: go-httpbin (mccutchen/go-httpbin) as the backend, and an nginx sidecar in front of it under the single "httpbin" hostname so both the NoSSL tests (port 80) and the SSL tests, which CONNECT-tunnel through the proxy to port 443, resolve the same name -- go-httpbin only listens on one port at a time, so it can't serve both protocols itself. nginx uses the repo's existing self-signed test cert; the SSL client tests already disable verification for it like other self-signed-cert tests in this suite. go-httpbin was picked over the more feature-complete kennethreitz/httpbin after finding the latter accepts a wrong digest-auth username as long as the password matches -- confirmed with a direct curl against the container, unrelated to anything in this repo. go-httpbin correctly rejects both. The trade-off is losing SHA-512 digest-auth coverage here, since go-httpbin only implements MD5 and SHA-256; nothing else in the suite exercises SHA-512 digest auth against a live server. Response body assertions are adjusted to go-httpbin's actual JSON shape (an added "authorized" field, no "algorithm" field), and the domain changes from httpcan.org to the self-hosted "httpbin". This only affects 'make proxy'/'make proxy_mbedtls'/'make proxy_wolfssl' and the Proxy Test CI workflow -- the default 'make' target is untouched.
This commit is contained in:
1 parent
f83d06538b
commit
88956ccad8
3 files changed
+59
-12
No files matched your search
@@ -18,3 +18,24 @@ services:
|
|||||||
context: ./
|
context: ./
|
||||||
args:
|
args:
|
||||||
auth: digest
|
auth: digest
|
||||||
|
|
||||||
|
# Self-hosted stand-in for the httpbin.org-style auth-testing endpoints
|
||||||
|
# (/basic-auth, /digest-auth) that BaseAuthTest/DigestAuthTest exercise
|
||||||
|
# through the proxies above, so those tests don't depend on an external
|
||||||
|
# site's uptime.
|
||||||
|
httpbin_backend:
|
||||||
|
image: mccutchen/go-httpbin:latest
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
# TLS termination in front of httpbin_backend (which only speaks plain
|
||||||
|
# HTTP) so the SSL variants of those tests can CONNECT-tunnel through the
|
||||||
|
# proxies to "httpbin" on port 443, same as the NoSSL variants do on 80.
|
||||||
|
httpbin:
|
||||||
|
image: nginx:alpine
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- httpbin_backend
|
||||||
|
volumes:
|
||||||
|
- ./httpbin_nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
- ../cert.pem:/etc/nginx/certs/cert.pem:ro
|
||||||
|
- ../key.pem:/etc/nginx/certs/key.pem:ro
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name httpbin;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://httpbin_backend:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name httpbin;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://httpbin_backend:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-12
@@ -173,7 +173,8 @@ template <typename T> void BaseAuthTestFromHTTPWatch(T &cli) {
|
|||||||
cli.Get("/basic-auth/hello/world",
|
cli.Get("/basic-auth/hello/world",
|
||||||
Headers{make_basic_authentication_header("hello", "world")});
|
Headers{make_basic_authentication_header("hello", "world")});
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\"}\n"),
|
EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\","
|
||||||
|
"\"authorized\":true}\n"),
|
||||||
normalizeJson(res->body));
|
normalizeJson(res->body));
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@@ -182,7 +183,8 @@ template <typename T> void BaseAuthTestFromHTTPWatch(T &cli) {
|
|||||||
cli.set_basic_auth("hello", "world");
|
cli.set_basic_auth("hello", "world");
|
||||||
auto res = cli.Get("/basic-auth/hello/world");
|
auto res = cli.Get("/basic-auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\"}\n"),
|
EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\","
|
||||||
|
"\"authorized\":true}\n"),
|
||||||
normalizeJson(res->body));
|
normalizeJson(res->body));
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@@ -203,13 +205,14 @@ template <typename T> void BaseAuthTestFromHTTPWatch(T &cli) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(BaseAuthTest, NoSSL) {
|
TEST(BaseAuthTest, NoSSL) {
|
||||||
Client cli("httpcan.org");
|
Client cli("httpbin");
|
||||||
BaseAuthTestFromHTTPWatch(cli);
|
BaseAuthTestFromHTTPWatch(cli);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_SSL_ENABLED
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
||||||
TEST(BaseAuthTest, SSL) {
|
TEST(BaseAuthTest, SSL) {
|
||||||
SSLClient cli("httpcan.org");
|
SSLClient cli("httpbin");
|
||||||
|
cli.enable_server_certificate_verification(false);
|
||||||
BaseAuthTestFromHTTPWatch(cli);
|
BaseAuthTestFromHTTPWatch(cli);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -228,21 +231,21 @@ template <typename T> void DigestAuthTestFromHTTPWatch(T &cli) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// go-httpbin (the "httpbin" test double) only implements MD5 and
|
||||||
|
// SHA-256 for digest auth, so SHA-256 is as far as this can exercise
|
||||||
|
// the client's digest-auth algorithm selection end-to-end.
|
||||||
std::vector<std::string> paths = {
|
std::vector<std::string> paths = {
|
||||||
"/digest-auth/auth/hello/world/MD5",
|
"/digest-auth/auth/hello/world/MD5",
|
||||||
"/digest-auth/auth/hello/world/SHA-256",
|
"/digest-auth/auth/hello/world/SHA-256",
|
||||||
"/digest-auth/auth/hello/world/SHA-512",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cli.set_digest_auth("hello", "world");
|
cli.set_digest_auth("hello", "world");
|
||||||
for (auto path : paths) {
|
for (auto path : paths) {
|
||||||
auto res = cli.Get(path.c_str());
|
auto res = cli.Get(path.c_str());
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
std::string algo(path.substr(path.rfind('/') + 1));
|
EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\","
|
||||||
EXPECT_EQ(
|
"\"authorized\":true}\n"),
|
||||||
normalizeJson("{\"algorithm\":\"" + algo +
|
normalizeJson(res->body));
|
||||||
"\",\"authenticated\":true,\"user\":\"hello\"}\n"),
|
|
||||||
normalizeJson(res->body));
|
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,12 +266,13 @@ template <typename T> void DigestAuthTestFromHTTPWatch(T &cli) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(DigestAuthTest, SSL) {
|
TEST(DigestAuthTest, SSL) {
|
||||||
SSLClient cli("httpcan.org");
|
SSLClient cli("httpbin");
|
||||||
|
cli.enable_server_certificate_verification(false);
|
||||||
DigestAuthTestFromHTTPWatch(cli);
|
DigestAuthTestFromHTTPWatch(cli);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DigestAuthTest, NoSSL) {
|
TEST(DigestAuthTest, NoSSL) {
|
||||||
Client cli("httpcan.org");
|
Client cli("httpbin");
|
||||||
DigestAuthTestFromHTTPWatch(cli);
|
DigestAuthTestFromHTTPWatch(cli);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in new issue
Block a user