| 215 | |
| 216 | |
| 217 | AP_DECLARE(int) ap_set_keepalive(request_rec *r) |
| 218 | { |
| 219 | int ka_sent = 0; |
| 220 | int left = r->server->keep_alive_max - r->connection->keepalives; |
| 221 | int wimpy = ap_find_token(r->pool, |
| 222 | apr_table_get(r->headers_out, "Connection"), |
| 223 | "close"); |
| 224 | const char *conn = apr_table_get(r->headers_in, "Connection"); |
| 225 | |
| 226 | /* The following convoluted conditional determines whether or not |
| 227 | * the current connection should remain persistent after this response |
| 228 | * (a.k.a. HTTP Keep-Alive) and whether or not the output message |
| 229 | * body should use the HTTP/1.1 chunked transfer-coding. In English, |
| 230 | * |
| 231 | * IF we have not marked this connection as errored; |
| 232 | * and the client isn't expecting 100-continue (PR47087 - more |
| 233 | * input here could be the client continuing when we're |
| 234 | * closing the request). |
| 235 | * and the response body has a defined length due to the status code |
| 236 | * being 304 or 204, the request method being HEAD, already |
| 237 | * having defined Content-Length or Transfer-Encoding: chunked, or |
| 238 | * the request version being HTTP/1.1 and thus capable of being set |
| 239 | * as chunked [we know the (r->chunked = 1) side-effect is ugly]; |
| 240 | * and the server configuration enables keep-alive; |
| 241 | * and the server configuration has a reasonable inter-request timeout; |
| 242 | * and there is no maximum # requests or the max hasn't been reached; |
| 243 | * and the response status does not require a close; |
| 244 | * and the response generator has not already indicated close; |
| 245 | * and the client did not request non-persistence (Connection: close); |
| 246 | * and we haven't been configured to ignore the buggy twit |
| 247 | * or they're a buggy twit coming through a HTTP/1.1 proxy |
| 248 | * and the client is requesting an HTTP/1.0-style keep-alive |
| 249 | * or the client claims to be HTTP/1.1 compliant (perhaps a proxy); |
| 250 | * and this MPM process is not already exiting |
| 251 | * THEN we can be persistent, which requires more headers be output. |
| 252 | * |
| 253 | * Note that the condition evaluation order is extremely important. |
| 254 | */ |
| 255 | if ((r->connection->keepalive != AP_CONN_CLOSE) |
| 256 | && !r->expecting_100 |
| 257 | && (r->header_only |
| 258 | || AP_STATUS_IS_HEADER_ONLY(r->status) |
| 259 | || apr_table_get(r->headers_out, "Content-Length") |
| 260 | || ap_is_chunked(r->pool, |
| 261 | apr_table_get(r->headers_out, |
| 262 | "Transfer-Encoding")) |
| 263 | || ((r->proto_num >= HTTP_VERSION(1,1)) |
| 264 | && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */ |
| 265 | && r->server->keep_alive |
| 266 | && (r->server->keep_alive_timeout > 0) |
| 267 | && ((r->server->keep_alive_max == 0) |
| 268 | || (left > 0)) |
| 269 | && !ap_status_drops_connection(r->status) |
| 270 | && !wimpy |
| 271 | && !ap_find_token(r->pool, conn, "close") |
| 272 | && (!apr_table_get(r->subprocess_env, "nokeepalive") |
| 273 | || apr_table_get(r->headers_in, "Via")) |
| 274 | && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) |
no test coverage detected