mirror of
https://github.com/apache/httpd.git
synced 2026-01-06 09:01:14 +03:00
http: Enforce consistently no response body with both 204 and 304 statuses.
Provide AP_STATUS_IS_HEADER_ONLY() helper/macro to check for 204 or 304 and use it where some special treatment is needed when no body is expected. Some of those places handled 204 only. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1837056 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,6 +1,9 @@
|
||||
-*- 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]
|
||||
|
||||
|
||||
@@ -570,6 +570,10 @@ AP_DECLARE(const char *) ap_get_server_built(void);
|
||||
((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)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@@ -346,11 +346,12 @@ static apr_status_t compress_filter(ap_filter_t *f, apr_bucket_brigade *bb)
|
||||
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);
|
||||
|
||||
@@ -642,18 +642,19 @@ static apr_status_t deflate_out_filter(ap_filter_t *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,
|
||||
@@ -1532,11 +1533,12 @@ static apr_status_t inflate_out_filter(ap_filter_t *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 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)
|
||||
) {
|
||||
|
||||
@@ -1251,7 +1251,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -1356,12 +1356,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -1440,7 +1443,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -254,9 +254,8 @@ AP_DECLARE(int) ap_set_keepalive(request_rec *r)
|
||||
*/
|
||||
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,
|
||||
@@ -1239,6 +1238,15 @@ AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
|
||||
|
||||
ap_run_insert_error_filter(r);
|
||||
|
||||
/* 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 (AP_STATUS_IS_HEADER_ONLY(status)) {
|
||||
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
|
||||
@@ -1247,19 +1255,6 @@ AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
|
||||
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) {
|
||||
ap_finalize_request_protocol(r);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == HTTP_NO_CONTENT) {
|
||||
ap_finalize_request_protocol(r);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r->assbackwards) {
|
||||
|
||||
|
||||
@@ -209,10 +209,18 @@ static h2_headers *create_response(h2_task *task, request_rec *r)
|
||||
/* 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);
|
||||
|
||||
@@ -1808,10 +1808,7 @@ int ap_proxy_http_process_response(proxy_http_req_t *req)
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -308,9 +308,8 @@ static apr_status_t policy_keepalive_out_filter(ap_filter_t *f,
|
||||
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")
|
||||
|
||||
@@ -1930,7 +1930,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user