mirror of
https://github.com/apache/httpd.git
synced 2026-10-23 22:49:01 +03:00
* modules/http/http_protocol.c (make_allow): Don't check for the
M_INVALID bit being set in the method mask if unregistered methods are allowed. That bit is never set by ap_method_list_add(), and this branch adding unregistered methods to Allow: never followed. * test/pyhttpd/mod_aptest/mod_aptest.c (aptest_allow_methods): New; pass the methods named in an AP-Test-Allow-Methods request header to ap_allow_methods(). * test/modules/core/test_009_allow_methods.py: New test suite. GitHub: closes #758, closes #428 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1938291 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -897,8 +897,7 @@ static char *make_allow(request_rec *r)
|
||||
|
||||
/* ### this is rather annoying. we should enforce registration of
|
||||
### these methods */
|
||||
if ((mask & (AP_METHOD_BIT << M_INVALID))
|
||||
&& (r->allowed_methods->method_list != NULL)
|
||||
if (r->allowed_methods->method_list != NULL
|
||||
&& (r->allowed_methods->method_list->nelts != 0)) {
|
||||
apr_array_cat(allow, r->allowed_methods->method_list);
|
||||
}
|
||||
|
||||
46
test/modules/core/test_009_allow_methods.py
Normal file
46
test/modules/core/test_009_allow_methods.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import pytest
|
||||
|
||||
from pyhttpd.conf import HttpdConf
|
||||
|
||||
|
||||
class TestAllowMethods:
|
||||
|
||||
@pytest.fixture(autouse=True, scope='class')
|
||||
def _class_scope(self, env):
|
||||
conf = HttpdConf(env)
|
||||
conf.add_vhost_test1()
|
||||
conf.install()
|
||||
assert env.apache_restart() == 0
|
||||
|
||||
# mod_aptest passes the methods named in AP-Test-Allow-Methods to
|
||||
# ap_allow_methods() from a fixups hook; the default handler then
|
||||
# merges its own and answers OPTIONS with the Allow header.
|
||||
def options(self, env, methods=None):
|
||||
options = ['-X', 'OPTIONS']
|
||||
if methods is not None:
|
||||
options.extend(['-H', f'AP-Test-Allow-Methods: {methods}'])
|
||||
r = env.curl_get(env.mkurl("http", "test1", "/index.html"),
|
||||
options=options)
|
||||
assert r.response, f"no response: {r.stderr}"
|
||||
assert r.response["status"] == 200
|
||||
return [m.strip() for m in r.response["header"]["allow"].split(',')]
|
||||
|
||||
def test_core_009_01(self, env):
|
||||
allow = self.options(env)
|
||||
for method in ["GET", "POST", "OPTIONS"]:
|
||||
assert method in allow, f"expected {method} in Allow: {allow}"
|
||||
|
||||
def test_core_009_02(self, env):
|
||||
allow = self.options(env, "DELETE")
|
||||
assert "DELETE" in allow, f"expected DELETE in Allow: {allow}"
|
||||
|
||||
# An extension method reaches make_allow() only through method_list,
|
||||
# which is emitted just when the M_INVALID bit is set in method_mask.
|
||||
def test_core_009_03(self, env):
|
||||
allow = self.options(env, "FROBNICATE")
|
||||
assert "FROBNICATE" in allow, f"expected FROBNICATE in Allow: {allow}"
|
||||
|
||||
def test_core_009_04(self, env):
|
||||
allow = self.options(env, "DELETE, FROBNICATE")
|
||||
for method in ["DELETE", "FROBNICATE"]:
|
||||
assert method in allow, f"expected {method} in Allow: {allow}"
|
||||
@@ -51,6 +51,29 @@ static int aptest_post_read_request(request_rec *r)
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the methods named in an "AP-Test-Allow-Methods" request header
|
||||
* via ap_allow_methods(), so a test can check how they are reflected in the
|
||||
* Allow response header.
|
||||
*/
|
||||
static int aptest_allow_methods(request_rec *r)
|
||||
{
|
||||
const char *methods = apr_table_get(r->headers_in, "AP-Test-Allow-Methods");
|
||||
char *list, *name, *last;
|
||||
|
||||
if (methods == NULL) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
list = apr_pstrdup(r->pool, methods);
|
||||
for (name = apr_strtok(list, ", ", &last); name != NULL;
|
||||
name = apr_strtok(NULL, ", ", &last)) {
|
||||
ap_allow_methods(r, MERGE_ALLOW, name, NULL);
|
||||
}
|
||||
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
/* Install this module into the apache2 infrastructure.
|
||||
*/
|
||||
static void aptest_hooks(apr_pool_t *pool)
|
||||
@@ -61,6 +84,7 @@ static void aptest_hooks(apr_pool_t *pool)
|
||||
/* test case monitoring */
|
||||
ap_hook_post_read_request(aptest_post_read_request, NULL,
|
||||
NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_fixups(aptest_allow_methods, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user