PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) mod_proxy_fcgi: Fix proxy-fcgi-pathinfo=full
- trunk patch: https://svn.apache.org/r1919547
- https://svn.apache.org/r1921238
- 2.4.x patch: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/489.diff
- PR: https://github.com/apache/httpd/pull/489
- +1: ylavic, covener, jim
-
- *) mod_http2: Fix failed request counting and keepalive timeout
- trunk patch: https://svn.apache.org/r1921805
- 2.4.x patch: svn merge -c r1921805 ^/httpd/httpd/trunk .
- +1: icing
-
*) mod_log_config: Fix LogFormat directive merging
trunk patch: https://svn.apache.org/r1921305
https://svn.apache.org/r1921306
* with an informative HTTP error response like 413. But of the
* client is too wrong, we RESET the stream */
stream->request_headers_failed > 100)) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c1,
+ H2_SSSN_STRM_MSG(session, frame->hd.stream_id,
+ "RST stream, header failures: %d"),
+ (int)stream->request_headers_failed);
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
return 0;
default:
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c1,
H2_SSSN_LOG(APLOGNO(03401), session,
- "conn error -> shutdown"));
+ "conn error -> shutdown, remote.emitted=%d"),
+ (int)session->remote.emitted_count);
h2_session_shutdown(session, arg, msg, 0);
break;
}
static void ev_stream_open(h2_session *session, h2_stream *stream)
{
if (H2_STREAM_CLIENT_INITIATED(stream->id)) {
- ++session->remote.emitted_count;
- if (stream->id > session->remote.emitted_max) {
- session->remote.emitted_max = stream->id;
+ if (stream->id > session->remote.accepted_max) {
session->local.accepted_max = stream->id;
}
}
/* Not an async mpm, we must continue waiting
* for client data to arrive until the configured
* server Timeout/KeepAliveTimeout happens */
- apr_time_t timeout = (session->open_streams == 0)?
+ apr_time_t timeout = ((session->open_streams == 0) &&
+ session->remote.emitted_count)?
session->s->keep_alive_timeout :
session->s->timeout;
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, c,
}
else if (H2_SS_IDLE == stream->state) {
if (!stream->rtmp) {
+ if (H2_STREAM_CLIENT_INITIATED(stream->id)) {
+ ++stream->session->remote.emitted_count;
+ if (stream->id > stream->session->remote.emitted_max)
+ session->remote.emitted_max = stream->id;
+ }
stream->rtmp = h2_request_create(stream->id, stream->pool,
NULL, NULL, NULL, NULL, NULL);
}
+import re
import pytest
from .env import H2Conf, H2TestEnv
r = env.nghttp().get(url, options=opt)
assert r.exit_code == 0, r
assert r.response is None
+
+ # test few failed headers, should
+ def test_h2_200_17(self, env):
+ url = env.mkurl("https", "cgi", "/")
+
+ # test few failed headers, should give response
+ def test_h2_200_17(self, env):
+ conf = H2Conf(env)
+ conf.add("""
+ LimitRequestFieldSize 20
+ LogLevel http2:debug
+ """)
+ conf.add_vhost_cgi()
+ conf.install()
+ assert env.apache_restart() == 0
+ re_emitted = re.compile(r'.* AH03401: .* shutdown, remote.emitted=1')
+ url = env.mkurl("https", "cgi", "/")
+ opt = []
+ for i in range(10):
+ opt += ["-H", f"x{i}: 012345678901234567890123456789"]
+ r = env.curl_get(url, options=opt)
+ assert r.response
+ assert r.response["status"] == 431
+ assert env.httpd_error_log.scan_recent(re_emitted)
+
+ # test too many failed headers, should give RST
+ def test_h2_200_18(self, env):
+ conf = H2Conf(env)
+ conf.add("""
+ LimitRequestFieldSize 20
+ LogLevel http2:debug
+ """)
+ conf.add_vhost_cgi()
+ conf.install()
+ assert env.apache_restart() == 0
+ re_emitted = re.compile(r'.* AH03401: .* shutdown, remote.emitted=1')
+ url = env.mkurl("https", "cgi", "/")
+ opt = []
+ for i in range(100):
+ opt += ["-H", f"x{i}: 012345678901234567890123456789"]
+ r = env.curl_get(url, options=opt)
+ assert r.response is None
+ assert env.httpd_error_log.scan_recent(re_emitted)
+
+ # test header 10 invalid headers, should trigger stream RST
+ def test_h2_200_19(self, env):
+ url = env.mkurl("https", "cgi", "/")
+ opt = []
+ invalid = '\x7f'
+ for i in range(10):
+ opt += ["-H", f"x{i}: {invalid}"]
+ r = env.curl_get(url, options=opt)
+ assert r.response is None
+