Merge pull request #2649 from nghttp2/nghttpx-upstream-span

nghttpx: Use std::span for upstream interface
This commit is contained in:
Tatsuhiro Tsujikawa
2026-03-23 22:04:19 +09:00
committed by GitHub
12 changed files with 53 additions and 56 deletions

View File

@@ -150,7 +150,7 @@ int APIDownstreamConnection::send_reply(unsigned int http_status,
break;
}
if (upstream->send_reply(downstream_, buf.data(), buf.size()) != 0) {
if (upstream->send_reply(downstream_, buf) != 0) {
return -1;
}

View File

@@ -77,7 +77,7 @@ int HealthMonitorDownstreamConnection::end_upload_data() {
resp.fs.add_header_token("content-length"sv, "0"sv, false,
http2::HD_CONTENT_LENGTH);
if (upstream->send_reply(downstream_, nullptr, 0) != 0) {
if (upstream->send_reply(downstream_, {}) != 0) {
return -1;
}

View File

@@ -1214,7 +1214,7 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
}
auto downstream = sd->dconn->get_downstream();
auto upstream = downstream->get_upstream();
rv = upstream->on_downstream_body(downstream, nullptr, 0, true);
rv = upstream->on_downstream_body(downstream, {}, true);
if (rv != 0) {
http2session->submit_rst_stream(frame->hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
@@ -1426,7 +1426,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
resp.unconsumed_body_length += len;
auto upstream = downstream->get_upstream();
rv = upstream->on_downstream_body(downstream, data, len, false);
rv = upstream->on_downstream_body(downstream, {data, len}, false);
if (rv != 0) {
http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);

View File

@@ -1472,22 +1472,22 @@ nghttp2_ssize downstream_data_read_callback(nghttp2_session *session,
}
} // namespace
int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) {
int Http2Upstream::send_reply(Downstream *downstream,
std::span<const uint8_t> body) {
int rv;
nghttp2_data_provider2 data_prd, *data_prd_ptr = nullptr;
const auto &req = downstream->request();
if (req.method != HTTP_HEAD && bodylen) {
if (req.method != HTTP_HEAD && !body.empty()) {
data_prd.source.ptr = downstream;
data_prd.read_callback = downstream_data_read_callback;
data_prd_ptr = &data_prd;
auto buf = downstream->get_response_buf();
buf->append(body, bodylen);
buf->append(body);
}
const auto &resp = downstream->response();
@@ -1896,10 +1896,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// WARNING: Never call directly or indirectly nghttp2_session_send or
// nghttp2_session_recv. These calls may delete downstream.
int Http2Upstream::on_downstream_body(Downstream *downstream,
const uint8_t *data, size_t len,
std::span<const uint8_t> data,
bool flush) {
auto body = downstream->get_response_buf();
body->append(data, len);
body->append(data);
if (flush) {
nghttp2_session_resume_data(
@@ -2008,7 +2008,7 @@ int Http2Upstream::redirect_to_https(Downstream *downstream) {
resp.http_status = 308;
resp.fs.add_header_token("location"sv, loc, false, http2::HD_LOCATION);
return send_reply(downstream, nullptr, 0);
return send_reply(downstream, {});
}
int Http2Upstream::consume(int32_t stream_id, size_t len) {

View File

@@ -75,14 +75,14 @@ public:
size_t consumed) override;
int on_downstream_header_complete(Downstream *downstream) override;
int on_downstream_body(Downstream *downstream, const uint8_t *data,
size_t len, bool flush) override;
int on_downstream_body(Downstream *downstream, std::span<const uint8_t> data,
bool flush) override;
int on_downstream_body_complete(Downstream *downstream) override;
void on_handler_delete() override;
int on_downstream_reset(Downstream *downstream, bool no_retry) override;
int send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) override;
int send_reply(Downstream *downstream,
std::span<const uint8_t> body) override;
int initiate_push(Downstream *downstream, std::string_view uri) override;
int response_riovec(struct iovec *iov, int iovcnt) const override;
void response_drain(size_t n) override;

View File

@@ -1415,10 +1415,10 @@ int Http3Upstream::on_downstream_header_complete(Downstream *downstream) {
}
int Http3Upstream::on_downstream_body(Downstream *downstream,
const uint8_t *data, size_t len,
std::span<const uint8_t> data,
bool flush) {
auto body = downstream->get_response_buf();
body->append(data, len);
body->append(data);
if (flush) {
nghttp3_conn_resume_stream(httpconn_, downstream->get_stream_id());
@@ -1618,21 +1618,21 @@ int Http3Upstream::resume_read(IOCtrlReason reason, Downstream *downstream,
return 0;
}
int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) {
int Http3Upstream::send_reply(Downstream *downstream,
std::span<const uint8_t> body) {
int rv;
nghttp3_data_reader data_read, *data_read_ptr = nullptr;
const auto &req = downstream->request();
if (req.method != HTTP_HEAD && bodylen) {
if (req.method != HTTP_HEAD && !body.empty()) {
data_read.read_data = downstream_read_data_callback;
data_read_ptr = &data_read;
auto buf = downstream->get_response_buf();
buf->append(body, bodylen);
buf->append(body);
}
const auto &resp = downstream->response();

View File

@@ -64,8 +64,8 @@ public:
ClientHandler *get_client_handler() const override;
int on_downstream_header_complete(Downstream *downstream) override;
int on_downstream_body(Downstream *downstream, const uint8_t *data,
size_t len, bool flush) override;
int on_downstream_body(Downstream *downstream, std::span<const uint8_t> data,
bool flush) override;
int on_downstream_body_complete(Downstream *downstream) override;
void on_handler_delete() override;
@@ -74,8 +74,8 @@ public:
void pause_read(IOCtrlReason reason) override;
int resume_read(IOCtrlReason reason, Downstream *downstream,
size_t consumed) override;
int send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) override;
int send_reply(Downstream *downstream,
std::span<const uint8_t> body) override;
int initiate_push(Downstream *downstream, std::string_view uri) override;

View File

@@ -1157,7 +1157,7 @@ int htp_bodycb(llhttp_t *htp, const char *data, size_t len) {
resp.recv_body_length += len;
return downstream->get_upstream()->on_downstream_body(
downstream, reinterpret_cast<const uint8_t *>(data), len, true);
downstream, as_uint8_span(std::span{data, len}), true);
}
} // namespace
@@ -1464,8 +1464,8 @@ int HttpDownstreamConnection::process_input(const uint8_t *data,
if (downstream_->get_upgraded()) {
// For upgraded connection, just pass data to the upstream.
rv = downstream_->get_upstream()->on_downstream_body(downstream_, data,
datalen, true);
rv = downstream_->get_upstream()->on_downstream_body(downstream_,
{data, datalen}, true);
if (rv != 0) {
return rv;
}
@@ -1507,7 +1507,7 @@ int HttpDownstreamConnection::process_input(const uint8_t *data,
if (nproc < datalen) {
// Data from data + nproc are for upgraded protocol.
rv = downstream_->get_upstream()->on_downstream_body(
downstream_, data + nproc, datalen - nproc, true);
downstream_, {data + nproc, datalen - nproc}, true);
if (rv != 0) {
return rv;
}

View File

@@ -961,8 +961,8 @@ int HttpsUpstream::downstream_error(DownstreamConnection *dconn, int events) {
return 0;
}
int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) {
int HttpsUpstream::send_reply(Downstream *downstream,
std::span<const uint8_t> body) {
const auto &req = downstream->request();
auto &resp = downstream->response();
auto &balloc = downstream->get_block_allocator();
@@ -1027,9 +1027,9 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
output->append("\r\n"sv);
if (req.method != HTTP_HEAD) {
output->append(body, bodylen);
output->append(body);
downstream->response_sent_body_length += bodylen;
downstream->response_sent_body_length += body.size();
}
downstream->set_response_state(DownstreamState::MSG_COMPLETE);
@@ -1333,20 +1333,20 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
int HttpsUpstream::on_downstream_body(Downstream *downstream,
const uint8_t *data, size_t len,
std::span<const uint8_t> data,
bool flush) {
if (len == 0) {
if (data.empty()) {
return 0;
}
auto output = downstream->get_response_buf();
if (downstream->get_chunked_response()) {
output->append(sizeof(len) * 2,
std::bind_front(util::CompactHexFormatter{}, len));
output->append(sizeof(data.size()) * 2,
std::bind_front(util::CompactHexFormatter{}, data.size()));
output->append("\r\n"sv);
}
output->append(data, len);
output->append(data);
downstream->response_sent_body_length += len;
downstream->response_sent_body_length += data.size();
if (downstream->get_chunked_response()) {
output->append("\r\n"sv);
@@ -1433,7 +1433,7 @@ int HttpsUpstream::redirect_to_https(Downstream *downstream) {
resp.fs.add_header_token("connection"sv, "close"sv, false,
http2::HD_CONNECTION);
return send_reply(downstream, nullptr, 0);
return send_reply(downstream, {});
}
void HttpsUpstream::log_response_headers(DefaultMemchunks *buf) const {

View File

@@ -69,14 +69,14 @@ public:
size_t consumed) override;
int on_downstream_header_complete(Downstream *downstream) override;
int on_downstream_body(Downstream *downstream, const uint8_t *data,
size_t len, bool flush) override;
int on_downstream_body(Downstream *downstream, std::span<const uint8_t> data,
bool flush) override;
int on_downstream_body_complete(Downstream *downstream) override;
void on_handler_delete() override;
int on_downstream_reset(Downstream *downstream, bool no_retry) override;
int send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) override;
int send_reply(Downstream *downstream,
std::span<const uint8_t> body) override;
int initiate_push(Downstream *downstream, std::string_view uri) override;
int response_riovec(struct iovec *iov, int iovcnt) const override;
void response_drain(size_t n) override;

View File

@@ -217,16 +217,14 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
mrb_int vallen;
mrb_get_args(mrb, "|s", &val, &vallen);
const uint8_t *body = nullptr;
size_t bodylen = 0;
std::span<const uint8_t> body;
if (resp.http_status == 0) {
resp.http_status = 200;
}
if (downstream->expect_response_body() && vallen > 0) {
body = reinterpret_cast<const uint8_t *>(val);
bodylen = as_unsigned(vallen);
body = as_uint8_span(std::span{val, as_unsigned(vallen)});
}
auto cl = resp.fs.header(http2::HD_CONTENT_LENGTH);
@@ -240,8 +238,7 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
resp.fs.content_length = -1;
} else {
auto content_length =
util::make_string_ref_uint(balloc, as_unsigned(vallen));
auto content_length = util::make_string_ref_uint(balloc, body.size());
if (cl) {
cl->value = content_length;
@@ -250,7 +247,7 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
http2::HD_CONTENT_LENGTH);
}
resp.fs.content_length = vallen;
resp.fs.content_length = static_cast<int64_t>(body.size());
}
auto date = resp.fs.header(http2::HD_DATE);
@@ -264,7 +261,7 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
auto upstream = downstream->get_upstream();
rv = upstream->send_reply(downstream, body, bodylen);
rv = upstream->send_reply(downstream, body);
if (rv != 0) {
mrb_raise(mrb, E_RUNTIME_ERROR, "could not send response");
}

View File

@@ -56,8 +56,8 @@ public:
virtual ClientHandler *get_client_handler() const = 0;
virtual int on_downstream_header_complete(Downstream *downstream) = 0;
virtual int on_downstream_body(Downstream *downstream, const uint8_t *data,
size_t len, bool flush) = 0;
virtual int on_downstream_body(Downstream *downstream,
std::span<const uint8_t> data, bool flush) = 0;
virtual int on_downstream_body_complete(Downstream *downstream) = 0;
virtual void on_handler_delete() = 0;
@@ -70,8 +70,8 @@ public:
virtual void pause_read(IOCtrlReason reason) = 0;
virtual int resume_read(IOCtrlReason reason, Downstream *downstream,
size_t consumed) = 0;
virtual int send_reply(Downstream *downstream, const uint8_t *body,
size_t bodylen) = 0;
virtual int send_reply(Downstream *downstream,
std::span<const uint8_t> body) = 0;
// Starts server push. The |downstream| is an associated stream for
// the pushed resource. This function returns 0 if it succeeds,