return COMPLETE_NONPERSISTENT_MSG;
/** \par
- * If we didn't send a keep-alive request header, then this
+ * If we sent a Connection:close request header, then this
* can not be a persistent connection.
*/
if (!flags.keepalive)
return COMPLETE_NONPERSISTENT_MSG;
+ /** \par
+ * If we banned reuse, then this cannot be a persistent connection.
+ */
+ if (flags.forceClose)
+ return COMPLETE_NONPERSISTENT_MSG;
+
/** \par
* If we haven't sent the whole request then this can not be a persistent
* connection.
delete cc;
}
- // Always send Connection because HTTP/1.0 servers need explicit "keep-alive"
- // while HTTP/1.1 servers need explicit "close", and we do not always know
- // the server expectations.
- hdr_out->putStr(Http::HdrType::CONNECTION, flags.keepalive ? "keep-alive" : "close");
+ // Always send Connection because HTTP/1.0 servers need explicit
+ // "keep-alive", HTTP/1.1 servers need explicit "close", Upgrade recipients
+ // need bare "upgrade", and we do not always know the server expectations.
+ if (!hdr_out->has(Http::HdrType::CONNECTION)) // forwardUpgrade() may add it
+ hdr_out->putStr(Http::HdrType::CONNECTION, flags.keepalive ? "keep-alive" : "close");
/* append Front-End-Https */
if (flags.front_end_https) {
* regardless of the security implications.
*/
hdrOut.putStr(Http::HdrType::CONNECTION, "upgrade");
+
+ // Connection:close and Connection:keepalive confuse some Upgrade
+ // recipients, so we do not send those headers. Our Upgrade request
+ // implicitly offers connection persistency per HTTP/1.1 defaults.
+ // Update the keepalive flag to reflect that offer.
+ // * If the server upgrades, then we would not be talking HTTP past the
+ // HTTP 101 control message, and HTTP persistence would be irrelevant.
+ // * Otherwise, our request will contradict onoff.server_pconns=off or
+ // other no-keepalive conditions (if any). We compensate by copying
+ // the original no-keepalive decision now and honoring it later.
+ flags.forceClose = !flags.keepalive;
+ flags.keepalive = true; // should already be true in most cases
}
}
/* build and pack headers */
{
HttpHeader hdr(hoRequest);
- forwardUpgrade(hdr);
+ forwardUpgrade(hdr); // before httpBuildRequestHeader() for CONNECTION
httpBuildRequestHeader(request.getRaw(), entry, fwd->al, &hdr, flags);
if (request->flags.pinned && request->flags.connectionAuth)
{
public:
unsigned int front_end_https = 0; ///< send "Front-End-Https: On" header (off/on/auto=2)
- bool keepalive = false; ///< whether to keep the connection persistent
+
+ /// whether the Squid-sent request offers to keep the connection persistent
+ bool keepalive = false;
+
+ /// whether Squid should not keep the connection persistent despite offering
+ /// to do so previously (and setting the keepalive flag)
+ bool forceClose = false;
+
bool only_if_cached = false;
/// Whether we are processing an HTTP 1xx control message.