nghttpx: Choose h1 protocol if headers have been sent to backend on retry

This commit is contained in:
Tatsuhiro Tsujikawa 2018-08-22 23:20:13 +09:00
parent 13ffece12d
commit 9b24e19763
3 changed files with 22 additions and 6 deletions

View File

@ -938,7 +938,8 @@ uint32_t ClientHandler::get_affinity_cookie(Downstream *downstream,
} }
std::unique_ptr<DownstreamConnection> std::unique_ptr<DownstreamConnection>
ClientHandler::get_downstream_connection(int &err, Downstream *downstream) { ClientHandler::get_downstream_connection(int &err, Downstream *downstream,
shrpx_proto pref_proto) {
size_t group_idx; size_t group_idx;
auto &downstreamconf = *worker_->get_downstream_config(); auto &downstreamconf = *worker_->get_downstream_config();
auto &routerconf = downstreamconf.router; auto &routerconf = downstreamconf.router;
@ -1041,7 +1042,8 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
i = 0; i = 0;
} }
addr = &shared_addr->addrs[shared_addr->affinity_hash[i].idx]; addr = &shared_addr->addrs[shared_addr->affinity_hash[i].idx];
if (addr->connect_blocker->blocked()) { if (addr->connect_blocker->blocked() ||
(pref_proto != PROTO_NONE && pref_proto != addr->proto)) {
continue; continue;
} }
break; break;
@ -1081,7 +1083,15 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
auto proto = PROTO_NONE; auto proto = PROTO_NONE;
if (http1_weight > 0 && http2_weight > 0) { if (pref_proto == PROTO_HTTP1) {
if (http1_weight > 0) {
proto = PROTO_HTTP1;
}
} else if (pref_proto == PROTO_HTTP2) {
if (http2_weight > 0) {
proto = PROTO_HTTP2;
}
} else if (http1_weight > 0 && http2_weight > 0) {
// We only advance cycle if both weight has nonzero to keep its // We only advance cycle if both weight has nonzero to keep its
// distance under WEIGHT_MAX. // distance under WEIGHT_MAX.
if (pri_less(shared_addr->http1_pri, shared_addr->http2_pri)) { if (pri_less(shared_addr->http1_pri, shared_addr->http2_pri)) {

View File

@ -102,9 +102,11 @@ public:
// Returns DownstreamConnection object based on request path. This // Returns DownstreamConnection object based on request path. This
// function returns non-null DownstreamConnection, and assigns 0 to // function returns non-null DownstreamConnection, and assigns 0 to
// |err| if it succeeds, or returns nullptr, and assigns negative // |err| if it succeeds, or returns nullptr, and assigns negative
// error code to |err|. // error code to |err|. If |pref_proto| is not PROTO_NONE, choose
// backend whose protocol is |pref_proto|.
std::unique_ptr<DownstreamConnection> std::unique_ptr<DownstreamConnection>
get_downstream_connection(int &err, Downstream *downstream); get_downstream_connection(int &err, Downstream *downstream,
shrpx_proto pref_proto = PROTO_NONE);
MemchunkPool *get_mcpool(); MemchunkPool *get_mcpool();
SSL *get_ssl() const; SSL *get_ssl() const;
// Call this function when HTTP/2 connection header is received at // Call this function when HTTP/2 connection header is received at

View File

@ -87,7 +87,11 @@ void retry_downstream_connection(Downstream *downstream,
downstream->pop_downstream_connection(); downstream->pop_downstream_connection();
int rv; int rv;
auto ndconn = handler->get_downstream_connection(rv, downstream); // We have to use h1 backend for retry if we have already written h1
// request in request buffer.
auto ndconn = handler->get_downstream_connection(
rv, downstream,
downstream->get_request_header_sent() ? PROTO_HTTP1 : PROTO_NONE);
if (ndconn) { if (ndconn) {
if (downstream->attach_downstream_connection(std::move(ndconn)) == 0 && if (downstream->attach_downstream_connection(std::move(ndconn)) == 0 &&
downstream->push_request_headers() == 0) { downstream->push_request_headers() == 0) {