diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index a90914de..dd6a1e27 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -1080,8 +1080,19 @@ ssize_t downstream_data_read_callback(nghttp2_session *session, auto downstream = static_cast(source->ptr); auto upstream = static_cast(downstream->get_upstream()); auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); + auto limit = handler->get_write_limit(); + + if(limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } + int nread = evbuffer_remove(body, buf, length); if(nread == -1) { ULOG(FATAL, upstream) << "evbuffer_remove() failed"; diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index e91e4e94..06c76eca 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -799,7 +799,19 @@ ssize_t spdy_data_read_callback(spdylay_session *session, auto downstream = static_cast(source->ptr); auto upstream = static_cast(downstream->get_upstream()); auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); + + auto limit = handler->get_write_limit(); + + if(limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } + int nread = evbuffer_remove(body, buf, length); if(nread == -1) { ULOG(FATAL, upstream) << "evbuffer_remove() failed";