# HG changeset patch # User John Rouillard # Date 1776668970 14400 # Node ID 31a8a6faa2fa07a8257020f219834557d4b9188b # Parent 7fadc97c716b2f4dca48442cbefc2860b9974998 bug: Allow UsageError exception to use more specific error code UsageError exception returned 400 error code but should return 405 when generated for a bad http method. Modified error handler to use 400 error code if self.response_code was less then 400. This should reproduce the standard error of 400 if one was not specified and preserve any other explicitly set response code. Also enhanced a test case to verify the 405 is returned. diff -r 7fadc97c716b -r 31a8a6faa2fa roundup/cgi/client.py --- a/roundup/cgi/client.py Mon Apr 20 03:02:11 2026 -0400 +++ b/roundup/cgi/client.py Mon Apr 20 03:09:30 2026 -0400 @@ -817,13 +817,18 @@ # Must check supplied Origin header for bad value first. csrf_ok = self.handle_csrf(api=True) except (Unauthorised, UsageError) as msg: + response_code = self.response_code + if response_code < 400: + # set the code to a 400 error as this is an error + # condition. + response_code = 400 # FIXME should format return value according to # client's accept header, so application/xml, text/plain etc.. - output = s2b('{ "error": { "status": 400, "msg": "%s"}}' % - str(msg)) + output = s2b('{ "error": {"status": %s, "msg": "%s"}}' % + (response_code, str(msg))) self.reject_request(output, message_type="application/json", - status=400) + status=response_code) csrf_ok = False # we had an error, failed check return @@ -1613,6 +1618,7 @@ # local addition to fail fast if invalid method. if method not in {'POST', 'PUT', 'DELETE', 'PATCH'}: + self.response_code = 405 # bad method raise UsageError("Bad Request: %s" % method) if 'HTTP_ORIGIN' in self.env: # list item 2 diff -r 7fadc97c716b -r 31a8a6faa2fa test/test_cgi.py --- a/test/test_cgi.py Mon Apr 20 03:02:11 2026 -0400 +++ b/test/test_cgi.py Mon Apr 20 03:09:30 2026 -0400 @@ -1177,6 +1177,7 @@ "HTTP_Sec_Fetch_Site": "same-site", "HTTP_Host": "foo.bar", "Result": "Bad Request: UNLOCK", + "response_code": 405 }, { # Case 12: POST should pass csrf because origin's host @@ -1210,6 +1211,9 @@ cl.main() self.assertIn(test['Result'], out[0]) + if "response_code" in test: + self.assertEqual(test['response_code'], cl.response_code) + del(out[0]) # get request with nonce