)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"88c02cacb514a26afa3453a7c30203f7fc264787","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We plan to allow PUT requests to create/update both custom traits"},{"line_number":10,"context_line":"and custom resource classes, without bodies. Prior to this change,"},{"line_number":11,"context_line":"the code would not all a PUT, POST or PATCH to not have a body. This was"},{"line_number":12,"context_line":"added in I6e7dffb5dc5f0cdc78a57e8df3ae9952c55163ae which was fixing an"},{"line_number":13,"context_line":"issue with how webob handles exceptions."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"ffe62b97_e67e6fad","line":11,"updated":"2017-03-29 19:22:10.000000000","message":"s/not all/not allow/","commit_id":"d29870b8297f9c80c2e2a4e76f2eaef4feab7763"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"88c02cacb514a26afa3453a7c30203f7fc264787","unresolved":false,"context_lines":[{"line_number":21,"context_line":"* If a request has a content-length (indicating the presence of a body),"},{"line_number":22,"context_line":"  verify that there is also a content-type. If not, raise a 400."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"basic-http.yaml has been change to modify one gabbi test to check a"},{"line_number":25,"context_line":"response body is correct and to add another test to confirm that the"},{"line_number":26,"context_line":"code that is doing the content-length check is passed through."},{"line_number":27,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"ffe62b97_e115393e","line":24,"updated":"2017-03-29 19:22:10.000000000","message":"s/been change/been changed/","commit_id":"d29870b8297f9c80c2e2a4e76f2eaef4feab7763"}],"nova/api/openstack/placement/handler.py":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"3eee49bfd0db9eb9530434860136697bb6011804","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_46d5271a","line":181,"range":{"start_line":181,"start_character":8,"end_line":181,"end_character":49},"updated":"2017-03-21 12:19:13.000000000","message":"I can\u0027t input a length that is match to the length of request body. It sounds like we implement a strange behaviour also. Can we just remove the check from the line 181 to line 185?","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"874b778fef8f6919491803a4ef5815da187cb762","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_85f55458","line":181,"in_reply_to":"1a1ced50_46d5271a","updated":"2017-03-21 13:07:08.000000000","message":"Checking for the content-length header is a way to check for the presence of a body, without actually reading from the body filehandle. Then, once we know there is a body we need to raise an error if there is no content-type header. That error should be a 400.\n\nIf we leave this code out, then the response code would be a 415 which should only be sent if the content-type header is set, but set incorrectly.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"707943a3486655a3f19352c7a071a73cc5829408","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_1a0297b4","line":181,"in_reply_to":"1a1ced50_6e33d514","updated":"2017-03-21 15:06:56.000000000","message":"discuss with Chris on the IRC. Chris pointed out that if we want to return 400 when no content-type and no content-length, we have to read the body. That is waste. And in the real world, most of client will send the content-length.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"c49e80205e545b8d1e38c36efafb028ff29f7776","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_8bd7234a","line":181,"in_reply_to":"1a1ced50_85f55458","updated":"2017-03-21 13:34:54.000000000","message":"sorry, I didn\u0027t describe clearly.\n\nI mean with this patch, I can request with header \u0027content-length: 1\u0027, but actually, the body is longer than that. The server still can accept the request. That is a strange API behaviour?\n\nAnd yes, agree that we should return 400 when no content-type. But we can return 400 in the decorator require_content","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"2e64f68d2ffe087e08fbb73f356dc345e4a2b268","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_ee3c25ca","line":181,"in_reply_to":"1a1ced50_8bd7234a","updated":"2017-03-21 13:45:26.000000000","message":"I think the strange behavior you are describing happens with or without this patch, doesn\u0027t it? It is common in most WSGI-based applications. It is often the case that content-length is wrong or that wsgi frameworks ignore it and just read the the body filehandle to its end. We\u0027re not trying to address that problem here, just a missing content-type header.\n\n\u003e But we can return 400 in the decorator require_content\n\nWe could but we don\u0027t want to require the require_content decorator everywhere, but we do want this enforcement everywhere, so having it works better.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"1ed0ef4c0f2a4ffe289fc9cfe3596a5a677151ee","unresolved":false,"context_lines":[{"line_number":178,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":179,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":180,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":181,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":182,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":183,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":184,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_6e33d514","line":181,"in_reply_to":"1a1ced50_ee3c25ca","updated":"2017-03-21 14:32:15.000000000","message":"yes, actually, we just ignore the \u0027content-length\u0027. I just didn\u0027t get why we need this logic at here. This patch makes me confuse about why we begin to take care about \u0027content-length\u0027.(yes, we actually didn\u0027t care about \u0027content-length\u0027, we actually care about \u0027content-type\u0027).\n\nif put the content-type checking in \u0027require_content\u0027 decorator, that sounds like clearly to me. If the API require a body, you need to pass the body and the header \u0027content-type\u0027. If the API didn\u0027t require a body, the server will ignore those headers.\n\nAnd with this patch, if no \u0027content-length\u0027 and \u0027content-type\u0027 sent, I will get 415, not the 400. I thought it should be 400 also, not the 415.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":6167,"name":"Ken\u0027ichi Ohmichi","email":"ken1ohmichi@gmail.com","username":"oomichi"},"change_message_id":"7d69f8be64858fb6c22cdb4fba50a45e4ed7c63c","unresolved":false,"context_lines":[{"line_number":179,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"},{"line_number":180,"context_line":"        # Check that an incoming request with a content-length"},{"line_number":181,"context_line":"        # header also has a content-type header. If not raise a 400."},{"line_number":182,"context_line":"        if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)):"},{"line_number":183,"context_line":"            if \u0027CONTENT_TYPE\u0027 not in environ:"},{"line_number":184,"context_line":"                raise webob.exc.HTTPBadRequest("},{"line_number":185,"context_line":"                    _(\u0027content-type header required\u0027),"}],"source_content_type":"text/x-python","patch_set":5,"id":"ffe62b97_fbd5a1ba","line":182,"range":{"start_line":182,"start_character":11,"end_line":182,"end_character":15},"updated":"2017-03-24 20:26:45.000000000","message":"I was a little confused this int() because of this \"if\".\nMaybe this int() could be useful for string value of CONTENT_LENGTH of \u00270\u0027. So\n\n if int(environ.get(\u0027CONTENT_LENGTH\u0027, 0)) \u003e 0:\n\nis more readable, but that is nit.","commit_id":"9a53efdcedfaa9312a94a44aadbf566e75351301"}],"nova/api/openstack/placement/util.py":[{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"258ee789860959b25bc14a3c25019941be0b68e3","unresolved":false,"context_lines":[{"line_number":126,"context_line":"                # a useful message in that case. This also avoids a"},{"line_number":127,"context_line":"                # KeyError raised when webob.exc eagerly fills in a"},{"line_number":128,"context_line":"                # Template for output we will never use."},{"line_number":129,"context_line":"                if not req.content_type:"},{"line_number":130,"context_line":"                    req.content_type \u003d \u0027None\u0027"},{"line_number":131,"context_line":"                raise webob.exc.HTTPUnsupportedMediaType("},{"line_number":132,"context_line":"                    _(\u0027The media type %(bad_type)s is not supported, \u0027"},{"line_number":133,"context_line":"                      \u0027use %(good_type)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_7f81cac2","line":130,"range":{"start_line":129,"start_character":16,"end_line":130,"end_character":45},"updated":"2017-03-21 10:42:57.000000000","message":"Emm...the strange thing is after I removed this code, then I didn\u0027t get a 500.\n\nThe request I tested is:\n\n\ncurl -g -i -X PUT http://hp-pc/placement/resource_classes/CUSTOM_C_4 -H \"OpenStack-API-Version: placement 1.4\"  -H \"X-Auth-Token: gAAAAABY0QQW4cctsk_F4Wa9LK5ke3wYiJUglecFyw4-cqVxoAfU6a-LSwvBPRWFknZ-5SN1NfcBt_4HRKolhwqyuSBvN-SKQMfNaFx4eAVeJfvUb5B-DBZwRVPbH-yCAto3H-L_5-0cZ4FF5xL-4EckcbOhuA_JBjeUZMfz8DzAJR1G0QKQJ08\" -d \u0027{\"name\": \"CUSTOM_C_5\"}\u0027\n\n\nHTTP/1.1 200 OK\nDate: Tue, 21 Mar 2017 10:59:49 GMT\nServer: Apache/2.4.18 (Ubuntu)\nOpenStack-API-Version: placement 1.4\nvary: OpenStack-API-Version\nx-openstack-request-id: req-f88524b1-36e1-4c1a-b0e8-e38bd2674580\nContent-Length: 100\nContent-Type: application/json\n\n\n{\"name\": \"CUSTOM_C_5\", \"links\": [{\"href\": \"/placement/resource_classes/CUSTOM_C_5\", \"rel\": \"self\"}]}","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"874b778fef8f6919491803a4ef5815da187cb762","unresolved":false,"context_lines":[{"line_number":127,"context_line":"                # KeyError raised when webob.exc eagerly fills in a"},{"line_number":128,"context_line":"                # Template for output we will never use."},{"line_number":129,"context_line":"                if not req.content_type:"},{"line_number":130,"context_line":"                    req.content_type \u003d \u0027None\u0027"},{"line_number":131,"context_line":"                raise webob.exc.HTTPUnsupportedMediaType("},{"line_number":132,"context_line":"                    _(\u0027The media type %(bad_type)s is not supported, \u0027"},{"line_number":133,"context_line":"                      \u0027use %(good_type)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_856ab4ec","line":130,"in_reply_to":"1a1ced50_06e6cf43","updated":"2017-03-21 13:07:08.000000000","message":"That\u0027s a result of the way webob handles creating error responses. It looks at the accept header. If the header is not present it uses it\u0027s own default.\n\nWe can fix that default in the new PlacementWsgify  decorator, but that should be a separate fix for a separate bug.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"3eee49bfd0db9eb9530434860136697bb6011804","unresolved":false,"context_lines":[{"line_number":126,"context_line":"                # a useful message in that case. This also avoids a"},{"line_number":127,"context_line":"                # KeyError raised when webob.exc eagerly fills in a"},{"line_number":128,"context_line":"                # Template for output we will never use."},{"line_number":129,"context_line":"                if not req.content_type:"},{"line_number":130,"context_line":"                    req.content_type \u003d \u0027None\u0027"},{"line_number":131,"context_line":"                raise webob.exc.HTTPUnsupportedMediaType("},{"line_number":132,"context_line":"                    _(\u0027The media type %(bad_type)s is not supported, \u0027"},{"line_number":133,"context_line":"                      \u0027use %(good_type)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_06e6cf43","line":130,"range":{"start_line":129,"start_character":16,"end_line":130,"end_character":45},"in_reply_to":"1a1ced50_7f81cac2","updated":"2017-03-21 12:19:13.000000000","message":"Thanks for Chris pointed to me, the \u0027curl\u0027 will send \u0027content-type\u0027 with \u0027-d\u0027 parameters.\n\nI did a test at here, we set the \"req.contenxt_type \u003d none\" at here. But finally I get an error message with \"\u0027Content-Type\u0027: \u0027text/html; charset\u003dUTF-8\u0027\"\n\nSo I thought why we didn\u0027t set the \"req.content_type \u003d \u0027application/json\u0027\" at here, than the api user can get a json response, and that can be parsed by the client which always assume the response is json from the openstack API.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"c49e80205e545b8d1e38c36efafb028ff29f7776","unresolved":false,"context_lines":[{"line_number":127,"context_line":"                # KeyError raised when webob.exc eagerly fills in a"},{"line_number":128,"context_line":"                # Template for output we will never use."},{"line_number":129,"context_line":"                if not req.content_type:"},{"line_number":130,"context_line":"                    req.content_type \u003d \u0027None\u0027"},{"line_number":131,"context_line":"                raise webob.exc.HTTPUnsupportedMediaType("},{"line_number":132,"context_line":"                    _(\u0027The media type %(bad_type)s is not supported, \u0027"},{"line_number":133,"context_line":"                      \u0027use %(good_type)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_cb9cbb5f","line":130,"in_reply_to":"1a1ced50_856ab4ec","updated":"2017-03-21 13:34:54.000000000","message":"agree that is separate bug.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"2e64f68d2ffe087e08fbb73f356dc345e4a2b268","unresolved":false,"context_lines":[{"line_number":127,"context_line":"                # KeyError raised when webob.exc eagerly fills in a"},{"line_number":128,"context_line":"                # Template for output we will never use."},{"line_number":129,"context_line":"                if not req.content_type:"},{"line_number":130,"context_line":"                    req.content_type \u003d \u0027None\u0027"},{"line_number":131,"context_line":"                raise webob.exc.HTTPUnsupportedMediaType("},{"line_number":132,"context_line":"                    _(\u0027The media type %(bad_type)s is not supported, \u0027"},{"line_number":133,"context_line":"                      \u0027use %(good_type)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"1a1ced50_4e30d9e8","line":130,"in_reply_to":"1a1ced50_cb9cbb5f","updated":"2017-03-21 13:45:26.000000000","message":"I\u0027ll make one.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"}],"nova/tests/functional/api/openstack/placement/gabbits/basic-http.yaml":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"1c55cf8d90e976b7373a01e13c0fded3a18e8299","unresolved":false,"context_lines":[{"line_number":91,"context_line":"  response_strings:"},{"line_number":92,"context_line":"      - content-type header required"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"# NOTE(cdent): This is an awkward test. It is not actually testing a"},{"line_number":95,"context_line":"# PUT of a resource provider. It is confirming that a PUT with no"},{"line_number":96,"context_line":"# body, no content-length header and no content-type header will"},{"line_number":97,"context_line":"# reach the desired handler."}],"source_content_type":"text/x-yaml","patch_set":2,"id":"1a1ced50_058964c9","line":94,"range":{"start_line":94,"start_character":15,"end_line":94,"end_character":38},"updated":"2017-03-21 13:05:02.000000000","message":"That\u0027s an understatement. :-P\n\nPerhaps when we get the traits API merged we can replace this with:\n\n    PUT /traits/CUSTOM_TRAIT_NAME\n\nso that we can have a direct PUT that doesn\u0027t expect a body.","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"874b778fef8f6919491803a4ef5815da187cb762","unresolved":false,"context_lines":[{"line_number":91,"context_line":"  response_strings:"},{"line_number":92,"context_line":"      - content-type header required"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"# NOTE(cdent): This is an awkward test. It is not actually testing a"},{"line_number":95,"context_line":"# PUT of a resource provider. It is confirming that a PUT with no"},{"line_number":96,"context_line":"# body, no content-length header and no content-type header will"},{"line_number":97,"context_line":"# reach the desired handler."}],"source_content_type":"text/x-yaml","patch_set":2,"id":"1a1ced50_c5474c75","line":94,"in_reply_to":"1a1ced50_058964c9","updated":"2017-03-21 13:07:08.000000000","message":"Yeah, good idea, but in the meantime...","commit_id":"39c4aefcdd1ed693489df06ca2e77288852a971c"}]}
