asio: Rewrite response body handling if response body is not expected

This commit is contained in:
Tatsuhiro Tsujikawa 2015-03-06 21:36:40 +09:00
parent d6f810d91a
commit 94ca9705ef
5 changed files with 39 additions and 22 deletions

View File

@ -325,7 +325,9 @@ int http2_handler::start_response(stream &strm) {
hd.second.sensitive)); hd.second.sensitive));
} }
nghttp2_data_provider prd; nghttp2_data_provider *prd_ptr = nullptr, prd;
auto &req = strm.request().impl();
if (::nghttp2::http2::expect_response_body(req.method(), res.status_code())) {
prd.source.ptr = &strm; prd.source.ptr = &strm;
prd.read_callback = prd.read_callback =
[](nghttp2_session *session, int32_t stream_id, uint8_t *buf, [](nghttp2_session *session, int32_t stream_id, uint8_t *buf,
@ -334,9 +336,10 @@ int http2_handler::start_response(stream &strm) {
auto &strm = *static_cast<stream *>(source->ptr); auto &strm = *static_cast<stream *>(source->ptr);
return strm.response().impl().call_read(buf, length, data_flags); return strm.response().impl().call_read(buf, length, data_flags);
}; };
prd_ptr = &prd;
}
rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(), rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(),
nva.size(), &prd); nva.size(), prd_ptr);
if (rv != 0) { if (rv != 0) {
return -1; return -1;

View File

@ -62,6 +62,13 @@ request_cb redirect_handler(int status_code, std::string uri) {
request_cb status_handler(int status_code) { request_cb status_handler(int status_code) {
return [status_code](const request &req, const response &res) { return [status_code](const request &req, const response &res) {
if (!::nghttp2::http2::expect_response_body(status_code)) {
res.write_head(status_code);
res.end();
return;
}
// we supply content-length for HEAD request, but body will not be
// sent.
auto html = create_html(status_code); auto html = create_html(status_code);
header_map h; header_map h;
h.emplace("content-length", header_value{util::utos(html.size())}); h.emplace("content-length", header_value{util::utos(html.size())});

View File

@ -29,6 +29,8 @@
#include "asio_server_http2_handler.h" #include "asio_server_http2_handler.h"
#include "asio_common.h" #include "asio_common.h"
#include "http2.h"
namespace nghttp2 { namespace nghttp2 {
namespace asio_http2 { namespace asio_http2 {
namespace server { namespace server {
@ -79,23 +81,13 @@ void response_impl::end(generator_cb cb) {
state_ = response_state::BODY_STARTED; state_ = response_state::BODY_STARTED;
} }
namespace {
bool expect_response_body(const std::string &method, int status_code) {
return method != "HEAD" && status_code / 100 != 1 && status_code != 304 &&
status_code != 204;
}
} // namespace
void response_impl::start_response() { void response_impl::start_response() {
auto handler = strm_->handler(); auto handler = strm_->handler();
auto &req = strm_->request().impl(); auto &req = strm_->request().impl();
// if response body is not expected, nullify it so that HEADERS has if (!::nghttp2::http2::expect_response_body(req.method(), status_code_)) {
// END_STREAM flag set.
if (!expect_response_body(req.method(), status_code_)) {
state_ = response_state::BODY_STARTED; state_ = response_state::BODY_STARTED;
generator_cb_ = generator_cb();
} }
if (handler->start_response(*strm_) != 0) { if (handler->start_response(*strm_) != 0) {

View File

@ -1092,6 +1092,14 @@ std::string path_join(const char *base_path, size_t base_pathlen,
return res; return res;
} }
bool expect_response_body(int status_code) {
return status_code / 100 != 1 && status_code != 304 && status_code != 204;
}
bool expect_response_body(const std::string &method, int status_code) {
return method != "HEAD" && expect_response_body(status_code);
}
} // namespace http2 } // namespace http2
} // namespace nghttp2 } // namespace nghttp2

View File

@ -282,6 +282,13 @@ std::string path_join(const char *base_path, size_t base_pathlen,
const char *rel_path, size_t rel_pathlen, const char *rel_path, size_t rel_pathlen,
const char *rel_query, size_t rel_querylen); const char *rel_query, size_t rel_querylen);
// true if response has body, taking into account the request method
// and status code.
bool expect_response_body(const std::string &method, int status_code);
// true if response has body, taking into account status code only.
bool expect_response_body(int status_code);
} // namespace http2 } // namespace http2
} // namespace nghttp2 } // namespace nghttp2