-*- coding: utf-8 -*-
Changes with Apache 2.5.1
+ *) http: Enforce consistently no response body with both 204 and 304
+ statuses. [Yann Ylavic]
+
*) mod_proxy_http: forward 100-continue, and minimize race conditions when
reusing backend connections. PR 60330. [Yann Ylavic, Jean-Frederic Clere]
((x) == HTTP_INTERNAL_SERVER_ERROR) || \
((x) == HTTP_SERVICE_UNAVAILABLE) || \
((x) == HTTP_NOT_IMPLEMENTED))
+
+/** does the status imply header only response (i.e. never w/ a body)? */
+#define AP_STATUS_IS_HEADER_ONLY(x) ((x) == HTTP_NO_CONTENT || \
+ (x) == HTTP_NOT_MODIFIED)
/** @} */
/**
const char *accepts;
/* Only work on main request, not subrequests, that are not
- * a 204 response with no content, and are not tagged with the
+ * responses with no content (204/304), and are not tagged with the
* no-brotli env variable, and are not a partial response to
* a Range request.
*/
- if (r->main || r->status == HTTP_NO_CONTENT
+ if (r->main
+ || AP_STATUS_IS_HEADER_ONLY(r->status)
|| apr_table_get(r->subprocess_env, "no-brotli")
|| apr_table_get(r->headers_out, "Content-Range")) {
ap_remove_output_filter(f);
/*
* Only work on main request, not subrequests,
- * that are not a 204 response with no content
+ * that are not responses with no content (204/304),
* and are not tagged with the no-gzip env variable
* and not a partial response to a Range request.
*/
- if ((r->main != NULL) || (r->status == HTTP_NO_CONTENT) ||
+ if ((r->main != NULL) ||
+ AP_STATUS_IS_HEADER_ONLY(r->status) ||
apr_table_get(r->subprocess_env, "no-gzip") ||
apr_table_get(r->headers_out, "Content-Range")
) {
if (APLOG_R_IS_LEVEL(r, APLOG_TRACE1)) {
const char *reason =
(r->main != NULL) ? "subrequest" :
- (r->status == HTTP_NO_CONTENT) ? "no content" :
+ AP_STATUS_IS_HEADER_ONLY(r->status) ? "no content" :
apr_table_get(r->subprocess_env, "no-gzip") ? "no-gzip" :
"content-range";
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
/*
* Only work on main request, not subrequests,
- * that are not a 204 response with no content
+ * that are not responses with no content (204/304),
* and not a partial response to a Range request,
* and only when Content-Encoding ends in gzip.
*/
- if (!ap_is_initial_req(r) || (r->status == HTTP_NO_CONTENT) ||
+ if (!ap_is_initial_req(r) ||
+ AP_STATUS_IS_HEADER_ONLY(r->status) ||
(apr_table_get(r->headers_out, "Content-Range") != NULL) ||
(check_gzip(r, r->headers_out, r->err_headers_out) == 0)
) {
}
else if (ctx->headers_sent) {
/* Eat body if response must not have one. */
- if (r->header_only || r->status == HTTP_NO_CONTENT) {
+ if (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) {
apr_brigade_cleanup(b);
return APR_SUCCESS;
}
basic_http_header_check(r, &protocol);
ap_set_keepalive(r);
- if (r->chunked) {
- apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
+ if (AP_STATUS_IS_HEADER_ONLY(r->status)) {
+ apr_table_unset(r->headers_out, "Transfer-Encoding");
apr_table_unset(r->headers_out, "Content-Length");
+ r->content_type = r->content_encoding = NULL;
+ r->content_languages = NULL;
+ r->clength = r->chunked = 0;
}
-
- if (r->status == HTTP_NO_CONTENT) {
+ else if (r->chunked) {
+ apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
apr_table_unset(r->headers_out, "Content-Length");
}
}
ctx->headers_sent = 1;
- if (r->header_only || r->status == HTTP_NO_CONTENT) {
+ if (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) {
apr_brigade_cleanup(b);
goto out;
}
*/
if ((r->connection->keepalive != AP_CONN_CLOSE)
&& !r->expecting_100
- && ((r->status == HTTP_NOT_MODIFIED)
- || (r->status == HTTP_NO_CONTENT)
- || r->header_only
+ && (r->header_only
+ || AP_STATUS_IS_HEADER_ONLY(r->status)
|| apr_table_get(r->headers_out, "Content-Length")
|| ap_find_last_token(r->pool,
apr_table_get(r->headers_out,
ap_run_insert_error_filter(r);
- /*
- * It's possible that the Location field might be in r->err_headers_out
- * instead of r->headers_out; use the latter if possible, else the
- * former.
- */
- if (location == NULL) {
- location = apr_table_get(r->err_headers_out, "Location");
- }
/* We need to special-case the handling of 204 and 304 responses,
* since they have specific HTTP requirements and do not include a
* message body. Note that being assbackwards here is not an option.
*/
- if (status == HTTP_NOT_MODIFIED) {
+ if (AP_STATUS_IS_HEADER_ONLY(status)) {
ap_finalize_request_protocol(r);
return;
}
- if (status == HTTP_NO_CONTENT) {
- ap_finalize_request_protocol(r);
- return;
+ /*
+ * It's possible that the Location field might be in r->err_headers_out
+ * instead of r->headers_out; use the latter if possible, else the
+ * former.
+ */
+ if (location == NULL) {
+ location = apr_table_get(r->err_headers_out, "Location");
}
if (!r->assbackwards) {
/* determine the protocol and whether we should use keepalives. */
ap_set_keepalive(r);
- if (r->chunked) {
+ if (AP_STATUS_IS_HEADER_ONLY(r->status)) {
+ apr_table_unset(r->headers_out, "Transfer-Encoding");
apr_table_unset(r->headers_out, "Content-Length");
+ r->content_type = r->content_encoding = NULL;
+ r->content_languages = NULL;
+ r->clength = r->chunked = 0;
}
-
+ else if (r->chunked) {
+ apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
+ apr_table_unset(r->headers_out, "Content-Length");
+ }
+
ctype = ap_make_content_type(r, r->content_type);
if (ctype) {
apr_table_setn(r->headers_out, "Content-Type", ctype);
}
/* send body - but only if a body is expected */
- if ((!r->header_only) && /* not HEAD request */
- (proxy_status != HTTP_NO_CONTENT) && /* not 204 */
- (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */
-
+ if (!r->header_only && !AP_STATUS_IS_HEADER_ONLY(proxy_status)) {
/* We need to copy the output headers and treat them as input
* headers as well. BUT, we need to do this before we remove
* TE, so that they are preserved accordingly for
if (result != policy_ignore && r->connection->keepalive != AP_CONN_CLOSE
&& !r->expecting_100 && !ap_status_drops_connection(r->status)) {
- if (!((r->status == HTTP_NOT_MODIFIED)
- || (r->status == HTTP_NO_CONTENT)
- || r->header_only
+ if (!(r->header_only
+ || AP_STATUS_IS_HEADER_ONLY(r->status)
|| apr_table_get(r->headers_out, "Content-Length")
|| ap_find_last_token(r->pool, apr_table_get(r->headers_out,
"Transfer-Encoding"), "chunked")
* such filters update or remove the C-L header, and just use it
* if present.
*/
- if (!(r->header_only
+ if (!((r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status))
&& !r->bytes_sent
&& (r->sent_bodyct
|| conf->http_cl_head_zero != AP_HTTP_CL_HEAD_ZERO_ENABLE