diff --git a/include/ircd/server/request.h b/include/ircd/server/request.h index 7215dbea2..66fbcae69 100644 --- a/include/ircd/server/request.h +++ b/include/ircd/server/request.h @@ -42,6 +42,11 @@ struct ircd::server::out /// written so far. This is only invoked for content. At the first /// invocation, the head has been fully written. std::function progress; + + /// Call server::out::gethead(request) to extract the details of the HTTP + /// request being sent by the request. This may not always be available, + /// like in some cases after the request was canceled. + static http::request::head gethead(const request &); }; /// Request data and options related to the receive side of the request. @@ -78,6 +83,11 @@ struct ircd::server::in /// copied there; this vector is cleared and content points there instead. /// An option can be set in request::opts to skip the last step. std::vector> chunks; + + /// Call server::in::gethead(request) to extract the details of the HTTP + /// response being received by the request. This may not always be + /// available if it has not been received or was discarded etc. + static http::response::head gethead(const request &); }; /// This is a handle for being a client to another server. This handle will diff --git a/ircd/server.cc b/ircd/server.cc index 6d60f7b76..b72e1becd 100644 --- a/ircd/server.cc +++ b/ircd/server.cc @@ -348,14 +348,11 @@ try if(request.tag && request.tag->cancellation) return ""; - parse::buffer pb{request.out.head}; - parse::capstan pc{pb, [](char *&read, char *stop) + const http::request::head head { - read = stop; - }}; + request.out.gethead(request) + }; - pc.read += size(request.out.head); - const http::request::head head{pc}; if(!head.method || !head.path) return ""; @@ -371,7 +368,7 @@ catch(const std::exception &e) log, "server::loghead(): %s", e.what() }; - return ""; + return ""; } ircd::string_view @@ -381,6 +378,72 @@ ircd::server::loghead(const request &request) return loghead(buf, request); } +// +// server::in +// + +ircd::http::response::head +ircd::server::in::gethead(const request &request) +try +{ + if(empty(request.in.head)) + return {}; + + if(request.tag && request.tag->cancellation) + return {}; + + parse::buffer pb{request.in.head}; + parse::capstan pc{pb, [](char *&read, char *stop) + { + read = stop; + }}; + + pc.read += size(request.in.head); + return http::response::head{pc}; +} +catch(const std::exception &e) +{ + log::critical + { + log, "server::in::gethead(): %s", e.what() + }; + + return {}; +} + +// +// server::out +// + +ircd::http::request::head +ircd::server::out::gethead(const request &request) +try +{ + if(empty(request.out.head)) + return {}; + + if(request.tag && request.tag->cancellation) + return {}; + + parse::buffer pb{request.out.head}; + parse::capstan pc{pb, [](char *&read, char *stop) + { + read = stop; + }}; + + pc.read += size(request.out.head); + return http::request::head{pc}; +} +catch(const std::exception &e) +{ + log::critical + { + log, "server::out::gethead(): %s", e.what() + }; + + return {}; +} + /////////////////////////////////////////////////////////////////////////////// // // server/peer.h