Skip to content

Commit e3d1943

Browse files
committed
fix empty body compression in serializer
1 parent 96dc24f commit e3d1943

2 files changed

Lines changed: 69 additions & 32 deletions

File tree

src/serializer.cpp

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ serializer(rts::context& ctx)
299299
: ctx_(ctx)
300300
, svc_(ctx.get_service<serializer_service>())
301301
, ws_(svc_.space_needed)
302+
, is_done_(true)
302303
{
303304
}
304305

@@ -307,8 +308,7 @@ serializer::
307308
reset() noexcept
308309
{
309310
ws_.clear();
310-
is_done_ = false;
311-
is_header_done_ = false;
311+
is_done_ = true;
312312
}
313313

314314
//------------------------------------------------
@@ -341,9 +341,7 @@ prepare() ->
341341
switch(st_)
342342
{
343343
case style::empty:
344-
return const_buffers_type(
345-
prepped_.begin(),
346-
prepped_.size());
344+
break;
347345

348346
case style::buffers:
349347
{
@@ -415,9 +413,32 @@ prepare() ->
415413
switch(st_)
416414
{
417415
case style::empty:
418-
return const_buffers_type(
419-
prepped_.begin(),
420-
prepped_.size());
416+
{
417+
if(out_capacity() == 0 || filter_done_)
418+
break;
419+
420+
const auto rs = filter_->process(
421+
buffers::mutable_buffer_span(
422+
out_prepare()),
423+
{}, // empty input
424+
false);
425+
426+
if(rs.ec.failed())
427+
{
428+
is_done_ = true;
429+
return rs.ec;
430+
}
431+
432+
out_commit(rs.out_bytes);
433+
434+
if(rs.finished)
435+
{
436+
filter_done_ = true;
437+
out_finish();
438+
}
439+
440+
break;
441+
}
421442

422443
case style::buffers:
423444
{
@@ -588,6 +609,7 @@ consume(
588609
if(needs_exp100_continue_)
589610
return;
590611

612+
ws_.clear();
591613
is_done_ = true;
592614
}
593615

@@ -612,10 +634,14 @@ start_init(
612634
message_view_base const& m)
613635
{
614636
// Precondition violation
615-
// if(!is_done_)
616-
// detail::throw_logic_error();
637+
if(!is_done_)
638+
detail::throw_logic_error();
617639

618-
reset();
640+
// TODO: to hold strong exception guarantee
641+
// `is_done_` should be set to true if an
642+
// exception is thrown during the start operation.
643+
is_done_ = false;
644+
is_header_done_ = false;
619645

620646
// VFALCO what do we do with
621647
// metadata error code failures?
@@ -677,31 +703,17 @@ serializer::
677703
start_empty(
678704
message_view_base const& m)
679705
{
680-
using mutable_buffer =
681-
buffers::mutable_buffer;
682-
683706
start_init(m);
684707
st_ = style::empty;
685708

686-
if(!is_chunked_)
687-
{
688-
prepped_ = make_array(
689-
1); // header
690-
}
691-
else
692-
{
693-
prepped_ = make_array(
694-
1 + // header
695-
1); // final chunk
709+
prepped_ = make_array(
710+
1 + // header
711+
2); // out buffer pairs
696712

697-
mutable_buffer final_chunk = {
698-
ws_.reserve_front(
699-
final_chunk_len),
700-
final_chunk_len };
701-
write_final_chunk({ final_chunk, {} });
713+
out_init();
702714

703-
prepped_[1] = final_chunk;
704-
}
715+
if(!filter_)
716+
out_finish();
705717

706718
prepped_[0] = { m.ph_->cbuf, m.ph_->size };
707719
more_input_ = false;

test/unit/compression.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,28 @@ struct zlib_test
344344
}while(!sr.is_done());
345345
}
346346

347+
static
348+
void
349+
serializer_empty(
350+
response_view res,
351+
serializer& sr,
352+
buffers::const_buffer body,
353+
buffers::string_buffer out)
354+
{
355+
BOOST_TEST(body.size() == 0);
356+
// empty body
357+
sr.start(res);
358+
do
359+
{
360+
auto cbs = sr.prepare();
361+
auto n = buffers::size(cbs.value());
362+
BOOST_TEST_GT(n, 0);
363+
buffers::copy(out.prepare(n), cbs.value());
364+
sr.consume(n);
365+
out.commit(n);
366+
}while(!sr.is_done());
367+
}
368+
347369
void
348370
test_serializer()
349371
{
@@ -374,8 +396,11 @@ struct zlib_test
374396
for(core::string_view encoding : encodings)
375397
for(auto chunked : { true, false })
376398
for(auto body_size : { 0, 7, 64 * 1024, 1024 * 1024 })
377-
for(auto driver : { serializer_buffers, serializer_stream, serializer_source })
399+
for(auto driver : { serializer_empty, serializer_buffers, serializer_stream, serializer_source })
378400
{
401+
if(driver == serializer_empty && body_size != 0)
402+
continue;
403+
379404
response resp;
380405
resp.set(field::content_encoding, encoding);
381406
if(chunked)

0 commit comments

Comments
 (0)