@@ -91,6 +91,32 @@ namespace vix::session
9191 return true ;
9292 }
9393
94+ task<bool > write_all (
95+ tcp_stream &stream,
96+ std::string_view data,
97+ vix::async::core::cancel_token token)
98+ {
99+ std::size_t written = 0 ;
100+
101+ while (written < data.size ())
102+ {
103+ const std::byte *ptr =
104+ reinterpret_cast <const std::byte *>(data.data () + written);
105+
106+ const std::size_t n = co_await stream.async_write (
107+ std::span<const std::byte>(ptr, data.size () - written),
108+ token);
109+
110+ if (n == 0 )
111+ {
112+ co_return false ;
113+ }
114+
115+ written += n;
116+ }
117+
118+ co_return true ;
119+ }
94120 inline bool is_close_connection (std::string_view value)
95121 {
96122 return equals_icase (value, " close" );
@@ -107,6 +133,7 @@ namespace vix::session
107133 return pos + 4 ;
108134 }
109135
136+ #ifdef VIX_BENCH_MODE
110137 inline bool raw_header_requests_close (std::string_view raw_header)
111138 {
112139 std::size_t line_start = 0 ;
@@ -153,6 +180,17 @@ namespace vix::session
153180 return false ;
154181 }
155182
183+ inline std::string_view strip_query_view (std::string_view target)
184+ {
185+ const auto q = target.find (' ?' );
186+ if (q == std::string_view::npos)
187+ {
188+ return target;
189+ }
190+
191+ return target.substr (0 , q);
192+ }
193+ #endif
156194 inline bool contains_token_icase (std::string_view text, std::string_view token)
157195 {
158196 if (token.empty ())
@@ -220,16 +258,6 @@ namespace vix::session
220258 return out;
221259 }
222260
223- inline std::string_view strip_query_view (std::string_view target)
224- {
225- const auto q = target.find (' ?' );
226- if (q == std::string_view::npos)
227- {
228- return target;
229- }
230-
231- return target.substr (0 , q);
232- }
233261 } // namespace
234262
235263 const std::regex Session::XSS_PATTERN (
@@ -724,24 +752,82 @@ namespace vix::session
724752
725753 try
726754 {
727- std::string wire = res.to_http_string ();
755+ if (!res.has_header (" Server" ))
756+ {
757+ res.set_header (" Server" , " Vix.cpp" );
758+ }
728759
729- std::size_t written = 0 ;
730- while (written < wire.size ())
760+ if (!res.has_header (" Date" ))
731761 {
732- const std::byte *ptr =
733- reinterpret_cast < const std::byte *>(wire. data () + written);
762+ res. set_header ( " Date " , vix::http::Response::http_date_now ());
763+ }
734764
735- const std::size_t n = co_await stream_->async_write (
736- std::span<const std::byte>(ptr, wire.size () - written),
737- timer_cancel_.token ());
765+ if (!res.has_header (" Content-Length" ))
766+ {
767+ res.set_header (" Content-Length" , std::to_string (res.body ().size ()));
768+ }
738769
739- if (n == 0 )
770+ if (!res.has_header (" Connection" ))
771+ {
772+ res.set_header (" Connection" , res.should_close () ? " close" : " keep-alive" );
773+ }
774+
775+ std::string header_block;
776+ header_block.reserve (256 + res.headers ().size () * 32 );
777+
778+ header_block += res.version ();
779+ header_block += ' ' ;
780+ header_block += std::to_string (res.status ());
781+ header_block += ' ' ;
782+
783+ if (!res.reason ().empty ())
784+ {
785+ header_block += res.reason ();
786+ }
787+ else
788+ {
789+ header_block += vix::http::reason_phrase (res.status ());
790+ }
791+
792+ header_block += " \r\n " ;
793+
794+ for (const auto &[name, value] : res.headers ())
795+ {
796+ header_block += name;
797+ header_block += " : " ;
798+ header_block += value;
799+ header_block += " \r\n " ;
800+ }
801+
802+ header_block += " \r\n " ;
803+
804+ const std::string &body = res.body ();
805+ const auto token = timer_cancel_.token ();
806+
807+ constexpr std::size_t SMALL_RESPONSE_THRESHOLD = 1024 ;
808+
809+ if (body.size () <= SMALL_RESPONSE_THRESHOLD )
810+ {
811+ std::string wire;
812+ wire.reserve (header_block.size () + body.size ());
813+ wire += header_block;
814+ wire += body;
815+
816+ const bool ok = co_await write_all (*stream_, wire, token);
817+ if (!ok)
740818 {
741- break ;
819+ must_close = true ;
742820 }
821+ }
822+ else
823+ {
824+ const bool header_ok = co_await write_all (*stream_, header_block, token);
825+ const bool body_ok = header_ok ? co_await write_all (*stream_, body, token) : false ;
743826
744- written += n;
827+ if (!header_ok || !body_ok)
828+ {
829+ must_close = true ;
830+ }
745831 }
746832
747833#ifndef VIX_BENCH_MODE
0 commit comments