)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c643f959bd03fb5ea7d01d8eb3a68fa3265c323f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"9edc0b52_c6ed2758","updated":"2022-03-15 22:24:55.000000000","message":"Thanks for this! I\u0027m a little surprised it hasn\u0027t bitten us earlier, but maybe it\u0027s just that clients *usually* also use UriEncode() -- or something like it -- to craft the request line that\u0027s sent.\n\nI\u0027ve got one little test change I\u0027ll push up, but then this looks good to go.","commit_id":"82eeb81861d4747c67695792e78dd3319a970f74"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c643f959bd03fb5ea7d01d8eb3a68fa3265c323f","unresolved":true,"context_lines":[{"line_number":402,"context_line":"        It won\u0027t require bucket name in canonical_uri for v4."},{"line_number":403,"context_line":"        \"\"\""},{"line_number":404,"context_line":"        return swob.wsgi_to_bytes(swob.wsgi_quote("},{"line_number":405,"context_line":"            self.environ.get(\u0027PATH_INFO\u0027, self.path), safe\u003d\u0027-_.~/\u0027))"},{"line_number":406,"context_line":""},{"line_number":407,"context_line":"    def _canonical_request(self):"},{"line_number":408,"context_line":"        # prepare \u0027canonical_request\u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"fb36f710_662dd079","line":405,"updated":"2022-03-15 22:24:55.000000000","message":"We\u0027ve had to deal with cases where re-quoting WSGI\u0027s unquoted line leads to SignatureMismatch errors (see https://bugs.launchpad.net/swift/+bug/1884991) -- the advantage of RAW_PATH_INFO is that it\u0027s *exactly* whatever the client put on the wire.\n\nBut, that was for v2 signatures -- and sure enough, the AWS docs are pretty darn clear for v4. The \"Example: PUT Object\" section is particularly compelling, indicating that you can send something like\n\n PUT test$file.text HTTP/1.1\n\nwith a signature where the canonical request looks more like\n\n PUT\n /test%24file.text\n ...\n\nOne minor nit: Python\u0027s quote() function already has the right safe characters:\n\n\u003e Letters, digits, and the characters \u0027_.-~\u0027 are never quoted. ... The optional safe parameter specifies additional ASCII characters that should not be quoted — its default value is \u0027/\u0027.\n\nthough it\u0027s fair to argue that explicit is better than implicit here.","commit_id":"82eeb81861d4747c67695792e78dd3319a970f74"}],"test/unit/common/middleware/s3api/test_s3request.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c643f959bd03fb5ea7d01d8eb3a68fa3265c323f","unresolved":true,"context_lines":[{"line_number":922,"context_line":"        sigv4_req \u003d SigV4Request(req.environ)"},{"line_number":923,"context_line":"        self.assertTrue("},{"line_number":924,"context_line":"            sigv4_req._canonical_request().endswith(b\u0027UNSIGNED-PAYLOAD\u0027))"},{"line_number":925,"context_line":"        self.assertTrue(sigv4_req.check_signature(\u0027secret\u0027))"},{"line_number":926,"context_line":""},{"line_number":927,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":928,"context_line":"    def test_check_sigv4_req_zero_content_length_sha256(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"153a941e_cdb0d02c","line":925,"updated":"2022-03-15 22:24:55.000000000","message":"Test pops here with the fix backed out; it\u0027d be a little more obvious with something like this applied:\n\n diff --git a/test/unit/common/middleware/s3api/test_s3request.py b/test/unit/common/middleware/s3api/test_s3request.py\n index 091da6b83..26a4bee3c 100644\n --- a/test/unit/common/middleware/s3api/test_s3request.py\n +++ b/test/unit/common/middleware/s3api/test_s3request.py\n @@ -920,8 +920,9 @@ class TestRequest(S3ApiTestCase):\n          req \u003d Request.blank(\n              environ[\u0027RAW_PATH_INFO\u0027], environ\u003denviron, headers\u003dheaders)\n          sigv4_req \u003d SigV4Request(req.environ)\n -        self.assertTrue(\n -            sigv4_req._canonical_request().endswith(b\u0027UNSIGNED-PAYLOAD\u0027))\n +        canonical_req \u003d sigv4_req._canonical_request()\n +        self.assertIn(b\u0027PUT\\n/test/~/file%2C1_1%3A1-1\\n\u0027, canonical_req)\n +        self.assertTrue(canonical_req.endswith(b\u0027UNSIGNED-PAYLOAD\u0027))\n          self.assertTrue(sigv4_req.check_signature(\u0027secret\u0027))\n  \n      @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)","commit_id":"82eeb81861d4747c67695792e78dd3319a970f74"}]}
