@@ -133,6 +133,23 @@ struct arguments_accumulator {
133133namespace detail {
134134
135135std::string_view http_request_impl::get_connection_value (std::string_view key, MHD_ValueKind kind) const {
136+ // Test-request path: connection_ is null, fall back to local storage.
137+ if (connection_ == nullptr ) {
138+ const auto * map = [&]() -> const http::header_map* {
139+ switch (kind) {
140+ case MHD_HEADER_KIND: return &headers_local;
141+ case MHD_FOOTER_KIND: return &footers_local;
142+ case MHD_COOKIE_KIND: return &cookies_local;
143+ default : return nullptr ;
144+ }
145+ }();
146+ if (map != nullptr ) {
147+ auto it = map->find (std::string (key));
148+ if (it != map->end ()) return it->second ;
149+ }
150+ return http_request::EMPTY;
151+ }
152+
136153 const char * header_c = MHD_lookup_connection_value (connection_, kind, key.data ());
137154
138155 if (header_c == nullptr ) return http_request::EMPTY;
@@ -153,6 +170,24 @@ MHD_Result http_request_impl::build_request_header(void* cls, MHD_ValueKind kind
153170http::header_view_map http_request_impl::get_headerlike_values (MHD_ValueKind kind) const {
154171 http::header_view_map headers;
155172
173+ // Test-request path: connection_ is null, build view map from local storage.
174+ if (connection_ == nullptr ) {
175+ const auto * map = [&]() -> const http::header_map* {
176+ switch (kind) {
177+ case MHD_HEADER_KIND: return &headers_local;
178+ case MHD_FOOTER_KIND: return &footers_local;
179+ case MHD_COOKIE_KIND: return &cookies_local;
180+ default : return nullptr ;
181+ }
182+ }();
183+ if (map != nullptr ) {
184+ for (const auto & [k, v] : *map) {
185+ headers[k] = v;
186+ }
187+ }
188+ return headers;
189+ }
190+
156191 MHD_get_connection_values (connection_, kind, &http_request_impl::build_request_header,
157192 reinterpret_cast <void *>(&headers));
158193
@@ -197,6 +232,11 @@ void http_request_impl::populate_args() const {
197232 if (args_populated) {
198233 return ;
199234 }
235+ // Test-request path: connection_ is null, args already set directly.
236+ if (connection_ == nullptr ) {
237+ args_populated = true ;
238+ return ;
239+ }
200240 arguments_accumulator aa;
201241 aa.unescaper = unescaper_;
202242 aa.arguments = &unescaped_args;
@@ -252,6 +292,10 @@ void http_request_impl::grow_last_arg(const std::string& key, const std::string&
252292
253293#ifdef HAVE_BAUTH
254294void http_request_impl::fetch_user_pass () const {
295+ // Test-request path: connection_ is null, credentials already set.
296+ if (connection_ == nullptr ) {
297+ return ;
298+ }
255299 struct MHD_BasicAuthInfo * info = MHD_basic_auth_get_username_password3 (connection_);
256300
257301 if (info != nullptr ) {
@@ -266,6 +310,10 @@ void http_request_impl::fetch_user_pass() const {
266310
267311#ifdef HAVE_GNUTLS
268312bool http_request_impl::has_tls_session () const {
313+ // Test-request path: connection_ is null, return the local flag.
314+ if (connection_ == nullptr ) {
315+ return tls_enabled_local;
316+ }
269317 const MHD_ConnectionInfo* conninfo = MHD_get_connection_info (connection_, MHD_CONNECTION_INFO_GNUTLS_SESSION);
270318 return (conninfo != nullptr );
271319}
@@ -514,6 +562,8 @@ http_arg_value http_request::get_arg(std::string_view key) const {
514562}
515563
516564std::string_view http_request::get_arg_flat (std::string_view key) const {
565+ impl_->populate_args ();
566+
517567 auto const it = impl_->unescaped_args .find (key);
518568
519569 if (it != impl_->unescaped_args .end ()) {
@@ -558,6 +608,11 @@ std::string_view http_request::get_querystring() const {
558608 return impl_->querystring ;
559609 }
560610
611+ // Test-request path: connection_ is null, querystring already set (or empty).
612+ if (impl_->connection_ == nullptr ) {
613+ return impl_->querystring ;
614+ }
615+
561616 MHD_get_connection_values (impl_->connection_ , MHD_GET_ARGUMENT_KIND,
562617 &detail::http_request_impl::build_request_querystring,
563618 reinterpret_cast <void *>(&impl_->querystring ));
@@ -589,6 +644,11 @@ std::string_view http_request::get_digested_user() const {
589644 return impl_->digested_user ;
590645 }
591646
647+ // Test-request path: connection_ is null, digested_user already set.
648+ if (impl_->connection_ == nullptr ) {
649+ return impl_->digested_user ;
650+ }
651+
592652 struct MHD_DigestAuthUsernameInfo * info = MHD_digest_auth_get_username3 (impl_->connection_ );
593653
594654 impl_->digested_user = EMPTY;
@@ -657,15 +717,33 @@ std::string_view http_request::get_requestor() const {
657717 return impl_->requestor_ip ;
658718 }
659719
720+ // Test-request path: connection_ is null, requestor_ip already set.
721+ if (impl_->connection_ == nullptr ) {
722+ return impl_->requestor_ip ;
723+ }
724+
660725 const MHD_ConnectionInfo* conninfo = MHD_get_connection_info (impl_->connection_ , MHD_CONNECTION_INFO_CLIENT_ADDRESS);
661726
727+ if (conninfo == nullptr ) {
728+ return EMPTY;
729+ }
730+
662731 impl_->requestor_ip = http::get_ip_str (conninfo->client_addr );
663732 return impl_->requestor_ip ;
664733}
665734
666735uint16_t http_request::get_requestor_port () const {
736+ // Test-request path: connection_ is null, use local port.
737+ if (impl_->connection_ == nullptr ) {
738+ return impl_->requestor_port_local ;
739+ }
740+
667741 const MHD_ConnectionInfo* conninfo = MHD_get_connection_info (impl_->connection_ , MHD_CONNECTION_INFO_CLIENT_ADDRESS);
668742
743+ if (conninfo == nullptr ) {
744+ return 0 ;
745+ }
746+
669747 return http::get_port (conninfo->client_addr );
670748}
671749
0 commit comments