)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     Jianjian Huo \u003cjhuo@nvidia.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2024-11-20 11:40:26 -0800"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix HEAD listing content-type first"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"text/plain to ?format\u003djson requests when running with eventlet\u003d0.38.0"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"fa66dd2d_47d354ae","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":35},"updated":"2024-11-21 13:15:00.000000000","message":"Can I suggest\n\n```\nEnsure correct content-type in container HEAD response\n```\n\nI don\u0027t think of a HEAD as being a listing","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Jianjian Huo \u003cjhuo@nvidia.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2024-11-20 11:40:26 -0800"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix HEAD listing content-type first"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"text/plain to ?format\u003djson requests when running with eventlet\u003d0.38.0"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"04762c16_7794aa07","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":35},"in_reply_to":"fa66dd2d_47d354ae","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix HEAD listing content-type first"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"text/plain to ?format\u003djson requests when running with eventlet\u003d0.38.0"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This avoids the problem of backend container server HEADs no longer"},{"line_number":13,"context_line":"having \u0027Content-Length: 0\u0027 by fixing the client HEAD resp headers before"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"383a62c6_b0031576","line":10,"range":{"start_line":9,"start_character":56,"end_line":10,"end_character":36},"updated":"2024-11-21 13:15:00.000000000","message":"the bug is the other way round - the response was always application/json which is what the backend always returns.\n\n```\nExpected header Content-Type to have value text/plain; charset\u003dutf-8, got application/json; charset\u003dutf-8\n```","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix HEAD listing content-type first"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"text/plain to ?format\u003djson requests when running with eventlet\u003d0.38.0"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This avoids the problem of backend container server HEADs no longer"},{"line_number":13,"context_line":"having \u0027Content-Length: 0\u0027 by fixing the client HEAD resp headers before"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"a28c8204_8c10366a","line":10,"range":{"start_line":9,"start_character":56,"end_line":10,"end_character":36},"in_reply_to":"383a62c6_b0031576","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":7,"context_line":"Ensure correct content-type in container HEAD response"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"application/json to ?format\u003dtxt requests (which is maybe not even a"},{"line_number":11,"context_line":"valid value for that qs param?), but only when running with"},{"line_number":12,"context_line":"eventlet\u003d\u003d0.38.0"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"This avoids the problem of backend container server HEADs no longer"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"e21e4d13_720aa466","line":11,"range":{"start_line":10,"start_character":42,"end_line":11,"end_character":30},"updated":"2024-11-22 12:03:16.000000000","message":"oh, I hadn\u0027t spotted that 😂 I guess ``text/plain`` should be the default response type so the cors test is kind of valid but usually we\u0027d write something like ``format\u003dunrecognised`` to provoke the default.","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":7,"context_line":"Ensure correct content-type in container HEAD response"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"application/json to ?format\u003dtxt requests (which is maybe not even a"},{"line_number":11,"context_line":"valid value for that qs param?), but only when running with"},{"line_number":12,"context_line":"eventlet\u003d\u003d0.38.0"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"This avoids the problem of backend container server HEADs no longer"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"bef694b7_c14b698d","line":11,"range":{"start_line":10,"start_character":42,"end_line":11,"end_character":30},"in_reply_to":"e21e4d13_720aa466","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1264f88da9223184a28386df6124fa02072e7ad6","unresolved":true,"context_lines":[{"line_number":7,"context_line":"Ensure correct content-type in container HEAD response"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"A failing CORS test in the gate discovered that we were responding"},{"line_number":10,"context_line":"application/json to ?format\u003dtxt requests (which is maybe not even a"},{"line_number":11,"context_line":"valid value for that qs param?), but only when running with"},{"line_number":12,"context_line":"eventlet\u003d\u003d0.38.0"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"This avoids the problem of backend container server HEADs no longer"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"c8b26e99_207d31b8","line":11,"range":{"start_line":10,"start_character":20,"end_line":11,"end_character":31},"updated":"2024-12-02 20:15:36.000000000","message":"Good catch -- according to https://docs.openstack.org/api-ref/object-store/index.html we ought to be sending `?format\u003dplain` if we want to be explicit.","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"e97d0231_ded1f815","updated":"2024-11-21 13:15:00.000000000","message":"The change makes sense, fixes the failing test, and adds new functional test that covers a regression. Nice!\n\nI\u0027ve suggested some more test coverage and cleanup in a follow-on sq? patch https://review.opendev.org/c/openstack/swift/+/935886\n\nLooking over my comments, -1 is actually for the incorrect commit message which I would normally just fix, but since I\u0027ve pushed some squashable fixups I figured the commit message fix could wait for another patchset.\n\nI was curious how we still manage to return Content-Length to clients given that both the backend response AND listing_formats seems to remove it ?!? Turns out that proxy-logging has an opinion too - see follow on patches.\n\nMy understanding is that container HEADs return 204 because the content-length of an equivalent GET is unknown. For the record, I think it would have been rfc compliant for container servers to return a *200* for a HEAD *without any content-length* because payload headers can be omitted from HEAD responses https://httpwg.org/specs/rfc7231.html#HEAD. However, that would still require this change because I doubt that a 200 with \u0027Content-Length: 0\u0027 would be compliant.\n\n\nMy testing results:\n\nWith eventlet 0.38.0 the ONLY functional tests that I see fail OMM are cors tests. This patch fixes those failures:\n\n```\nvagrant@vagrant:~/swift$ pip list|grep eventlet\neventlet               0.38.0\n\nvagrant@vagrant:~/swift$ ./test/cors/main.py\n/home/vagrant/.local/lib/python3.8/site-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.20) or chardet (3.0.4) doesn\u0027t match a supported version!\n  warnings.warn(\"urllib3 ({}) or chardet ({}) doesn\u0027t match a supported \"\nTested firefox in 2.4s\n1..84\n\n\u003csnip\u003e\n\nnot ok 16 - firefox: container - HEAD format\u003dtxt\n  FAIL:\n  Expected header Content-Type to have value text/plain; charset\u003dutf-8, got application/json; charset\u003dutf-8 HasHeaders/\u003c@http://localhost:8000/harness.js:85:17\nok 17 - firefox: container - HEAD format\u003djson\nnot ok 18 - firefox: container - HEAD format\u003dxml\n  FAIL:\n  Expected header Content-Type to have value application/xml; charset\u003dutf-8, got application/json; charset\u003dutf-8 HasHeaders/\u003c@http://localhost:8000/harness.js:85:17\n\n\u003csnip\u003e\n```\n\nThe new functional test fails when I revert the fix in listing_formats\n\n```\n\u003e       self.assertEqual(resp.getheader(\u0027Content-Type\u0027),\n                         \u0027text/plain; charset\u003dutf-8\u0027)\nE       AssertionError: \u0027application/json; charset\u003dutf-8\u0027 !\u003d \u0027text/plain; charset\u003dutf-8\u0027\nE       - application/json; charset\u003dutf-8\nE       + text/plain; charset\u003dutf-8\n```","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f751cb866c529e3089d264640248e70d4e5d5c79","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"089ca9e3_0e4cba99","updated":"2024-11-20 21:09:33.000000000","message":"recheck\nprobably random failure from openstacksdk-functional-devstack:\nfunctional: 1190799 C exit 1 (1171.12 seconds) /home/zuul/src/opendev.org/openstack/openstacksdk\u003e stestr --test-path ./openstack/tests/functional/ run --serial pid\u003d95156 [tox/execute/api.py:286]\n.pkg: 1190801 D delete package /home/zuul/src/opendev.org/openstack/openstacksdk/.tox/.tmp/package/1/openstacksdk-4.1.1.dev16.tar.gz [tox/tox_env/python/virtual_env/package/pyproject.py:224]\n  functional: FAIL code 1 (1190.65\u003dsetup[19.53]+cmd[1171.12] seconds)\n  evaluation failed :( (1190.71 seconds)","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"8d019306_8001ef32","updated":"2024-11-21 16:53:33.000000000","message":"thanks for the sq!\n\nthis has been a fun one to noodle with.","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"f8b465931022ef95024cda137dbebefc8a772f25","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"e82c09a0_162ccbc1","updated":"2024-11-21 23:43:49.000000000","message":"Looking great, and maybe only a nit. But the Swift-ism here is to use HeaderKeyDict so we don\u0027t have to worry about header cases.. thats basically the point of it 😊","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5db10442a189373e85cc25587ca0fd60252980fd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"2cc478dc_83f91398","updated":"2024-11-22 18:18:17.000000000","message":"I didn\u0027t see any func test fail without the ``title()`` being applied when the content-length header is added, but turns out that is because func tests use a swiftclient HTTPConnection which uses requests which returns a CaseInsensitiveDict.\n\nClay showed that a curl does reveal a regression in the on-the-wire header case if ``title`` is not used in ``set_header()``.\n\nThere\u0027s a test change to cover regression in the title-casing here 936053: sq? test for title case | https://review.opendev.org/c/openstack/swift/+/936053\n\nMy +2 stands with or without that follow-on being squashed (or something like it). I think this patch is good to go to get the gate fixed and we can consider Matt\u0027s HeaderKeyDict follow up after.","commit_id":"d3c4edbb106c2aecf5b79efb644d1a5915550e66"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3aa01ca960e4b2d54b4c5579b118731bf4a5fde7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"6b080ba2_3af7d251","updated":"2024-11-22 12:14:07.000000000","message":"I quite like Matt\u0027s follow-on to use HeaderKeyDict rather than the bespoke header list manipulation. However, once the split-title-join is removed in set_header, I feel less urgency to expand the scope *of this patchset* to rework the header handling, so I\u0027m torn between making-everything-better vs keeping-diff-targeted.\n\nI couldn\u0027t get ``functional/test_container.py`` to fail when I removed the ``set_header`` title-ing *altogether*, which held me back from actually merging this because I\u0027m concerned that Clay saw something with the header case I can\u0027t reproduce, and therefore I cannot validate the tweak I made to the title-ing in this patchset.","commit_id":"d3c4edbb106c2aecf5b79efb644d1a5915550e66"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"7cb71544_293eb370","updated":"2024-11-22 23:40:04.000000000","message":"I think we are going to need both this patch and the author\u0027s second approach (https://review.opendev.org/c/openstack/swift/+/936066). This patch is a good reinforcement in the middleware layer and has a few good refactoring as well.\n\nThanks for work to unblock our gate!","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"9ee84ba3_f14e9346","updated":"2024-11-22 20:44:44.000000000","message":"I\u0027d like to be able to merge patches again, and dealing with the behavior change in new eventlet seems like a good idea.\n\nWe could have taken an alternative approach:\n\n936066: Ensure correct content-type in container HEAD response | https://review.opendev.org/c/openstack/swift/+/936066","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"ef09885031dc04d832004804ba09a4986cf53ec0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"0887db4a_58d93243","updated":"2024-11-22 20:26:11.000000000","message":"This looks great and seems to have all the squashed things in there too.\n\nlet\u0027s fix the gate! (assuming Zuul passes)","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"308609385cba8933b17643d92d04083f7c1f6fb3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"af47a2a0_588c8adb","updated":"2024-11-25 08:59:36.000000000","message":"Putting the +2 back on.. and giving it a +A due to Jians +1, which is good enough for me!","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1264f88da9223184a28386df6124fa02072e7ad6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"949879c7_20512259","updated":"2024-12-02 20:15:36.000000000","message":"There was maybe a little more churn than I would have liked, given that this needs to be backported to fix stable gates, but it\u0027s probably fine. IDK that I like the `content-length: 0` change, though; what was the rationale there?","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"dc4afa1dc264d938189f129fcfbe7116d0a2d381","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"d461102d_881df986","updated":"2024-11-25 02:21:39.000000000","message":"recheck","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"7cc1a93305e8f664a6199deb1725e3760e81893d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"a1441185_27d00fc7","updated":"2024-11-25 06:38:08.000000000","message":"recheck\n\nwhy is rolling upgrade now not passing","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"}],"swift/common/middleware/listing_formats.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":221,"context_line":"            set_header(\u0027content-type\u0027, out_content_type + \u0027; charset\u003dutf-8\u0027)"},{"line_number":222,"context_line":"            set_header(\u0027content-length\u0027, None)  # don\u0027t know, can\u0027t determine"},{"line_number":223,"context_line":"            start_response(status, headers)"},{"line_number":224,"context_line":"            return resp_iter"},{"line_number":225,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"831e54e8_7454ea77","line":222,"range":{"start_line":222,"start_character":12,"end_line":222,"end_character":47},"updated":"2024-11-21 13:15:00.000000000","message":"API container HEAD requests *do* have a content-length header [0]. So this has to be wrong, or at least indicate that something else is wrong in another middleware that *is* inserting the content-length header. \n\nThe API docs [1] are pretty clear that container HEAD responses *do* have Content-Length, so if anything it should be *added* here.\n\nAFAICT, with eventlet 0.38.0 meaning we no longer get a content-length from the backend, we\u0027re relying on proxy-logging [2] to insert the content-length header in the HEAD response [3] (or some other middleware that happens to construct a Response object in the container HEAD path, which is what I serendipitously had in the one passing patch on feature/mpu)?\n\n[0] https://review.opendev.org/c/openstack/swift/+/935886\n[1] https://docs.openstack.org/api-ref/object-store/#show-container-metadata\n[2] https://review.opendev.org/c/openstack/swift/+/935888\n[3] https://review.opendev.org/c/openstack/swift/+/935887","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":221,"context_line":"            set_header(\u0027content-type\u0027, out_content_type + \u0027; charset\u003dutf-8\u0027)"},{"line_number":222,"context_line":"            set_header(\u0027content-length\u0027, None)  # don\u0027t know, can\u0027t determine"},{"line_number":223,"context_line":"            start_response(status, headers)"},{"line_number":224,"context_line":"            return resp_iter"},{"line_number":225,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"146f54a6_bb429e57","line":222,"range":{"start_line":222,"start_character":12,"end_line":222,"end_character":47},"in_reply_to":"831e54e8_7454ea77","updated":"2024-11-21 16:53:33.000000000","message":"yeah that\u0027s pretty crazy.\n\nApparently 204 can have Content-Length [1]\n\nSo let\u0027s squash in a belts and braces fix for that too?  it simplifies the logic of the set_helper closure too.\n\n[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204#receiving_a_response_after_deleting_an_image","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":198,"context_line":"            else:"},{"line_number":199,"context_line":"                # sadly, functional testing suggests casing matters in this"},{"line_number":200,"context_line":"                # case and I couldn\u0027t find an helper that does this in swob"},{"line_number":201,"context_line":"                header \u003d \u0027-\u0027.join(p.title() for p in header.split(\u0027-\u0027))"},{"line_number":202,"context_line":"                headers.append((header, str(value)))"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"        if not status.startswith((\u0027200 \u0027, \u0027204 \u0027)):"}],"source_content_type":"text/x-python","patch_set":3,"id":"87e3b6c4_0290885a","line":201,"range":{"start_line":201,"start_character":25,"end_line":201,"end_character":71},"updated":"2024-11-22 12:03:16.000000000","message":"looks like title() treats ``-`` as a delimiter so no need to split and join. https://docs.python.org/3/library/stdtypes.html#str.title\n\n```\n\u0027content-length\u0027.title()\n\u0027Content-Length\u0027\n``` \n\nIndeed, HeaderKeyDict just uses ``key.title()``","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":198,"context_line":"            else:"},{"line_number":199,"context_line":"                # sadly, functional testing suggests casing matters in this"},{"line_number":200,"context_line":"                # case and I couldn\u0027t find an helper that does this in swob"},{"line_number":201,"context_line":"                header \u003d \u0027-\u0027.join(p.title() for p in header.split(\u0027-\u0027))"},{"line_number":202,"context_line":"                headers.append((header, str(value)))"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"        if not status.startswith((\u0027200 \u0027, \u0027204 \u0027)):"}],"source_content_type":"text/x-python","patch_set":3,"id":"a9718f6c_3f003577","line":201,"range":{"start_line":201,"start_character":25,"end_line":201,"end_character":71},"in_reply_to":"87e3b6c4_0290885a","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"f8b465931022ef95024cda137dbebefc8a772f25","unresolved":true,"context_lines":[{"line_number":199,"context_line":"                # sadly, functional testing suggests casing matters in this"},{"line_number":200,"context_line":"                # case and I couldn\u0027t find an helper that does this in swob"},{"line_number":201,"context_line":"                header \u003d \u0027-\u0027.join(p.title() for p in header.split(\u0027-\u0027))"},{"line_number":202,"context_line":"                headers.append((header, str(value)))"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"        if not status.startswith((\u0027200 \u0027, \u0027204 \u0027)):"},{"line_number":205,"context_line":"            start_response(status, headers)"}],"source_content_type":"text/x-python","patch_set":3,"id":"84900a4e_f1865f67","line":202,"updated":"2024-11-21 23:43:49.000000000","message":"HeaderKeyDict?\n\nCan we just convert header to a headerkeydict:\n```\nheaders_dict \u003d HeaderKeyDict(headers)\n```\n\nUse that thoughout the function, then we wouldn\u0027t even need to use the header_to_index map anymore and then at the end whenever we do the `start_respone` we just:\n\n```\nstart_response(status, list(headers_dict.items())\n```","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":199,"context_line":"                # sadly, functional testing suggests casing matters in this"},{"line_number":200,"context_line":"                # case and I couldn\u0027t find an helper that does this in swob"},{"line_number":201,"context_line":"                header \u003d \u0027-\u0027.join(p.title() for p in header.split(\u0027-\u0027))"},{"line_number":202,"context_line":"                headers.append((header, str(value)))"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"        if not status.startswith((\u0027200 \u0027, \u0027204 \u0027)):"},{"line_number":205,"context_line":"            start_response(status, headers)"}],"source_content_type":"text/x-python","patch_set":3,"id":"f38329bf_3edfad6f","line":202,"in_reply_to":"64d5082f_fd9d59e8","updated":"2024-11-22 20:44:44.000000000","message":"Done","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"ac67aa6008c0959a39dfa0aaaa44d6585e92d73c","unresolved":true,"context_lines":[{"line_number":199,"context_line":"                # sadly, functional testing suggests casing matters in this"},{"line_number":200,"context_line":"                # case and I couldn\u0027t find an helper that does this in swob"},{"line_number":201,"context_line":"                header \u003d \u0027-\u0027.join(p.title() for p in header.split(\u0027-\u0027))"},{"line_number":202,"context_line":"                headers.append((header, str(value)))"},{"line_number":203,"context_line":""},{"line_number":204,"context_line":"        if not status.startswith((\u0027200 \u0027, \u0027204 \u0027)):"},{"line_number":205,"context_line":"            start_response(status, headers)"}],"source_content_type":"text/x-python","patch_set":3,"id":"64d5082f_fd9d59e8","line":202,"in_reply_to":"84900a4e_f1865f67","updated":"2024-11-22 07:09:15.000000000","message":"something like this: https://review.opendev.org/c/openstack/swift/+/935998","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":223,"context_line":"            # proxy logging (and maybe other mw?) seem to be good about"},{"line_number":224,"context_line":"            # sticking this on HEAD/204 but we do it here to be responsible"},{"line_number":225,"context_line":"            # and explicit"},{"line_number":226,"context_line":"            set_header(\u0027content-length\u0027, 0)"},{"line_number":227,"context_line":"            start_response(status, headers)"},{"line_number":228,"context_line":"            return resp_iter"},{"line_number":229,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"7859baf0_3afd3cbb","line":226,"updated":"2024-11-22 12:03:16.000000000","message":"I confirmed my conviction that proxy_logging was doing this by removing proxy_logging (both instances) from my pipeline, applying this patch to get the new func test but then reverting listing_formats.py to master...\n\nI also commented out the content-type assertion in the func test which would of course fail, to focus on content-length...\n\n```\n        # HEAD will *always* 204\n        self.assertEqual(resp.status, 204)\n        # self.assertEqual(resp.getheader(\u0027Content-Type\u0027),\n        #                  \u0027text/plain; charset\u003dutf-8\u0027)\n\u003e       self.assertEqual(resp.getheader(\u0027Content-Length\u0027), \u00270\u0027)\nE       AssertionError: None !\u003d \u00270\u0027\n\ntest/functional/test_container.py:135: AssertionError\n```","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":223,"context_line":"            # proxy logging (and maybe other mw?) seem to be good about"},{"line_number":224,"context_line":"            # sticking this on HEAD/204 but we do it here to be responsible"},{"line_number":225,"context_line":"            # and explicit"},{"line_number":226,"context_line":"            set_header(\u0027content-length\u0027, 0)"},{"line_number":227,"context_line":"            start_response(status, headers)"},{"line_number":228,"context_line":"            return resp_iter"},{"line_number":229,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"6b8df0f8_46ddd044","line":226,"in_reply_to":"7859baf0_3afd3cbb","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":true,"context_lines":[{"line_number":215,"context_line":""},{"line_number":216,"context_line":"        def set_header(header, value):"},{"line_number":217,"context_line":"            if value is None:"},{"line_number":218,"context_line":"                del headers[header_to_index[header]]"},{"line_number":219,"context_line":"            else:"},{"line_number":220,"context_line":"                headers[header_to_index[header]] \u003d ("},{"line_number":221,"context_line":"                    headers[header_to_index[header]][0], str(value))"}],"source_content_type":"text/x-python","patch_set":5,"id":"88d0bb57_8e0dd8ba","side":"PARENT","line":218,"updated":"2024-11-22 23:40:04.000000000","message":"why this didn\u0027t raise KeyError exception if ``\u0027content-length\u0027`` doesn\u0027t exist? but the new change won\u0027t have this issue.","commit_id":"ffbf17e47c0c76d4daa6e40811338e4abec1beb4"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"455af494f6a692f2d299d49d49ef0db5e817cc1c","unresolved":false,"context_lines":[{"line_number":215,"context_line":""},{"line_number":216,"context_line":"        def set_header(header, value):"},{"line_number":217,"context_line":"            if value is None:"},{"line_number":218,"context_line":"                del headers[header_to_index[header]]"},{"line_number":219,"context_line":"            else:"},{"line_number":220,"context_line":"                headers[header_to_index[header]] \u003d ("},{"line_number":221,"context_line":"                    headers[header_to_index[header]][0], str(value))"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f52d1c9_4d705fc4","side":"PARENT","line":218,"in_reply_to":"1613fa95_69d71ae6","updated":"2024-11-25 18:26:33.000000000","message":"ACK. it was the original bug which returned json format instead of txt.","commit_id":"ffbf17e47c0c76d4daa6e40811338e4abec1beb4"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"73ad5755ced015bb92f134265db3e713f13dc469","unresolved":true,"context_lines":[{"line_number":215,"context_line":""},{"line_number":216,"context_line":"        def set_header(header, value):"},{"line_number":217,"context_line":"            if value is None:"},{"line_number":218,"context_line":"                del headers[header_to_index[header]]"},{"line_number":219,"context_line":"            else:"},{"line_number":220,"context_line":"                headers[header_to_index[header]] \u003d ("},{"line_number":221,"context_line":"                    headers[header_to_index[header]][0], str(value))"}],"source_content_type":"text/x-python","patch_set":5,"id":"1613fa95_69d71ae6","side":"PARENT","line":218,"in_reply_to":"88d0bb57_8e0dd8ba","updated":"2024-11-25 11:41:06.000000000","message":"If content-length wasn\u0027t in headers then resp_length would be None and the method would return at line 214. But it\u0027s unfortunate that correctness here relied on the resp_length behavior.","commit_id":"ffbf17e47c0c76d4daa6e40811338e4abec1beb4"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":false,"context_lines":[{"line_number":183,"context_line":"            start_response(status, headers)"},{"line_number":184,"context_line":"            return resp_iter"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        headers_dict \u003d HeaderKeyDict(headers)"},{"line_number":187,"context_line":"        resp_content_type \u003d headers_dict.get("},{"line_number":188,"context_line":"            \u0027content-type\u0027, \u0027\u0027).partition(\u0027;\u0027)[0]"},{"line_number":189,"context_line":"        resp_length \u003d headers_dict.get(\u0027content-length\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"d72ee8e5_fae995e3","line":186,"updated":"2024-11-22 23:40:04.000000000","message":"nice usage of HeaderKeyDict; also, it\u0027s correct to be moved here after the handling of ``status``.","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":true,"context_lines":[{"line_number":196,"context_line":"            else:"},{"line_number":197,"context_line":"                headers_dict[\u0027vary\u0027] \u003d \u0027Accept\u0027"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if resp_content_type !\u003d \u0027application/json\u0027:"},{"line_number":200,"context_line":"            start_response(status, headers)"},{"line_number":201,"context_line":"            return resp_iter"},{"line_number":202,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"ded81086_1104bc01","line":199,"updated":"2024-11-22 23:40:04.000000000","message":"nit: this branch ``if resp_content_type !\u003d \u0027application/json\u0027`` can be moved to line 190 (before ``if can_vary``)","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"7ee058a85018037dc7afeba42cea8736ec9b01f4","unresolved":true,"context_lines":[{"line_number":197,"context_line":"                headers_dict[\u0027vary\u0027] \u003d \u0027Accept\u0027"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if resp_content_type !\u003d \u0027application/json\u0027:"},{"line_number":200,"context_line":"            start_response(status, headers)"},{"line_number":201,"context_line":"            return resp_iter"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"}],"source_content_type":"text/x-python","patch_set":5,"id":"a743aff5_2ccecc27","line":200,"updated":"2024-11-24 22:19:32.000000000","message":"Oh, or should this also be `list(headers_dict.items())` as the headers might have been changed. (ie Vary\u003dAccepted might have been added). But we\u0027re not passing that back.","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"11ff194e4e31830fadf18c04c69ddb015063544f","unresolved":true,"context_lines":[{"line_number":197,"context_line":"                headers_dict[\u0027vary\u0027] \u003d \u0027Accept\u0027"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if resp_content_type !\u003d \u0027application/json\u0027:"},{"line_number":200,"context_line":"            start_response(status, headers)"},{"line_number":201,"context_line":"            return resp_iter"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"}],"source_content_type":"text/x-python","patch_set":5,"id":"8a02e8d4_d004dcfc","line":200,"in_reply_to":"a743aff5_2ccecc27","updated":"2024-11-24 23:13:17.000000000","message":"This definitely used to pass on master:\n\n```\n     def test_add_vary_when_content_type_not_json(self):                                                                                                                                                                                                   \n         self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a\u0027, HTTPNoContent, {                                                                                                                                                                                        \n             \u0027Content-Length\u0027: \u00270\u0027,                                                                                                                                                                                                                        \n             \u0027Content-Type\u0027: \u0027text/plain\u0027}, b\u0027\u0027)                                                                                                                                                                                                           \n         req \u003d Request.blank(\u0027/v1/a\u0027, method\u003d\u0027HEAD\u0027)                                                                                                                                                                                                       \n         resp \u003d req.get_response(self.app)                                                                                                                                                                                                                 \n         self.assertEqual(resp.body, b\u0027\u0027)                                                                                                                                                                                                                  \n         # We actually returned early, we didn\u0027t change things in the                                                                                                                                                                                      \n         # request, but added the vary to let the cache know this                                                                                                                                                                                          \n         # request could vary based on Accept as we didn\u0027t pass in                                                                                                                                                                                         \n         # a format.                                                                                                                                                                                                                                       \n         self.assertEqual(resp.headers[\u0027Content-Type\u0027],                                                                                                                                                                                                    \n                          \u0027text/plain\u0027)                                                                                                                                                                                                                    \n         self.assertEqual(resp.headers[\u0027Vary\u0027], \u0027Accept\u0027)                                                                                                                                                                                                  \n         self.assertEqual(self.fake_swift.calls[-1], (                                                                                                                                                                                                     \n             \u0027HEAD\u0027, \u0027/v1/a?format\u003djson\u0027))             \n```\n\nDo Ii\u0027ll fix it and push up a new patchset.. then based on others +2 and jianjain\u0027s +1 I\u0027ll I might just go +A it and fix the gate. (so long as zuul likes it ;)","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":false,"context_lines":[{"line_number":209,"context_line":"            start_response(status, list(headers_dict.items()))"},{"line_number":210,"context_line":"            return resp_iter"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"        if resp_length is None or \\"},{"line_number":213,"context_line":"                int(resp_length) \u003e MAX_CONTAINER_LISTING_CONTENT_LENGTH:"},{"line_number":214,"context_line":"            start_response(status, list(headers_dict.items()))"},{"line_number":215,"context_line":"            return resp_iter"}],"source_content_type":"text/x-python","patch_set":5,"id":"0fb9e330_a864ca19","line":212,"updated":"2024-11-22 23:40:04.000000000","message":"okay, this is the main fix by moving this if branch to be after ``if req.method \u003d\u003d \u0027HEAD\u0027``.","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1264f88da9223184a28386df6124fa02072e7ad6","unresolved":true,"context_lines":[{"line_number":183,"context_line":"            start_response(status, headers)"},{"line_number":184,"context_line":"            return resp_iter"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        headers_dict \u003d HeaderKeyDict(headers)"},{"line_number":187,"context_line":"        resp_content_type \u003d headers_dict.get("},{"line_number":188,"context_line":"            \u0027content-type\u0027, \u0027\u0027).partition(\u0027;\u0027)[0]"},{"line_number":189,"context_line":"        resp_length \u003d headers_dict.get(\u0027content-length\u0027)"}],"source_content_type":"text/x-python","patch_set":6,"id":"720591da_b7a48554","line":186,"updated":"2024-12-02 20:15:36.000000000","message":"FYI -- this has impacts if there are repeated headers. I remember seeing this with other middlewares and `WWW-Authenticate` in the DSVM jobs (which is why we can\u0027t `@wsgify` everything).\n\nProbably shouldn\u0027t impact listing-formats, though, at least not at this point (ie, after checking status code) -- but it does make me wonder if we might prefer to just make a `swob.Response`.","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"73ad5755ced015bb92f134265db3e713f13dc469","unresolved":true,"context_lines":[{"line_number":186,"context_line":"        headers_dict \u003d HeaderKeyDict(headers)"},{"line_number":187,"context_line":"        resp_content_type \u003d headers_dict.get("},{"line_number":188,"context_line":"            \u0027content-type\u0027, \u0027\u0027).partition(\u0027;\u0027)[0]"},{"line_number":189,"context_line":"        resp_length \u003d headers_dict.get(\u0027content-length\u0027)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"        if can_vary:"},{"line_number":192,"context_line":"            if \u0027vary\u0027 in headers_dict:"}],"source_content_type":"text/x-python","patch_set":6,"id":"c6e1efcc_b9a29526","line":189,"updated":"2024-11-25 11:41:06.000000000","message":"nit: this isn\u0027t used until after the possible return at line 201","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1264f88da9223184a28386df6124fa02072e7ad6","unresolved":true,"context_lines":[{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":204,"context_line":"            headers_dict[\u0027content-type\u0027] \u003d out_content_type + \u0027; charset\u003dutf-8\u0027"},{"line_number":205,"context_line":"            # proxy logging (and maybe other mw?) seem to be good about"},{"line_number":206,"context_line":"            # sticking this on HEAD/204 but we do it here to be responsible"},{"line_number":207,"context_line":"            # and explicit"},{"line_number":208,"context_line":"            headers_dict[\u0027content-length\u0027] \u003d 0"},{"line_number":209,"context_line":"            start_response(status, list(headers_dict.items()))"},{"line_number":210,"context_line":"            return resp_iter"},{"line_number":211,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"a6bfc622_4e9401ba","line":208,"range":{"start_line":205,"start_character":12,"end_line":208,"end_character":46},"updated":"2024-12-02 20:15:36.000000000","message":"This doesn\u0027t sit well with me. Explicitly setting the content-length implies that (assuming no other changes in the system, which is a **huge** caveat for any kind of listings) a subsequent GET should respond with the same content-length. That\u0027s why I was popping it off before.","commit_id":"fa889358acf7675efba2de095777886b4c1ff7f8"}],"test/functional/test_container.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":111,"context_line":"            # retry despite the request having been successfully processed."},{"line_number":112,"context_line":"            self.assertIn(resp.status, (204, 404))"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def test_content_type(self):"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"ca57f9d7_0be3c581","line":114,"updated":"2024-11-21 13:15:00.000000000","message":"I find that having the method name(s) in test names helps me when scanning a file for potentially relevant tests","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":111,"context_line":"            # retry despite the request having been successfully processed."},{"line_number":112,"context_line":"            self.assertIn(resp.status, (204, 404))"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def test_content_type(self):"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"4112864f_8e141d97","line":114,"in_reply_to":"ca57f9d7_0be3c581","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def test_content_type(self):"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"},{"line_number":118,"context_line":"            conn.request(method, parsed.path + \u0027/\u0027 + container + qs, \u0027\u0027, {"},{"line_number":119,"context_line":"                \u0027X-Auth-Token\u0027: token})"}],"source_content_type":"text/x-python","patch_set":2,"id":"58257c3d_c54e6b6e","line":116,"range":{"start_line":116,"start_character":12,"end_line":116,"end_character":15},"updated":"2024-11-21 13:15:00.000000000","message":"``req`` is used so widely as the name of a Request object that I found this a confusing *method* name, vs something verb-like e.g. ``send_req``","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def test_content_type(self):"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"},{"line_number":118,"context_line":"            conn.request(method, parsed.path + \u0027/\u0027 + container + qs, \u0027\u0027, {"},{"line_number":119,"context_line":"                \u0027X-Auth-Token\u0027: token})"}],"source_content_type":"text/x-python","patch_set":2,"id":"60d92055_f531eb69","line":116,"range":{"start_line":116,"start_character":12,"end_line":116,"end_character":15},"in_reply_to":"58257c3d_c54e6b6e","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"},{"line_number":118,"context_line":"            conn.request(method, parsed.path + \u0027/\u0027 + container + qs, \u0027\u0027, {"},{"line_number":119,"context_line":"                \u0027X-Auth-Token\u0027: token})"},{"line_number":120,"context_line":"            return check_response(conn)"},{"line_number":121,"context_line":"        resp \u003d retry(req, \u0027GET\u0027, self.name, {})"}],"source_content_type":"text/x-python","patch_set":2,"id":"84416e25_be246042","line":118,"range":{"start_line":118,"start_character":73,"end_line":118,"end_character":74},"updated":"2024-11-21 13:15:00.000000000","message":"nit: seems unnecessary to leave the \u0027{\u0027 dangling here, and contrary to style elsewhere in this file","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        def req(url, token, parsed, conn, method, container, params):"},{"line_number":117,"context_line":"            qs \u003d \u0027?%s\u0027 % urllib.parse.urlencode(params) if params else \u0027\u0027"},{"line_number":118,"context_line":"            conn.request(method, parsed.path + \u0027/\u0027 + container + qs, \u0027\u0027, {"},{"line_number":119,"context_line":"                \u0027X-Auth-Token\u0027: token})"},{"line_number":120,"context_line":"            return check_response(conn)"},{"line_number":121,"context_line":"        resp \u003d retry(req, \u0027GET\u0027, self.name, {})"}],"source_content_type":"text/x-python","patch_set":2,"id":"c0c63519_783b9c74","line":118,"range":{"start_line":118,"start_character":73,"end_line":118,"end_character":74},"in_reply_to":"84416e25_be246042","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":120,"context_line":"            return check_response(conn)"},{"line_number":121,"context_line":"        resp \u003d retry(req, \u0027GET\u0027, self.name, {})"},{"line_number":122,"context_line":"        # GET is still 204 if there\u0027s no objects!?"},{"line_number":123,"context_line":"        self.assertEqual(resp.status, 204)"},{"line_number":124,"context_line":"        # we respond text/plain by default"},{"line_number":125,"context_line":"        self.assertEqual(resp.getheader(\u0027Content-Type\u0027),"},{"line_number":126,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"78a003df_cf3afd2a","line":123,"updated":"2024-11-21 13:15:00.000000000","message":"for completeness, repeat for HEAD to the empty container","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":120,"context_line":"            return check_response(conn)"},{"line_number":121,"context_line":"        resp \u003d retry(req, \u0027GET\u0027, self.name, {})"},{"line_number":122,"context_line":"        # GET is still 204 if there\u0027s no objects!?"},{"line_number":123,"context_line":"        self.assertEqual(resp.status, 204)"},{"line_number":124,"context_line":"        # we respond text/plain by default"},{"line_number":125,"context_line":"        self.assertEqual(resp.getheader(\u0027Content-Type\u0027),"},{"line_number":126,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff7af9fc_c924dc76","line":123,"in_reply_to":"78a003df_cf3afd2a","updated":"2024-11-21 16:53:33.000000000","message":"Done","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fe2205661aeccd8a1abfdccdf410647d2fd53eef","unresolved":true,"context_lines":[{"line_number":147,"context_line":"        resp \u003d retry(req, \u0027HEAD\u0027, self.name, {\u0027format\u0027: \u0027json\u0027})"},{"line_number":148,"context_line":"        self.assertEqual(resp.status, 204)"},{"line_number":149,"context_line":"        self.assertEqual(resp.getheader(\u0027Content-Type\u0027),"},{"line_number":150,"context_line":"                         \u0027application/json; charset\u003dutf-8\u0027)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    def test_multi_metadata(self):"},{"line_number":153,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":2,"id":"c3f428b2_3351db0f","line":150,"updated":"2024-11-21 13:15:00.000000000","message":"we could test \u0027xml\u0027 too while we\u0027re at it","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03677a339238f78137af4f334a9b0d968a6a6d05","unresolved":false,"context_lines":[{"line_number":147,"context_line":"        resp \u003d retry(req, \u0027HEAD\u0027, self.name, {\u0027format\u0027: \u0027json\u0027})"},{"line_number":148,"context_line":"        self.assertEqual(resp.status, 204)"},{"line_number":149,"context_line":"        self.assertEqual(resp.getheader(\u0027Content-Type\u0027),"},{"line_number":150,"context_line":"                         \u0027application/json; charset\u003dutf-8\u0027)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    def test_multi_metadata(self):"},{"line_number":153,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":2,"id":"34e2a336_9cb1e185","line":150,"in_reply_to":"c3f428b2_3351db0f","updated":"2024-11-21 16:53:33.000000000","message":"we could test format\u003dtxt while were at it - although I\u0027m not sure exactly how to demonstrate the expected value should be format\u003dplain\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/common/middleware/listing_formats.py#L30","commit_id":"0653ba17d6929f403e341e57586326f77b8bf47a"}],"test/unit/common/middleware/test_listing_formats.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":132,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":133,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"},{"line_number":134,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":135,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def test_accept_content_type_on_missing_qs(self):"},{"line_number":138,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a/c\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"b336020c_56238964","line":135,"updated":"2024-11-22 12:03:16.000000000","message":"+1, this adds coverage the case that the func-cors test was (perhaps unintentionally) hitting with format\u003dtxt","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":133,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"},{"line_number":134,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":135,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def test_accept_content_type_on_missing_qs(self):"},{"line_number":138,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a/c\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"1b6f5423_4373573e","line":135,"in_reply_to":"b336020c_56238964","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":145,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":146,"context_line":"                         \u0027application/xml; charset\u003dutf-8\u0027)"},{"line_number":147,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":148,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def test_accept_ignored_on_invalid_qs(self):"},{"line_number":151,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a/c\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"14e03233_4957b3a6","line":148,"updated":"2024-11-22 12:03:16.000000000","message":"+1 this fails on master because without content-length neither the query string or accept header are applied","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":145,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":146,"context_line":"                         \u0027application/xml; charset\u003dutf-8\u0027)"},{"line_number":147,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":148,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def test_accept_ignored_on_invalid_qs(self):"},{"line_number":151,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a/c\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"599ad3e6_0a700b1d","line":148,"in_reply_to":"14e03233_4957b3a6","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":158,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":159,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"},{"line_number":160,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":161,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def test_valid_content_type_on_xml_head(self):"},{"line_number":164,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"c0ad610b_49ff9e46","line":161,"updated":"2024-11-22 12:03:16.000000000","message":"+1 this fails on master because without content-length neither the query string or accept header are applied","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":158,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":159,"context_line":"                         \u0027text/plain; charset\u003dutf-8\u0027)"},{"line_number":160,"context_line":"        self.assertEqual(self.fake_swift.calls[-1], ("},{"line_number":161,"context_line":"            \u0027HEAD\u0027, \u0027/v1/a/c?format\u003djson\u0027))"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def test_valid_content_type_on_xml_head(self):"},{"line_number":164,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a\u0027, HTTPNoContent, {"}],"source_content_type":"text/x-python","patch_set":3,"id":"b1f732cc_412d4f79","line":161,"in_reply_to":"c0ad610b_49ff9e46","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f75e36a58c6dee6a3ae16ff721743b71eb10795b","unresolved":true,"context_lines":[{"line_number":181,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027}, b\u0027\u0027)"},{"line_number":182,"context_line":"        req \u003d Request.blank(\u0027/v1/a?format\u003dxml\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":183,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":184,"context_line":"        self.assertEqual(resp.body, b\u0027\u0027)"},{"line_number":185,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":186,"context_line":"                         \u0027application/xml; charset\u003dutf-8\u0027)"},{"line_number":187,"context_line":"        # query param overrides header, so it won\u0027t vary"}],"source_content_type":"text/x-python","patch_set":3,"id":"e582ec33_f2a32271","line":184,"updated":"2024-11-22 12:03:16.000000000","message":"with the latest patchset there\u0027s now several tests that have no content-length in the fake response, but since this one calls it out in the test name it makes sense to actually assert that the content-length is now inserted\n\n```\nself.assertEqual(resp.headers[\u0027Content-Length\u0027], \u00270\u0027)\n```","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"454eac295ae911ed57bc10f56e84a8777d1c05f6","unresolved":false,"context_lines":[{"line_number":181,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027}, b\u0027\u0027)"},{"line_number":182,"context_line":"        req \u003d Request.blank(\u0027/v1/a?format\u003dxml\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":183,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":184,"context_line":"        self.assertEqual(resp.body, b\u0027\u0027)"},{"line_number":185,"context_line":"        self.assertEqual(resp.headers[\u0027Content-Type\u0027],"},{"line_number":186,"context_line":"                         \u0027application/xml; charset\u003dutf-8\u0027)"},{"line_number":187,"context_line":"        # query param overrides header, so it won\u0027t vary"}],"source_content_type":"text/x-python","patch_set":3,"id":"48651910_3ee71fb8","line":184,"in_reply_to":"e582ec33_f2a32271","updated":"2024-11-22 20:44:44.000000000","message":"Acknowledged","commit_id":"68c6437ec085ec95e5a2c94395090ac1a4609fa8"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1e0d6bd1f880a95392e3464f1847890fe9d4d3fe","unresolved":true,"context_lines":[{"line_number":180,"context_line":"        # responses"},{"line_number":181,"context_line":"        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a\u0027, HTTPNoContent, {"},{"line_number":182,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027}, b\u0027\u0027)"},{"line_number":183,"context_line":"        req \u003d Request.blank(\u0027/v1/a?format\u003dxml\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":184,"context_line":"        status, headers, body \u003d req.call_application(self.app)"},{"line_number":185,"context_line":"        self.assertEqual(b\u0027\u0027.join(body), b\u0027\u0027)"},{"line_number":186,"context_line":"        headers_dict \u003d dict(headers)"}],"source_content_type":"text/x-python","patch_set":5,"id":"db1d40e7_f307dcc1","line":183,"updated":"2024-11-22 23:40:04.000000000","message":"The author said ``format\u003dtxt`` is not a valid value in the commit message \"?format\u003dtxt requests (which is maybe not even a valid value for that qs param?)\". Even though it may not be valid, but Zuul/CORS test does this, we should add a test for it as well?\n\nBelow test passed on my vasio.\n\n```\n    def test_valid_content_type_on_txt_head_with_no_content_length(self):\n        # note: eventlet 0.38.0 stopped including content-length with 204\n        # responses\n        self.fake_swift.register(\u0027HEAD\u0027, \u0027/v1/a\u0027, HTTPNoContent, {\n            \u0027Content-Type\u0027: \u0027application/json\u0027}, b\u0027\u0027)\n        req \u003d Request.blank(\u0027/v1/a?format\u003dtxt\u0027, method\u003d\u0027HEAD\u0027)\n        status, headers, body \u003d req.call_application(self.app)\n        self.assertEqual(b\u0027\u0027.join(body), b\u0027\u0027)\n        headers_dict \u003d dict(headers)\n        self.assertEqual(headers_dict.get(\u0027Content-Length\u0027), \u00270\u0027, headers)\n        self.assertEqual(headers_dict[\u0027Content-Type\u0027],\n                         \u0027text/plain; charset\u003dutf-8\u0027)\n        # query param overrides header, so it won\u0027t vary\n        self.assertNotIn(\u0027Vary\u0027, HeaderKeyDict(headers_dict))\n        self.assertEqual(self.fake_swift.calls[-1], (\n            \u0027HEAD\u0027, \u0027/v1/a?format\u003djson\u0027))\n```","commit_id":"21ddc60e7cd136a07ed2177bb19209f9ed7b0ede"}]}
