)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":13,"context_line":"TODO:"},{"line_number":14,"context_line":" - tests for different configs (post-as-copy)"},{"line_number":15,"context_line":" - unit tests"},{"line_number":16,"context_line":" - func tests with other middleware (obj. versioning, *LO, crypto)"},{"line_number":17,"context_line":" - conditional_gets"},{"line_number":18,"context_line":" - OPTION method"},{"line_number":19,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":31,"id":"dada55a8_aef71a8b","line":16,"range":{"start_line":16,"start_character":54,"end_line":16,"end_character":57},"updated":"2016-07-22 19:35:18.000000000","message":"FWIW, it seems like we should be able to have a symlink that points to a DLO, but we won\u0027t be able to have a DLO that references a symlink. DLO uses container listings to not only get object names but also object sizes. Symlinks will necessarily have a 0-byte size in container listings, which will cause DLO to bomb out when it finds data in the dereferenced link.\n\nSLO should work both ways, though. Probably worth having a test that involves a submanifest that gets replaced with a symlink.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"}],"api-ref/source/parameters.yaml":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":862,"context_line":"    The ``X-Symlink-Target`` must also be set for this to"},{"line_number":863,"context_line":"    be effective."},{"line_number":864,"context_line":"    You must UTF-8-encode and then URL-encode the account name"},{"line_number":865,"context_line":"    before you include them in this header."},{"line_number":866,"context_line":"  in: header"},{"line_number":867,"context_line":"  required: false"},{"line_number":868,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":51,"id":"1a430d35_0e7ef5ad","line":865,"range":{"start_line":865,"start_character":23,"end_line":865,"end_character":27},"updated":"2017-02-07 19:33:54.000000000","message":"it","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":862,"context_line":"    The ``X-Symlink-Target`` must also be set for this to"},{"line_number":863,"context_line":"    be effective."},{"line_number":864,"context_line":"    You must UTF-8-encode and then URL-encode the account name"},{"line_number":865,"context_line":"    before you include them in this header."},{"line_number":866,"context_line":"  in: header"},{"line_number":867,"context_line":"  required: false"},{"line_number":868,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":51,"id":"fa31d9ce_8f91329d","line":865,"range":{"start_line":865,"start_character":23,"end_line":865,"end_character":27},"in_reply_to":"1a430d35_0e7ef5ad","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":1128,"context_line":"  type: string"},{"line_number":1129,"context_line":"symlink:"},{"line_number":1130,"context_line":"  description: |"},{"line_number":1131,"context_line":"    If you include the ``symlink\u003dtrue`` query parameter"},{"line_number":1132,"context_line":"    and the object is a symlink, then the response will include"},{"line_number":1133,"context_line":"    data and metadata from the symlink itself rather than from the target."},{"line_number":1134,"context_line":"  in: query"}],"source_content_type":"text/x-yaml","patch_set":51,"id":"1a430d35_62214d9f","line":1131,"range":{"start_line":1131,"start_character":33,"end_line":1131,"end_character":37},"updated":"2017-02-07 19:33:54.000000000","message":"\u0027get\u0027, now?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":1128,"context_line":"  type: string"},{"line_number":1129,"context_line":"symlink:"},{"line_number":1130,"context_line":"  description: |"},{"line_number":1131,"context_line":"    If you include the ``symlink\u003dtrue`` query parameter"},{"line_number":1132,"context_line":"    and the object is a symlink, then the response will include"},{"line_number":1133,"context_line":"    data and metadata from the symlink itself rather than from the target."},{"line_number":1134,"context_line":"  in: query"}],"source_content_type":"text/x-yaml","patch_set":51,"id":"fa31d9ce_0f3aa298","line":1131,"range":{"start_line":1131,"start_character":33,"end_line":1131,"end_character":37},"in_reply_to":"1a430d35_62214d9f","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":1136,"context_line":"  type: string"},{"line_number":1137,"context_line":"symlink_copy:"},{"line_number":1138,"context_line":"  description: |"},{"line_number":1139,"context_line":"    If you include the ``symlink-true`` query parameter"},{"line_number":1140,"context_line":"    and the object is a symlink, the target object"},{"line_number":1141,"context_line":"    contents are not copied. Instead, the symlink is copied to"},{"line_number":1142,"context_line":"    the create a new symlink to the same target."}],"source_content_type":"text/x-yaml","patch_set":51,"id":"1a430d35_0ea7d54f","line":1139,"range":{"start_line":1139,"start_character":32,"end_line":1139,"end_character":33},"updated":"2017-02-07 19:33:54.000000000","message":"\u003d, not -, yes?\n\nAlso, \u0027get\u0027, not \u0027true\u0027?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":1136,"context_line":"  type: string"},{"line_number":1137,"context_line":"symlink_copy:"},{"line_number":1138,"context_line":"  description: |"},{"line_number":1139,"context_line":"    If you include the ``symlink-true`` query parameter"},{"line_number":1140,"context_line":"    and the object is a symlink, the target object"},{"line_number":1141,"context_line":"    contents are not copied. Instead, the symlink is copied to"},{"line_number":1142,"context_line":"    the create a new symlink to the same target."}],"source_content_type":"text/x-yaml","patch_set":51,"id":"fa31d9ce_8f46921f","line":1139,"range":{"start_line":1139,"start_character":32,"end_line":1139,"end_character":33},"in_reply_to":"1a430d35_0ea7d54f","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":1145,"context_line":"  type: string"},{"line_number":1146,"context_line":"symlink_post:"},{"line_number":1147,"context_line":"  description: |"},{"line_number":1148,"context_line":"    If you include the ``symlink-true`` query parameter"},{"line_number":1149,"context_line":"    and the object is a symlink, the target object"},{"line_number":1150,"context_line":"    metadata is not updated. Instead, the metadata of the"},{"line_number":1151,"context_line":"    symlink itself will be updated."}],"source_content_type":"text/x-yaml","patch_set":51,"id":"1a430d35_c23681e6","line":1148,"range":{"start_line":1148,"start_character":32,"end_line":1148,"end_character":37},"updated":"2017-02-07 19:33:54.000000000","message":"\u003dpost, yeah?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":1145,"context_line":"  type: string"},{"line_number":1146,"context_line":"symlink_post:"},{"line_number":1147,"context_line":"  description: |"},{"line_number":1148,"context_line":"    If you include the ``symlink-true`` query parameter"},{"line_number":1149,"context_line":"    and the object is a symlink, the target object"},{"line_number":1150,"context_line":"    metadata is not updated. Instead, the metadata of the"},{"line_number":1151,"context_line":"    symlink itself will be updated."}],"source_content_type":"text/x-yaml","patch_set":51,"id":"fa31d9ce_af5516c7","line":1148,"range":{"start_line":1148,"start_character":32,"end_line":1148,"end_character":37},"in_reply_to":"1a430d35_c23681e6","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":1139,"context_line":"    If you include the ``symlink\u003dget`` query parameter"},{"line_number":1140,"context_line":"    and the object is a symlink, the target object"},{"line_number":1141,"context_line":"    contents are not copied. Instead, the symlink is copied to"},{"line_number":1142,"context_line":"    the create a new symlink to the same target."},{"line_number":1143,"context_line":"  in: query"},{"line_number":1144,"context_line":"  required: false"},{"line_number":1145,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":53,"id":"dfeb2761_e28f1f21","line":1142,"range":{"start_line":1142,"start_character":4,"end_line":1142,"end_character":8},"updated":"2017-04-03 09:05:38.000000000","message":"Is not this \u0027the\u0027 unnecessary?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1139,"context_line":"    If you include the ``symlink\u003dget`` query parameter"},{"line_number":1140,"context_line":"    and the object is a symlink, the target object"},{"line_number":1141,"context_line":"    contents are not copied. Instead, the symlink is copied to"},{"line_number":1142,"context_line":"    the create a new symlink to the same target."},{"line_number":1143,"context_line":"  in: query"},{"line_number":1144,"context_line":"  required: false"},{"line_number":1145,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":53,"id":"bff0334d_460df43c","line":1142,"range":{"start_line":1142,"start_character":4,"end_line":1142,"end_character":8},"in_reply_to":"dfeb2761_e28f1f21","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":1145,"context_line":"  type: string"},{"line_number":1146,"context_line":"symlink_post:"},{"line_number":1147,"context_line":"  description: |"},{"line_number":1148,"context_line":"    If you include the ``symlink\u003dpost`` query parameter"},{"line_number":1149,"context_line":"    and the object is a symlink, the target object"},{"line_number":1150,"context_line":"    metadata is not updated. Instead, the metadata of the"},{"line_number":1151,"context_line":"    symlink itself will be updated."},{"line_number":1152,"context_line":"  in: query"},{"line_number":1153,"context_line":"  required: false"},{"line_number":1154,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":53,"id":"dfeb2761_42c7eb46","line":1151,"range":{"start_line":1148,"start_character":1,"end_line":1151,"end_character":35},"updated":"2017-04-03 09:05:38.000000000","message":"I think this explanation looks like that we can update target object metadata without ``symlink\u003dpost``.\nBehavior of POST without ``symlink\u003dpost`` should be explained.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1145,"context_line":"  type: string"},{"line_number":1146,"context_line":"symlink_post:"},{"line_number":1147,"context_line":"  description: |"},{"line_number":1148,"context_line":"    If you include the ``symlink\u003dpost`` query parameter"},{"line_number":1149,"context_line":"    and the object is a symlink, the target object"},{"line_number":1150,"context_line":"    metadata is not updated. Instead, the metadata of the"},{"line_number":1151,"context_line":"    symlink itself will be updated."},{"line_number":1152,"context_line":"  in: query"},{"line_number":1153,"context_line":"  required: false"},{"line_number":1154,"context_line":"  type: string"}],"source_content_type":"text/x-yaml","patch_set":53,"id":"bff0334d_260af025","line":1151,"range":{"start_line":1148,"start_character":1,"end_line":1151,"end_character":35},"in_reply_to":"dfeb2761_42c7eb46","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"}],"api-ref/source/storage-object-services.inc":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":673,"context_line":"400 status code is returned and the object metadata is not modified."},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink when the ``symlink\u003dtrue`` query"},{"line_number":676,"context_line":"sring is not used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dtrue`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a 300-series error response to the client."},{"line_number":679,"context_line":"The POST is never redirected to the target object."}],"source_content_type":"text/x-c++src","patch_set":51,"id":"5a3905b3_d254cb55","line":676,"updated":"2017-01-19 23:50:02.000000000","message":"The double-negative is a little confusing; I think I\u0027d prefer\n\n\u003e POST requests should only be sent to a symlink when the ``symlink\u003dtrue`` query string is used.\n\nor even\n\n\u003e POST requests should not be sent to a symlink unless the ``symlink\u003dtrue`` query string is used.\n\nsince it at least brings the negatives closer together.\n\nAlso, s/sring/string/","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":673,"context_line":"400 status code is returned and the object metadata is not modified."},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink when the ``symlink\u003dtrue`` query"},{"line_number":676,"context_line":"sring is not used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dtrue`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a 300-series error response to the client."},{"line_number":679,"context_line":"The POST is never redirected to the target object."}],"source_content_type":"text/x-c++src","patch_set":51,"id":"fa31d9ce_2b0d2ce8","line":676,"in_reply_to":"5a3905b3_d254cb55","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":675,"context_line":"POST requests should not be sent to a symlink when the ``symlink\u003dtrue`` query"},{"line_number":676,"context_line":"sring is not used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dtrue`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a 300-series error response to the client."},{"line_number":679,"context_line":"The POST is never redirected to the target object."},{"line_number":680,"context_line":""},{"line_number":681,"context_line":"Example requests and responses:"}],"source_content_type":"text/x-c++src","patch_set":51,"id":"5a3905b3_b2d65fc3","line":678,"range":{"start_line":678,"start_character":33,"end_line":678,"end_character":49},"updated":"2017-01-19 23:50:02.000000000","message":"May as well be explicit; \"307 Temporary Redirect\". I\u0027m also not sure we really want \"error\" ... I mean, it kinda is, but we *did* apply the metadata, it\u0027s just that the client should probably go do this *other* thing, too.","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":675,"context_line":"POST requests should not be sent to a symlink when the ``symlink\u003dtrue`` query"},{"line_number":676,"context_line":"sring is not used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dtrue`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a 300-series error response to the client."},{"line_number":679,"context_line":"The POST is never redirected to the target object."},{"line_number":680,"context_line":""},{"line_number":681,"context_line":"Example requests and responses:"}],"source_content_type":"text/x-c++src","patch_set":51,"id":"fa31d9ce_2bdb6c50","line":678,"range":{"start_line":678,"start_character":33,"end_line":678,"end_character":49},"in_reply_to":"5a3905b3_b2d65fc3","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":320,"context_line":"and new manifest objects share the same set of segment objects."},{"line_number":321,"context_line":""},{"line_number":322,"context_line":"To copy a symlink either with a COPY or a PUT with the"},{"line_number":323,"context_line":"``X-Copy-From`` request, include the ``symlink\u003dtrue`` query string."},{"line_number":324,"context_line":"The new symlink will have the same target as the original."},{"line_number":325,"context_line":"The target object is not copied. Instead, both the original"},{"line_number":326,"context_line":"and new symlinks point to the same target object."}],"source_content_type":"text/x-c++src","patch_set":53,"id":"dfeb2761_02bb230e","line":323,"range":{"start_line":323,"start_character":47,"end_line":323,"end_character":51},"updated":"2017-04-03 09:05:38.000000000","message":"``symlink\u003dget`` is correct.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":320,"context_line":"and new manifest objects share the same set of segment objects."},{"line_number":321,"context_line":""},{"line_number":322,"context_line":"To copy a symlink either with a COPY or a PUT with the"},{"line_number":323,"context_line":"``X-Copy-From`` request, include the ``symlink\u003dtrue`` query string."},{"line_number":324,"context_line":"The new symlink will have the same target as the original."},{"line_number":325,"context_line":"The target object is not copied. Instead, both the original"},{"line_number":326,"context_line":"and new symlinks point to the same target object."}],"source_content_type":"text/x-c++src","patch_set":53,"id":"bff0334d_a1514a11","line":323,"range":{"start_line":323,"start_character":47,"end_line":323,"end_character":51},"in_reply_to":"dfeb2761_02bb230e","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":673,"context_line":"400 status code is returned and the object metadata is not modified."},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."}],"source_content_type":"text/x-c++src","patch_set":53,"id":"dfeb2761_225507c7","line":676,"range":{"start_line":676,"start_character":0,"end_line":676,"end_character":5},"updated":"2017-04-03 09:05:38.000000000","message":"string","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":673,"context_line":"400 status code is returned and the object metadata is not modified."},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."}],"source_content_type":"text/x-c++src","patch_set":53,"id":"bff0334d_c89fb14e","line":676,"in_reply_to":"dfeb2761_225507c7","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."},{"line_number":680,"context_line":""}],"source_content_type":"text/x-c++src","patch_set":53,"id":"dfeb2761_02c5635b","line":677,"range":{"start_line":677,"start_character":30,"end_line":677,"end_character":73},"updated":"2017-04-03 09:05:38.000000000","message":"I think the fact that \"the applied metadata will not be included in response of GET/HEAD request to the symlink without ``symlink\u003dget``\" should be explained.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."},{"line_number":680,"context_line":""}],"source_content_type":"text/x-c++src","patch_set":53,"id":"dfeb2761_e2603fa8","line":677,"range":{"start_line":677,"start_character":23,"end_line":677,"end_character":28},"updated":"2017-04-03 09:05:38.000000000","message":"string","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."},{"line_number":680,"context_line":""}],"source_content_type":"text/x-c++src","patch_set":53,"id":"bff0334d_a876ad05","line":677,"in_reply_to":"dfeb2761_02c5635b","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"POST requests should not be sent to a symlink unless the ``symlink\u003dpost`` query"},{"line_number":676,"context_line":"sring is used. When a POST request is sent to a symlink without the"},{"line_number":677,"context_line":"``symlink\u003dpost`` query sring, the metadata will be applied to the symlink,"},{"line_number":678,"context_line":"but the request will result in a ``307 Temporary Redirect`` response to the"},{"line_number":679,"context_line":"client. The POST is never redirected to the target object."},{"line_number":680,"context_line":""}],"source_content_type":"text/x-c++src","patch_set":53,"id":"bff0334d_88a9a97c","line":677,"in_reply_to":"dfeb2761_e2603fa8","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"60d5d2f6e8eb7f46e67907427a8f65f601c93c4a","unresolved":false,"context_lines":[{"line_number":748,"context_line":"   - object: object"},{"line_number":749,"context_line":"   - bulk-delete: bulk-delete"},{"line_number":750,"context_line":"   - extract-archive: extract-archive"},{"line_number":751,"context_line":"   - symlink: symlink_post"},{"line_number":752,"context_line":"   - X-Auth-Token: X-Auth-Token"},{"line_number":753,"context_line":"   - X-Service-Token: X-Service-Token"},{"line_number":754,"context_line":"   - X-Object-Meta-name: X-Object-Meta-name"}],"source_content_type":"text/x-c++src","patch_set":74,"id":"df87a7cf_a45008d6","line":751,"updated":"2017-12-06 10:02:18.000000000","message":"This parameter is reverted while developing","commit_id":"2259484862c19d67e5e93e8345f0560e6672a857"}],"doc/saio/swift/proxy-server.conf":[{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":9,"context_line":"[pipeline:main]"},{"line_number":10,"context_line":"# Yes, proxy-logging appears twice. This is so that"},{"line_number":11,"context_line":"# middleware-originated requests get logged too."},{"line_number":12,"context_line":"pipeline \u003d catch_errors gatekeeper healthcheck proxy-logging cache bulk tempurl ratelimit crossdomain container_sync tempauth staticweb container-quotas account-quotas slo dlo symlink versioned_writes proxy-logging proxy-server"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"[filter:catch_errors]"},{"line_number":15,"context_line":"use \u003d egg:swift#catch_errors"}],"source_content_type":"text/plain","patch_set":26,"id":"3a29b11f_5730919e","line":12,"updated":"2015-10-25 12:00:27.000000000","message":"Okay, with this ordering you can have a symlink point to a SLO manifest and that\u0027ll work... and you can have a symlink as a segment of a SLO manifest too. Good.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"}],"doc/source/api/object_api_v1_overview.rst":[{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":91,"context_line":"   -  Upload objects directly to the Object Storage system from a"},{"line_number":92,"context_line":"      browser by using form **POST** middleware."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"   -  Create symbolic links to existing objects."},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"The account, container, and object hierarchy affects the way you"},{"line_number":97,"context_line":"interact with the Object Storage API."}],"source_content_type":"text/x-rst","patch_set":53,"id":"dfeb2761_02d683f2","line":94,"range":{"start_line":94,"start_character":31,"end_line":94,"end_character":40},"updated":"2017-04-03 09:05:38.000000000","message":"I think we can create symbolic links to non-existing objects.\n\"Create symbolic links to another object path\" is correct.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":91,"context_line":"   -  Upload objects directly to the Object Storage system from a"},{"line_number":92,"context_line":"      browser by using form **POST** middleware."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"   -  Create symbolic links to existing objects."},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"The account, container, and object hierarchy affects the way you"},{"line_number":97,"context_line":"interact with the Object Storage API."}],"source_content_type":"text/x-rst","patch_set":53,"id":"bff0334d_e8039541","line":94,"range":{"start_line":94,"start_character":31,"end_line":94,"end_character":40},"in_reply_to":"dfeb2761_02d683f2","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"}],"doc/source/cors.rst":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e1668f32aec21e43295255f85df2a6b58cc1032f","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    An OPTIONS request to a symlink object will respond with the options for"},{"line_number":54,"context_line":"    the symlink only, the request will not be redirected to the target object."},{"line_number":55,"context_line":"    Therefore, if the symlink\u0027s target object is in another container with"},{"line_number":56,"context_line":"    cors settings, the response will not reflect the settings."},{"line_number":57,"context_line":""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"-----------------"}],"source_content_type":"text/x-rst","patch_set":76,"id":"df87a7cf_2b42ee0f","line":56,"range":{"start_line":56,"start_character":4,"end_line":56,"end_character":8},"updated":"2017-12-13 10:33:20.000000000","message":"nit: capitalize","commit_id":"2968cb6b11898a26df9e1546c589cc1a15ae7db9"}],"etc/proxy-server.conf-sample":[{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":758,"context_line":"#"},{"line_number":759,"context_line":"# Note: Put after dlo, before versioned_writes in the pipeline."},{"line_number":760,"context_line":"[filter:symlink]"},{"line_number":761,"context_line":"use \u003d egg:swift#symlink"}],"source_content_type":"application/octet-stream","patch_set":30,"id":"bab6814e_0f886cc4","line":761,"updated":"2016-05-26 10:23:32.000000000","message":"symloop_max option needs to be documented here","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":758,"context_line":"#"},{"line_number":759,"context_line":"# Note: Put after dlo, before versioned_writes in the pipeline."},{"line_number":760,"context_line":"[filter:symlink]"},{"line_number":761,"context_line":"use \u003d egg:swift#symlink"}],"source_content_type":"application/octet-stream","patch_set":30,"id":"dada55a8_2959a435","line":761,"in_reply_to":"bab6814e_0f886cc4","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":801,"context_line":"# in the pipeline in order for existing encrypted data to be read."},{"line_number":802,"context_line":"# disable_encryption \u003d False"},{"line_number":803,"context_line":"#"},{"line_number":804,"context_line":"# Note: Put after dlo, before versioned_writes in the pipeline."},{"line_number":805,"context_line":"[filter:symlink]"},{"line_number":806,"context_line":"use \u003d egg:swift#symlink"},{"line_number":807,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"}],"source_content_type":"application/octet-stream","patch_set":31,"id":"dada55a8_ae6c3a37","line":804,"updated":"2016-07-22 19:35:18.000000000","message":"So if versioned_writes is updated to use symlinks, it will need to work with the raw sysmeta headers instead of the client-facing headers?","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":801,"context_line":"# in the pipeline in order for existing encrypted data to be read."},{"line_number":802,"context_line":"# disable_encryption \u003d False"},{"line_number":803,"context_line":"#"},{"line_number":804,"context_line":"# Note: Put after dlo, before versioned_writes in the pipeline."},{"line_number":805,"context_line":"[filter:symlink]"},{"line_number":806,"context_line":"use \u003d egg:swift#symlink"},{"line_number":807,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"}],"source_content_type":"application/octet-stream","patch_set":31,"id":"dada55a8_245662d2","line":804,"in_reply_to":"dada55a8_ae6c3a37","updated":"2016-07-27 16:27:16.000000000","message":"This configuration file actually needed to be updated and I missed it. I\u0027ve now put symlink after versioned_writes as I\u0027d expect it to be able to use it using client-facing headers.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":805,"context_line":"[filter:symlink]"},{"line_number":806,"context_line":"use \u003d egg:swift#symlink"},{"line_number":807,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":808,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":809,"context_line":"# will be produced."},{"line_number":810,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":38,"id":"9a89bdaa_da853ccf","line":809,"range":{"start_line":808,"start_character":63,"end_line":809,"end_character":18},"updated":"2016-09-08 10:39:29.000000000","message":"It will probably be best if you mention here that a 412 (HTTPPreconditionFailed) is returned.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":805,"context_line":"[filter:symlink]"},{"line_number":806,"context_line":"use \u003d egg:swift#symlink"},{"line_number":807,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":808,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":809,"context_line":"# will be produced."},{"line_number":810,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":38,"id":"9a89bdaa_7b117651","line":809,"range":{"start_line":808,"start_character":63,"end_line":809,"end_character":18},"in_reply_to":"9a89bdaa_da853ccf","updated":"2016-09-09 19:55:29.000000000","message":"Done","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"9da7a5aea5358a880d1b0c22dff1e9841005a2f5","unresolved":false,"context_lines":[{"line_number":779,"context_line":"# deprecated. See documentation for more details."},{"line_number":780,"context_line":"# allow_versioned_writes \u003d false"},{"line_number":781,"context_line":""},{"line_number":782,"context_line":"# Note: Put after auth and before dlo and slo middlewares."},{"line_number":783,"context_line":"# If you don\u0027t put it in the pipeline, it will be inserted for you."},{"line_number":784,"context_line":"[filter:copy]"},{"line_number":785,"context_line":"use \u003d egg:swift#copy"}],"source_content_type":"application/octet-stream","patch_set":40,"id":"ba5da102_1094f140","line":782,"updated":"2016-11-03 01:57:58.000000000","message":"Add a note that if you use both symlinks and crypto, the symlinks middleware must come first.  I haven\u0027t looked at why there are failures if you switch these, but the symlink functests fail if you have symlink after crypto.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":779,"context_line":"# deprecated. See documentation for more details."},{"line_number":780,"context_line":"# allow_versioned_writes \u003d false"},{"line_number":781,"context_line":""},{"line_number":782,"context_line":"# Note: Put after auth and before dlo and slo middlewares."},{"line_number":783,"context_line":"# If you don\u0027t put it in the pipeline, it will be inserted for you."},{"line_number":784,"context_line":"[filter:copy]"},{"line_number":785,"context_line":"use \u003d egg:swift#copy"}],"source_content_type":"application/octet-stream","patch_set":40,"id":"9a629dbe_a6fdaab2","line":782,"in_reply_to":"ba5da102_1094f140","updated":"2016-11-15 19:53:28.000000000","message":"Lines 793-797 detail encryption configuration and mention including at the very end. I expanded on the symlink note to mention encryption","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"0e93805777fd19db1ff9d56a752460b474fa53e1","unresolved":false,"context_lines":[{"line_number":829,"context_line":"[filter:symlink]"},{"line_number":830,"context_line":"use \u003d egg:swift#symlink"},{"line_number":831,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":832,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":833,"context_line":"# will be produced."},{"line_number":834,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":40,"id":"3a98d1f4_60812ac3","line":833,"range":{"start_line":832,"start_character":63,"end_line":833,"end_character":19},"updated":"2016-09-30 11:53:45.000000000","message":"nit: It will probably be best if you mention here that a 412 (HTTPPreconditionFailed) is returned.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":829,"context_line":"[filter:symlink]"},{"line_number":830,"context_line":"use \u003d egg:swift#symlink"},{"line_number":831,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":832,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":833,"context_line":"# will be produced."},{"line_number":834,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":40,"id":"9a629dbe_0625765a","line":833,"range":{"start_line":832,"start_character":63,"end_line":833,"end_character":19},"in_reply_to":"3a98d1f4_60812ac3","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":855,"context_line":"[filter:symlink]"},{"line_number":856,"context_line":"use \u003d egg:swift#symlink"},{"line_number":857,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":858,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 412"},{"line_number":859,"context_line":"# (HTTPPreconditionFailed) error response will be produced."},{"line_number":860,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":51,"id":"5a3905b3_7337a6b0","line":859,"range":{"start_line":858,"start_character":65,"end_line":859,"end_character":32},"updated":"2017-01-19 23:50:02.000000000","message":"400 Bad Request now, yeah?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":855,"context_line":"[filter:symlink]"},{"line_number":856,"context_line":"use \u003d egg:swift#symlink"},{"line_number":857,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":858,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 412"},{"line_number":859,"context_line":"# (HTTPPreconditionFailed) error response will be produced."},{"line_number":860,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":51,"id":"fa31d9ce_ab74bc35","line":859,"range":{"start_line":858,"start_character":65,"end_line":859,"end_character":32},"in_reply_to":"5a3905b3_7337a6b0","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":920,"context_line":"[filter:listing_formats]"},{"line_number":921,"context_line":"use \u003d egg:swift#listing_formats"},{"line_number":922,"context_line":""},{"line_number":923,"context_line":"# Note: Put after slo, dlo, but before versioned_writes and encryption in the"},{"line_number":924,"context_line":"# pipeline."},{"line_number":925,"context_line":"[filter:symlink]"},{"line_number":926,"context_line":"use \u003d egg:swift#symlink"}],"source_content_type":"application/octet-stream","patch_set":59,"id":"7f515b1d_1f184ad1","line":923,"range":{"start_line":923,"start_character":27,"end_line":923,"end_character":55},"updated":"2017-10-05 11:25:05.000000000","message":"In above pipeline sample and \"doc/saio/swift/proxy-server.conf\", symlink is after versioned_writes.\nWhich is correct? Note or pipeline samples?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":920,"context_line":"[filter:listing_formats]"},{"line_number":921,"context_line":"use \u003d egg:swift#listing_formats"},{"line_number":922,"context_line":""},{"line_number":923,"context_line":"# Note: Put after slo, dlo, but before versioned_writes and encryption in the"},{"line_number":924,"context_line":"# pipeline."},{"line_number":925,"context_line":"[filter:symlink]"},{"line_number":926,"context_line":"use \u003d egg:swift#symlink"}],"source_content_type":"application/octet-stream","patch_set":59,"id":"5f4e5783_b2cd9967","line":923,"range":{"start_line":923,"start_character":27,"end_line":923,"end_character":55},"in_reply_to":"7f515b1d_1f184ad1","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"60d5d2f6e8eb7f46e67907427a8f65f601c93c4a","unresolved":false,"context_lines":[{"line_number":940,"context_line":"[filter:symlink]"},{"line_number":941,"context_line":"use \u003d egg:swift#symlink"},{"line_number":942,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":943,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 400"},{"line_number":944,"context_line":"# (HTTPBadRequest) error response will be produced."},{"line_number":945,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":74,"id":"df87a7cf_c422ec52","line":944,"range":{"start_line":943,"start_character":65,"end_line":944,"end_character":51},"updated":"2017-12-06 10:02:18.000000000","message":"This is 409 not 400 BadRequest.","commit_id":"2259484862c19d67e5e93e8345f0560e6672a857"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e1668f32aec21e43295255f85df2a6b58cc1032f","unresolved":false,"context_lines":[{"line_number":939,"context_line":"# pipeline."},{"line_number":940,"context_line":"[filter:symlink]"},{"line_number":941,"context_line":"use \u003d egg:swift#symlink"},{"line_number":942,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":943,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 409"},{"line_number":944,"context_line":"# (HTTPConflict) error response will be produced."},{"line_number":945,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":76,"id":"df87a7cf_0bf12a01","line":942,"range":{"start_line":942,"start_character":2,"end_line":942,"end_character":66},"updated":"2017-12-13 10:33:20.000000000","message":"nit: this sentence suggests to me that by default I can have 2 symlinks that point to another symlink i.e. 3 symlinks in total, the last pointing to a target. The next sentence is clearer. Perhaps:\n\n  Symlinks can point to other symlinks provided the number of symlinks in a chain does not exceed the symloop_max value.","commit_id":"2968cb6b11898a26df9e1546c589cc1a15ae7db9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":939,"context_line":"# pipeline."},{"line_number":940,"context_line":"[filter:symlink]"},{"line_number":941,"context_line":"use \u003d egg:swift#symlink"},{"line_number":942,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":943,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 409"},{"line_number":944,"context_line":"# (HTTPConflict) error response will be produced."},{"line_number":945,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":76,"id":"df87a7cf_327d5ae7","line":942,"range":{"start_line":942,"start_character":2,"end_line":942,"end_character":66},"in_reply_to":"df87a7cf_0bf12a01","updated":"2017-12-14 01:13:05.000000000","message":"Done at follow up.","commit_id":"2968cb6b11898a26df9e1546c589cc1a15ae7db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e1668f32aec21e43295255f85df2a6b58cc1032f","unresolved":false,"context_lines":[{"line_number":940,"context_line":"[filter:symlink]"},{"line_number":941,"context_line":"use \u003d egg:swift#symlink"},{"line_number":942,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":943,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 409"},{"line_number":944,"context_line":"# (HTTPConflict) error response will be produced."},{"line_number":945,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":76,"id":"df87a7cf_6bd7964c","line":943,"range":{"start_line":943,"start_character":47,"end_line":943,"end_character":62},"updated":"2017-12-13 10:33:20.000000000","message":"nit: remove the double back ticks - it\u0027s not rst and there is no other use of them in this file","commit_id":"2968cb6b11898a26df9e1546c589cc1a15ae7db9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":940,"context_line":"[filter:symlink]"},{"line_number":941,"context_line":"use \u003d egg:swift#symlink"},{"line_number":942,"context_line":"# Symlinks can point to other symlinks up to the symloop_max value. If the"},{"line_number":943,"context_line":"# number of chained symlinks exceeds the limit ``symloop_max`` a 409"},{"line_number":944,"context_line":"# (HTTPConflict) error response will be produced."},{"line_number":945,"context_line":"# symloop_max \u003d 2"}],"source_content_type":"application/octet-stream","patch_set":76,"id":"df87a7cf_926b061e","line":943,"range":{"start_line":943,"start_character":47,"end_line":943,"end_character":62},"in_reply_to":"df87a7cf_6bd7964c","updated":"2017-12-14 01:13:05.000000000","message":"Done at follow up","commit_id":"2968cb6b11898a26df9e1546c589cc1a15ae7db9"}],"swift/common/internal_client.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":614,"context_line":"        headers \u003d headers or {}"},{"line_number":615,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":616,"context_line":"        if query_string:"},{"line_number":617,"context_line":"            path +\u003d \u0027?\u0027 + query_string"},{"line_number":618,"context_line":"        resp \u003d self.make_request(\u0027GET\u0027, path, headers, acceptable_statuses)"},{"line_number":619,"context_line":"        return (resp.status_int, resp.headers, resp.app_iter)"},{"line_number":620,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_ce731eb1","line":617,"updated":"2017-10-05 09:04:37.000000000","message":"It might be YAGNI but why not we have the code in make_request method? Isn\u0027t it useful for other requests?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":614,"context_line":"        headers \u003d headers or {}"},{"line_number":615,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":616,"context_line":"        if query_string:"},{"line_number":617,"context_line":"            path +\u003d \u0027?\u0027 + query_string"},{"line_number":618,"context_line":"        resp \u003d self.make_request(\u0027GET\u0027, path, headers, acceptable_statuses)"},{"line_number":619,"context_line":"        return (resp.status_int, resp.headers, resp.app_iter)"},{"line_number":620,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_d1c3be56","line":617,"in_reply_to":"7f515b1d_ce731eb1","updated":"2017-10-05 11:25:05.000000000","message":"I added this change for symlink with container-sync.\nBut as I said in swift/container/sync.py comment, I will update the method for symlink with container-sync.\nSo this change will be removed with the update.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"db12b6bda65fa9bd71c9aaacc9c117cd09832752","unresolved":false,"context_lines":[{"line_number":614,"context_line":"        headers \u003d headers or {}"},{"line_number":615,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":616,"context_line":"        if query_string:"},{"line_number":617,"context_line":"            path +\u003d \u0027?\u0027 + query_string"},{"line_number":618,"context_line":"        resp \u003d self.make_request(\u0027GET\u0027, path, headers, acceptable_statuses)"},{"line_number":619,"context_line":"        return (resp.status_int, resp.headers, resp.app_iter)"},{"line_number":620,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_bf108b58","line":617,"in_reply_to":"7f515b1d_d1c3be56","updated":"2017-10-25 17:10:40.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        :param account: The object\u0027s account."},{"line_number":619,"context_line":"        :param container: The object\u0027s container."},{"line_number":620,"context_line":"        :param obj: The object name."},{"line_number":621,"context_line":"        :param headers: Headers to send with request, defaults to empty dict."},{"line_number":622,"context_line":"        :param acceptable_statuses: List of status for valid responses,"},{"line_number":623,"context_line":"                                    defaults to (2,)."},{"line_number":624,"context_line":"        :param params: A dict of params to be set in request query string,"}],"source_content_type":"text/x-python","patch_set":79,"id":"df87a7cf_3209dadc","line":621,"range":{"start_line":621,"start_character":54,"end_line":621,"end_character":76},"updated":"2017-12-14 01:13:05.000000000","message":"exactly it\u0027s as\n\n headers \u003d headers or {}\n\nbut it\u0027s not a kwargs (i.e. required argument), tho.","commit_id":"99b89aea1051208e3d71afa35fcd62035e702628"}],"swift/common/middleware/copy.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4ef2d5b7048c101418cae75242e4e4593bc26b7a","unresolved":false,"context_lines":[{"line_number":254,"context_line":"        self.object_post_as_copy \u003d \\"},{"line_number":255,"context_line":"            config_true_value(conf.get(\u0027object_post_as_copy\u0027, \u0027true\u0027))"},{"line_number":256,"context_line":"        register_swift_info(\u0027copy\u0027,"},{"line_number":257,"context_line":"                            object_post_as_copy\u003dself.object_post_as_copy)"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"    def _load_object_post_as_copy_conf(self, conf):"},{"line_number":260,"context_line":"        if (\u0027object_post_as_copy\u0027 in conf or \u0027__file__\u0027 not in conf):"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_72118aac","line":257,"updated":"2016-08-08 20:56:47.000000000","message":"Do we actually need this? Would it be better as a separate change?\n\nI\u0027m not necessarily opposed to exposing it (since as a client, it\u0027s fairly easy to find out this value -- time how long it takes to POST to a 5GB object), but it feels out-of-scope here.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"08ff1b642d153bc149d1f3dad72a58f90072c65e","unresolved":false,"context_lines":[{"line_number":254,"context_line":"        self.object_post_as_copy \u003d \\"},{"line_number":255,"context_line":"            config_true_value(conf.get(\u0027object_post_as_copy\u0027, \u0027true\u0027))"},{"line_number":256,"context_line":"        register_swift_info(\u0027copy\u0027,"},{"line_number":257,"context_line":"                            object_post_as_copy\u003dself.object_post_as_copy)"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"    def _load_object_post_as_copy_conf(self, conf):"},{"line_number":260,"context_line":"        if (\u0027object_post_as_copy\u0027 in conf or \u0027__file__\u0027 not in conf):"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_112d8746","line":257,"in_reply_to":"9ad45d7e_72118aac","updated":"2016-08-24 15:15:56.000000000","message":"agreed, this was left by mistake. It was necessary for determining to skip or not symlink POST func tests. I will remove in the next patchset","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"}],"swift/common/middleware/crypto/decrypter.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b1bea3ad8fa4c375f316d52737635aa374c6b637","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                                     to be decrypted but crypto meta was not"},{"line_number":104,"context_line":"                                     found."},{"line_number":105,"context_line":"        \"\"\""},{"line_number":106,"context_line":"        extracted_value, crypto_meta \u003d extract_crypto_meta(value)"},{"line_number":107,"context_line":"        if crypto_meta:"},{"line_number":108,"context_line":"            self.crypto.check_crypto_meta(crypto_meta)"},{"line_number":109,"context_line":"            value \u003d self.decrypt_value(extracted_value, key, crypto_meta)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_56f7ff59","line":106,"range":{"start_line":106,"start_character":8,"end_line":106,"end_character":18},"updated":"2017-12-11 16:08:53.000000000","message":"ok. this change is necessary so that the decryptor does not strip off symlink taget from etag.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"b3fce795cd4e67f31f2b2480b161c2862bcfc839","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                                     to be decrypted but crypto meta was not"},{"line_number":104,"context_line":"                                     found."},{"line_number":105,"context_line":"        \"\"\""},{"line_number":106,"context_line":"        extracted_value, crypto_meta \u003d extract_crypto_meta(value)"},{"line_number":107,"context_line":"        if crypto_meta:"},{"line_number":108,"context_line":"            self.crypto.check_crypto_meta(crypto_meta)"},{"line_number":109,"context_line":"            value \u003d self.decrypt_value(extracted_value, key, crypto_meta)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_4755f9f8","line":106,"range":{"start_line":106,"start_character":8,"end_line":106,"end_character":18},"in_reply_to":"df87a7cf_56f7ff59","updated":"2017-12-12 01:54:43.000000000","message":"Yes. In particular the case if encryption is in pipeline but disabled (attempting decrypt but it\u0027s not encrypted).","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"swift/common/middleware/symlink.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2011 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_763610e9","line":1,"updated":"2015-10-12 01:02:23.000000000","message":"Change to \"2010-2015\"","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2011 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_f25c58ef","line":1,"in_reply_to":"7a2fa921_763610e9","updated":"2015-10-13 19:08:05.000000000","message":"Done","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":84,"context_line":"            # value is always None causing this code to use last-modified,"},{"line_number":85,"context_line":"            # which only has 1 second granularity. Need to figure out correct"},{"line_number":86,"context_line":"            # method for fetching the timestamp."},{"line_number":87,"context_line":"            timestamp \u003d self._response_header_value(\u0027swift_x_timestamp\u0027)"},{"line_number":88,"context_line":"            if timestamp is None:"},{"line_number":89,"context_line":"                timestamp \u003d time.mktime(time.strptime("},{"line_number":90,"context_line":"                                        self._response_header_value("}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_164a3c56","line":87,"updated":"2015-10-12 01:02:23.000000000","message":"do you want \u0027x-timestamp\u0027 instead of \u0027swift_x_timestamp\u0027?","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":84,"context_line":"            # value is always None causing this code to use last-modified,"},{"line_number":85,"context_line":"            # which only has 1 second granularity. Need to figure out correct"},{"line_number":86,"context_line":"            # method for fetching the timestamp."},{"line_number":87,"context_line":"            timestamp \u003d self._response_header_value(\u0027swift_x_timestamp\u0027)"},{"line_number":88,"context_line":"            if timestamp is None:"},{"line_number":89,"context_line":"                timestamp \u003d time.mktime(time.strptime("},{"line_number":90,"context_line":"                                        self._response_header_value("}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_fb250c5c","line":87,"in_reply_to":"7a2fa921_164a3c56","updated":"2015-10-13 19:08:05.000000000","message":"The header merging is a work-in-progress","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":97,"context_line":"                    # merge in newest_link_headers"},{"line_number":98,"context_line":"                    merge_keys \u003d []"},{"line_number":99,"context_line":"                    for (h, v) in newest_link_headers:"},{"line_number":100,"context_line":"                        merge_keys.append(h)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"                    merged_headers \u003d [(h, v) for (h, v) in"},{"line_number":103,"context_line":"                                      self._response_headers"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_f677809d","line":100,"updated":"2015-10-12 01:02:23.000000000","message":"You could do : \nmerge_keys \u003d [h for (h, v) in newest_link_headers]","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                                      self._response_headers"},{"line_number":104,"context_line":"                                      if h not in merge_keys]"},{"line_number":105,"context_line":"                    self._response_headers \u003d merged_headers"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"                    for (h, v) in newest_link_headers:"},{"line_number":108,"context_line":"                        self._response_headers.append((h, v))"},{"line_number":109,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_7c2111b4","line":106,"updated":"2015-10-12 01:02:23.000000000","message":"why is there the local variable \"merged_headers\"?  could self._response_headers just be set directly?","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                                      self._response_headers"},{"line_number":104,"context_line":"                                      if h not in merge_keys]"},{"line_number":105,"context_line":"                    self._response_headers \u003d merged_headers"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"                    for (h, v) in newest_link_headers:"},{"line_number":108,"context_line":"                        self._response_headers.append((h, v))"},{"line_number":109,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_52c42c3f","line":106,"in_reply_to":"7a2fa921_7c2111b4","updated":"2015-10-13 19:08:05.000000000","message":"I wasn\u0027t sure if a comprehension could both walk over a given list, self._response_headers, and assign to the same list.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"            target_path \u003d \u0027/%s/%s/%s/%s\u0027 % (version, target_acct,"},{"line_number":124,"context_line":"                                            target_cont, target_obj)"},{"line_number":125,"context_line":"            line \u003d \u0027handle_get target_path %s\u0027 % (target_path,)"},{"line_number":126,"context_line":"            self.logger.info(line)"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"            self.env[\u0027PATH_INFO\u0027] \u003d target_path"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_df24d7b3","line":125,"updated":"2015-10-12 01:02:23.000000000","message":"This could just be logged directly without the \"line\" variable.  Similar statement for other log messages.  And other places where a local variable is created to only be used once.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"            target_path \u003d \u0027/%s/%s/%s/%s\u0027 % (version, target_acct,"},{"line_number":124,"context_line":"                                            target_cont, target_obj)"},{"line_number":125,"context_line":"            line \u003d \u0027handle_get target_path %s\u0027 % (target_path,)"},{"line_number":126,"context_line":"            self.logger.info(line)"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"            self.env[\u0027PATH_INFO\u0027] \u003d target_path"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_d2a4bc09","line":125,"in_reply_to":"7a2fa921_df24d7b3","updated":"2015-10-13 19:08:05.000000000","message":"I expect all this debug logging to eventually disappear.\nI keep the separate \"line\" just for convenience of typing.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                    errmsg \u003d \u0027PUT ?symlink\u003dtrue not zero-length\u0027"},{"line_number":221,"context_line":"                    self.logger.info(errmsg)"},{"line_number":222,"context_line":"                    # data \u003d req.body_file.read()"},{"line_number":223,"context_line":"                    # line \u003d \u0027body: %s\u0027 % (data,)"},{"line_number":224,"context_line":"                    # self.logger.info(line)"},{"line_number":225,"context_line":"                    return HTTPBadRequest(body\u003derrmsg)("},{"line_number":226,"context_line":"                        self.env, self._start_response)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_bf71dbaa","line":223,"updated":"2015-10-12 01:02:23.000000000","message":"this could just be \"data\" instead of (data,).  Similar statement for other string formats.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                    errmsg \u003d \u0027PUT ?symlink\u003dtrue not zero-length\u0027"},{"line_number":221,"context_line":"                    self.logger.info(errmsg)"},{"line_number":222,"context_line":"                    # data \u003d req.body_file.read()"},{"line_number":223,"context_line":"                    # line \u003d \u0027body: %s\u0027 % (data,)"},{"line_number":224,"context_line":"                    # self.logger.info(line)"},{"line_number":225,"context_line":"                    return HTTPBadRequest(body\u003derrmsg)("},{"line_number":226,"context_line":"                        self.env, self._start_response)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_d27b5c7a","line":223,"in_reply_to":"7a2fa921_bf71dbaa","updated":"2015-10-13 19:08:05.000000000","message":"All this debug logging should eventually disappear.\nI used the tuple syntax to make it easy to add/remove debug fields as needed.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                headers\u003d{\u0027x-auth-token\u0027: req.headers.get(\u0027x-auth-token\u0027)},"},{"line_number":276,"context_line":"                agent\u003d(\u0027%(orig)s \u0027 + \u0027Symlink\u0027), swift_source\u003d\u0027SY\u0027)"},{"line_number":277,"context_line":"            src_resp \u003d src_req.get_response(self.app)"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"            if not src_resp.headers.get("},{"line_number":280,"context_line":"                    \u0027X-Object-Sysmeta-Symlink-Target-Object\u0027):"},{"line_number":281,"context_line":"                errmsg \u003d (\u0027COPY ?symlink\u003dtrue source missing \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_df9937d2","line":278,"updated":"2015-10-12 01:02:23.000000000","message":"should there be a check for a successful response here?   maybe have a unit test case where this subrequest is not successful to assert the correct behavior.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"55116cf4f8e248dc3e675da7d7e69b4425707231","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                headers\u003d{\u0027x-auth-token\u0027: req.headers.get(\u0027x-auth-token\u0027)},"},{"line_number":276,"context_line":"                agent\u003d(\u0027%(orig)s \u0027 + \u0027Symlink\u0027), swift_source\u003d\u0027SY\u0027)"},{"line_number":277,"context_line":"            src_resp \u003d src_req.get_response(self.app)"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"            if not src_resp.headers.get("},{"line_number":280,"context_line":"                    \u0027X-Object-Sysmeta-Symlink-Target-Object\u0027):"},{"line_number":281,"context_line":"                errmsg \u003d (\u0027COPY ?symlink\u003dtrue source missing \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a2ca52d_d1acb1ef","line":278,"in_reply_to":"7a2fa921_df9937d2","updated":"2015-10-13 19:08:05.000000000","message":"Done","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"11488b767c03279ba5484c9d6746d583236dd27b","unresolved":false,"context_lines":[{"line_number":309,"context_line":"        except ValueError:"},{"line_number":310,"context_line":"            # not an object request"},{"line_number":311,"context_line":"            return None"},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":314,"context_line":"            resp \u003d self.handle_get_head()"},{"line_number":315,"context_line":"        elif req.method \u003d\u003d \u0027PUT\u0027:"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a2fa921_3fe38b35","line":312,"updated":"2015-10-12 01:02:23.000000000","message":"Instead of the if/elif block, you could change the method names to match the request strings and do this:\n\nif hasattr(_SymlinkContext, req.method):\n  return getattr(self, req.method)()\n\nif it is simply pass-through such as \"OPTIONS\", then it can fall to the \"else\" case - no need for a special method.","commit_id":"70116b5347d74521d3000426f6a080445d080458"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                    # merge in newest_link_headers"},{"line_number":189,"context_line":"                    merge_keys \u003d []"},{"line_number":190,"context_line":"                    for (h, v) in newest_link_headers:"},{"line_number":191,"context_line":"                        if \u0027-meta-\u0027 in h.lower():"},{"line_number":192,"context_line":"                            merge_keys.append(h)"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"                    merged_headers \u003d [(h, v) for (h, v) in"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_f7243d61","line":191,"updated":"2015-10-25 12:00:27.000000000","message":"I feel like we\u0027ve got an is_object_meta() function laying around the codebase somewhere... try swift.common.request_helpers.is_user_meta(\u0027object\u0027, h)","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                    # merge in newest_link_headers"},{"line_number":189,"context_line":"                    merge_keys \u003d []"},{"line_number":190,"context_line":"                    for (h, v) in newest_link_headers:"},{"line_number":191,"context_line":"                        if \u0027-meta-\u0027 in h.lower():"},{"line_number":192,"context_line":"                            merge_keys.append(h)"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"                    merged_headers \u003d [(h, v) for (h, v) in"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_ed93ff4d","line":191,"in_reply_to":"3a29b11f_f7243d61","updated":"2015-10-26 14:48:08.000000000","message":"Done","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    def handle_put(self):"},{"line_number":227,"context_line":"        req \u003d Request(self.env)"},{"line_number":228,"context_line":"        if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027true\u0027:"},{"line_number":229,"context_line":"            if req.headers.get(\u0027X-Copy-From\u0027):"},{"line_number":230,"context_line":"                # code fragment from proxy/controller/obj.py"},{"line_number":231,"context_line":"                # server_side_copy.py"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_172a192d","line":228,"updated":"2015-10-25 12:00:27.000000000","message":"There\u0027s something clean in here trying to break out; I can almost see it.\n\nI feel like a COPY with ?symlink\u003dtrue should be turned into a GET with ?symlink\u003dtrue and a PUT with ?symlink\u003dtrue.\n\nMaybe the answer for now is don\u0027t do anything special. When COPY gets pulled into left-end-of-the-pipeline middleware, this will all go away.\n\nAlternatively, if you want to get in the middle of COPY requests now (which I don\u0027t recommend that you do), there\u0027s a hooking mechanism that you may find useful. Look for swift.copy_hook and see if that does what you want.\n\nIdeally, this whole handle_put method would know exactly nothing about COPY requests.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    def handle_put(self):"},{"line_number":227,"context_line":"        req \u003d Request(self.env)"},{"line_number":228,"context_line":"        if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027true\u0027:"},{"line_number":229,"context_line":"            if req.headers.get(\u0027X-Copy-From\u0027):"},{"line_number":230,"context_line":"                # code fragment from proxy/controller/obj.py"},{"line_number":231,"context_line":"                # server_side_copy.py"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_4d5eb346","line":228,"in_reply_to":"3a29b11f_172a192d","updated":"2015-10-26 14:48:08.000000000","message":"Clean-up may have to wait for server-side-copy middleware to be done. For now, COPY is converted into a PUT+X-Copy-From, so symlinks needs to handle this feature of PUT requests.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":248,"context_line":"                    agent\u003d(\u0027%(orig)s \u0027 + \u0027Symlink\u0027), swift_source\u003d\u0027SY\u0027)"},{"line_number":249,"context_line":"                src_resp \u003d src_req.get_response(self.app)"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"                if not is_success(src_resp.status_int):"},{"line_number":252,"context_line":"                    errmsg \u003d (\u0027PUT X-Copy-From with ?symlink\u003dtrue \u0027"},{"line_number":253,"context_line":"                              \u0027unable to HEAD source\u0027)"},{"line_number":254,"context_line":"                    self.logger.info(errmsg)"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_b71fa508","line":251,"updated":"2015-10-25 12:00:27.000000000","message":"We\u0027ve got to distinguish between 404, 4xx and 5xx here at a minimum. You\u0027re gonna get 404s when people break their symlinks, and showing that to the user as a 412 is just confusing. On the other hand, if the proxy hands us a 502, we can\u0027t just go make that into a 412 because a 412 says it\u0027s the user\u0027s fault!\n\nHopefully all this logic can just go away when COPY makes it to middleware. It\u0027s hard enough to deal with a single request for a single resource; having one request that talks about two resources is nuts, and then to chase symlinks and have N \u003e 2 resources in play, and somehow come up with a single response code to encapsulate all this? That\u0027s a nightmare and a half.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":248,"context_line":"                    agent\u003d(\u0027%(orig)s \u0027 + \u0027Symlink\u0027), swift_source\u003d\u0027SY\u0027)"},{"line_number":249,"context_line":"                src_resp \u003d src_req.get_response(self.app)"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"                if not is_success(src_resp.status_int):"},{"line_number":252,"context_line":"                    errmsg \u003d (\u0027PUT X-Copy-From with ?symlink\u003dtrue \u0027"},{"line_number":253,"context_line":"                              \u0027unable to HEAD source\u0027)"},{"line_number":254,"context_line":"                    self.logger.info(errmsg)"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_f003d20b","line":251,"in_reply_to":"3a29b11f_b71fa508","updated":"2015-10-26 14:48:08.000000000","message":"If we can define the desired error behaviour I can implement it. Some refactoring may also help to share code and simplify the PUT+X-Copy-From and COPY. A clean solution may have to wait for the server-side-copy middleware.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":374,"context_line":"        resp \u003d self._app_call(self.env)"},{"line_number":375,"context_line":"        return resp"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":"    def handle_options(self):"},{"line_number":378,"context_line":"        req \u003d Request(self.env)"},{"line_number":379,"context_line":""},{"line_number":380,"context_line":"        if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027true\u0027:"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_d71ca115","line":377,"updated":"2015-10-25 12:00:27.000000000","message":"Any chance we could just not do anything special for OPTIONS requests? Let them be handled by their container, same as any normal object?\n\nI have two worries: first, that this will confuse users; and second, that this makes OPTIONS requests far more expensive.\n\nRight now all our CORS stuff is based on the container. With this, we don\u0027t have that property any more; a change to /v1/a/red-things can break CORS for the object named /v1/a/hard-things/brick, but only if the latter is a symlink. \n\nSecond, an OPTIONS request right now can be handled with just one call to get_container_info(). That\u0027s at most one hit to a container DB, and there\u0027s a decent probability that the container info is cached anyway, so the proxy doesn\u0027t end up doing any work. This adds a whole bunch of additional object-server HEAD requests, and that\u0027ll really slow OPTIONS requests down. It might even make the CORS preflight check *more* expensive for Swift than just fetching the darn object.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":374,"context_line":"        resp \u003d self._app_call(self.env)"},{"line_number":375,"context_line":"        return resp"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":"    def handle_options(self):"},{"line_number":378,"context_line":"        req \u003d Request(self.env)"},{"line_number":379,"context_line":""},{"line_number":380,"context_line":"        if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027true\u0027:"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_f051920f","line":377,"in_reply_to":"3a29b11f_d71ca115","updated":"2015-10-26 14:48:08.000000000","message":"A good topic for discussion. I was attempting to get OPTIONS to return the correct result for the entire symlink chain. This may be expensive since HEADs are required to detect/follow the chain. Symlinks support redirection to alternate containers, so following the chain is required to find the alternate containers.","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":486,"context_line":"    Symlinks allow references to one object path to transparently access"},{"line_number":487,"context_line":"    another object."},{"line_number":488,"context_line":"    An important use case is to use a path in one container to access an object"},{"line_number":489,"context_line":"    in a different container, with a differenct policy."},{"line_number":490,"context_line":"    This allows policy cost/performance tradeoffs to be made on individual"},{"line_number":491,"context_line":"    objects."},{"line_number":492,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_77190d22","line":489,"updated":"2015-10-25 12:00:27.000000000","message":"nit: \"different\"","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":486,"context_line":"    Symlinks allow references to one object path to transparently access"},{"line_number":487,"context_line":"    another object."},{"line_number":488,"context_line":"    An important use case is to use a path in one container to access an object"},{"line_number":489,"context_line":"    in a different container, with a differenct policy."},{"line_number":490,"context_line":"    This allows policy cost/performance tradeoffs to be made on individual"},{"line_number":491,"context_line":"    objects."},{"line_number":492,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_cdede38f","line":489,"in_reply_to":"3a29b11f_77190d22","updated":"2015-10-26 14:48:08.000000000","message":"Done","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2015 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_2fb29094","line":1,"updated":"2016-05-26 10:23:32.000000000","message":"nit: 2016 ?","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2015 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_693f1cb4","line":1,"in_reply_to":"bab6814e_2fb29094","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"3192f751ed9aca6a67c5cffb4ea1be57e202c3e3","unresolved":false,"context_lines":[{"line_number":31,"context_line":"the container of the symlink object."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"For a cross-account symlink, also include the header"},{"line_number":34,"context_line":"``X-Object-Symlink-Target-Account: \u003caccount\u003e``. If omitted, it defaults to"},{"line_number":35,"context_line":"the account of the symlink object."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_ef8088c1","line":34,"updated":"2016-05-26 09:44:26.000000000","message":"Am I missing something here ? Why not just one header like this ? \n\n    X-Object-Symlink-Target: account/container/object","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":31,"context_line":"the container of the symlink object."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"For a cross-account symlink, also include the header"},{"line_number":34,"context_line":"``X-Object-Symlink-Target-Account: \u003caccount\u003e``. If omitted, it defaults to"},{"line_number":35,"context_line":"the account of the symlink object."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_a95c7419","line":34,"in_reply_to":"bab6814e_ef8088c1","updated":"2016-07-22 18:24:05.000000000","message":"reduced to two headers, similar to COPY.\nX-Symlink-Target-Object: cont/obj\nX-Symlink-Target-Account: acc","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":144,"context_line":"        self.env \u003d dict(env)"},{"line_number":145,"context_line":"        self.env[\u0027HTTP_USER_AGENT\u0027] \u003d \\"},{"line_number":146,"context_line":"            \u0027%s Symlink\u0027 % self.env.get(\u0027HTTP_USER_AGENT\u0027)"},{"line_number":147,"context_line":"        self.env[\u0027swift.source\u0027] \u003d \u0027SY\u0027"},{"line_number":148,"context_line":"        self.agent \u003d None  # see wsgi.py, use original env\u0027s HTTP_USER_AGENT"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def handle_get_head(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_b219c38a","line":147,"updated":"2016-05-26 10:23:32.000000000","message":"Add this to http://docs.openstack.org/developer/swift/logs.html","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        return resp"},{"line_number":286,"context_line":""},{"line_number":287,"context_line":"    def handle_post_delete(self):"},{"line_number":288,"context_line":"        req \u003d Request(self.env)"},{"line_number":289,"context_line":"        if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":290,"context_line":"            errmsg \u003d \u0027POST/DELETE with ?symlink\u003dtrue not allowed\u0027"},{"line_number":291,"context_line":"            self.logger.info(errmsg)"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_4de0bc96","line":288,"updated":"2016-05-26 10:23:32.000000000","message":"Consider doing this in calling method and pass req instance here. Same comment elsewhere too for handle_* methods","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        return resp"},{"line_number":286,"context_line":""},{"line_number":287,"context_line":"    def handle_post_delete(self):"},{"line_number":288,"context_line":"        req \u003d Request(self.env)"},{"line_number":289,"context_line":"        if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":290,"context_line":"            errmsg \u003d \u0027POST/DELETE with ?symlink\u003dtrue not allowed\u0027"},{"line_number":291,"context_line":"            self.logger.info(errmsg)"}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_c98f2873","line":288,"in_reply_to":"bab6814e_4de0bc96","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":295,"context_line":"        resp \u003d self._app_call(self.env)"},{"line_number":296,"context_line":"        return resp"},{"line_number":297,"context_line":""},{"line_number":298,"context_line":"    def handle_options(self):"},{"line_number":299,"context_line":"        req \u003d Request(self.env)"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"        if config_true_value(req.params.get(\u0027symlink\u0027)):"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_0d251408","line":298,"updated":"2016-05-26 10:23:32.000000000","message":"This method is a little confusing. Needs some comments on what\u0027s being done.","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":368,"context_line":"        try:"},{"line_number":369,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":370,"context_line":"        except ValueError:"},{"line_number":371,"context_line":"            # not an object request"},{"line_number":372,"context_line":"            return None"},{"line_number":373,"context_line":""},{"line_number":374,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_0de6b414","line":371,"range":{"start_line":371,"start_character":17,"end_line":371,"end_character":18},"updated":"2016-05-26 10:23:32.000000000","message":"You can move this object or not validation to handle_request()","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":368,"context_line":"        try:"},{"line_number":369,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":370,"context_line":"        except ValueError:"},{"line_number":371,"context_line":"            # not an object request"},{"line_number":372,"context_line":"            return None"},{"line_number":373,"context_line":""},{"line_number":374,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_29dfe43a","line":371,"range":{"start_line":371,"start_character":17,"end_line":371,"end_character":18},"in_reply_to":"bab6814e_0de6b414","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":414,"context_line":"        self.app \u003d app"},{"line_number":415,"context_line":"        self.conf \u003d conf"},{"line_number":416,"context_line":""},{"line_number":417,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink_middle\u0027)"},{"line_number":418,"context_line":""},{"line_number":419,"context_line":"        self.symloop_max \u003d int(self.conf.get(\u0027symloop_max\u0027,"},{"line_number":420,"context_line":"                                             DEFAULT_SYMLOOP_MAX))"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_cd5aecf1","line":417,"range":{"start_line":417,"start_character":69,"end_line":417,"end_character":71},"updated":"2016-05-26 10:23:32.000000000","message":"nit: symlink_middleware may be ?","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":414,"context_line":"        self.app \u003d app"},{"line_number":415,"context_line":"        self.conf \u003d conf"},{"line_number":416,"context_line":""},{"line_number":417,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink_middle\u0027)"},{"line_number":418,"context_line":""},{"line_number":419,"context_line":"        self.symloop_max \u003d int(self.conf.get(\u0027symloop_max\u0027,"},{"line_number":420,"context_line":"                                             DEFAULT_SYMLOOP_MAX))"}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_09bdc0d7","line":417,"range":{"start_line":417,"start_character":69,"end_line":417,"end_character":71},"in_reply_to":"bab6814e_cd5aecf1","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"21b9f5deecf309f6d87f15968e13b61ba5ff6aef","unresolved":false,"context_lines":[{"line_number":428,"context_line":"def filter_factory(global_conf, **local_conf):"},{"line_number":429,"context_line":"    conf \u003d global_conf.copy()"},{"line_number":430,"context_line":"    conf.update(local_conf)"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def symlink_mw(app):"},{"line_number":433,"context_line":"        return SymlinkMiddleware(app, conf)"},{"line_number":434,"context_line":"    return symlink_mw"}],"source_content_type":"text/x-python","patch_set":30,"id":"bab6814e_2ddf386a","line":431,"updated":"2016-05-26 10:23:32.000000000","message":"Expose middleware to /info calls using register_swift_info()","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"60630772b506ea6175bb3879ea62050a9bf76657","unresolved":false,"context_lines":[{"line_number":428,"context_line":"def filter_factory(global_conf, **local_conf):"},{"line_number":429,"context_line":"    conf \u003d global_conf.copy()"},{"line_number":430,"context_line":"    conf.update(local_conf)"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def symlink_mw(app):"},{"line_number":433,"context_line":"        return SymlinkMiddleware(app, conf)"},{"line_number":434,"context_line":"    return symlink_mw"}],"source_content_type":"text/x-python","patch_set":30,"id":"dada55a8_e99aec12","line":431,"in_reply_to":"bab6814e_2ddf386a","updated":"2016-07-22 18:24:05.000000000","message":"Done","commit_id":"a8cf98b2f0d621a4cc0f45f551367e07a1b9d43e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. When post-as-copy is off, a POST will result in a"},{"line_number":51,"context_line":"300-series error. When post-as-copy is on, the data from the target object gets"},{"line_number":52,"context_line":"copied to the symlink object and the symlink becomes a regular object."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":55,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_6e43626d","line":52,"updated":"2016-07-22 19:35:18.000000000","message":"I don\u0027t know that I like having this behavioral difference... I\u0027m also not sure how to resolve it, though.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. When post-as-copy is off, a POST will result in a"},{"line_number":51,"context_line":"300-series error. When post-as-copy is on, the data from the target object gets"},{"line_number":52,"context_line":"copied to the symlink object and the symlink becomes a regular object."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":55,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":31,"id":"bacf61ea_19728511","line":52,"in_reply_to":"bacf61ea_a126e9cb","updated":"2017-10-13 20:49:00.000000000","message":"we could, but that would still be a different behavior than fast post, because the symlink would never get the new metadata.\nWith fast post, we first store the new metadata on the symlink and then return error.\n\nHow about adding a check for post_as_copy on both GET and PUT handling, such that on the GET, we never follow the symlink and on PUT a 307 gets returned","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dd385dd1fe21b233bedf1ddc9f5c59ab321a0258","unresolved":false,"context_lines":[{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. When post-as-copy is off, a POST will result in a"},{"line_number":51,"context_line":"300-series error. When post-as-copy is on, the data from the target object gets"},{"line_number":52,"context_line":"copied to the symlink object and the symlink becomes a regular object."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":55,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":31,"id":"bacf61ea_a126e9cb","line":52,"in_reply_to":"dada55a8_04ed1eef","updated":"2016-07-28 18:44:23.000000000","message":"Hmmm... on the GET half, we\u0027ll have swift.post_as_copy in the env, right? How about we raise the 307 then?","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. When post-as-copy is off, a POST will result in a"},{"line_number":51,"context_line":"300-series error. When post-as-copy is on, the data from the target object gets"},{"line_number":52,"context_line":"copied to the symlink object and the symlink becomes a regular object."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":55,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_04ed1eef","line":52,"in_reply_to":"dada55a8_6e43626d","updated":"2016-07-27 16:27:16.000000000","message":"yeah, I\u0027m not sure how to resolve it either and I agree it is not ideal to have the different behavior. Life will be easier once we deprecate and finally remove post-as-copy","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"An OPTIONS request to a symlink will traverse through a chain of symlinks"},{"line_number":62,"context_line":"to reach a target object. All symlinks in the chain, and the target object,"},{"line_number":63,"context_line":"must allow access, otherwise the OPTIONS request will fail."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"Errors"},{"line_number":66,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_f11c576c","line":63,"range":{"start_line":63,"start_character":29,"end_line":63,"end_character":58},"updated":"2016-07-22 19:35:18.000000000","message":"Should it? Issuing an OPTIONS request to a non-existent object or an object I can\u0027t access (because I\u0027m anonymous) still 200s on master.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"An OPTIONS request to a symlink will traverse through a chain of symlinks"},{"line_number":62,"context_line":"to reach a target object. All symlinks in the chain, and the target object,"},{"line_number":63,"context_line":"must allow access, otherwise the OPTIONS request will fail."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"Errors"},{"line_number":66,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_e40538c2","line":63,"range":{"start_line":63,"start_character":29,"end_line":63,"end_character":58},"in_reply_to":"dada55a8_f11c576c","updated":"2016-07-27 16:27:16.000000000","message":"TBD. I added a comment on the handle_options about working on a better implementation for OPTIONS request, will need to think a bit more about it.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":69,"context_line":""},{"line_number":70,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_d1479349","line":72,"range":{"start_line":72,"start_character":17,"end_line":72,"end_character":39},"updated":"2016-07-22 19:35:18.000000000","message":"I don\u0027t know that this is a client error, really. There\u0027s no way for the client to re-form its request so it\u0027ll suddenly work properly. Would a 508 be better?","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":69,"context_line":""},{"line_number":70,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"bacf61ea_84b72cd7","line":72,"range":{"start_line":72,"start_character":17,"end_line":72,"end_character":39},"in_reply_to":"bacf61ea_dc1e6262","updated":"2017-10-13 20:49:00.000000000","message":"Ok, changing to 422.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dd385dd1fe21b233bedf1ddc9f5c59ab321a0258","unresolved":false,"context_lines":[{"line_number":69,"context_line":""},{"line_number":70,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"bacf61ea_dc1e6262","line":72,"range":{"start_line":72,"start_character":17,"end_line":72,"end_character":39},"in_reply_to":"dada55a8_44071681","updated":"2016-07-28 18:44:23.000000000","message":"The client making the request won\u0027t necessarily be able to do anything about it, though; they may have read-only access. This seems distinct from things like 409s on container PUT with a different X-Storage-Policy or 413 on quota exceeded -- there, we know the user has permission to make the necessary adjustments if they really want to make it happen.\n\nAt the same time, I suppose we *do* send back a 409 for busted SLOs, regardless of whether the user can fix it... and it seems that 5xx is generally used when swift is in a bad state, rather than when user data is in a bad state. But 412 definitely doesn\u0027t seem right -- the client put no conditions on the request! If we really wanted to stick with 4xx, *maybe* 422 would be appropriate?","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":69,"context_line":""},{"line_number":70,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_44071681","line":72,"range":{"start_line":72,"start_character":17,"end_line":72,"end_character":39},"in_reply_to":"dada55a8_d1479349","updated":"2016-07-27 16:27:16.000000000","message":"Yeah, this is a difficult one because the loop is \"introduced\" by the client. They should be able to fix it by deleting some symlinks or re-pointing to the correct target object.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"* OPTIONS without the query parameter ``?symlink\u003dtrue``"},{"line_number":77,"context_line":"  traversing more than ``symloop_max`` chained symlinks"}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_b1ae5fe5","line":74,"range":{"start_line":74,"start_character":23,"end_line":74,"end_character":36},"updated":"2016-07-22 19:35:18.000000000","message":"303 implies that the follow-up request should be a GET; I think we want 307.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":71,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":72,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"* POSTs will produce a 303 See Other error."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"* OPTIONS without the query parameter ``?symlink\u003dtrue``"},{"line_number":77,"context_line":"  traversing more than ``symloop_max`` chained symlinks"}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_44f1d669","line":74,"range":{"start_line":74,"start_character":23,"end_line":74,"end_character":36},"in_reply_to":"dada55a8_b1ae5fe5","updated":"2016-07-27 16:27:16.000000000","message":"Done","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        return resp"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":"    def handle_request(self, start_response):"},{"line_number":356,"context_line":"        req \u003d Request(self.env)"},{"line_number":357,"context_line":"        try:"},{"line_number":358,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_b14adf25","line":355,"updated":"2016-07-22 19:35:18.000000000","message":"I think I\u0027d prefer this logic be in SymlinkMiddleware.__call__ so we can avoid ever creating a SymlinkContext for non-objects.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        return resp"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":"    def handle_request(self, start_response):"},{"line_number":356,"context_line":"        req \u003d Request(self.env)"},{"line_number":357,"context_line":"        try:"},{"line_number":358,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_0f91b799","line":355,"in_reply_to":"dada55a8_b14adf25","updated":"2016-07-27 16:27:16.000000000","message":"Done","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4ef2d5b7048c101418cae75242e4e4593bc26b7a","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            req.headers[TGT_ACCT_SYSMETA_SYMLINK_HDR] \u003d \\"},{"line_number":241,"context_line":"                check_account_format(req, symlink_account)"},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":246,"context_line":"        if is_success(self._get_status_int()) and \\"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_32a0b2f4","line":243,"updated":"2016-08-08 20:56:47.000000000","message":"So we still do the PUT? Why?\n\nI suppose it mimics the behavior with fast-post, but the post doesn\u0027t *do* anything, right? Since it\u0027s a new object with a new timestamp, we don\u0027t have the same consistency issue that causes headaches with fast-post.\n\nI kinda feel like we should raise the redirect immediately during the GET, skip the PUT request, and drop the meta on the floor.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"08ff1b642d153bc149d1f3dad72a58f90072c65e","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            req.headers[TGT_ACCT_SYSMETA_SYMLINK_HDR] \u003d \\"},{"line_number":241,"context_line":"                check_account_format(req, symlink_account)"},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":246,"context_line":"        if is_success(self._get_status_int()) and \\"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_e0b1e4e2","line":243,"in_reply_to":"9ad45d7e_32a0b2f4","updated":"2016-08-24 15:15:56.000000000","message":"\u003e So we still do the PUT? Why?\nI\u0027m assuming you are talking about in the case of POST_as_copy. \n\nYes, I think we need it because we want the same behavior as fast-post where the metadata is stored with symlink. If we return the 307 on the GET, then the metadata never makes its way to the object server.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b0298db24bc441920e01510cbe865f58324503db","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            req.headers[TGT_ACCT_SYSMETA_SYMLINK_HDR] \u003d \\"},{"line_number":241,"context_line":"                check_account_format(req, symlink_account)"},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":246,"context_line":"        if is_success(self._get_status_int()) and \\"}],"source_content_type":"text/x-python","patch_set":34,"id":"1ac06dbe_2dd5fab8","line":243,"in_reply_to":"9ad45d7e_e0b1e4e2","updated":"2016-08-24 19:07:18.000000000","message":"OK, I think I\u0027m on board with it for the sake of consistency. It makes is start to feel like an intentional design decision rather than a wart of the consistency engine, but the discussions around POSTing X-Object-Manifest headers make me think that having a single set of expectations would be better.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4ef2d5b7048c101418cae75242e4e4593bc26b7a","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        \"\"\""},{"line_number":297,"context_line":"        TODO work on this method"},{"line_number":298,"context_line":"        What I don\u0027t like about this implementation is that now every OPTIONS"},{"line_number":299,"context_line":"        request requires at least one HEAD request on the object."},{"line_number":300,"context_line":"        \"\"\""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        if config_true_value(req.params.get(\u0027symlink\u0027)):"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_920fdee0","line":299,"updated":"2016-08-08 20:56:47.000000000","message":"...and currently on master we don\u0027t need to talk to the object-servers *at all*, right? I\u0027m still inclined to not do any special OPTIONS handling; rather, let the proxy-server deal with it. If you want to test out whether you can actually read the target, just do a HEAD.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"08ff1b642d153bc149d1f3dad72a58f90072c65e","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        \"\"\""},{"line_number":297,"context_line":"        TODO work on this method"},{"line_number":298,"context_line":"        What I don\u0027t like about this implementation is that now every OPTIONS"},{"line_number":299,"context_line":"        request requires at least one HEAD request on the object."},{"line_number":300,"context_line":"        \"\"\""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        if config_true_value(req.params.get(\u0027symlink\u0027)):"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_ecf3ba9c","line":299,"in_reply_to":"9ad45d7e_920fdee0","updated":"2016-08-24 15:15:56.000000000","message":"correct, honestly I have the same inclination, but I wanted to leave this out here to get comments from others.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":22,"context_line":"cost/performance tradeoffs to be made on individual objects."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"Clients create a Swift symlink by performing a zero-length PUT request"},{"line_number":25,"context_line":"with the header ``X-Symlink-Target-Object: \u003ccontainer\u003e/\u003cobject\u003e``."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"For a cross-account symlink, also include the header"},{"line_number":28,"context_line":"``X-Symlink-Target-Account: \u003caccount\u003e``. If omitted, it defaults to"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_90f33e0a","line":25,"updated":"2016-09-05 08:28:58.000000000","message":"X-Symlink-Target-Object references both the container and object, then the X-Symlink-Target-Account you only specify the account. This makes target-object a bit confusing I think. What if we just use:\n\n  X-Symlink-Target\n\nWhich keeps the symlink api x header smaller, which in my opinion is good.","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":22,"context_line":"cost/performance tradeoffs to be made on individual objects."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"Clients create a Swift symlink by performing a zero-length PUT request"},{"line_number":25,"context_line":"with the header ``X-Symlink-Target-Object: \u003ccontainer\u003e/\u003cobject\u003e``."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"For a cross-account symlink, also include the header"},{"line_number":28,"context_line":"``X-Symlink-Target-Account: \u003caccount\u003e``. If omitted, it defaults to"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_b51b3dc9","line":25,"in_reply_to":"9a89bdaa_90f33e0a","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink without the query parameter ``?symlink\u003dtrue``"},{"line_number":37,"context_line":"will reference the object pointed to by the symlink\u0027s Target-Account and"},{"line_number":38,"context_line":"Target-Object. If the symlink does not have a Target-Account specified it will"},{"line_number":39,"context_line":"use its own account/container. A symlink can point to another symlink."},{"line_number":40,"context_line":"Chained symlinks will be traversed until a target object is found. If the"},{"line_number":41,"context_line":"number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":42,"context_line":"will be produced. The value of ``symloop_max`` can be defined in the symlink"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_b0f842e7","line":39,"updated":"2016-09-05 08:28:58.000000000","message":"If Target-Account isn\u0027t specified it\u0027ll use its own container. You mean account because the container isn\u0027t specified here.. right?","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink without the query parameter ``?symlink\u003dtrue``"},{"line_number":37,"context_line":"will reference the object pointed to by the symlink\u0027s Target-Account and"},{"line_number":38,"context_line":"Target-Object. If the symlink does not have a Target-Account specified it will"},{"line_number":39,"context_line":"use its own account/container. A symlink can point to another symlink."},{"line_number":40,"context_line":"Chained symlinks will be traversed until a target object is found. If the"},{"line_number":41,"context_line":"number of chained symlinks exceeds the limit ``symloop_max`` an error response"},{"line_number":42,"context_line":"will be produced. The value of ``symloop_max`` can be defined in the symlink"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_957559fb","line":39,"in_reply_to":"9a89bdaa_b0f842e7","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":157,"context_line":"                                          tgt_obj)])"},{"line_number":158,"context_line":"        if tgt_acct:"},{"line_number":159,"context_line":"            self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":160,"context_line":"                                          tgt_acct)])"},{"line_number":161,"context_line":"        return resp"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def handle_get_head(self, req):"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_d0ddc671","line":160,"updated":"2016-09-05 08:28:58.000000000","message":"Can\u0027t we roll this up, rather then checking while looping and then checking and extending:\n\n  resp \u003d self._app_call(req.environ)\n  for key, val in self._response_headers:\n      if key.lower() \u003d\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:\n          self._response_headers.extend([(\u0027X-Symlink-Target-Object\u0027,\n                                          val)])\n      elif key.lower() \u003d\u003d TGT_ACCT_SYSMETA_SYMLINK_HDR:\n          self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,\n                                          val)])\n\n  return resp","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":157,"context_line":"                                          tgt_obj)])"},{"line_number":158,"context_line":"        if tgt_acct:"},{"line_number":159,"context_line":"            self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":160,"context_line":"                                          tgt_acct)])"},{"line_number":161,"context_line":"        return resp"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def handle_get_head(self, req):"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_95d9d924","line":160,"in_reply_to":"9a89bdaa_d0ddc671","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":283,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":284,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":285,"context_line":"            return HTTPTemporaryRedirect(body\u003derrmsg)("},{"line_number":286,"context_line":"                req.environ, self._start_response)"},{"line_number":287,"context_line":"        else:"},{"line_number":288,"context_line":"            return resp"},{"line_number":289,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_f0daca77","line":286,"updated":"2016-09-05 08:28:58.000000000","message":"Your going to the effort of finding the right target_acct, but never using it. Did you go to the trouble here so you can add a Location header to the 307 reponse?","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":283,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":284,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":285,"context_line":"            return HTTPTemporaryRedirect(body\u003derrmsg)("},{"line_number":286,"context_line":"                req.environ, self._start_response)"},{"line_number":287,"context_line":"        else:"},{"line_number":288,"context_line":"            return resp"},{"line_number":289,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_55a5919f","line":286,"in_reply_to":"9a89bdaa_f0daca77","updated":"2016-09-07 20:02:37.000000000","message":"I believe that\u0027s correct ;)\n\nat one point (many many patchsets ago) I was trying to add the Location header but then realized that was not working as I expected and probably forgot to remove the account here.\n\nRemoved now.","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        \"\"\""},{"line_number":165,"context_line":"        count \u003d 0"},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"        while count \u003c\u003d self.symloop_max:"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":170,"context_line":"            if not is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_3b50e00a","line":167,"range":{"start_line":167,"start_character":14,"end_line":167,"end_character":39},"updated":"2016-09-08 10:39:29.000000000","message":"I\u0027m trying to picture this in my head:\n\n    0 \u003c\u003d 2 : True\n    1 \u003c\u003d 2 : True\n    2 \u003c\u003d 2 : True\n    3 \u003c\u003d 2 : False\n\nSo in effect when symloop_max is 2, is the chain followed thrice ? Or am I just not thinking this through ?","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        \"\"\""},{"line_number":165,"context_line":"        count \u003d 0"},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"        while count \u003c\u003d self.symloop_max:"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":170,"context_line":"            if not is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_b68a3562","line":167,"range":{"start_line":167,"start_character":14,"end_line":167,"end_character":39},"in_reply_to":"9a89bdaa_3b50e00a","updated":"2016-09-09 19:55:29.000000000","message":"the max is 2. The count is only increased once it is detected that the request is for a symlink object. So object #1 can be a symlink, object #2 can also be a symlink, but not object #3.\n\nCheck out unit test: test_symlink_too_deep and test_symlink_change_symloopmax","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":201,"context_line":"        # exceeded symloop_max"},{"line_number":202,"context_line":"        errmsg \u003d \u0027Too many levels of symbolic links\u0027"},{"line_number":203,"context_line":"        self.logger.info(errmsg)"},{"line_number":204,"context_line":"        return HTTPPreconditionFailed(body\u003derrmsg)(req.environ,"},{"line_number":205,"context_line":"                                                   self._start_response)"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def handle_put(self, req):"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_f6768f04","line":204,"updated":"2016-09-08 10:39:29.000000000","message":"Does it make sense to include the value of symloop_max in the response like they do with other constraints ?","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":201,"context_line":"        # exceeded symloop_max"},{"line_number":202,"context_line":"        errmsg \u003d \u0027Too many levels of symbolic links\u0027"},{"line_number":203,"context_line":"        self.logger.info(errmsg)"},{"line_number":204,"context_line":"        return HTTPPreconditionFailed(body\u003derrmsg)(req.environ,"},{"line_number":205,"context_line":"                                                   self._start_response)"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def handle_put(self, req):"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_6d8d2ed2","line":204,"in_reply_to":"9a89bdaa_f6768f04","updated":"2016-09-09 19:55:29.000000000","message":"Done","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":212,"context_line":"        :param req: HTTP PUT object request"},{"line_number":213,"context_line":"        :returns: HTTP Response"},{"line_number":214,"context_line":"        \"\"\""},{"line_number":215,"context_line":"        if req.content_length:"},{"line_number":216,"context_line":"            return HTTPBadRequest("},{"line_number":217,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":218,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_85b50f7f","line":215,"range":{"start_line":215,"start_character":11,"end_line":215,"end_character":29},"updated":"2016-09-08 10:39:29.000000000","message":"Wondering what would be the behaviour if it\u0027s a chunked PUT...","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"d76b3d24cd5a115634f8c36c465a376e72f19cf7","unresolved":false,"context_lines":[{"line_number":212,"context_line":"        :param req: HTTP PUT object request"},{"line_number":213,"context_line":"        :returns: HTTP Response"},{"line_number":214,"context_line":"        \"\"\""},{"line_number":215,"context_line":"        if req.content_length:"},{"line_number":216,"context_line":"            return HTTPBadRequest("},{"line_number":217,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":218,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_d3159849","line":215,"range":{"start_line":215,"start_character":11,"end_line":215,"end_character":29},"in_reply_to":"9a89bdaa_0d70220a","updated":"2016-09-12 04:24:21.000000000","message":"+1 to not allowing symlinks to have bodies.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":212,"context_line":"        :param req: HTTP PUT object request"},{"line_number":213,"context_line":"        :returns: HTTP Response"},{"line_number":214,"context_line":"        \"\"\""},{"line_number":215,"context_line":"        if req.content_length:"},{"line_number":216,"context_line":"            return HTTPBadRequest("},{"line_number":217,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":218,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_0d70220a","line":215,"range":{"start_line":215,"start_character":11,"end_line":215,"end_character":29},"in_reply_to":"9a89bdaa_85b50f7f","updated":"2016-09-09 19:55:29.000000000","message":"good catch. I\u0027m leaning towards adding a check that would not allow chunked encoding, but this may contradict a rfc. OTOH we could allow symlinks to have bodies, but I think that complicates the concept and could potentially have clients uploading data to symlink objects when they didn\u0027t really mean to.\n\nFor now, I\u0027d like to hear other people\u0027s thoughts on this.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":232,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":235,"context_line":"        if is_success(self._get_status_int()) and \\"},{"line_number":236,"context_line":"                \u0027swift.post_as_copy\u0027 in req.environ:"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_78d0aec9","line":235,"range":{"start_line":235,"start_character":11,"end_line":235,"end_character":46},"updated":"2016-09-08 10:39:29.000000000","message":"The else part is executed if either of the conditions fail. If it was POST request, and if the request failed for whatever reason and \"swift.post_as_copy\" is present, the else part is executed i.e the original error is returned back and not a 307. I guess this is intentional.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":232,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":235,"context_line":"        if is_success(self._get_status_int()) and \\"},{"line_number":236,"context_line":"                \u0027swift.post_as_copy\u0027 in req.environ:"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_68b8bc11","line":235,"range":{"start_line":235,"start_character":11,"end_line":235,"end_character":46},"in_reply_to":"9a89bdaa_78d0aec9","updated":"2016-09-09 19:55:29.000000000","message":"right, we only want to return a 307 if the request was successful but also happens to be a POST request.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":275,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":276,"context_line":"            return HTTPTemporaryRedirect(body\u003derrmsg)("},{"line_number":277,"context_line":"                req.environ, self._start_response)"},{"line_number":278,"context_line":"        else:"},{"line_number":279,"context_line":"            return resp"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_4592274d","line":277,"range":{"start_line":276,"start_character":12,"end_line":277,"end_character":50},"updated":"2016-09-08 10:39:29.000000000","message":"The RFC states that the server responding with a 307 should have a \u0027Location\u0027 header.\n\nhttps://tools.ietf.org/html/rfc7231#section-6.4.7\n\nSame comment for line 240","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":275,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":276,"context_line":"            return HTTPTemporaryRedirect(body\u003derrmsg)("},{"line_number":277,"context_line":"                req.environ, self._start_response)"},{"line_number":278,"context_line":"        else:"},{"line_number":279,"context_line":"            return resp"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_bb864c11","line":277,"range":{"start_line":276,"start_character":12,"end_line":277,"end_character":50},"in_reply_to":"9a89bdaa_4592274d","updated":"2016-09-09 19:55:29.000000000","message":"Done","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":283,"context_line":"        Handle object requests"},{"line_number":284,"context_line":"        \"\"\""},{"line_number":285,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":286,"context_line":"            if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":287,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":288,"context_line":"            else:"},{"line_number":289,"context_line":"                resp \u003d self.handle_get_head(req)"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_e5525b66","line":286,"range":{"start_line":286,"start_character":15,"end_line":286,"end_character":32},"updated":"2016-09-08 10:39:29.000000000","message":"This will allow the query param to have any of the following values:\n\n    TRUE_VALUES \u003d set((\u0027true\u0027, \u00271\u0027, \u0027yes\u0027, \u0027on\u0027, \u0027t\u0027, \u0027y\u0027))\n\nI hope this is intentional.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":283,"context_line":"        Handle object requests"},{"line_number":284,"context_line":"        \"\"\""},{"line_number":285,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":286,"context_line":"            if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":287,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":288,"context_line":"            else:"},{"line_number":289,"context_line":"                resp \u003d self.handle_get_head(req)"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_084e503a","line":286,"range":{"start_line":286,"start_character":15,"end_line":286,"end_character":32},"in_reply_to":"9a89bdaa_e5525b66","updated":"2016-09-09 19:55:29.000000000","message":"yes, i think this is pretty common in swift","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":297,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":298,"context_line":"        else:"},{"line_number":299,"context_line":"            # DELETEs for a symlink behave like any other object"},{"line_number":300,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        start_response(self._response_status, self._response_headers,"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_85e7cfaa","line":299,"range":{"start_line":299,"start_character":14,"end_line":299,"end_character":21},"updated":"2016-09-08 10:39:29.000000000","message":"Also OPTIONS","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":297,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":298,"context_line":"        else:"},{"line_number":299,"context_line":"            # DELETEs for a symlink behave like any other object"},{"line_number":300,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        start_response(self._response_status, self._response_headers,"}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_08757062","line":299,"range":{"start_line":299,"start_character":14,"end_line":299,"end_character":21},"in_reply_to":"9a89bdaa_85e7cfaa","updated":"2016-09-09 19:55:29.000000000","message":"Done","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"d9e5e495aac6fcdb618223a09238c81dc9b893e0","unresolved":false,"context_lines":[{"line_number":44,"context_line":"``symloop_max`` value is 2."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dtrue``"},{"line_number":47,"context_line":"will reference the symlink itself."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. Because of eventual consistency the object server can"}],"source_content_type":"text/x-python","patch_set":40,"id":"da6895a0_98943f38","line":47,"updated":"2016-10-22 11:30:16.000000000","message":"nit: does it make sense to move this to line 36 before it is discussed what happens without the extra param?","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":44,"context_line":"``symloop_max`` value is 2."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dtrue``"},{"line_number":47,"context_line":"will reference the symlink itself."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":50,"context_line":"to the target object. Because of eventual consistency the object server can"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_6324640c","line":47,"in_reply_to":"da6895a0_98943f38","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"d9e5e495aac6fcdb618223a09238c81dc9b893e0","unresolved":false,"context_lines":[{"line_number":54,"context_line":"never be merged back with the target object, so issuing a GET/HEAD on symlink"},{"line_number":55,"context_line":"or directly to the target object will not return the metadata that was sent"},{"line_number":56,"context_line":"as part of the POST, unless the request contains the ``?symlink\u003dtrue``"},{"line_number":57,"context_line":"parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":40,"id":"da6895a0_d8b5d7cd","line":57,"updated":"2016-10-22 11:30:16.000000000","message":"This is a long sentence to stick with.  It might help to clarify/remind in this way:\n\n\"as part of the POST\"\nto\n\"as part of the POST to symlink\"","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":54,"context_line":"never be merged back with the target object, so issuing a GET/HEAD on symlink"},{"line_number":55,"context_line":"or directly to the target object will not return the metadata that was sent"},{"line_number":56,"context_line":"as part of the POST, unless the request contains the ``?symlink\u003dtrue``"},{"line_number":57,"context_line":"parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_a65cca19","line":57,"in_reply_to":"da6895a0_d8b5d7cd","updated":"2016-11-15 19:53:28.000000000","message":"I tried to clarify further, can you take a look and let me know what you think. Also feel free to re-write as you see fit.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"d9e5e495aac6fcdb618223a09238c81dc9b893e0","unresolved":false,"context_lines":[{"line_number":57,"context_line":"parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"A COPY request to a symlink will copy the target object. A COPY request to a"},{"line_number":63,"context_line":"symlink with the query parameter ``?symlink\u003dtrue`` will copy the symlink"}],"source_content_type":"text/x-python","patch_set":40,"id":"da6895a0_b8990371","line":60,"updated":"2016-10-22 11:30:16.000000000","message":"Is it worth giving some direction on the proper way to delete the target object?","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":57,"context_line":"parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"A COPY request to a symlink will copy the target object. A COPY request to a"},{"line_number":63,"context_line":"symlink with the query parameter ``?symlink\u003dtrue`` will copy the symlink"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_834df8c5","line":60,"in_reply_to":"ba5da102_1a5bc755","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":57,"context_line":"parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"A COPY request to a symlink will copy the target object. A COPY request to a"},{"line_number":63,"context_line":"symlink with the query parameter ``?symlink\u003dtrue`` will copy the symlink"}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_1a5bc755","line":60,"in_reply_to":"da6895a0_b8990371","updated":"2016-11-07 02:52:48.000000000","message":"Nevermind.  I am not sure what I was thinking before.  It should be clear to simply issue a delete as normal to the target.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"d9e5e495aac6fcdb618223a09238c81dc9b893e0","unresolved":false,"context_lines":[{"line_number":75,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":76,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"\"\"\""},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"da6895a0_18c82f55","line":78,"updated":"2016-10-22 11:30:16.000000000","message":"This sounds as if all POSTs error.\nYou can POST to a symlink to update symlink meta (using symlink\u003dtrue),\nor POST directly to target object to update target meta.\n\nMaybe specify POST to symlink without symlink\u003dtrue will produce ...","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":75,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":76,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"\"\"\""},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_c3c9b027","line":78,"in_reply_to":"9a629dbe_80924ef4","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"1b6ee1946d201d2bdc8c9c357ac7128d34d4d14c","unresolved":false,"context_lines":[{"line_number":75,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":76,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"\"\"\""},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_80924ef4","line":78,"in_reply_to":"da6895a0_18c82f55","updated":"2016-11-11 21:45:55.000000000","message":"talked to Thiago in IRC: the POST to a symlink to update symlink meta (using symlink\u003dtrue) will not be supported.  so, nevermind on this comment.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"d9e5e495aac6fcdb618223a09238c81dc9b893e0","unresolved":false,"context_lines":[{"line_number":150,"context_line":"                                              val)])"},{"line_number":151,"context_line":"            elif key.lower() \u003d\u003d TGT_ACCT_SYSMETA_SYMLINK_HDR:"},{"line_number":152,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":153,"context_line":"                                              val)])"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        return resp"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"da6895a0_78120bb6","line":153,"updated":"2016-10-22 11:30:16.000000000","message":"Why is this if/elif?  I thought you could have both.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":150,"context_line":"                                              val)])"},{"line_number":151,"context_line":"            elif key.lower() \u003d\u003d TGT_ACCT_SYSMETA_SYMLINK_HDR:"},{"line_number":152,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":153,"context_line":"                                              val)])"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        return resp"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_83e418ac","line":153,"in_reply_to":"da6895a0_78120bb6","updated":"2016-11-15 19:53:28.000000000","message":"It can. The for loop is iterating over each header, so the key will either be one or the other, if both headers are in _response_headers, they will both be found.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":237,"context_line":"        if is_success(self._get_status_int()) and \\"},{"line_number":238,"context_line":"                \u0027swift.post_as_copy\u0027 in req.environ:"},{"line_number":239,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":240,"context_line":"            target_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR)"},{"line_number":241,"context_line":"            target_acct \u003d symlink_account if symlink_account else acct"}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_da86af12","line":238,"updated":"2016-11-07 02:52:48.000000000","message":"if this was a POST using \u0027symlink\u003dtrue\u0027, then this should return successfully, correct?\n\nAlso, is there a reason that the swift.post_as_copy cannot be checked before making the _app_call?  The PUT request was carried out already and returned success.  My understanding is that we want to prevent the PUT from happening if it is from a post_as_copy, and return redirect.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":237,"context_line":"        if is_success(self._get_status_int()) and \\"},{"line_number":238,"context_line":"                \u0027swift.post_as_copy\u0027 in req.environ:"},{"line_number":239,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":240,"context_line":"            target_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR)"},{"line_number":241,"context_line":"            target_acct \u003d symlink_account if symlink_account else acct"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_4305a043","line":238,"in_reply_to":"9a629dbe_8057ae24","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"1b6ee1946d201d2bdc8c9c357ac7128d34d4d14c","unresolved":false,"context_lines":[{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        # if this was really a POST request, then return HTTPTemporaryRedirect"},{"line_number":237,"context_line":"        if is_success(self._get_status_int()) and \\"},{"line_number":238,"context_line":"                \u0027swift.post_as_copy\u0027 in req.environ:"},{"line_number":239,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":240,"context_line":"            target_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR)"},{"line_number":241,"context_line":"            target_acct \u003d symlink_account if symlink_account else acct"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_8057ae24","line":238,"in_reply_to":"ba5da102_da86af12","updated":"2016-11-11 21:45:55.000000000","message":"talked to Thiago in IRC: the POST to a symlink to update symlink meta (using symlink\u003dtrue) will not be supported. I also think I understand now why the post_as_copy check comes afterwards. so, nevermind on this comment.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        POSTs to a symlink will be handled just like a normal object by the"},{"line_number":260,"context_line":"        object server. It cannot reject it because it may not have symlink"},{"line_number":261,"context_line":"        state when the POST lands. If the object server is able to detect that"},{"line_number":262,"context_line":"        it is a symlink, it will add the sysmeta target object header to the"},{"line_number":263,"context_line":"        response and this method will return an HTTPTemporaryRedirect error if"},{"line_number":264,"context_line":"        it finds that header in the reponse."},{"line_number":265,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_ba349b4a","line":262,"updated":"2016-11-07 02:52:48.000000000","message":"May want to reword - it sounds like there would be object server changes for this adding of sysmeta, but I believe that this is true now because the sysmeta is always included in a POST response. https://review.openstack.org/#/c/357559/","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        POSTs to a symlink will be handled just like a normal object by the"},{"line_number":260,"context_line":"        object server. It cannot reject it because it may not have symlink"},{"line_number":261,"context_line":"        state when the POST lands. If the object server is able to detect that"},{"line_number":262,"context_line":"        it is a symlink, it will add the sysmeta target object header to the"},{"line_number":263,"context_line":"        response and this method will return an HTTPTemporaryRedirect error if"},{"line_number":264,"context_line":"        it finds that header in the reponse."},{"line_number":265,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_a68a0a62","line":262,"in_reply_to":"ba5da102_ba349b4a","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        response and this method will return an HTTPTemporaryRedirect error if"},{"line_number":264,"context_line":"        it finds that header in the reponse."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"        TODO: need to document fast post."},{"line_number":267,"context_line":""},{"line_number":268,"context_line":"        :param req: HTTP POST object request"},{"line_number":269,"context_line":"        :returns: HTTPTemporaryRedirect if POSTing to a symlink."}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_5a461fc0","line":266,"updated":"2016-11-07 02:52:48.000000000","message":"Is there something special to consider for fast post?  I am curious to see this documentation.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        response and this method will return an HTTPTemporaryRedirect error if"},{"line_number":264,"context_line":"        it finds that header in the reponse."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"        TODO: need to document fast post."},{"line_number":267,"context_line":""},{"line_number":268,"context_line":"        :param req: HTTP POST object request"},{"line_number":269,"context_line":"        :returns: HTTPTemporaryRedirect if POSTing to a symlink."}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_267efa69","line":266,"in_reply_to":"ba5da102_5a461fc0","updated":"2016-11-15 19:53:28.000000000","message":"i think this is old, there should no longer be any difference between fast post or not","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":269,"context_line":"        :returns: HTTPTemporaryRedirect if POSTing to a symlink."},{"line_number":270,"context_line":"        :returns: HTTP Response"},{"line_number":271,"context_line":"        \"\"\""},{"line_number":272,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":273,"context_line":"        if not is_success(self._get_status_int()):"},{"line_number":274,"context_line":"            return resp"},{"line_number":275,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_5a90dfec","line":272,"updated":"2016-11-07 02:52:48.000000000","message":"Similarly here as in PUT, I am wondering if it is ok that the POST is going to happen whether or not the post was to a symlink.  I dont see changes in the object server where it will look at the symlink status and reject the request if not appropriate.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":269,"context_line":"        :returns: HTTPTemporaryRedirect if POSTing to a symlink."},{"line_number":270,"context_line":"        :returns: HTTP Response"},{"line_number":271,"context_line":"        \"\"\""},{"line_number":272,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":273,"context_line":"        if not is_success(self._get_status_int()):"},{"line_number":274,"context_line":"            return resp"},{"line_number":275,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_66db927c","line":272,"in_reply_to":"9a629dbe_9559dc90","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"6c430550351be607d68262a24c01fd51daabf7ba","unresolved":false,"context_lines":[{"line_number":269,"context_line":"        :returns: HTTPTemporaryRedirect if POSTing to a symlink."},{"line_number":270,"context_line":"        :returns: HTTP Response"},{"line_number":271,"context_line":"        \"\"\""},{"line_number":272,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":273,"context_line":"        if not is_success(self._get_status_int()):"},{"line_number":274,"context_line":"            return resp"},{"line_number":275,"context_line":""}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_9559dc90","line":272,"in_reply_to":"ba5da102_5a90dfec","updated":"2016-11-10 19:44:52.000000000","message":"I chatted with Alistair on this.  He reminded me that we changed our stance on mods to the object server; the concern is that object server should not reject a POST based on thinking it has a symlink, because that info may be stale.\n\nSo, the changes still take affect.  we just respond in a way that indicates you cant trust the results.  I am now on board with this.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"58a30f7c0ae6a5b8338bf00edec256746a2f3e64","unresolved":false,"context_lines":[{"line_number":275,"context_line":""},{"line_number":276,"context_line":"        target_obj \u003d self._response_header_value("},{"line_number":277,"context_line":"            TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":278,"context_line":"        if target_obj:"},{"line_number":279,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":280,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":281,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"}],"source_content_type":"text/x-python","patch_set":40,"id":"ba5da102_faaff328","line":278,"updated":"2016-11-07 02:52:48.000000000","message":"Similarly here as in PUT, if this was a POST using \u0027symlink\u003dtrue\u0027, then this should return successfully, correct?","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fecce07098d04ad5c4a0cf099977667f4f5e720b","unresolved":false,"context_lines":[{"line_number":275,"context_line":""},{"line_number":276,"context_line":"        target_obj \u003d self._response_header_value("},{"line_number":277,"context_line":"            TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":278,"context_line":"        if target_obj:"},{"line_number":279,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":280,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":281,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_c6d29e5b","line":278,"in_reply_to":"9a629dbe_e036aa01","updated":"2016-11-15 19:53:28.000000000","message":"Done","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"1b6ee1946d201d2bdc8c9c357ac7128d34d4d14c","unresolved":false,"context_lines":[{"line_number":275,"context_line":""},{"line_number":276,"context_line":"        target_obj \u003d self._response_header_value("},{"line_number":277,"context_line":"            TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":278,"context_line":"        if target_obj:"},{"line_number":279,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":280,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":281,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"}],"source_content_type":"text/x-python","patch_set":40,"id":"9a629dbe_e036aa01","line":278,"in_reply_to":"ba5da102_faaff328","updated":"2016-11-11 21:45:55.000000000","message":"talked to Thiago in IRC: the POST to a symlink to update symlink meta (using symlink\u003dtrue) will not be supported.  so, nevermind on this comment.","commit_id":"bf022506601a60cdddf0197b42a6f77bdca5b339"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"fc5b220aa78c7cd0a04fa4c2e9e17dc95345fab2","unresolved":false,"context_lines":[{"line_number":48,"context_line":"Clients should not send POST requests to a symlink. They are never redirected"},{"line_number":49,"context_line":"to the target object. Because of eventual consistency the object server can"},{"line_number":50,"context_line":"never know for sure if the current object is a symlink or not. When a POST"},{"line_number":51,"context_line":"request is sent to a symlink, the metadata it will be applied to the symlink,"},{"line_number":52,"context_line":"but the request will result in a 300-series error response to the client."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"The metadata that was applied to a symlink will never be merged back with the"}],"source_content_type":"text/x-python","patch_set":42,"id":"5a74a57a_60f8847d","line":51,"updated":"2016-11-30 20:48:39.000000000","message":"s/metadata it will/metadata will/","commit_id":"789202e84f1b0c9a0d8cebdd6f044810973813e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":31,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":32,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":33,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":34,"context_line":"error. The referenced object need not exist at symlink-creation time."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dtrue`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_b524a6c6","line":34,"updated":"2017-01-10 00:29:50.000000000","message":"we should say 404 here","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":54,"context_line":"The metadata that was applied to a symlink will never be merged back with the"},{"line_number":55,"context_line":"target object. Issuing a GET/HEAD on symlink or directly to the target"},{"line_number":56,"context_line":"object will not return the metadata that was sent as part of the POST to the"},{"line_number":57,"context_line":"symlink, unless the request contains the ``?symlink\u003dtrue`` parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_0fe2c59f","line":57,"updated":"2017-01-10 00:29:50.000000000","message":"reword this to speak separately about GET/HEAD w/ or w/o ?symlink\u003dtrue","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":54,"context_line":"The metadata that was applied to a symlink will never be merged back with the"},{"line_number":55,"context_line":"target object. Issuing a GET/HEAD on symlink or directly to the target"},{"line_number":56,"context_line":"object will not return the metadata that was sent as part of the POST to the"},{"line_number":57,"context_line":"symlink, unless the request contains the ``?symlink\u003dtrue`` parameter."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":60,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_0e0f9c88","line":57,"in_reply_to":"ba5201f7_0fe2c59f","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":78,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":79,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":82,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_f233a4f4","line":79,"updated":"2017-01-10 00:29:50.000000000","message":"nope, it\u0027s not a Precondition (if-match, etc) - just 400 is fine.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dtrue``"},{"line_number":78,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":79,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":82,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_70eb9e78","line":79,"in_reply_to":"ba5201f7_f233a4f4","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":78,"context_line":"  traversing more than ``symloop_max`` chained symlinks"},{"line_number":79,"context_line":"  will produce a 412 PreconditionFailed error."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"* POSTs will produce a 307 Temporary Redirect error."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"\"\"\""},{"line_number":84,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_52863066","line":81,"updated":"2017-01-10 00:29:50.000000000","message":"look at us all fancy with the new hawtness - seems pretty close to 302 - i\u0027m down","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":94,"context_line":"from swift.common.http import is_success, is_client_error, is_redirection"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"DEFAULT_SYMLOOP_MAX \u003d 2"},{"line_number":97,"context_line":"TGT_OBJ_SYMLINK_HDR \u003d \u0027x-symlink-target\u0027"},{"line_number":98,"context_line":"TGT_OBJ_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \\"},{"line_number":99,"context_line":"    \u0027symlink-target-object\u0027"},{"line_number":100,"context_line":"TGT_ACCT_SYMLINK_HDR \u003d \u0027x-symlink-target-account\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_351196b0","line":97,"updated":"2017-01-10 00:29:50.000000000","message":"is paul back?  waht is this?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"565e11527502ce8c6b69756ef89684b385905d0b","unresolved":false,"context_lines":[{"line_number":96,"context_line":"DEFAULT_SYMLOOP_MAX \u003d 2"},{"line_number":97,"context_line":"TGT_OBJ_SYMLINK_HDR \u003d \u0027x-symlink-target\u0027"},{"line_number":98,"context_line":"TGT_OBJ_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \\"},{"line_number":99,"context_line":"    \u0027symlink-target-object\u0027"},{"line_number":100,"context_line":"TGT_ACCT_SYMLINK_HDR \u003d \u0027x-symlink-target-account\u0027"},{"line_number":101,"context_line":"TGT_ACCT_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \\"},{"line_number":102,"context_line":"    \u0027symlink-target-account\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_154bb2b1","line":99,"updated":"2017-01-10 00:29:50.000000000","message":"i will *constantly* forget this is symlink-target-*object* instead of just symlink-target like the client header","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":96,"context_line":"DEFAULT_SYMLOOP_MAX \u003d 2"},{"line_number":97,"context_line":"TGT_OBJ_SYMLINK_HDR \u003d \u0027x-symlink-target\u0027"},{"line_number":98,"context_line":"TGT_OBJ_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \\"},{"line_number":99,"context_line":"    \u0027symlink-target-object\u0027"},{"line_number":100,"context_line":"TGT_ACCT_SYMLINK_HDR \u003d \u0027x-symlink-target-account\u0027"},{"line_number":101,"context_line":"TGT_ACCT_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \\"},{"line_number":102,"context_line":"    \u0027symlink-target-account\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_2e60d800","line":99,"in_reply_to":"ba5201f7_154bb2b1","updated":"2017-10-13 20:49:00.000000000","message":"changed to actually have only one sysmeta header.\nThere is still two client facing headers, target and target-account, but only one sysmeta header: target\n\nThe sysmeta will always contain the account. either the one provided by the user or the same as symlink.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":113,"context_line":"    :raise: HTTPPreconditionFailed if x-symlink-target value"},{"line_number":114,"context_line":"            is not well formatted."},{"line_number":115,"context_line":"    \"\"\""},{"line_number":116,"context_line":"    # if the request is a copy, the headers might be in sysmeta already"},{"line_number":117,"context_line":"    if TGT_OBJ_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":118,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d \\"},{"line_number":119,"context_line":"            req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_350ffa37","line":116,"updated":"2016-12-17 00:31:46.000000000","message":"COPY would come to us as a GET, right? So don\u0027t we already translate the headers in handle_get_head_symlink?\n\nOr is this to guard against clients providing x-symlink-target headers during a COPY?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":113,"context_line":"    :raise: HTTPPreconditionFailed if x-symlink-target value"},{"line_number":114,"context_line":"            is not well formatted."},{"line_number":115,"context_line":"    \"\"\""},{"line_number":116,"context_line":"    # if the request is a copy, the headers might be in sysmeta already"},{"line_number":117,"context_line":"    if TGT_OBJ_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":118,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d \\"},{"line_number":119,"context_line":"            req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_949ca45e","line":116,"in_reply_to":"1a6eadb0_350ffa37","updated":"2017-01-09 20:13:28.000000000","message":"In the case of a POST with post_as_copy \u003d true, the header will only be in sysmeta. That\u0027s because the GET part of the COPY would be handled by the handle_get_head() method and not by handle_get_head_symlink().\n\nBut you did bring up a good point about that this would also guard against clients providing x-symlink-target headers during a COPY. I do like that behavior (it seems correct to me), but could be convinced otherwise. wdyt?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":117,"context_line":"    if TGT_OBJ_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":118,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d \\"},{"line_number":119,"context_line":"            req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"},{"line_number":120,"context_line":"    if TGT_ACCT_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":121,"context_line":"        req.headers[TGT_ACCT_SYMLINK_HDR] \u003d \\"},{"line_number":122,"context_line":"            req.headers[TGT_ACCT_SYSMETA_SYMLINK_HDR]"},{"line_number":123,"context_line":"    return check_path_header(req, TGT_OBJ_SYMLINK_HDR, 2,"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_153d9edc","line":120,"updated":"2016-12-17 00:31:46.000000000","message":"Can we have TGT_ACCT_SYSMETA_SYMLINK_HDR set without having TGT_OBJ_SYSMETA_SYMLINK_HDR set?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":117,"context_line":"    if TGT_OBJ_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":118,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d \\"},{"line_number":119,"context_line":"            req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"},{"line_number":120,"context_line":"    if TGT_ACCT_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":121,"context_line":"        req.headers[TGT_ACCT_SYMLINK_HDR] \u003d \\"},{"line_number":122,"context_line":"            req.headers[TGT_ACCT_SYSMETA_SYMLINK_HDR]"},{"line_number":123,"context_line":"    return check_path_header(req, TGT_OBJ_SYMLINK_HDR, 2,"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_748020f8","line":120,"in_reply_to":"1a6eadb0_153d9edc","updated":"2017-01-09 20:13:28.000000000","message":"it would be ignored if you did. see line 315.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a5ee3b9a27a3472b70ca6b0b2b3bc923fce7135e","unresolved":false,"context_lines":[{"line_number":168,"context_line":"        \"\"\""},{"line_number":169,"context_line":"        count \u003d 0"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        while count \u003c\u003d self.symloop_max:"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":174,"context_line":"            if not is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":43,"id":"da4df55a_f21ec26e","line":171,"updated":"2016-12-27 21:12:41.000000000","message":"nit:\n\n for count in range(self.symloop_max):\n\n...and then we never need to actually *use* count.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":168,"context_line":"        \"\"\""},{"line_number":169,"context_line":"        count \u003d 0"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        while count \u003c\u003d self.symloop_max:"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":174,"context_line":"            if not is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_fd70a9de","line":171,"in_reply_to":"da4df55a_f21ec26e","updated":"2017-01-09 20:13:28.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a5ee3b9a27a3472b70ca6b0b2b3bc923fce7135e","unresolved":false,"context_lines":[{"line_number":192,"context_line":""},{"line_number":193,"context_line":"            # if it\u0027s a symlink, follow symlink"},{"line_number":194,"context_line":"            # unless this GET request is part of a POST as COPY"},{"line_number":195,"context_line":"            if target_obj and \u0027swift.post_as_copy\u0027 not in req.environ:"},{"line_number":196,"context_line":"                version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":197,"context_line":"                target_acct \u003d target_acct if target_acct else acct"},{"line_number":198,"context_line":"                target_path \u003d \u0027/%s/%s/%s\u0027 % (version, target_acct, target_obj)"}],"source_content_type":"text/x-python","patch_set":43,"id":"da4df55a_f237a2fc","line":195,"range":{"start_line":195,"start_character":30,"end_line":195,"end_character":69},"updated":"2016-12-27 21:12:41.000000000","message":"Oh! This is why my POST-to-SLO is 400ing! We don\u0027t have a good way to determine whether this is a POST to a symlink or a HEAD as a result of a POST to an SLO :-(","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":192,"context_line":""},{"line_number":193,"context_line":"            # if it\u0027s a symlink, follow symlink"},{"line_number":194,"context_line":"            # unless this GET request is part of a POST as COPY"},{"line_number":195,"context_line":"            if target_obj and \u0027swift.post_as_copy\u0027 not in req.environ:"},{"line_number":196,"context_line":"                version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":197,"context_line":"                target_acct \u003d target_acct if target_acct else acct"},{"line_number":198,"context_line":"                target_path \u003d \u0027/%s/%s/%s\u0027 % (version, target_acct, target_obj)"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_ab61bbd5","line":195,"range":{"start_line":195,"start_character":30,"end_line":195,"end_character":69},"in_reply_to":"da4df55a_f237a2fc","updated":"2017-01-09 20:13:28.000000000","message":"we decided to remove any support for post-as-copy to symlink.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":231,"context_line":"        _check_symlink_header(req)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d req.headers.get("},{"line_number":234,"context_line":"            TGT_OBJ_SYMLINK_HDR)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        # check if symlink targets an object in a different account"},{"line_number":237,"context_line":"        symlink_account \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_709260f7","line":234,"updated":"2016-12-17 00:31:46.000000000","message":"I think we need an lstrip(\u0027/\u0027) here? Something.\n\nSince _check_symlink_header relies on check_path (which massages whatever it\u0027s given to a form that includes a leading slash), headers like \u0027/c/o\u0027 are considered valid. But when we go to construct the target again we add another slash, creating a path like /v1/a//c/o which triggers a (sigh) 412:\n\n $ curl http://saio:8090/v1/AUTH_test/c/sym?symlink\u003dtrue\n*   Trying 192.168.8.80...\n* TCP_NODELAY set\n* Connected to saio (192.168.8.80) port 8090 (#0)\n\u003e GET /v1/AUTH_test/c/sym?symlink\u003dtrue HTTP/1.1\n\u003e Host: saio:8090\n\u003e User-Agent: curl/7.51.0\n\u003e Accept: application/json;q\u003d1, text/*;q\u003d.9, */*;q\u003d.8\n\u003e\n\u003c HTTP/1.1 200 OK\n\u003c Content-Length: 0\n\u003c Accept-Ranges: bytes\n\u003c Last-Modified: Fri, 16 Dec 2016 23:45:58 GMT\n\u003c Connection: close\n\u003c Etag: d41d8cd98f00b204e9800998ecf8427e\n\u003c X-Timestamp: 1481931957.78752\n\u003c Date: Fri, 16 Dec 2016 23:46:29 GMT\n\u003c Content-Type: application/x-www-form-urlencoded\n\u003c X-Symlink-Target: /c/slo\n\u003c X-Trans-Id: tx8b2ee04f262a4bcba8b0e-0058547cd5\n\u003c X-Openstack-Request-Id: tx8b2ee04f262a4bcba8b0e-0058547cd5\n\u003c\n* Curl_http_done: called premature \u003d\u003d 0\n* Closing connection 0\n\n $ curl http://saio:8090/v1/AUTH_test/c/sym\n*   Trying 192.168.8.80...\n* TCP_NODELAY set\n* Connected to saio (192.168.8.80) port 8090 (#0)\n\u003e GET /v1/AUTH_test/c/sym HTTP/1.1\n\u003e Host: saio:8090\n\u003e User-Agent: curl/7.51.0\n\u003e Accept: application/json;q\u003d1, text/*;q\u003d.9, */*;q\u003d.8\n\u003e\n\u003c HTTP/1.1 412 Precondition Failed\n\u003c Content-Length: 7\n\u003c Content-Type: text/html; charset\u003dUTF-8\n\u003c X-Trans-Id: tx66e85fb552dc409fae077-0058547cba\n\u003c X-Openstack-Request-Id: tx66e85fb552dc409fae077-0058547cba\n\u003c Date: Fri, 16 Dec 2016 23:46:02 GMT\n\u003c\n* Curl_http_done: called premature \u003d\u003d 0\n* Connection #0 to host saio left intact\nBad URL","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":231,"context_line":"        _check_symlink_header(req)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d req.headers.get("},{"line_number":234,"context_line":"            TGT_OBJ_SYMLINK_HDR)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        # check if symlink targets an object in a different account"},{"line_number":237,"context_line":"        symlink_account \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_c26ac080","line":234,"in_reply_to":"1a6eadb0_709260f7","updated":"2017-01-09 20:13:28.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":286,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":287,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":288,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"},{"line_number":289,"context_line":"            target_acct \u003d target_acct if target_acct else acct"},{"line_number":290,"context_line":"            location_hdr \u003d \"%s/%s/%s/%s\" % (req.host_url, version, target_acct,"},{"line_number":291,"context_line":"                                            target_obj)"},{"line_number":292,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_5049e42f","line":289,"range":{"start_line":289,"start_character":26,"end_line":289,"end_character":62},"updated":"2016-12-17 00:31:46.000000000","message":"_response_header_value doesn\u0027t have an optional default\u003dNone arg? Lame :-(\n\nI guess another option would be to add\n\n or acct\n\nto the line above...","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":286,"context_line":"            version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":287,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":288,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"},{"line_number":289,"context_line":"            target_acct \u003d target_acct if target_acct else acct"},{"line_number":290,"context_line":"            location_hdr \u003d \"%s/%s/%s/%s\" % (req.host_url, version, target_acct,"},{"line_number":291,"context_line":"                                            target_obj)"},{"line_number":292,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_43cab66f","line":289,"in_reply_to":"1a6eadb0_5049e42f","updated":"2017-01-09 20:13:28.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":287,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":288,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"},{"line_number":289,"context_line":"            target_acct \u003d target_acct if target_acct else acct"},{"line_number":290,"context_line":"            location_hdr \u003d \"%s/%s/%s/%s\" % (req.host_url, version, target_acct,"},{"line_number":291,"context_line":"                                            target_obj)"},{"line_number":292,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":293,"context_line":"                \u0027POST directly to target object\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_70c7c063","line":290,"range":{"start_line":290,"start_character":44,"end_line":290,"end_character":56},"updated":"2016-12-17 00:31:46.000000000","message":"This is going to have problems when behind a load balancer or TLS terminator -- see bug 1572011. Might be worth adding a configurable URL base, like Zaitcev did in Ie15cf2aff4f7e6bcf68b67ae733c77bb9353587a.\n\nOr maybe we should just send \u0027/v1/...\u0027 and fix up how swob resolves that over in https://github.com/openstack/swift/blob/2.12.0/swift/common/swob.py#L1377-L1379 ?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":287,"context_line":"            target_acct \u003d self._response_header_value("},{"line_number":288,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR)"},{"line_number":289,"context_line":"            target_acct \u003d target_acct if target_acct else acct"},{"line_number":290,"context_line":"            location_hdr \u003d \"%s/%s/%s/%s\" % (req.host_url, version, target_acct,"},{"line_number":291,"context_line":"                                            target_obj)"},{"line_number":292,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":293,"context_line":"                \u0027POST directly to target object\u0027"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_1803f00e","line":290,"range":{"start_line":290,"start_character":44,"end_line":290,"end_character":56},"in_reply_to":"1a6eadb0_70c7c063","updated":"2017-01-09 20:13:28.000000000","message":"settled for relative path...","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":301,"context_line":"        \"\"\""},{"line_number":302,"context_line":"        Handle object requests"},{"line_number":303,"context_line":"        \"\"\""},{"line_number":304,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":305,"context_line":"            if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":306,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":307,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_bb3939a6","line":304,"updated":"2016-12-17 00:31:46.000000000","message":"Not sure where else to complain about this, but...\n\nTrying to POST (-as-copy) to an SLO that includes a symlink as a segment gets me a 400 like\n\n{\"Errors\": [\n [\"/c/o2\", \"Too small; each segment must be at least 1 byte.\"],\n [\"/c/o2\", \"Size Mismatch\"],\n [\"/c/o2\", \"Etag Mismatch\"]]}\n\n...only I\u0027m not really sure why? SLO is killing any query strings explicitly :-/\n\nFWIW, the logs look like http://paste.openstack.org/show/592685/ -- not sure if that\u0027ll actually help.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":301,"context_line":"        \"\"\""},{"line_number":302,"context_line":"        Handle object requests"},{"line_number":303,"context_line":"        \"\"\""},{"line_number":304,"context_line":"        if req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":305,"context_line":"            if config_true_value(req.params.get(\u0027symlink\u0027)):"},{"line_number":306,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":307,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_eb80234c","line":304,"in_reply_to":"1a6eadb0_bb3939a6","updated":"2017-01-09 20:13:28.000000000","message":"we decided to remove support for post-as-copy in symlink as it is being deprecated and will eventually be removed from swift.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":316,"context_line":"                                      TGT_OBJ_SYSMETA_SYMLINK_HDR in"},{"line_number":317,"context_line":"                                      req.headers):"},{"line_number":318,"context_line":"            # if this PUT is derivative of a COPY request, the headers will"},{"line_number":319,"context_line":"            # be in sysmeta already"},{"line_number":320,"context_line":"            resp \u003d self.handle_put(req)"},{"line_number":321,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":322,"context_line":"            resp \u003d self.handle_post(req)"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_d0309458","line":319,"updated":"2016-12-17 00:31:46.000000000","message":"Wouldn\u0027t the GET half have already translated it back to the client header? Can we *just* look for the client header?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":316,"context_line":"                                      TGT_OBJ_SYSMETA_SYMLINK_HDR in"},{"line_number":317,"context_line":"                                      req.headers):"},{"line_number":318,"context_line":"            # if this PUT is derivative of a COPY request, the headers will"},{"line_number":319,"context_line":"            # be in sysmeta already"},{"line_number":320,"context_line":"            resp \u003d self.handle_put(req)"},{"line_number":321,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":322,"context_line":"            resp \u003d self.handle_post(req)"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_dd400c37","line":319,"in_reply_to":"1a6eadb0_d0309458","updated":"2017-01-09 20:13:28.000000000","message":"removed it since we won\u0027t support slow-post anymore","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":342,"context_line":"    objects."},{"line_number":343,"context_line":"    \"\"\""},{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    def __init__(self, app, conf, symloop_max, logger\u003dNone):"},{"line_number":346,"context_line":"        self.app \u003d app"},{"line_number":347,"context_line":"        self.conf \u003d conf"},{"line_number":348,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink_middleware\u0027)"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_50ad64e7","line":345,"range":{"start_line":345,"start_character":47,"end_line":345,"end_character":53},"updated":"2016-12-17 00:31:46.000000000","message":"Unused?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":342,"context_line":"    objects."},{"line_number":343,"context_line":"    \"\"\""},{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    def __init__(self, app, conf, symloop_max, logger\u003dNone):"},{"line_number":346,"context_line":"        self.app \u003d app"},{"line_number":347,"context_line":"        self.conf \u003d conf"},{"line_number":348,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink_middleware\u0027)"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_e90c6b3d","line":345,"in_reply_to":"1a6eadb0_50ad64e7","updated":"2017-01-09 20:13:28.000000000","message":"it\u0027s actually used in a couple of places.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":355,"context_line":"        except ValueError:"},{"line_number":356,"context_line":"            # not an object request"},{"line_number":357,"context_line":"            return self.app(env, start_response)"},{"line_number":358,"context_line":"        else:"},{"line_number":359,"context_line":"            context \u003d SymlinkContext(self)"},{"line_number":360,"context_line":"            resp \u003d context.handle_object(req, start_response)"},{"line_number":361,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_b0eb1812","line":358,"range":{"start_line":358,"start_character":8,"end_line":358,"end_character":13},"updated":"2016-12-17 00:31:46.000000000","message":"nit: not really necessary since the except block returns.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":355,"context_line":"        except ValueError:"},{"line_number":356,"context_line":"            # not an object request"},{"line_number":357,"context_line":"            return self.app(env, start_response)"},{"line_number":358,"context_line":"        else:"},{"line_number":359,"context_line":"            context \u003d SymlinkContext(self)"},{"line_number":360,"context_line":"            resp \u003d context.handle_object(req, start_response)"},{"line_number":361,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_899bdfc8","line":358,"in_reply_to":"1a6eadb0_b0eb1812","updated":"2017-01-09 20:13:28.000000000","message":"Done","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":366,"context_line":"    conf \u003d global_conf.copy()"},{"line_number":367,"context_line":"    conf.update(local_conf)"},{"line_number":368,"context_line":""},{"line_number":369,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":370,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":371,"context_line":""},{"line_number":372,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_d0797494","line":369,"range":{"start_line":369,"start_character":32,"end_line":369,"end_character":43},"updated":"2016-12-17 00:31:46.000000000","message":"Should we in some way force this to be at least 1?\n\nIs there value in allowing 0 or negative numbers?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":366,"context_line":"    conf \u003d global_conf.copy()"},{"line_number":367,"context_line":"    conf.update(local_conf)"},{"line_number":368,"context_line":""},{"line_number":369,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":370,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":371,"context_line":""},{"line_number":372,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_2e9f5951","line":369,"in_reply_to":"1a6eadb0_d0797494","updated":"2017-01-09 20:13:28.000000000","message":"added a check for \u003c 1 and then set it to DEFAULT_SYMLOOP_MAX\nwdyt?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_8e306558","line":34,"updated":"2017-01-19 23:50:02.000000000","message":"If the client *didn\u0027t* specify a Content-Type, should we set it to application/symlink or let the proxy-server try to auto-detect from object name?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_4b150047","line":34,"in_reply_to":"5a3905b3_8e306558","updated":"2017-02-17 18:58:12.000000000","message":"I think Clay brought this up and ended up concluding that it wasn\u0027t a good idea....but I can\u0027t remember the exact reason :(","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":203,"context_line":"                req \u003d make_subrequest("},{"line_number":204,"context_line":"                    req.environ, path\u003dtarget_path, method\u003dreq.method,"},{"line_number":205,"context_line":"                    headers\u003dreq.headers,"},{"line_number":206,"context_line":"                    swift_source\u003d\u0027SYM\u0027)"},{"line_number":207,"context_line":"                req.headers.pop(\u0027X-Backend-Storage-Policy-Index\u0027, None)"},{"line_number":208,"context_line":"            else:"},{"line_number":209,"context_line":"                if target_path:"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_6deed623","line":206,"range":{"start_line":206,"start_character":20,"end_line":206,"end_character":38},"updated":"2017-01-19 23:50:02.000000000","message":"I\u0027m debating whether we should actually set a swift_source here. I kinda remember Clay saying something about us recommending that you ignore the bytes transferred when parsing logs if there\u0027s a swift_source ... in which case, you want the actual final transfer to appear to come from the user. On the other hand, though, if you\u0027re interested in the number of client requests, you don\u0027t want symlinks inflating it...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":225,"context_line":"        :param req: HTTP PUT object request"},{"line_number":226,"context_line":"        :returns: HTTP Response"},{"line_number":227,"context_line":"        \"\"\""},{"line_number":228,"context_line":"        data \u003d req.body_file.read()"},{"line_number":229,"context_line":"        if data:"},{"line_number":230,"context_line":"            return HTTPBadRequest("},{"line_number":231,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_dcd142fd","line":228,"updated":"2017-01-19 23:50:02.000000000","message":"Doesn\u0027t this read *everything*? Better to just read(1); if we see anything, send the response \u0026 drop the connection.","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":225,"context_line":"        :param req: HTTP PUT object request"},{"line_number":226,"context_line":"        :returns: HTTP Response"},{"line_number":227,"context_line":"        \"\"\""},{"line_number":228,"context_line":"        data \u003d req.body_file.read()"},{"line_number":229,"context_line":"        if data:"},{"line_number":230,"context_line":"            return HTTPBadRequest("},{"line_number":231,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_ce465e4e","line":228,"in_reply_to":"5a3905b3_dcd142fd","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        cont_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR).lstrip(\"/\")"},{"line_number":246,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d \"/%s/%s\" % (sym_acct,"},{"line_number":247,"context_line":"                                                               cont_obj)"},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        return self._app_call(req.environ)"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_8ecce536","line":247,"updated":"2017-01-19 23:50:02.000000000","message":"Yeah, may as well take advantage of the fact that we\u0027ve got separate client/backend headers! I like it!","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        cont_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR).lstrip(\"/\")"},{"line_number":246,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d \"/%s/%s\" % (sym_acct,"},{"line_number":247,"context_line":"                                                               cont_obj)"},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        return self._app_call(req.environ)"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_e4867d15","line":247,"in_reply_to":"1a430d35_a27df51d","updated":"2017-02-17 18:58:12.000000000","message":"left as is and added a func test for cross-account copy","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"        cont_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR).lstrip(\"/\")"},{"line_number":246,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d \"/%s/%s\" % (sym_acct,"},{"line_number":247,"context_line":"                                                               cont_obj)"},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        return self._app_call(req.environ)"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"1a430d35_a27df51d","line":247,"in_reply_to":"5a3905b3_8ecce536","updated":"2017-02-07 19:33:54.000000000","message":"Note that there\u0027s a subtle change in behavior compared to previous patchsets: given a symlink that was originally PUT with only a X-Symlink-Target header, COPYing it to another account used to reference the corresponding container/object in the new account, but now will still continue to reference the object in the original account. I think I prefer the new behavior -- do we have tests for that cross-account copy?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":272,"context_line":"            return resp"},{"line_number":273,"context_line":""},{"line_number":274,"context_line":"        sym_target \u003d self._response_header_value(TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":275,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":276,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":277,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":278,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_ae9fe101","line":275,"range":{"start_line":275,"start_character":26,"end_line":275,"end_character":65},"updated":"2017-01-19 23:50:02.000000000","message":"nit: Maybe\n\n req.params.get(\u0027symlink\u0027) !\u003d \u0027post\u0027\n\n? Does anyone actually care?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":272,"context_line":"            return resp"},{"line_number":273,"context_line":""},{"line_number":274,"context_line":"        sym_target \u003d self._response_header_value(TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":275,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":276,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":277,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":278,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_e1c22f84","line":275,"in_reply_to":"5a3905b3_ae9fe101","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":275,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":276,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":277,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":278,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":279,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":280,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":281,"context_line":"            return HTTPTemporaryRedirect("}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_37efc1e9","line":278,"updated":"2017-01-19 23:50:02.000000000","message":"Cool, looks like the RFC explicitly allows relative locations: https://tools.ietf.org/html/rfc7231#section-7.1.2\n\nFor some reason I had it in my head that it wasn\u0027t generally a good idea... Oh! That\u0027s why -- the old RFC said to use absolute URIs: https://tools.ietf.org/html/rfc2616.html#section-14.30\n\nHmm...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":275,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":276,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":277,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":278,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":279,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":280,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":281,"context_line":"            return HTTPTemporaryRedirect("}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_88d98cf5","line":278,"in_reply_to":"5a3905b3_37efc1e9","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":297,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":298,"context_line":"            # the symlink only, not the referenced target"},{"line_number":299,"context_line":"            if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":300,"context_line":"                    (\u0027swift.source\u0027 in req.environ and"},{"line_number":301,"context_line":"                     req.environ[\u0027swift.source\u0027]) \u003d\u003d \u0027VW\u0027:"},{"line_number":302,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":303,"context_line":"            else:"},{"line_number":304,"context_line":"                resp \u003d self.handle_get_head(req)"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_4e2d9da6","line":301,"range":{"start_line":300,"start_character":20,"end_line":301,"end_character":57},"updated":"2017-01-19 23:50:02.000000000","message":"Better as\n\n req.environ.get(\u0027swift.source\u0027) \u003d\u003d \u0027VW\u0027\n\n? I suppose either way we end up with a vaguely-nonsense comparison.\n\nShould symlink be aware of versioned_writes, or should versioned_writes be aware of symlink? I vaguely prefer versioned_writes having the added complexity instead, but that may be tainted by my future plans for versioned_writes. FWIW, it already has to know about dlo (although I\u0027m not exactly sure why...)","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":298,"context_line":"            # the symlink only, not the referenced target"},{"line_number":299,"context_line":"            if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":300,"context_line":"                    (\u0027swift.source\u0027 in req.environ and"},{"line_number":301,"context_line":"                     req.environ[\u0027swift.source\u0027]) \u003d\u003d \u0027VW\u0027:"},{"line_number":302,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":303,"context_line":"            else:"},{"line_number":304,"context_line":"                resp \u003d self.handle_get_head(req)"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_014e63c0","line":301,"in_reply_to":"5a3905b3_4e2d9da6","updated":"2017-02-17 18:58:12.000000000","message":"made the suggested change.\n\nRegarding where to place the code, it is also something I had struggled with. We unfortunately don\u0027t have a systematic way of determining where to add this type of code (knowledge about other middlewares), so it becomes quite a subjective approach. I don\u0027t think I can argue too strongly on one or the other, I went with this approach here with the idea that symlink is \"further down in the pipeline\" so it should know what\u0027s come before it ??? I\u0027m not so sure that\u0027s a better argument than put in in versioned_writes because it already knows about dlo, but if more people feel strong about that I\u0027d be happy to move it...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":328,"context_line":"    objects."},{"line_number":329,"context_line":"    \"\"\""},{"line_number":330,"context_line":""},{"line_number":331,"context_line":"    def __init__(self, app, conf, symloop_max, logger\u003dNone):"},{"line_number":332,"context_line":"        self.app \u003d app"},{"line_number":333,"context_line":"        self.conf \u003d conf"},{"line_number":334,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink\u0027)"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_39a09d9f","line":331,"range":{"start_line":331,"start_character":47,"end_line":331,"end_character":53},"updated":"2017-01-19 23:50:02.000000000","message":"No, seriously, we never use this. We use get_logger to set self.logger based on conf.","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":328,"context_line":"    objects."},{"line_number":329,"context_line":"    \"\"\""},{"line_number":330,"context_line":""},{"line_number":331,"context_line":"    def __init__(self, app, conf, symloop_max, logger\u003dNone):"},{"line_number":332,"context_line":"        self.app \u003d app"},{"line_number":333,"context_line":"        self.conf \u003d conf"},{"line_number":334,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink\u0027)"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_fc80188d","line":331,"in_reply_to":"5a3905b3_39a09d9f","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":338,"context_line":"            msg \u003d \u0027Symlink middleware does not support \u0027 \\"},{"line_number":339,"context_line":"                \u0027object_post_as_copy \u003d true\u0027"},{"line_number":340,"context_line":"            self.logger.error(msg)"},{"line_number":341,"context_line":"            sys.exit(\"Error: %s\" % msg)"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"    def __call__(self, env, start_response):"},{"line_number":344,"context_line":"        req \u003d Request(env)"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_3ce326a5","line":341,"updated":"2017-01-19 23:50:02.000000000","message":"Better to\n\n raise ValueError(msg)\n\n? I know there was another cleanup like that in https://review.openstack.org/#/c/393388/ ... although I guess it doesn\u0027t have the same sort of noisy logging that led to https://bugs.launchpad.net/swift/+bug/1578321 so maybe sys.exit() is fine?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":338,"context_line":"            msg \u003d \u0027Symlink middleware does not support \u0027 \\"},{"line_number":339,"context_line":"                \u0027object_post_as_copy \u003d true\u0027"},{"line_number":340,"context_line":"            self.logger.error(msg)"},{"line_number":341,"context_line":"            sys.exit(\"Error: %s\" % msg)"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"    def __call__(self, env, start_response):"},{"line_number":344,"context_line":"        req \u003d Request(env)"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_84ca216d","line":341,"in_reply_to":"5a3905b3_3ce326a5","updated":"2017-02-17 18:58:12.000000000","message":"left as is for now","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c239bbd24d3a3c645848754f368cafc5f1dc041a","unresolved":false,"context_lines":[{"line_number":382,"context_line":""},{"line_number":383,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":384,"context_line":"    if symloop_max \u003c 1:"},{"line_number":385,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":386,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":387,"context_line":""},{"line_number":388,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":51,"id":"5a3905b3_f9261515","line":385,"updated":"2017-01-19 23:50:02.000000000","message":"I think I\u0027d prefer either\n\n symloop_max \u003d max(1, int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX)))\n\nor\n\n if symloop_max \u003c 1:\n     raise ValueError(\u0027symloop_max must be a positive integer\u0027)\n\nShould we enforce any sort of strict upper bound?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":382,"context_line":""},{"line_number":383,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":384,"context_line":"    if symloop_max \u003c 1:"},{"line_number":385,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":386,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":387,"context_line":""},{"line_number":388,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_6857f857","line":385,"in_reply_to":"5a3905b3_f9261515","updated":"2017-02-17 18:58:12.000000000","message":"changed the first suggestion. For now I\u0027m ok with not enforcing an upper bound.","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4c52bc437761c8d525073fc554bd0a2df0ff01a1","unresolved":false,"context_lines":[{"line_number":181,"context_line":"            if not is_success(self._get_status_int()):"},{"line_number":182,"context_line":"                # these errors could happen for a number of reasons like"},{"line_number":183,"context_line":"                # Range requests or conditional gets. If it\u0027s a symlink"},{"line_number":184,"context_line":"                # let\u0027s try to send the request to the target object"},{"line_number":185,"context_line":"                if (is_client_error(self._get_status_int()) or"},{"line_number":186,"context_line":"                    is_redirection(self._get_status_int())) and \\"},{"line_number":187,"context_line":"                        self._response_header_value("}],"source_content_type":"text/x-python","patch_set":52,"id":"da36d5c6_519ddfba","line":184,"updated":"2017-02-22 23:00:25.000000000","message":"The conditional gets can be eliminated from this scenario by [1]. Even with [1] EC range requests still seem to return 416, which I suspect may be due to the ECAppIter. If that is the case then the good news is that the error is raised in the proxy obj controller so should not cause further backend requests (but TBH I did not verify that).\n\n[1]http://paste.openstack.org/show/600120/\n[2] https://github.com/openstack/swift/blob/e8a80e874a5086e94c5ae93e3a9191cb813d1631/swift/proxy/controllers/obj.py#L1169-L1169","commit_id":"a50c203af4609e1dc2bb690137086179b531bdb1"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":66,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":67,"context_line":"object will not be deleted."},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request to a symlink will copy the target object. A COPY request to a"},{"line_number":70,"context_line":"symlink with the query parameter ``?symlink\u003dget`` will copy the symlink"},{"line_number":71,"context_line":"itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_c5d54545","line":71,"range":{"start_line":69,"start_character":0,"end_line":71,"end_character":7},"updated":"2017-04-03 09:05:38.000000000","message":"I think PUT request with ``X-Copy-From`` with symlink should be explained.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request to a symlink will copy the target object. A COPY request to a"},{"line_number":70,"context_line":"symlink with the query parameter ``?symlink\u003dget`` will copy the symlink"},{"line_number":71,"context_line":"itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_e85f153f","line":71,"in_reply_to":"dfeb2761_c5d54545","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        tree \u003d ElementTree.fromstring(resp_body)"},{"line_number":183,"context_line":"        for elem in tree.iter(\u0027hash\u0027):"},{"line_number":184,"context_line":"            hash_param \u003d elem.text.encode(\u0027utf8\u0027)"},{"line_number":185,"context_line":"            hash_value, meta \u003d parse_header(hash_param)"},{"line_number":186,"context_line":"            elem.text \u003d hash_value.decode(\u0027utf8\u0027)"},{"line_number":187,"context_line":"        new_body \u003d ElementTree.tostring(tree, encoding\u003d\u0027UTF-8\u0027).replace("},{"line_number":188,"context_line":"            \"\u003c?xml version\u003d\u00271.0\u0027 encoding\u003d\u0027UTF-8\u0027?\u003e\","}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_85117daf","line":185,"range":{"start_line":185,"start_character":12,"end_line":185,"end_character":55},"updated":"2017-04-03 09:05:38.000000000","message":"In this method, \u0027symlink_path\u0027 will not be included in response.\nIs this behavior is correct?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        tree \u003d ElementTree.fromstring(resp_body)"},{"line_number":183,"context_line":"        for elem in tree.iter(\u0027hash\u0027):"},{"line_number":184,"context_line":"            hash_param \u003d elem.text.encode(\u0027utf8\u0027)"},{"line_number":185,"context_line":"            hash_value, meta \u003d parse_header(hash_param)"},{"line_number":186,"context_line":"            elem.text \u003d hash_value.decode(\u0027utf8\u0027)"},{"line_number":187,"context_line":"        new_body \u003d ElementTree.tostring(tree, encoding\u003d\u0027UTF-8\u0027).replace("},{"line_number":188,"context_line":"            \"\u003c?xml version\u003d\u00271.0\u0027 encoding\u003d\u0027UTF-8\u0027?\u003e\","}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_e824b5c8","line":185,"in_reply_to":"dfeb2761_85117daf","updated":"2017-05-19 16:29:21.000000000","message":"yes, during the PTG Clay and Tim mentioned how we need to main the XML schema","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":184,"context_line":"            hash_param \u003d elem.text.encode(\u0027utf8\u0027)"},{"line_number":185,"context_line":"            hash_value, meta \u003d parse_header(hash_param)"},{"line_number":186,"context_line":"            elem.text \u003d hash_value.decode(\u0027utf8\u0027)"},{"line_number":187,"context_line":"        new_body \u003d ElementTree.tostring(tree, encoding\u003d\u0027UTF-8\u0027).replace("},{"line_number":188,"context_line":"            \"\u003c?xml version\u003d\u00271.0\u0027 encoding\u003d\u0027UTF-8\u0027?\u003e\","},{"line_number":189,"context_line":"            \u0027\u003c?xml version\u003d\"1.0\" encoding\u003d\"UTF-8\"?\u003e\u0027, 1)"},{"line_number":190,"context_line":"        self.update_content_length(len(new_body))"},{"line_number":191,"context_line":"        return [new_body]"},{"line_number":192,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_051d6dbc","line":189,"range":{"start_line":187,"start_character":63,"end_line":189,"end_character":56},"updated":"2017-04-03 09:05:38.000000000","message":"Why do you replace the string?\nIf there are any reason, the reason should be written in comment.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":191,"context_line":"        return [new_body]"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    def extract_symlink_path_json(self, obj_dict):"},{"line_number":194,"context_line":"        if \u0027hash\u0027 in obj_dict:"},{"line_number":195,"context_line":"            hash_value, meta \u003d parse_header(obj_dict[\u0027hash\u0027])"},{"line_number":196,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":197,"context_line":"            if \u0027symlink_path\u0027 in meta:"},{"line_number":198,"context_line":"                obj_dict[\u0027symlink_path\u0027] \u003d meta[\u0027symlink_path\u0027]"},{"line_number":199,"context_line":"        return obj_dict"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_e5060987","line":198,"range":{"start_line":194,"start_character":0,"end_line":198,"end_character":63},"updated":"2017-04-03 09:05:38.000000000","message":"I think this method will remove some strings from \u0027hash\u0027 other than \u0027symlink_path\u0027.\nFor example, if the \u0027hash\u0027 is \u0027etag; symlink_path\u003d/a/c/o; another_info\u003dfoo\u0027, the \u0027another_info\u0027 is removed from obj_dict.\nThis behavior will restricts other (future) middleware implementation.\nTherefore, this method should return strings other than \u0027symlink_path\u0027 to obj_dict.\n\u0027swift.common.utils.extract_swift_bytes\u0027 will satisfies the requirement.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":191,"context_line":"        return [new_body]"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    def extract_symlink_path_json(self, obj_dict):"},{"line_number":194,"context_line":"        if \u0027hash\u0027 in obj_dict:"},{"line_number":195,"context_line":"            hash_value, meta \u003d parse_header(obj_dict[\u0027hash\u0027])"},{"line_number":196,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":197,"context_line":"            if \u0027symlink_path\u0027 in meta:"},{"line_number":198,"context_line":"                obj_dict[\u0027symlink_path\u0027] \u003d meta[\u0027symlink_path\u0027]"},{"line_number":199,"context_line":"        return obj_dict"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_e1d04353","line":198,"range":{"start_line":194,"start_character":0,"end_line":198,"end_character":63},"in_reply_to":"dfeb2761_e5060987","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":219,"context_line":"        for key, val in self._response_headers:"},{"line_number":220,"context_line":"            if key.lower() \u003d\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:"},{"line_number":221,"context_line":"                acct, cont_obj \u003d split_path(val, 1, 2, True)"},{"line_number":222,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":223,"context_line":"                                              acct)])"},{"line_number":224,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target\u0027,"},{"line_number":225,"context_line":"                                              cont_obj)])"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_05e0cd95","line":222,"range":{"start_line":222,"start_character":48,"end_line":222,"end_character":74},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \u0027TGT_ACCT_SYMLINK_HDR.title()\u0027 is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":219,"context_line":"        for key, val in self._response_headers:"},{"line_number":220,"context_line":"            if key.lower() \u003d\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:"},{"line_number":221,"context_line":"                acct, cont_obj \u003d split_path(val, 1, 2, True)"},{"line_number":222,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":223,"context_line":"                                              acct)])"},{"line_number":224,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target\u0027,"},{"line_number":225,"context_line":"                                              cont_obj)])"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_97876d62","line":222,"range":{"start_line":222,"start_character":48,"end_line":222,"end_character":74},"in_reply_to":"dfeb2761_05e0cd95","updated":"2017-05-19 16:29:21.000000000","message":"for now planning to leaving these as is. Since we started using constant values like TGT_ACCT_SYMLINK_HDR we sort of lost a default way of doing things, so the code base is not very consistent and it is not clear the correct approach","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":221,"context_line":"                acct, cont_obj \u003d split_path(val, 1, 2, True)"},{"line_number":222,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target-Account\u0027,"},{"line_number":223,"context_line":"                                              acct)])"},{"line_number":224,"context_line":"                self._response_headers.extend([(\u0027X-Symlink-Target\u0027,"},{"line_number":225,"context_line":"                                              cont_obj)])"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"        return resp"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_85edfd8c","line":224,"range":{"start_line":224,"start_character":48,"end_line":224,"end_character":66},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \u0027TGT_OBJ_SYMLINK_HDR.title()\u0027 is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7ae1248b6a2d45fc9e72d6959f31ffdbb77d499d","unresolved":false,"context_lines":[{"line_number":226,"context_line":""},{"line_number":227,"context_line":"        return resp"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    def handle_get_head(self, req):"},{"line_number":230,"context_line":"        \"\"\""},{"line_number":231,"context_line":"        handle get/head request and in case the response is a symlink,"},{"line_number":232,"context_line":"        redirect request to target object."}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_fd655546","line":229,"range":{"start_line":229,"start_character":0,"end_line":229,"end_character":35},"updated":"2017-04-04 07:39:42.000000000","message":"I think this method is too nested.\nHow about \u003chttps://gist.github.com/KazuhiroMiyahara/a91ecb0e306ace759504a1368029a24c\u003e?\n\n(I have not tested this code yet.)","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":226,"context_line":""},{"line_number":227,"context_line":"        return resp"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    def handle_get_head(self, req):"},{"line_number":230,"context_line":"        \"\"\""},{"line_number":231,"context_line":"        handle get/head request and in case the response is a symlink,"},{"line_number":232,"context_line":"        redirect request to target object."}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_cf536de2","line":229,"range":{"start_line":229,"start_character":0,"end_line":229,"end_character":35},"in_reply_to":"dfeb2761_fd655546","updated":"2017-05-19 16:29:21.000000000","message":"Thanks for the suggestion, for now I\u0027m willing to keep as is. The gist basically removes just the for loop and replaces with the recursive call, but I\u0027m not a big fan of the symlink_count variable on the function sig.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        \"\"\""},{"line_number":237,"context_line":"        # the \u0027+ 1\u0027 is for the request for the actual object itself"},{"line_number":238,"context_line":"        target_path \u003d \u0027\u0027"},{"line_number":239,"context_line":"        for count in range(self.symloop_max + 1):"},{"line_number":240,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":241,"context_line":"            if not is_success(self._get_status_int()):"},{"line_number":242,"context_line":"                # these errors could happen for EC Range requests. If it\u0027s a"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_652559c2","line":239,"range":{"start_line":239,"start_character":8,"end_line":239,"end_character":49},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \u0027for _ in range(self.symloop_max + 1):\u0027 is better.\nBecause \u0027count\u0027 is not used in this loop.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        \"\"\""},{"line_number":237,"context_line":"        # the \u0027+ 1\u0027 is for the request for the actual object itself"},{"line_number":238,"context_line":"        target_path \u003d \u0027\u0027"},{"line_number":239,"context_line":"        for count in range(self.symloop_max + 1):"},{"line_number":240,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":241,"context_line":"            if not is_success(self._get_status_int()):"},{"line_number":242,"context_line":"                # these errors could happen for EC Range requests. If it\u0027s a"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_ef6f4990","line":239,"range":{"start_line":239,"start_character":8,"end_line":239,"end_character":49},"in_reply_to":"dfeb2761_652559c2","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":241,"context_line":"            if not is_success(self._get_status_int()):"},{"line_number":242,"context_line":"                # these errors could happen for EC Range requests. If it\u0027s a"},{"line_number":243,"context_line":"                # symlink let\u0027s try to send the request to the target object."},{"line_number":244,"context_line":"                if self._get_status_int() \u003d\u003d 416 and \\"},{"line_number":245,"context_line":"                        self._response_header_value("},{"line_number":246,"context_line":"                        TGT_OBJ_SYSMETA_SYMLINK_HDR):"},{"line_number":247,"context_line":"                    pass"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_583c7cc7","line":244,"range":{"start_line":244,"start_character":45,"end_line":244,"end_character":48},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \u0027HTTP_REQUESTED_RANGE_NOT_SATISFIABLE\u0027 of swift.common.http is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":241,"context_line":"            if not is_success(self._get_status_int()):"},{"line_number":242,"context_line":"                # these errors could happen for EC Range requests. If it\u0027s a"},{"line_number":243,"context_line":"                # symlink let\u0027s try to send the request to the target object."},{"line_number":244,"context_line":"                if self._get_status_int() \u003d\u003d 416 and \\"},{"line_number":245,"context_line":"                        self._response_header_value("},{"line_number":246,"context_line":"                        TGT_OBJ_SYSMETA_SYMLINK_HDR):"},{"line_number":247,"context_line":"                    pass"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_4f275d66","line":244,"range":{"start_line":244,"start_character":45,"end_line":244,"end_character":48},"in_reply_to":"dfeb2761_583c7cc7","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":293,"context_line":"        _check_symlink_header(req)"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"        # check if symlink targets an object in a different account"},{"line_number":296,"context_line":"        version, acct, cont, obj \u003d req.split_path(4, 4, True)"},{"line_number":297,"context_line":"        if TGT_ACCT_SYMLINK_HDR in req.headers:"},{"line_number":298,"context_line":"            sym_acct \u003d check_account_format("},{"line_number":299,"context_line":"                req, req.headers.get(TGT_ACCT_SYMLINK_HDR))"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_b8a4a8ba","line":296,"range":{"start_line":296,"start_character":8,"end_line":296,"end_character":32},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \u0027_junk, acct, _junk, _junk \u003d req.split_path(4, 4, True)\u0027 is better.\nBecause, version, cont, and obj are not used.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":301,"context_line":"            sym_acct \u003d acct"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        cont_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR).lstrip(\"/\")"},{"line_number":304,"context_line":"        symlink_path \u003d \"/%s/%s\" % (sym_acct, cont_obj)"},{"line_number":305,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":306,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":307,"context_line":"            \"%s; symlink_path\u003d%s\" % (MD5_OF_EMPTY_STRING, symlink_path)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_f8723049","line":304,"range":{"start_line":304,"start_character":23,"end_line":304,"end_character":54},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \"/\".join([sym_acct, cont_obj]) is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":301,"context_line":"            sym_acct \u003d acct"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        cont_obj \u003d req.headers.get(TGT_OBJ_SYMLINK_HDR).lstrip(\"/\")"},{"line_number":304,"context_line":"        symlink_path \u003d \"/%s/%s\" % (sym_acct, cont_obj)"},{"line_number":305,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":306,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":307,"context_line":"            \"%s; symlink_path\u003d%s\" % (MD5_OF_EMPTY_STRING, symlink_path)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_ef906951","line":304,"range":{"start_line":304,"start_character":23,"end_line":304,"end_character":54},"in_reply_to":"dfeb2761_f8723049","updated":"2017-05-19 16:29:21.000000000","message":"keeping as is for now. Join will not put the / in front of the string.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":336,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":337,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":338,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":339,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":340,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":341,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":342,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":343,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_f84350ae","line":340,"range":{"start_line":339,"start_character":1,"end_line":340,"end_character":48},"updated":"2017-04-03 09:05:38.000000000","message":"I think this message is not correct, because our POST to symlink is allowed when the POST has \u0027?symlink\u003dpost\u0027.\nTherefore the message should explain that POST to symlink requires \"?sylmink\u003dpost\".","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":336,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":337,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":338,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":339,"context_line":"            errmsg \u003d \u0027POST to symlink is not allowed. \u0027 + \\"},{"line_number":340,"context_line":"                \u0027POST directly to target object\u0027"},{"line_number":341,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":342,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":343,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_8f9445ea","line":340,"range":{"start_line":339,"start_character":1,"end_line":340,"end_character":48},"in_reply_to":"dfeb2761_f84350ae","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":348,"context_line":"        \"\"\""},{"line_number":349,"context_line":"        Handle object requests"},{"line_number":350,"context_line":"        \"\"\""},{"line_number":351,"context_line":"        if TGT_OBJ_SYMLINK_HDR in req.headers and (req.method \u003d\u003d \u0027POST\u0027):"},{"line_number":352,"context_line":"            resp \u003d HTTPBadRequest("},{"line_number":353,"context_line":"                body\u003d\u0027A PUT request is required to set a symlink target\u0027,"},{"line_number":354,"context_line":"                request\u003dreq,"},{"line_number":355,"context_line":"                content_type\u003d\u0027text/plain\u0027)(req.environ, self._start_response)"},{"line_number":356,"context_line":"        elif req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":357,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":358,"context_line":"            # the symlink only, not the referenced target"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_dbff66ff","line":355,"range":{"start_line":351,"start_character":1,"end_line":355,"end_character":77},"updated":"2017-04-03 09:05:38.000000000","message":"I think this implementation should be included in handle_post method.\nBecause, this handles POST request.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":348,"context_line":"        \"\"\""},{"line_number":349,"context_line":"        Handle object requests"},{"line_number":350,"context_line":"        \"\"\""},{"line_number":351,"context_line":"        if TGT_OBJ_SYMLINK_HDR in req.headers and (req.method \u003d\u003d \u0027POST\u0027):"},{"line_number":352,"context_line":"            resp \u003d HTTPBadRequest("},{"line_number":353,"context_line":"                body\u003d\u0027A PUT request is required to set a symlink target\u0027,"},{"line_number":354,"context_line":"                request\u003dreq,"},{"line_number":355,"context_line":"                content_type\u003d\u0027text/plain\u0027)(req.environ, self._start_response)"},{"line_number":356,"context_line":"        elif req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":357,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":358,"context_line":"            # the symlink only, not the referenced target"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_cf7feda9","line":355,"range":{"start_line":351,"start_character":1,"end_line":355,"end_character":77},"in_reply_to":"dfeb2761_dbff66ff","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":354,"context_line":"                request\u003dreq,"},{"line_number":355,"context_line":"                content_type\u003d\u0027text/plain\u0027)(req.environ, self._start_response)"},{"line_number":356,"context_line":"        elif req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":357,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":358,"context_line":"            # the symlink only, not the referenced target"},{"line_number":359,"context_line":"            if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":360,"context_line":"                    req.environ.get(\u0027swift.source\u0027) \u003d\u003d \u0027VW\u0027:"},{"line_number":361,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_5877dcd5","line":358,"range":{"start_line":357,"start_character":1,"end_line":358,"end_character":57},"updated":"2017-04-03 09:05:38.000000000","message":"Should symlink middleware resolve the requirement?\nI think the requirement is versioned writes middleware\u0027s requirement.\nSo, versioned_writes middleware should resolve it by adding \u0027?symlink\u003dget\u0027 to its GET request.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":354,"context_line":"                request\u003dreq,"},{"line_number":355,"context_line":"                content_type\u003d\u0027text/plain\u0027)(req.environ, self._start_response)"},{"line_number":356,"context_line":"        elif req.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":357,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":358,"context_line":"            # the symlink only, not the referenced target"},{"line_number":359,"context_line":"            if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":360,"context_line":"                    req.environ.get(\u0027swift.source\u0027) \u003d\u003d \u0027VW\u0027:"},{"line_number":361,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_8f30c509","line":358,"range":{"start_line":357,"start_character":1,"end_line":358,"end_character":57},"in_reply_to":"dfeb2761_5877dcd5","updated":"2017-05-19 16:29:21.000000000","message":"Yeah, we talked about this is a previous patchset, the argument could go both ways and there\u0027s no clear way which one is better. I think it is one of the downsides of the wsgi middleware design, it is hard to deal with dependencies.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":361,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":362,"context_line":"            else:"},{"line_number":363,"context_line":"                resp \u003d self.handle_get_head(req)"},{"line_number":364,"context_line":"        elif req.method \u003d\u003d \u0027PUT\u0027 and (TGT_OBJ_SYMLINK_HDR in req.headers):"},{"line_number":365,"context_line":"            resp \u003d self.handle_put(req)"},{"line_number":366,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":367,"context_line":"            resp \u003d self.handle_post(req)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_7b5a9a2a","line":364,"range":{"start_line":364,"start_character":32,"end_line":364,"end_character":73},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, this filtering should included in handle_put method.\nBecause I think this filtering is handling PUT request.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":363,"context_line":"                resp \u003d self.handle_get_head(req)"},{"line_number":364,"context_line":"        elif req.method \u003d\u003d \u0027PUT\u0027 and (TGT_OBJ_SYMLINK_HDR in req.headers):"},{"line_number":365,"context_line":"            resp \u003d self.handle_put(req)"},{"line_number":366,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":367,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":368,"context_line":"        else:"},{"line_number":369,"context_line":"            # DELETE and OPTION reqs for a symlink behave like any other object"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_d831ac0d","line":366,"range":{"start_line":366,"start_character":13,"end_line":366,"end_character":35},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, req.method \u003d\u003d \u0027POST\u0027 is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":363,"context_line":"                resp \u003d self.handle_get_head(req)"},{"line_number":364,"context_line":"        elif req.method \u003d\u003d \u0027PUT\u0027 and (TGT_OBJ_SYMLINK_HDR in req.headers):"},{"line_number":365,"context_line":"            resp \u003d self.handle_put(req)"},{"line_number":366,"context_line":"        elif req.method in (\u0027POST\u0027):"},{"line_number":367,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":368,"context_line":"        else:"},{"line_number":369,"context_line":"            # DELETE and OPTION reqs for a symlink behave like any other object"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_6a03270f","line":366,"range":{"start_line":366,"start_character":13,"end_line":366,"end_character":35},"in_reply_to":"dfeb2761_d831ac0d","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":417,"context_line":""},{"line_number":418,"context_line":"        return resp"},{"line_number":419,"context_line":""},{"line_number":420,"context_line":"    def _load_object_post_as_copy_conf(self, conf):"},{"line_number":421,"context_line":"        \"\"\""},{"line_number":422,"context_line":"        While we are in the process of deprecating object_post_as_copy, we need"},{"line_number":423,"context_line":"        to make sure that the user does not have it enabled as symlinks"},{"line_number":424,"context_line":"        middleware does not support it. This method should be removed when"},{"line_number":425,"context_line":"        object_post_as_copy is completely removed from code."},{"line_number":426,"context_line":"        \"\"\""},{"line_number":427,"context_line":"        if (\u0027__file__\u0027 not in conf):"},{"line_number":428,"context_line":"            return False"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        cp \u003d ConfigParser()"},{"line_number":431,"context_line":"        if os.path.isdir(conf[\u0027__file__\u0027]):"},{"line_number":432,"context_line":"            read_conf_dir(cp, conf[\u0027__file__\u0027])"},{"line_number":433,"context_line":"        else:"},{"line_number":434,"context_line":"            cp.read(conf[\u0027__file__\u0027])"},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"        object_post_as_copy \u003d False"},{"line_number":437,"context_line":"        for section in cp.sections():"},{"line_number":438,"context_line":"            if cp.has_option(section, \u0027object_post_as_copy\u0027):"},{"line_number":439,"context_line":"                object_post_as_copy \u003d config_true_value("},{"line_number":440,"context_line":"                    cp.get(section, \u0027object_post_as_copy\u0027))"},{"line_number":441,"context_line":"        return object_post_as_copy"},{"line_number":442,"context_line":""},{"line_number":443,"context_line":""},{"line_number":444,"context_line":"def filter_factory(global_conf, **local_conf):"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_9b843e0e","line":441,"range":{"start_line":420,"start_character":0,"end_line":441,"end_character":34},"updated":"2017-04-03 09:05:38.000000000","message":"There is a similar method \"swift.common.middleware.copy.ServerSideCopyMiddleware._load_object_post_as_copy_conf\".\nI think these two methods should be moved to utils and shared.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":417,"context_line":""},{"line_number":418,"context_line":"        return resp"},{"line_number":419,"context_line":""},{"line_number":420,"context_line":"    def _load_object_post_as_copy_conf(self, conf):"},{"line_number":421,"context_line":"        \"\"\""},{"line_number":422,"context_line":"        While we are in the process of deprecating object_post_as_copy, we need"},{"line_number":423,"context_line":"        to make sure that the user does not have it enabled as symlinks"},{"line_number":424,"context_line":"        middleware does not support it. This method should be removed when"},{"line_number":425,"context_line":"        object_post_as_copy is completely removed from code."},{"line_number":426,"context_line":"        \"\"\""},{"line_number":427,"context_line":"        if (\u0027__file__\u0027 not in conf):"},{"line_number":428,"context_line":"            return False"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        cp \u003d ConfigParser()"},{"line_number":431,"context_line":"        if os.path.isdir(conf[\u0027__file__\u0027]):"},{"line_number":432,"context_line":"            read_conf_dir(cp, conf[\u0027__file__\u0027])"},{"line_number":433,"context_line":"        else:"},{"line_number":434,"context_line":"            cp.read(conf[\u0027__file__\u0027])"},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"        object_post_as_copy \u003d False"},{"line_number":437,"context_line":"        for section in cp.sections():"},{"line_number":438,"context_line":"            if cp.has_option(section, \u0027object_post_as_copy\u0027):"},{"line_number":439,"context_line":"                object_post_as_copy \u003d config_true_value("},{"line_number":440,"context_line":"                    cp.get(section, \u0027object_post_as_copy\u0027))"},{"line_number":441,"context_line":"        return object_post_as_copy"},{"line_number":442,"context_line":""},{"line_number":443,"context_line":""},{"line_number":444,"context_line":"def filter_factory(global_conf, **local_conf):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_2a74ff98","line":441,"range":{"start_line":420,"start_character":0,"end_line":441,"end_character":34},"in_reply_to":"dfeb2761_9b843e0e","updated":"2017-05-19 16:29:21.000000000","message":"the purpose is not exactly the same, keeping it from now, could be removed in a future patch","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":446,"context_line":"    conf.update(local_conf)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":449,"context_line":"    if symloop_max \u003c 1:"},{"line_number":450,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":451,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":452,"context_line":""},{"line_number":453,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_9be79ee5","line":450,"range":{"start_line":449,"start_character":0,"end_line":450,"end_character":46},"updated":"2017-04-03 09:05:38.000000000","message":"I think the config update should be logged or should raise error.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":446,"context_line":"    conf.update(local_conf)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":449,"context_line":"    if symloop_max \u003c 1:"},{"line_number":450,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":451,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":452,"context_line":""},{"line_number":453,"context_line":"    def symlink_mw(app):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_0aaee3e6","line":450,"range":{"start_line":449,"start_character":0,"end_line":450,"end_character":46},"in_reply_to":"dfeb2761_9be79ee5","updated":"2017-05-19 16:29:21.000000000","message":"we documented that the value cannot be less than 1.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":448,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":449,"context_line":"    if symloop_max \u003c 1:"},{"line_number":450,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":451,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":452,"context_line":""},{"line_number":453,"context_line":"    def symlink_mw(app):"},{"line_number":454,"context_line":"        return SymlinkMiddleware(app, conf, symloop_max)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_3b51b263","line":451,"range":{"start_line":451,"start_character":32,"end_line":451,"end_character":33},"updated":"2017-04-03 09:05:38.000000000","message":"Is this \u0027s\u0027 needed?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":448,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":449,"context_line":"    if symloop_max \u003c 1:"},{"line_number":450,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":451,"context_line":"    register_swift_info(\u0027symlinks\u0027, symloop_max\u003dsymloop_max)"},{"line_number":452,"context_line":""},{"line_number":453,"context_line":"    def symlink_mw(app):"},{"line_number":454,"context_line":"        return SymlinkMiddleware(app, conf, symloop_max)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_0a970393","line":451,"range":{"start_line":451,"start_character":32,"end_line":451,"end_character":33},"in_reply_to":"dfeb2761_3b51b263","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":262,"context_line":"                target_path \u003d \u0027/%s%s\u0027 % (version, target)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"                # make sure the new request uses it\u0027s container_info"},{"line_number":265,"context_line":"                req \u003d make_subrequest("},{"line_number":266,"context_line":"                    req.environ, path\u003dtarget_path, method\u003dreq.method,"},{"line_number":267,"context_line":"                    headers\u003dreq.headers,"},{"line_number":268,"context_line":"                    swift_source\u003d\u0027SYM\u0027)"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_7aa5e003","line":265,"updated":"2017-05-19 17:30:35.000000000","message":"I\u0027m suddenly reminded of https://github.com/openstack/swift/blob/e8a80e8/swift/common/middleware/dlo.py#L235-L236 and wonder if we need something similar around here...","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d4307554165d6b853b486f523128638a696be84b","unresolved":false,"context_lines":[{"line_number":262,"context_line":"                target_path \u003d \u0027/%s%s\u0027 % (version, target)"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"                # make sure the new request uses it\u0027s container_info"},{"line_number":265,"context_line":"                req \u003d make_subrequest("},{"line_number":266,"context_line":"                    req.environ, path\u003dtarget_path, method\u003dreq.method,"},{"line_number":267,"context_line":"                    headers\u003dreq.headers,"},{"line_number":268,"context_line":"                    swift_source\u003d\u0027SYM\u0027)"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_a2a2574a","line":265,"in_reply_to":"ff0f0b1f_7aa5e003","updated":"2017-05-26 21:05:46.000000000","message":"I modified a functional test to catch this, but I ended up not having to add the req.acl \u003d None line here.\n\nMaybe I\u0027m missing something, but it seems to work ok?? can you double-check and see if I\u0027m missing something I don\u0027t understand\n\nLooking at make_subrequest and make_env it doesn\u0027t seem like it copies the acls, but idk...looks like DLO needed so I\u0027m not sure...","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":265,"context_line":"                req \u003d make_subrequest("},{"line_number":266,"context_line":"                    req.environ, path\u003dtarget_path, method\u003dreq.method,"},{"line_number":267,"context_line":"                    headers\u003dreq.headers,"},{"line_number":268,"context_line":"                    swift_source\u003d\u0027SYM\u0027)"},{"line_number":269,"context_line":"                req.headers.pop(\u0027X-Backend-Storage-Policy-Index\u0027, None)"},{"line_number":270,"context_line":"            else:"},{"line_number":271,"context_line":"                if target_path:"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_3a2888e0","line":268,"range":{"start_line":268,"start_character":20,"end_line":268,"end_character":38},"updated":"2017-05-19 17:30:35.000000000","message":"Did we ever come to a decision about swift_source? I\u0027m still a little worried that operators may be in the habit of ignoring bytes transferred for billing when there\u0027s a swift_source set -- in which case symlink GETs may be hard to bill for. Maybe Clay can offer more insights?","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d4307554165d6b853b486f523128638a696be84b","unresolved":false,"context_lines":[{"line_number":265,"context_line":"                req \u003d make_subrequest("},{"line_number":266,"context_line":"                    req.environ, path\u003dtarget_path, method\u003dreq.method,"},{"line_number":267,"context_line":"                    headers\u003dreq.headers,"},{"line_number":268,"context_line":"                    swift_source\u003d\u0027SYM\u0027)"},{"line_number":269,"context_line":"                req.headers.pop(\u0027X-Backend-Storage-Policy-Index\u0027, None)"},{"line_number":270,"context_line":"            else:"},{"line_number":271,"context_line":"                if target_path:"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_42913bf1","line":268,"range":{"start_line":268,"start_character":20,"end_line":268,"end_character":38},"in_reply_to":"ff0f0b1f_3a2888e0","updated":"2017-05-26 21:05:46.000000000","message":"I\u0027m not really sure on this one, hoping Clay can helpout","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":345,"context_line":"            return resp"},{"line_number":346,"context_line":""},{"line_number":347,"context_line":"        sym_target \u003d self._response_header_value(TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":348,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":349,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":350,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":351,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_5aed7c89","line":348,"range":{"start_line":348,"start_character":26,"end_line":348,"end_character":58},"updated":"2017-05-19 17:30:35.000000000","message":"same nit as before:\n\n s/not ([^ ]*) \u003d\u003d/\\1 !\u003d/","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d4307554165d6b853b486f523128638a696be84b","unresolved":false,"context_lines":[{"line_number":345,"context_line":"            return resp"},{"line_number":346,"context_line":""},{"line_number":347,"context_line":"        sym_target \u003d self._response_header_value(TGT_OBJ_SYSMETA_SYMLINK_HDR)"},{"line_number":348,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":349,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":350,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":351,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_4210664e","line":348,"range":{"start_line":348,"start_character":26,"end_line":348,"end_character":58},"in_reply_to":"ff0f0b1f_5aed7c89","updated":"2017-05-26 21:05:46.000000000","message":"Done","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":348,"context_line":"        if sym_target and not req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027post\u0027:"},{"line_number":349,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":350,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":351,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":352,"context_line":"            errmsg \u003d \u0027To POST to symlink, Use the symlink\u003dpost \u0027 + \\"},{"line_number":353,"context_line":"                \u0027query paramater. Otherwise, POST directly to target object\u0027"},{"line_number":354,"context_line":"            return HTTPTemporaryRedirect("}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_5aa21c4d","line":351,"updated":"2017-05-19 17:30:35.000000000","message":"Note to self -- consider interactions with domain_remap.","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":349,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":350,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":351,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":352,"context_line":"            errmsg \u003d \u0027To POST to symlink, Use the symlink\u003dpost \u0027 + \\"},{"line_number":353,"context_line":"                \u0027query paramater. Otherwise, POST directly to target object\u0027"},{"line_number":354,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":355,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_9ac1d4e7","line":352,"range":{"start_line":352,"start_character":42,"end_line":352,"end_character":45},"updated":"2017-05-19 17:30:35.000000000","message":"nit: s/Use/use/","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d4307554165d6b853b486f523128638a696be84b","unresolved":false,"context_lines":[{"line_number":349,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":350,"context_line":"            location_hdr \u003d \"/%s%s\" % (version, sym_target)"},{"line_number":351,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":352,"context_line":"            errmsg \u003d \u0027To POST to symlink, Use the symlink\u003dpost \u0027 + \\"},{"line_number":353,"context_line":"                \u0027query paramater. Otherwise, POST directly to target object\u0027"},{"line_number":354,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":355,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_e597443a","line":352,"range":{"start_line":352,"start_character":42,"end_line":352,"end_character":45},"in_reply_to":"ff0f0b1f_9ac1d4e7","updated":"2017-05-26 21:05:46.000000000","message":"Done","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e928e40e2f18f62ae4794cbadb89c8e0844a28ef","unresolved":false,"context_lines":[{"line_number":454,"context_line":"    conf.update(local_conf)"},{"line_number":455,"context_line":""},{"line_number":456,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":457,"context_line":"    if symloop_max \u003c 1:"},{"line_number":458,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":459,"context_line":"    register_swift_info(\u0027symlink\u0027, symloop_max\u003dsymloop_max)"},{"line_number":460,"context_line":""}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_1a2024b0","line":457,"updated":"2017-05-19 17:30:35.000000000","message":"Part of me wonders whether there might be a use-case for\n\n symloop_max \u003d 0\n\n... we still get the special handling, but disable the actual server-side redirection...\n\nCould totally be a follow-up, though, once we actually think of a use-case.","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d4307554165d6b853b486f523128638a696be84b","unresolved":false,"context_lines":[{"line_number":454,"context_line":"    conf.update(local_conf)"},{"line_number":455,"context_line":""},{"line_number":456,"context_line":"    symloop_max \u003d int(conf.get(\u0027symloop_max\u0027, DEFAULT_SYMLOOP_MAX))"},{"line_number":457,"context_line":"    if symloop_max \u003c 1:"},{"line_number":458,"context_line":"        symloop_max \u003d int(DEFAULT_SYMLOOP_MAX)"},{"line_number":459,"context_line":"    register_swift_info(\u0027symlink\u0027, symloop_max\u003dsymloop_max)"},{"line_number":460,"context_line":""}],"source_content_type":"text/x-python","patch_set":54,"id":"ff0f0b1f_97124261","line":457,"in_reply_to":"ff0f0b1f_1a2024b0","updated":"2017-05-26 21:05:46.000000000","message":"ok, leaving as a follow-up","commit_id":"9fbcdc78d136bd9a62f65e6714649f5f5908e81b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":24,"context_line":"Clients create a Swift symlink by performing a zero-length PUT request"},{"line_number":25,"context_line":"with the header ``X-Symlink-Target: \u003ccontainer\u003e/\u003cobject\u003e``. For a cross-account"},{"line_number":26,"context_line":"symlink, the header ``X-Symlink-Target-Account: \u003caccount\u003e`` must be included."},{"line_number":27,"context_line":"If omitted, it defaults to the account of the symlink object."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_1f39b8d5","line":27,"updated":"2017-10-03 11:08:39.000000000","message":"Is that resolved on GET, right?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":24,"context_line":"Clients create a Swift symlink by performing a zero-length PUT request"},{"line_number":25,"context_line":"with the header ``X-Symlink-Target: \u003ccontainer\u003e/\u003cobject\u003e``. For a cross-account"},{"line_number":26,"context_line":"symlink, the header ``X-Symlink-Target-Account: \u003caccount\u003e`` must be included."},{"line_number":27,"context_line":"If omitted, it defaults to the account of the symlink object."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_e598376b","line":27,"in_reply_to":"7f515b1d_1f39b8d5","updated":"2017-10-13 20:49:00.000000000","message":"@Kota, on PUT those headers are stored as sysmeta. On GET/HEAD we would look at both headers to solve the target path.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":24,"context_line":"Clients create a Swift symlink by performing a zero-length PUT request"},{"line_number":25,"context_line":"with the header ``X-Symlink-Target: \u003ccontainer\u003e/\u003cobject\u003e``. For a cross-account"},{"line_number":26,"context_line":"symlink, the header ``X-Symlink-Target-Account: \u003caccount\u003e`` must be included."},{"line_number":27,"context_line":"If omitted, it defaults to the account of the symlink object."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_e539edd6","line":27,"in_reply_to":"7f515b1d_1f39b8d5","updated":"2017-10-16 08:38:48.000000000","message":"Omitted target-account is resolved in PUT requests.\nI added more explanation for target-account metadata omitted case.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_3fe914e5","line":32,"range":{"start_line":31,"start_character":14,"end_line":32,"end_character":6},"updated":"2017-10-03 11:08:39.000000000","message":"it might be \"to change an existing object as symlink with a POST request (i.e. POST X-Symlink-Target header to an existing normal object)\", correctly.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_a5fc15b5","line":32,"range":{"start_line":31,"start_character":14,"end_line":32,"end_character":6},"in_reply_to":"5f4e5783_65c5673c","updated":"2017-10-16 08:38:48.000000000","message":"I assumed that \"changing an existing regular object\" means (1) POST \u0027X-Symlink-Target\u0027 to an existing non-symlink and \"creating a brand new object\" means (2) POST \u0027X-Symlink-Target\u0027 to nothing.\nIf my understanding is correct, errors in (2) is not specific to symlink.\nSo I changed description to clarify (1) case.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_cb0ff485","line":32,"range":{"start_line":31,"start_character":14,"end_line":32,"end_character":6},"in_reply_to":"5f4e5783_65c5673c","updated":"2017-10-26 12:48:32.000000000","message":"correct. either case, POST with X-Symlink-Target results in 400 BadRequest so probably the reason I stopped the sentence is \"to create a symlink with a POST\" that is not consist with Swift object creation.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_65c5673c","line":32,"range":{"start_line":31,"start_character":14,"end_line":32,"end_character":6},"in_reply_to":"7f515b1d_3fe914e5","updated":"2017-10-13 20:49:00.000000000","message":"I think the current sentence is generic to apply to either changing an existing regular object or creating a brand new object, no? In either case a POST with \u0027X-Symlink-Target\u0027 will result in error.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_f820e49d","line":33,"range":{"start_line":33,"start_character":47,"end_line":33,"end_character":53},"updated":"2017-10-05 11:25:05.000000000","message":"s/objecs/objects/","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":30,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_194976cf","line":33,"range":{"start_line":33,"start_character":47,"end_line":33,"end_character":53},"in_reply_to":"7f515b1d_f820e49d","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_9fc12857","line":34,"updated":"2017-10-03 11:08:39.000000000","message":"why not this is auto-inserted by middleware?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_45968140","line":34,"in_reply_to":"5f4e5783_e50dd790","updated":"2017-10-16 08:38:48.000000000","message":"I read thiago and alistair\u0027s discussion on IRC. (If anyone want to read the discussion, please watch the discussion log link in the etherpad page.)\nI agree with the idea of replace \u0027recommend\u0027 with \u0027suggest\u0027.\nSo I think this topic is done.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":31,"context_line":"attempting to create a symlink with a POST request will result in a 400-series"},{"line_number":32,"context_line":"error. The referenced object need not exist at symlink-creation time. It is"},{"line_number":33,"context_line":"recommended to set the Content-Type of symlink objecs to a distinct value"},{"line_number":34,"context_line":"such as ``application/symlink``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_e50dd790","line":34,"in_reply_to":"7f515b1d_9fc12857","updated":"2017-10-13 20:49:00.000000000","message":"i\u0027m not against the idea, but just playing devil\u0027s advocate, what are the pros and cons of doing that? Discussion is on-going here: https://etherpad.openstack.org/p/swift_symlink_remaining_discussion_points","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"},{"line_number":38,"context_line":"parameter ``?symlink\u003dget`` will reference the object pointed to by the"},{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_ffc7fc62","line":39,"range":{"start_line":39,"start_character":0,"end_line":39,"end_character":42},"updated":"2017-10-03 11:08:39.000000000","message":"X-Symlink-Target-Account and X-Symlink-Target, strictly.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"},{"line_number":38,"context_line":"parameter ``?symlink\u003dget`` will reference the object pointed to by the"},{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_79d4eabd","line":39,"range":{"start_line":39,"start_character":0,"end_line":39,"end_character":42},"in_reply_to":"7f515b1d_ffc7fc62","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"},{"line_number":38,"context_line":"parameter ``?symlink\u003dget`` will reference the object pointed to by the"},{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_9fa6c8c0","line":40,"range":{"start_line":39,"start_character":44,"end_line":40,"end_character":53},"updated":"2017-10-03 11:08:39.000000000","message":"Is this same description with Line 27?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"},{"line_number":38,"context_line":"parameter ``?symlink\u003dget`` will reference the object pointed to by the"},{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_85b919cd","line":40,"range":{"start_line":39,"start_character":44,"end_line":40,"end_character":53},"in_reply_to":"5f4e5783_39d672c5","updated":"2017-10-16 08:38:48.000000000","message":"I think duplicated description is confusing.\nI removed this sentence.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":36,"context_line":"A GET/HEAD request to a symlink with the query parameter ``?symlink\u003dget`` will"},{"line_number":37,"context_line":"reference the symlink itself. A GET/HEAD request to a symlink without the query"},{"line_number":38,"context_line":"parameter ``?symlink\u003dget`` will reference the object pointed to by the"},{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_39d672c5","line":40,"range":{"start_line":39,"start_character":44,"end_line":40,"end_character":53},"in_reply_to":"7f515b1d_9fa6c8c0","updated":"2017-10-13 20:49:00.000000000","message":"correct","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"A symlink can point to another symlink. Chained symlinks will be traversed"},{"line_number":45,"context_line":"until a target object is found. If the number of chained symlinks exceeds the"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_df97a044","line":42,"range":{"start_line":42,"start_character":6,"end_line":42,"end_character":13},"updated":"2017-10-03 11:08:39.000000000","message":"perhaps, we should define the \"final\" here. it seems like the object whose body is returned even if it\u0027s nested (symlooped) symlink below.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":39,"context_line":"symlink\u0027s Target-Account and Target-Object. If the symlink does not have a"},{"line_number":40,"context_line":"Target-Account specified it will use its own account. The response of the"},{"line_number":41,"context_line":"GET/HEAD request will contain a ``Content-Location`` header with the location"},{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"A symlink can point to another symlink. Chained symlinks will be traversed"},{"line_number":45,"context_line":"until a target object is found. If the number of chained symlinks exceeds the"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_f9dfbad3","line":42,"range":{"start_line":42,"start_character":6,"end_line":42,"end_character":13},"in_reply_to":"7f515b1d_df97a044","updated":"2017-10-13 20:49:00.000000000","message":"Done. removed final","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"A symlink can point to another symlink. Chained symlinks will be traversed"},{"line_number":45,"context_line":"until a target object is found. If the number of chained symlinks exceeds the"},{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_9f8fe828","line":45,"range":{"start_line":45,"start_character":8,"end_line":45,"end_character":14},"updated":"2017-10-03 11:08:39.000000000","message":"non-symlink object","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"A symlink can point to another symlink. Chained symlinks will be traversed"},{"line_number":45,"context_line":"until a target object is found. If the number of chained symlinks exceeds the"},{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_45320160","line":45,"range":{"start_line":45,"start_character":8,"end_line":45,"end_character":14},"in_reply_to":"5f4e5783_25f08f67","updated":"2017-10-16 08:38:48.000000000","message":"In my understanding, \"target\" of a symlink means an object which referred by the symlink directly.\nSo I think \"until a target object is found\" is not correct.\nI updated the sentence.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":42,"context_line":"of the final target object."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"A symlink can point to another symlink. Chained symlinks will be traversed"},{"line_number":45,"context_line":"until a target object is found. If the number of chained symlinks exceeds the"},{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_25f08f67","line":45,"range":{"start_line":45,"start_character":8,"end_line":45,"end_character":14},"in_reply_to":"7f515b1d_9f8fe828","updated":"2017-10-13 20:49:00.000000000","message":"I\u0027d prefer we keep the term \u0027target object\u0027 than introducing a new term to mean the same thing. Keeping the terminology simple makes it easier for users to understand the documentation.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_ff75bc32","line":49,"updated":"2017-10-03 11:08:39.000000000","message":"just a quick question. When we loop the symlink and slo (i.e. symlink -\u003e slo -\u003e symlink -\u003e slo...), can it be detected by this (or slo) middleware?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_ee12be61","line":49,"in_reply_to":"5f4e5783_8515999e","updated":"2017-10-26 12:48:32.000000000","message":"OK, that\u0027s be multiplication of symloop_max and slo recursion_depth.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_8515999e","line":49,"in_reply_to":"7f515b1d_8e6526e4","updated":"2017-10-16 08:38:48.000000000","message":"I will add a test for detecting symlink and slo loop.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":46,"context_line":"limit ``symloop_max`` an error response will be produced. The value of"},{"line_number":47,"context_line":"``symloop_max`` can be defined in the symlink config section of"},{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_8e6526e4","line":49,"in_reply_to":"7f515b1d_ff75bc32","updated":"2017-10-05 11:25:05.000000000","message":"In my understanding, the loop can be detected.\nBecause symlink middleware is after slo in proxy pipeline, slo middleware will check slo manifest count in the loop.\nIt means max manifest count in the loop is 10(\u003d max_slo_recursion_depth) and max symlink chain length between slo is 2(\u003d symloop_max).\nTherefore, max symlink and slo chain length is 32.\n(i.e. (symlink -\u003e symlink -\u003e slo)*10 + (symlink -\u003e symlink))","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"798d8d7d2295bafd0237c24f82878e42f7df86f9","unresolved":false,"context_lines":[{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_5cccc833","line":53,"range":{"start_line":51,"start_character":0,"end_line":53,"end_character":7},"updated":"2017-10-03 11:53:24.000000000","message":"I was discussing this in irc with Kota - is this statement correct or does the presence or not of symlink\u003dpost *only* affect the response code? My (very brief) reading of the code suggests that the POST is always sent to the object server at line 328.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_25a14547","line":53,"range":{"start_line":51,"start_character":0,"end_line":53,"end_character":7},"in_reply_to":"5f4e5783_bc4c959e","updated":"2017-10-16 08:38:48.000000000","message":"Umm... we need discuss \"symlink\u003dpost\". I think this is not discussed well now.\nI added this topic to https://etherpad.openstack.org/p/swift_symlink_remaining_discussion_points #6.\nSo let\u0027s add opinion to the etherpad page.\nI think we should start from necessity and use cases of \"symlink\u003dpost\"...","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"cb871c121a2bb9a38c68effb2520ae06438956a0","unresolved":false,"context_lines":[{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_cc453f17","line":53,"range":{"start_line":51,"start_character":0,"end_line":53,"end_character":7},"in_reply_to":"7f515b1d_09edb024","updated":"2017-10-06 11:01:46.000000000","message":"I might find newer discussion here, https://etherpad.openstack.org/p/swift_symlinks\n\nAccording to the etherpad whenever we should return 3xx series response if the response include symlink target header. Then if it\u0027s normal object (i.e. w/o symlink header), pass through the response (i.e. 202 accepted) to the client. I suppose Alistair\u0027s feeling is from there, maybe?\n\nAnd reading the etherpad, I may find some strange points between current code and the etherpad. I\u0027ll try to confirm the issue in the next week.\n\nEspecially, I couldn\u0027t find the design decision for container updates (i.e. object listing support for symlink) so I\u0027d love to raise the issue and try to discuss how we can resolve it.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_09edb024","line":53,"range":{"start_line":51,"start_character":0,"end_line":53,"end_character":7},"in_reply_to":"7f515b1d_5cccc833","updated":"2017-10-05 11:25:05.000000000","message":"I think your reading is correct.\nNew metadata will be applied to the symlink object regardless of whether \"symlink\u003dpost\" is present or not.\nThe presence or not only affects the response code.\n\nThe main reason for this behavior (i.e. POST to symlink without \"symlink\u003dpost\" is applied to the symlink) is eventual consistency of .meta file.\nIf we want to apply POST without \"symlink\u003dpost\" only to non-symlink objects, it will be hard to judge the newest .data file in the object path is symlink or non-symlink when we have symlink object and non-symlink object in the same object path.\n\nThe discussion detail is in this etherpad page.\nhttps://etherpad.openstack.org/p/swift_symlink_post_strategy","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":48,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":49,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_bc4c959e","line":53,"range":{"start_line":51,"start_character":0,"end_line":53,"end_character":7},"in_reply_to":"7f515b1d_cc453f17","updated":"2017-10-13 20:49:00.000000000","message":"just to confirm what Kazuhiro already said, the presence of \u0027symlink\u003dpost\u0027 only affects the response code.\n\nMaybe we can work on the wording to make it more clear to readers","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_dfd32000","line":56,"range":{"start_line":53,"start_character":8,"end_line":56,"end_character":71},"updated":"2017-10-03 11:08:39.000000000","message":"Sorry, I didn\u0027t get what the description intended. Does this attempt to the reason, the new metadata is only applied to the symlink object other than the target object?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_c57dd1b2","line":56,"range":{"start_line":53,"start_character":8,"end_line":56,"end_character":71},"in_reply_to":"5f4e5783_670c463b","updated":"2017-10-16 08:38:48.000000000","message":"I think this description need to be more clarified.\nI will update this after \"symlink\u003dpost\" discussion finished.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"A POST request to a symlink must be accompanied of the query parameter"},{"line_number":52,"context_line":"``?symlink\u003dpost`` to have the new metadata applied to the symlink object"},{"line_number":53,"context_line":"itself. Otherwise, POST requests should not be sent to symlinks; they are never"},{"line_number":54,"context_line":"redirected to the target object and the metadata will never be merged back with"},{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_670c463b","line":56,"range":{"start_line":53,"start_character":8,"end_line":56,"end_character":71},"in_reply_to":"7f515b1d_dfd32000","updated":"2017-10-13 20:49:00.000000000","message":"Correct, the intent of this text is to make it clear to readers that a POST request does not apply changes to the target object, but only to the symlink object itself, furthermore, that that those changes (metadata) is not returned on a GET that returns the target object.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_5f017069","line":58,"range":{"start_line":58,"start_character":44,"end_line":58,"end_character":51},"updated":"2017-10-03 11:08:39.000000000","message":"target object, right? ah, it looks like NO. it\u0027s the symlink object.\n\nInteresting, it\u0027s not successful response (i.e. not 2xx) but the metadata should be applied, is it really correct?\n\n(assuming, not yet checked):\nTo say correctly, the POST request will be done just as well as normal POST not depending on the object type. The 3xx series response will be used for notification that the requested metadata is NOT applied to the target object when it\u0027s symlink object. The applied metadata to the symlink object can be retrieved only with GET request with \"?symlink\u003dget\" so that the client cannot retrieve the target object body with the applied metadata via symlink object unless the clients issues POST to the target object directly.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":55,"context_line":"the target object. Because of eventual consistency, the object"},{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_074b5259","line":58,"range":{"start_line":58,"start_character":44,"end_line":58,"end_character":51},"in_reply_to":"7f515b1d_5f017069","updated":"2017-10-13 20:49:00.000000000","message":"yes! you are correct! POST applies only to symlink object.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_a52a867b","line":59,"updated":"2017-10-03 11:08:39.000000000","message":"Should we describe the response introduces the actual location via \"Location\" header, right?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":56,"context_line":"server can not know for sure if the current object is a symlink or not."},{"line_number":57,"context_line":"When a POST request without the ``?symlink\u003dpost`` parameter is sent to a"},{"line_number":58,"context_line":"symlink, the metadata will be applied to the object, but the request will"},{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_f10c5c3c","line":59,"in_reply_to":"7f515b1d_a52a867b","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."},{"line_number":63,"context_line":"A GET/HEAD request sent to the symlink with the ``?symlink\u003dget`` query string"},{"line_number":64,"context_line":"will return only the metadata that is stored on the symlink object itself."},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_aa7b75f2","line":62,"updated":"2017-10-03 11:08:39.000000000","message":"to say correctly, \"and its content for GET\"","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":59,"context_line":"result in a 300-series error response to the client."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."},{"line_number":63,"context_line":"A GET/HEAD request sent to the symlink with the ``?symlink\u003dget`` query string"},{"line_number":64,"context_line":"will return only the metadata that is stored on the symlink object itself."},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_714bccaf","line":62,"in_reply_to":"7f515b1d_aa7b75f2","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."},{"line_number":63,"context_line":"A GET/HEAD request sent to the symlink with the ``?symlink\u003dget`` query string"},{"line_number":64,"context_line":"will return only the metadata that is stored on the symlink object itself."},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":67,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_ea74cdff","line":64,"updated":"2017-10-03 11:08:39.000000000","message":"Oh, not. the GET with symlink\u003dget respond the empty content which is symlink body. Make sense, that is the reason why we need to make 3xx response for POST.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata that is stored on the target object."},{"line_number":63,"context_line":"A GET/HEAD request sent to the symlink with the ``?symlink\u003dget`` query string"},{"line_number":64,"context_line":"will return only the metadata that is stored on the symlink object itself."},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":67,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_e7b3964c","line":64,"in_reply_to":"7f515b1d_ea74cdff","updated":"2017-10-13 20:49:00.000000000","message":"correct","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request, or a PUT request with a ``X-Copy-From`` header, to a symlink"},{"line_number":70,"context_line":"will copy the target object. The same request to a symlink with the query"},{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_2c53306d","line":71,"updated":"2017-10-03 11:08:39.000000000","message":"Hmm... to be honest, I don\u0027t like to make a PUT request with symlink\u003dget that looks weird. I understand the query parameter is only affected GET source and the api is like as SLO thing though.\n\nCould we make the query arg in X-Copy-From header value?\n\ne.g.\n  PUT /v1/account/container/target\n  X-COPY-From: /container/source?symlink\u003dget","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"bac66a5684c1c34839711d7ff42be1aa33762a6a","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request, or a PUT request with a ``X-Copy-From`` header, to a symlink"},{"line_number":70,"context_line":"will copy the target object. The same request to a symlink with the query"},{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_4e531de3","line":71,"in_reply_to":"5f4e5783_180b5024","updated":"2017-10-26 04:17:02.000000000","message":"I and thiago and tim discussed this. The conclusion is that we keep current copy style even if some people feel it weird.\nThe discussion information and url link to disucussion log on irc is in the etherpad page. If you want to know about the discussion, please look them.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request, or a PUT request with a ``X-Copy-From`` header, to a symlink"},{"line_number":70,"context_line":"will copy the target object. The same request to a symlink with the query"},{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_180b5024","line":71,"in_reply_to":"5f4e5783_a7d59e45","updated":"2017-10-16 08:38:48.000000000","message":"I like the idea of similar API of SLO. But I want to get more community members\u0027 opinions.\nLet\u0027s discuss this on etherpad page https://etherpad.openstack.org/p/swift_symlink_remaining_discussion_points #3.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"A COPY request, or a PUT request with a ``X-Copy-From`` header, to a symlink"},{"line_number":70,"context_line":"will copy the target object. The same request to a symlink with the query"},{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_a7d59e45","line":71,"in_reply_to":"7f515b1d_2c53306d","updated":"2017-10-13 20:49:00.000000000","message":"I think one of the reason we went with this option is consistency of the API. If we are already doing something similar to SLO, I think it is worse to introduce something very different in symlinks, because it confuses users. IMO we should strive for consistency to make it easier for app devs.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"Tempurls can be used to GET/HEAD symlink objects, but PUT is not allowed and"},{"line_number":77,"context_line":"will result in a 400-series error. The GET/HEAD tempurls honor the scope of"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_2a8b05c3","line":74,"updated":"2017-10-03 11:08:39.000000000","message":"It may not a security issue but I\u0027d like to suggest NOTE for the case different CORS setting between 2 containers could be a problem here.\n(not sure on the possibility, I\u0027d like to make it if *IT\u0027S POSSIBLE)\n\ne.g.\n container     | A      | B     |\n allow-origin | foo   | bar  |\n object          | SYM | TGT |\n\nIn this situation, container A, B has different allow-origin each other. Then, creating a symlink object (named SYM) in container A to link an object (named TGT) in container B. OPTIONS request to SYM can respond \u0027it\u0027s OK to request\u0027 to the request from \u0027foo\u0027, actually it can return TAR object which is not allowed from \u0027foo\u0027.\n\nIf the ACL applied to both A and B containers correctly, the actual request (e.g. GET) after pre-flight OPTIONS will reply as 4xx series (or 2xx if it\u0027s allowed) so it may not a big problem for now.\n\nHmm... I\u0027m not sure this is discussed enough for current design, though.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"bac66a5684c1c34839711d7ff42be1aa33762a6a","unresolved":false,"context_lines":[{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"Tempurls can be used to GET/HEAD symlink objects, but PUT is not allowed and"},{"line_number":77,"context_line":"will result in a 400-series error. The GET/HEAD tempurls honor the scope of"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_8efb55bf","line":74,"in_reply_to":"5f4e5783_982f4087","updated":"2017-10-26 04:17:02.000000000","message":"I and thiago and tim discussed this. The conclusion is that we accept and keep current behavior. Because DLO/SLO have same behaviors about CORS and following DLO/SLO behaviro has advantage of consistency.\nThe discussion information and url link to disucussion log on irc is in the etherpad page. If you want to know about the discussion, please look them.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":71,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":74,"context_line":"only, the request will not be redirected to the target object."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"Tempurls can be used to GET/HEAD symlink objects, but PUT is not allowed and"},{"line_number":77,"context_line":"will result in a 400-series error. The GET/HEAD tempurls honor the scope of"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_982f4087","line":74,"in_reply_to":"7f515b1d_2a8b05c3","updated":"2017-10-16 08:38:48.000000000","message":"I think we need to organize information and opinions about this.\nLet\u0027s discuss on etherpad page https://etherpad.openstack.org/p/swift_symlink_remaining_discussion_points #4.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"class SymlinkContainerContext(WSGIContext):"},{"line_number":137,"context_line":"    def __init__(self, symlink_mw):"},{"line_number":138,"context_line":"        WSGIContext.__init__(self, symlink_mw.app)"},{"line_number":139,"context_line":"        self.app \u003d symlink_mw.app"},{"line_number":140,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_b53a75ca","line":137,"updated":"2017-10-05 09:04:37.000000000","message":"ah, I\u0027d like to change here too as well as SymlinkObjectContext","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"class SymlinkContainerContext(WSGIContext):"},{"line_number":137,"context_line":"    def __init__(self, symlink_mw):"},{"line_number":138,"context_line":"        WSGIContext.__init__(self, symlink_mw.app)"},{"line_number":139,"context_line":"        self.app \u003d symlink_mw.app"},{"line_number":140,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_cb93e5a2","line":137,"in_reply_to":"7f515b1d_b53a75ca","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"},{"line_number":141,"context_line":"        self.logger \u003d symlink_mw.logger"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def handle_get(self, req, start_response):"},{"line_number":144,"context_line":"        app_resp \u003d self._app_call(req.environ)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_956539e4","line":143,"updated":"2017-10-05 09:04:37.000000000","message":"perhaps, handle_container is consistent with SymlinkObjectContext as the entry point for callers.\n\nAnd I\u0027d like to add docs for those entry point what\u0027s returned.\n\nlikely:\n\n\"\"\"\nHandle container request.\n:return: Response Iterator after start_response called.\n\n\"\"\"","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"},{"line_number":141,"context_line":"        self.logger \u003d symlink_mw.logger"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def handle_get(self, req, start_response):"},{"line_number":144,"context_line":"        app_resp \u003d self._app_call(req.environ)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if is_success(self._get_status_int()):"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_6b907144","line":143,"in_reply_to":"7f515b1d_956539e4","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class SymlinkObjectContext(WSGIContext):"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"    def __init__(self, symlink_mw):"},{"line_number":183,"context_line":"        WSGIContext.__init__(self, symlink_mw.app)"},{"line_number":184,"context_line":"        self.app \u003d symlink_mw.app"},{"line_number":185,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_1797514a","line":182,"range":{"start_line":182,"start_character":24,"end_line":182,"end_character":34},"updated":"2017-10-03 11:08:39.000000000","message":"To be consistent with other WSGIContext instances (e.g. copy, versioned_writes), I\u0027d like to make the args starts from \"wsgi_app\", not symlink middleware itself.\n\ni.e.\n\n def __init__(self, app, logger, symloop_max):\n    super(SymlinkObjectContext, self).__init__(app)\n    self.app \u003d app\n    self.symloop_max \u003d symloop_max\n    self.logger \u003d logger","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class SymlinkObjectContext(WSGIContext):"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"    def __init__(self, symlink_mw):"},{"line_number":183,"context_line":"        WSGIContext.__init__(self, symlink_mw.app)"},{"line_number":184,"context_line":"        self.app \u003d symlink_mw.app"},{"line_number":185,"context_line":"        self.symloop_max \u003d symlink_mw.symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_0b821d50","line":182,"range":{"start_line":182,"start_character":24,"end_line":182,"end_character":34},"in_reply_to":"7f515b1d_1797514a","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        Handle get/head request when client sent parameter ?symlink\u003dget"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"        :param req: HTTP GET or HEAD object request with param ?symlink\u003dget"},{"line_number":193,"context_line":"        :returns: HTTP Response"},{"line_number":194,"context_line":"        \"\"\""},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"        resp \u003d self._app_call(req.environ)"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_d82528ad","line":193,"updated":"2017-10-05 09:04:37.000000000","message":"This is NOT swift.swob.HTTPResponse but Response Iterator for wsgi frame work intsead. Other docs also get wrong.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        Handle get/head request when client sent parameter ?symlink\u003dget"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"        :param req: HTTP GET or HEAD object request with param ?symlink\u003dget"},{"line_number":193,"context_line":"        :returns: HTTP Response"},{"line_number":194,"context_line":"        \"\"\""},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"        resp \u003d self._app_call(req.environ)"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_8bc16d31","line":193,"in_reply_to":"7f515b1d_d82528ad","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":242,"context_line":"            # if it\u0027s a symlink, follow symlink"},{"line_number":243,"context_line":"            if target:"},{"line_number":244,"context_line":"                version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":245,"context_line":"                target_path \u003d \u0027/%s%s\u0027 % (version, target)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"                # make sure the new request uses it\u0027s container_info"},{"line_number":248,"context_line":"                req \u003d make_subrequest("}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_a6b84910","line":245,"updated":"2017-10-03 11:08:39.000000000","message":"Please use os.path.join wherever to build a new path otherwise we have to think of the slash existence everywhere by hand :/","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":242,"context_line":"            # if it\u0027s a symlink, follow symlink"},{"line_number":243,"context_line":"            if target:"},{"line_number":244,"context_line":"                version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":245,"context_line":"                target_path \u003d \u0027/%s%s\u0027 % (version, target)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"                # make sure the new request uses it\u0027s container_info"},{"line_number":248,"context_line":"                req \u003d make_subrequest("}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_8bf96d4e","line":245,"in_reply_to":"7f515b1d_a6b84910","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            else:"},{"line_number":254,"context_line":"                if target_path:"},{"line_number":255,"context_line":"                    self._response_headers.extend([(\u0027Content-Location\u0027,"},{"line_number":256,"context_line":"                                                    target_path)])"},{"line_number":257,"context_line":"                return resp"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # exceeded symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_0b760871","line":256,"updated":"2017-10-03 11:08:39.000000000","message":"In F2F asking to Kazuhiro, I found we don\u0027t have the test that Content-Location will appear only when the link was traversed once or more times. He will add the unit test soon.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"db12b6bda65fa9bd71c9aaacc9c117cd09832752","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            else:"},{"line_number":254,"context_line":"                if target_path:"},{"line_number":255,"context_line":"                    self._response_headers.extend([(\u0027Content-Location\u0027,"},{"line_number":256,"context_line":"                                                    target_path)])"},{"line_number":257,"context_line":"                return resp"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # exceeded symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_9f226fb8","line":256,"in_reply_to":"5f4e5783_1880f045","updated":"2017-10-25 17:10:40.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            else:"},{"line_number":254,"context_line":"                if target_path:"},{"line_number":255,"context_line":"                    self._response_headers.extend([(\u0027Content-Location\u0027,"},{"line_number":256,"context_line":"                                                    target_path)])"},{"line_number":257,"context_line":"                return resp"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # exceeded symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_1880f045","line":256,"in_reply_to":"5f4e5783_c6aabcd0","updated":"2017-10-16 08:38:48.000000000","message":"The test will check that \"Content-Location\" doesn\u0027t appear in GET/HEAD response to non-symlink objects.\nThis is test for backward compatibility.\nI\u0027m sorry for not adding the unit test yet.\nI will make it.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            else:"},{"line_number":254,"context_line":"                if target_path:"},{"line_number":255,"context_line":"                    self._response_headers.extend([(\u0027Content-Location\u0027,"},{"line_number":256,"context_line":"                                                    target_path)])"},{"line_number":257,"context_line":"                return resp"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # exceeded symloop_max"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_c6aabcd0","line":256,"in_reply_to":"7f515b1d_0b760871","updated":"2017-10-13 20:49:00.000000000","message":"Not sure I understand, we have several tests in unit tests that check \u0027Content-Location\u0027. please clarify","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        :returns: HTTP Response"},{"line_number":274,"context_line":"        \"\"\""},{"line_number":275,"context_line":"        data \u003d req.body_file.read(1)"},{"line_number":276,"context_line":"        if data:"},{"line_number":277,"context_line":"            return HTTPBadRequest("},{"line_number":278,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":279,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_9f3368ab","line":276,"updated":"2017-10-03 11:08:39.000000000","message":"Why not just ?:\n\n--- a/swift/common/middleware/symlink.py\n+++ b/swift/common/middleware/symlink.py\n@@ -272,8 +272,8 @@ class SymlinkObjectContext(WSGIContext):\n         :param req: HTTP PUT object request\n         :returns: HTTP Response\n         \"\"\"\n-        data \u003d req.body_file.read(1)\n-        if data:\n+        # data \u003d req.body_file.read(1)\n+        if req.content_length !\u003d 0:\n             return HTTPBadRequest(\n                 body\u003d\u0027Symlink requests require a zero byte body\u0027,\n                 request\u003dreq,\n\nI\u0027m not so familiar with wsgi.input but the body read could cause some buffered (redundant, extra) read, maybe?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"db12b6bda65fa9bd71c9aaacc9c117cd09832752","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        :returns: HTTP Response"},{"line_number":274,"context_line":"        \"\"\""},{"line_number":275,"context_line":"        data \u003d req.body_file.read(1)"},{"line_number":276,"context_line":"        if data:"},{"line_number":277,"context_line":"            return HTTPBadRequest("},{"line_number":278,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":279,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_3f1dbb73","line":276,"in_reply_to":"5f4e5783_586668c3","updated":"2017-10-25 17:10:40.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        :returns: HTTP Response"},{"line_number":274,"context_line":"        \"\"\""},{"line_number":275,"context_line":"        data \u003d req.body_file.read(1)"},{"line_number":276,"context_line":"        if data:"},{"line_number":277,"context_line":"            return HTTPBadRequest("},{"line_number":278,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":279,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_586668c3","line":276,"in_reply_to":"5f4e5783_86a84477","updated":"2017-10-16 08:38:48.000000000","message":"In etherpad page https://etherpad.openstack.org/p/swift_symlinks , this topic was discussed.\n\n4) what is the robust way to check for zero-length PUT requests in the middleware?\n    [torgomatic: Content-Length header with value 0; if Content-Length is missing, reply with 400. clients can count to 0 without needing to buffer anything, so chunked input is no good here]\n\nSo I will update this function with this idea.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        :returns: HTTP Response"},{"line_number":274,"context_line":"        \"\"\""},{"line_number":275,"context_line":"        data \u003d req.body_file.read(1)"},{"line_number":276,"context_line":"        if data:"},{"line_number":277,"context_line":"            return HTTPBadRequest("},{"line_number":278,"context_line":"                body\u003d\u0027Symlink requests require a zero byte body\u0027,"},{"line_number":279,"context_line":"                request\u003dreq,"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_86a84477","line":276,"in_reply_to":"7f515b1d_9f3368ab","updated":"2017-10-13 20:49:00.000000000","message":"@Kota, it was done this way to protect from requests that don\u0027t contain a content_length (e.g., transfer-encoding)","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":295,"context_line":""},{"line_number":296,"context_line":"        # store info in container listings that this object is a symlink"},{"line_number":297,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":298,"context_line":"            \"%s; symlink_path\u003d%s\" % (MD5_OF_EMPTY_STRING, symlink_path)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        return self._app_call(req.environ)"},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_58bb780d","line":298,"updated":"2017-10-05 09:04:37.000000000","message":"Oh, this is why we have to avoid NON empty symlink for PUT.\n\nI wondered if we just update the footer callback instead but it seems worse because for the case, we have to calculate etag at proxy even if replicated non encrypted policy that should be overhead.\n\nHmm... anyway, this statement is not tested by unit tests. When I removed those 2 lines, no test failed.\n\nAnd, I\u0027m not sure this is right thing for now. Exactly, finding symlink objects on GET container requests could be useful but I cannot find the use cases, swift processes that WANT to use the GET container result. If no use case exist, it seems to make the code simpler I\u0027m feeling.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":295,"context_line":""},{"line_number":296,"context_line":"        # store info in container listings that this object is a symlink"},{"line_number":297,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":298,"context_line":"            \"%s; symlink_path\u003d%s\" % (MD5_OF_EMPTY_STRING, symlink_path)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        return self._app_call(req.environ)"},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_861de4be","line":298,"in_reply_to":"7f515b1d_58bb780d","updated":"2017-10-13 20:49:00.000000000","message":"Done, added test.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":295,"context_line":""},{"line_number":296,"context_line":"        # store info in container listings that this object is a symlink"},{"line_number":297,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":298,"context_line":"            \"%s; symlink_path\u003d%s\" % (MD5_OF_EMPTY_STRING, symlink_path)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        return self._app_call(req.environ)"},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_64fc493e","line":298,"in_reply_to":"7f515b1d_58bb780d","updated":"2017-10-05 11:25:05.000000000","message":"In Atlanta PTG discussion, I and thiago discussed how to find target objects of deleted symlinks in auto-tiering containers to delete target objects which are in hidden containers.\nThe conclusion was that ContainerDB have the target path information and auto-tiering processes refer them.\nSo this container listing update was implemented for auto-tiering.\nBut in current auto-tiering design (with general task queue), auto-tiering processes can resolve the problem with the general task queue architecture.\nTherefore, I think there are no use cases of symlink path information in container listing now...","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":372,"context_line":"    \"\"\""},{"line_number":373,"context_line":"    Middleware that implements symlinks."},{"line_number":374,"context_line":""},{"line_number":375,"context_line":"    Symlinks allow references to one object path to transparently access"},{"line_number":376,"context_line":"    another object."},{"line_number":377,"context_line":"    An important use case is to use a path in one container to access an object"},{"line_number":378,"context_line":"    in a different container, with a different policy."}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_253e96c0","line":375,"range":{"start_line":375,"start_character":66,"end_line":375,"end_character":72},"updated":"2017-10-03 11:08:39.000000000","message":"nits) access to?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":372,"context_line":"    \"\"\""},{"line_number":373,"context_line":"    Middleware that implements symlinks."},{"line_number":374,"context_line":""},{"line_number":375,"context_line":"    Symlinks allow references to one object path to transparently access"},{"line_number":376,"context_line":"    another object."},{"line_number":377,"context_line":"    An important use case is to use a path in one container to access an object"},{"line_number":378,"context_line":"    in a different container, with a different policy."}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_46cb6c1d","line":375,"range":{"start_line":375,"start_character":66,"end_line":375,"end_character":72},"in_reply_to":"7f515b1d_253e96c0","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":386,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink\u0027)"},{"line_number":387,"context_line":"        self.symloop_max \u003d symloop_max"},{"line_number":388,"context_line":""},{"line_number":389,"context_line":"    def __call__(self, env, start_response):"},{"line_number":390,"context_line":"        req \u003d Request(env)"},{"line_number":391,"context_line":"        try:"},{"line_number":392,"context_line":"            parts \u003d req.split_path(3, 4, True)"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_4b9d2008","line":389,"updated":"2017-10-03 11:08:39.000000000","message":"IIUC, the middleware should catch HTTPException as the last resort or catch the exception for wherever can raise HTTPException. e.g.  check_account_format in ObjectContext.handle_put can raise HTTPPreconditionFaild but it\u0027s never caught in the middleware that could be a problem.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"db12b6bda65fa9bd71c9aaacc9c117cd09832752","unresolved":false,"context_lines":[{"line_number":386,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink\u0027)"},{"line_number":387,"context_line":"        self.symloop_max \u003d symloop_max"},{"line_number":388,"context_line":""},{"line_number":389,"context_line":"    def __call__(self, env, start_response):"},{"line_number":390,"context_line":"        req \u003d Request(env)"},{"line_number":391,"context_line":"        try:"},{"line_number":392,"context_line":"            parts \u003d req.split_path(3, 4, True)"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_1f20bfab","line":389,"in_reply_to":"5f4e5783_38da8c4a","updated":"2017-10-25 17:10:40.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"610561dba46743f527461bf43106590cc0c76a67","unresolved":false,"context_lines":[{"line_number":386,"context_line":"        self.logger \u003d get_logger(self.conf, log_route\u003d\u0027symlink\u0027)"},{"line_number":387,"context_line":"        self.symloop_max \u003d symloop_max"},{"line_number":388,"context_line":""},{"line_number":389,"context_line":"    def __call__(self, env, start_response):"},{"line_number":390,"context_line":"        req \u003d Request(env)"},{"line_number":391,"context_line":"        try:"},{"line_number":392,"context_line":"            parts \u003d req.split_path(3, 4, True)"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_38da8c4a","line":389,"in_reply_to":"7f515b1d_4b9d2008","updated":"2017-10-16 08:38:48.000000000","message":"OK. I will update for this function by referring your following patch.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":389,"context_line":"    def __call__(self, env, start_response):"},{"line_number":390,"context_line":"        req \u003d Request(env)"},{"line_number":391,"context_line":"        try:"},{"line_number":392,"context_line":"            parts \u003d req.split_path(3, 4, True)"},{"line_number":393,"context_line":"        except ValueError:"},{"line_number":394,"context_line":"            return self.app(env, start_response)"},{"line_number":395,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_8552ea11","line":392,"updated":"2017-10-03 11:08:39.000000000","message":"I prefer to make the assigned variable as:\n\n version, acc, con, obj \u003d req.split_path(3, 4, True)\n\nrather than parts and index access below.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":389,"context_line":"    def __call__(self, env, start_response):"},{"line_number":390,"context_line":"        req \u003d Request(env)"},{"line_number":391,"context_line":"        try:"},{"line_number":392,"context_line":"            parts \u003d req.split_path(3, 4, True)"},{"line_number":393,"context_line":"        except ValueError:"},{"line_number":394,"context_line":"            return self.app(env, start_response)"},{"line_number":395,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_3a85245b","line":392,"in_reply_to":"7f515b1d_8552ea11","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":28,"context_line":"with the header ``X-Symlink-Target: \u003ccontainer\u003e/\u003cobject\u003e``. For a cross-account"},{"line_number":29,"context_line":"symlink, the header ``X-Symlink-Target-Account: \u003caccount\u003e`` must be included."},{"line_number":30,"context_line":"If omitted, it is inserted automatically with the account of the symlink"},{"line_number":31,"context_line":"object in the PUT request process."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":34,"context_line":"with a non-empty request body will result in a 400-series error. Also,"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_6b1a4017","line":31,"updated":"2017-10-26 12:48:32.000000000","message":"OK, and the whole path is in sysmeta. make sense.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":34,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":35,"context_line":"attempting to change an existing object as symlink with a POST request will"},{"line_number":36,"context_line":"result in a 400-series error. The target object need not exist at"},{"line_number":37,"context_line":"symlink-creation time. It is suggested to set the ``Content-Type`` of symlink"},{"line_number":38,"context_line":"objects to a distinct value such as ``application/symlink``."}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_4b49c4b4","line":35,"range":{"start_line":35,"start_character":21,"end_line":35,"end_character":42},"updated":"2017-10-26 12:48:32.000000000","message":"Looking back at the Thiago\u0027s comment on patch set 59, that doesn\u0027t depend on object existence. Just\n\n\u003e POST with X-Symlink-Target header always results in a 400-series error.\n\nseems enough?","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Symlinks must be zero-byte objects. Attempting to PUT a symlink"},{"line_number":34,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":35,"context_line":"attempting to change an existing object as symlink with a POST request will"},{"line_number":36,"context_line":"result in a 400-series error. The target object need not exist at"},{"line_number":37,"context_line":"symlink-creation time. It is suggested to set the ``Content-Type`` of symlink"},{"line_number":38,"context_line":"objects to a distinct value such as ``application/symlink``."}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_e826d9b7","line":35,"range":{"start_line":35,"start_character":21,"end_line":35,"end_character":42},"in_reply_to":"3f4b6375_4b49c4b4","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":34,"context_line":"with a non-empty request body will result in a 400-series error. Also,"},{"line_number":35,"context_line":"attempting to change an existing object as symlink with a POST request will"},{"line_number":36,"context_line":"result in a 400-series error. The target object need not exist at"},{"line_number":37,"context_line":"symlink-creation time. It is suggested to set the ``Content-Type`` of symlink"},{"line_number":38,"context_line":"objects to a distinct value such as ``application/symlink``."},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"A GET/HEAD request to a symlink will resolve in a request to the target"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_8bafbc28","line":37,"range":{"start_line":37,"start_character":29,"end_line":37,"end_character":38},"updated":"2017-10-26 12:48:32.000000000","message":"ok, this is just a suggestion.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":51,"context_line":"proxy-server.conf. If not specified, the default ``symloop_max`` value is 2. If"},{"line_number":52,"context_line":"a value less than 1 is specified, the default value will be used."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"A POST request to a symlink will result in a 307 TemporaryRedirect response."},{"line_number":55,"context_line":"The response will contain a ``Location`` header with the path of the target"},{"line_number":56,"context_line":"object as the value. The request is never redirected to the target object by"},{"line_number":57,"context_line":"Swift. Nevertheless, the metadata in the POST request will be applied to the"},{"line_number":58,"context_line":"symlink because object servers cannot know for sure if the current object is a"},{"line_number":59,"context_line":"symlink or not in eventual consistency."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata (and data in the case of GET) that is"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_69900896","line":59,"range":{"start_line":54,"start_character":0,"end_line":59,"end_character":39},"updated":"2017-10-26 12:48:32.000000000","message":"Those description looks much better than the previous one, great!","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":58,"context_line":"symlink because object servers cannot know for sure if the current object is a"},{"line_number":59,"context_line":"symlink or not in eventual consistency."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata (and data in the case of GET) that is"},{"line_number":63,"context_line":"stored on the target object. A GET/HEAD request sent to the symlink with"},{"line_number":64,"context_line":"the ``?symlink\u003dget`` query string will return only the metadata that is stored"},{"line_number":65,"context_line":"on the symlink object itself."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":68,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_c9425c0f","line":65,"range":{"start_line":61,"start_character":1,"end_line":65,"end_character":29},"updated":"2017-10-26 12:48:32.000000000","message":"Perhaps, it might be better to move those lines up to around Line 53? (above on POST description) My intention is this block explains about GET/HEAD and we could gather the explanation into the same block.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":58,"context_line":"symlink because object servers cannot know for sure if the current object is a"},{"line_number":59,"context_line":"symlink or not in eventual consistency."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Issuing a GET/HEAD request to the symlink or directly to the target"},{"line_number":62,"context_line":"object will return only the metadata (and data in the case of GET) that is"},{"line_number":63,"context_line":"stored on the target object. A GET/HEAD request sent to the symlink with"},{"line_number":64,"context_line":"the ``?symlink\u003dget`` query string will return only the metadata that is stored"},{"line_number":65,"context_line":"on the symlink object itself."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"A DELETE request to a symlink will delete the symlink itself. The target"},{"line_number":68,"context_line":"object will not be deleted."}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_c83b1dcf","line":65,"range":{"start_line":61,"start_character":1,"end_line":65,"end_character":29},"in_reply_to":"3f4b6375_c9425c0f","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":72,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":75,"context_line":"only, the request will not be redirected to the target object. Please note that"},{"line_number":76,"context_line":"even if after OPTIONS request, a GET/HEAD request to a symlink without"},{"line_number":77,"context_line":"``?symlink\u003dget`` will be affected by not only the container of the symlink but"},{"line_number":78,"context_line":"also the container of the target object."},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"Tempurls can be used to GET/HEAD symlink objects, but PUT is not allowed and"},{"line_number":81,"context_line":"will result in a 400-series error. The GET/HEAD tempurls honor the scope of"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_09d99455","line":78,"range":{"start_line":75,"start_character":63,"end_line":78,"end_character":40},"updated":"2017-10-26 12:48:32.000000000","message":"sorry, I couldn\u0027t get those new instructions. What does it mean...","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":72,"context_line":"parameter ``?symlink\u003dget`` will copy the symlink itself."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"An OPTIONS request to a symlink will respond with the options for the symlink"},{"line_number":75,"context_line":"only, the request will not be redirected to the target object. Please note that"},{"line_number":76,"context_line":"even if after OPTIONS request, a GET/HEAD request to a symlink without"},{"line_number":77,"context_line":"``?symlink\u003dget`` will be affected by not only the container of the symlink but"},{"line_number":78,"context_line":"also the container of the target object."},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"Tempurls can be used to GET/HEAD symlink objects, but PUT is not allowed and"},{"line_number":81,"context_line":"will result in a 400-series error. The GET/HEAD tempurls honor the scope of"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_e8eb79ad","line":78,"range":{"start_line":75,"start_character":63,"end_line":78,"end_character":40},"in_reply_to":"3f4b6375_09d99455","updated":"2017-11-13 12:27:45.000000000","message":"I intended to explain behavior about CORS which you commented at https://review.openstack.org/#/c/232162/59/swift/common/middleware/symlink.py@74 .\nBut this explanation is bad. I changed this more simple.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        redirect request to target object."},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"        :param req: HTTP GET or HEAD object request"},{"line_number":242,"context_line":"        :returns: HTTP Response"},{"line_number":243,"context_line":"        \"\"\""},{"line_number":244,"context_line":"        try:"},{"line_number":245,"context_line":"            return self._recursive_get_head(req)"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_15be49b3","line":242,"range":{"start_line":242,"start_character":18,"end_line":242,"end_character":31},"updated":"2017-10-26 12:48:32.000000000","message":"Response Iterator","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        redirect request to target object."},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"        :param req: HTTP GET or HEAD object request"},{"line_number":242,"context_line":"        :returns: HTTP Response"},{"line_number":243,"context_line":"        \"\"\""},{"line_number":244,"context_line":"        try:"},{"line_number":245,"context_line":"            return self._recursive_get_head(req)"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_c8d0bdfa","line":242,"range":{"start_line":242,"start_character":18,"end_line":242,"end_character":31},"in_reply_to":"3f4b6375_15be49b3","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":246,"context_line":"        except LinkIterError:"},{"line_number":247,"context_line":"            errmsg \u003d \u0027Too many levels of symbolic links, \u0027 \\"},{"line_number":248,"context_line":"                     \u0027maximum allowed is %d\u0027 % self.symloop_max"},{"line_number":249,"context_line":"            self.logger.info(errmsg)"},{"line_number":250,"context_line":"            return HTTPConflict("},{"line_number":251,"context_line":"                body\u003derrmsg, request\u003dreq, content_type\u003d\u0027text/plain\u0027)("},{"line_number":252,"context_line":"                    req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_55ea81d7","line":249,"range":{"start_line":249,"start_character":11,"end_line":249,"end_character":36},"updated":"2017-10-26 12:48:32.000000000","message":"I\u0027d love to change the log level at least debug (or delete this line). That is because this info level log line can appear frequently if user would do GET against to such an invalid target chain. And it can be bomb on swift admin logs...","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":246,"context_line":"        except LinkIterError:"},{"line_number":247,"context_line":"            errmsg \u003d \u0027Too many levels of symbolic links, \u0027 \\"},{"line_number":248,"context_line":"                     \u0027maximum allowed is %d\u0027 % self.symloop_max"},{"line_number":249,"context_line":"            self.logger.info(errmsg)"},{"line_number":250,"context_line":"            return HTTPConflict("},{"line_number":251,"context_line":"                body\u003derrmsg, request\u003dreq, content_type\u003d\u0027text/plain\u0027)("},{"line_number":252,"context_line":"                    req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_88dac514","line":249,"range":{"start_line":249,"start_character":11,"end_line":249,"end_character":36},"in_reply_to":"3f4b6375_55ea81d7","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    # Content-Location will be applied only when one or more"},{"line_number":281,"context_line":"                    # symlink recursion occurred."},{"line_number":282,"context_line":"                    self._response_headers.extend("},{"line_number":283,"context_line":"                        [(\u0027Content-Location\u0027, req.path)])"},{"line_number":284,"context_line":"                return resp"},{"line_number":285,"context_line":"            elif self.loop_count \u003e\u003d self.symloop_max:"},{"line_number":286,"context_line":"                raise LinkIterError()"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_8901043b","line":283,"updated":"2017-10-26 12:48:32.000000000","message":"So we should set symlink-target path instead of the last request path.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    # Content-Location will be applied only when one or more"},{"line_number":281,"context_line":"                    # symlink recursion occurred."},{"line_number":282,"context_line":"                    self._response_headers.extend("},{"line_number":283,"context_line":"                        [(\u0027Content-Location\u0027, req.path)])"},{"line_number":284,"context_line":"                return resp"},{"line_number":285,"context_line":"            elif self.loop_count \u003e\u003d self.symloop_max:"},{"line_number":286,"context_line":"                raise LinkIterError()"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_b6f83bc4","line":283,"in_reply_to":"3f4b6375_8901043b","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":338,"context_line":"        symlink_path \u003d quote(os.path.join(\u0027/\u0027, sym_acct, sym_cont, sym_obj))"},{"line_number":339,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"        # Store info in container listings that this object is a symlink."},{"line_number":342,"context_line":"        # The reason why we use not content-type string, but etag string is"},{"line_number":343,"context_line":"        # that both of symlink information and etag strings are updated only by"},{"line_number":344,"context_line":"        # PUT. This design can cause strange hash values in downgraded Swift"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_182e8091","line":341,"range":{"start_line":341,"start_character":33,"end_line":341,"end_character":43},"updated":"2017-10-26 12:48:32.000000000","message":"update","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":338,"context_line":"        symlink_path \u003d quote(os.path.join(\u0027/\u0027, sym_acct, sym_cont, sym_obj))"},{"line_number":339,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"        # Store info in container listings that this object is a symlink."},{"line_number":342,"context_line":"        # The reason why we use not content-type string, but etag string is"},{"line_number":343,"context_line":"        # that both of symlink information and etag strings are updated only by"},{"line_number":344,"context_line":"        # PUT. This design can cause strange hash values in downgraded Swift"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_280bd18e","line":341,"range":{"start_line":341,"start_character":33,"end_line":341,"end_character":43},"in_reply_to":"3f4b6375_182e8091","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":339,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"        # Store info in container listings that this object is a symlink."},{"line_number":342,"context_line":"        # The reason why we use not content-type string, but etag string is"},{"line_number":343,"context_line":"        # that both of symlink information and etag strings are updated only by"},{"line_number":344,"context_line":"        # PUT. This design can cause strange hash values in downgraded Swift"},{"line_number":345,"context_line":"        # scenario, but we accept this now and we move this forward."},{"line_number":346,"context_line":"        # This implementation is compatible with encryption, because symlinks"},{"line_number":347,"context_line":"        # are zero-byte objects and encryption middleware doesn\u0027t encrypt"},{"line_number":348,"context_line":"        # zero-byte objects."}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_351dc573","line":345,"range":{"start_line":342,"start_character":0,"end_line":345,"end_character":68},"updated":"2017-10-26 12:48:32.000000000","message":"The expression could be a bit complex (and indirect).\n\nHow about:\n\n\u003e we have a design decision to use etag space to store symlink info for object listing because it\u0027s immutable unless the object is overwritten. This may impact the downgrade scenario that the symlink info can be appeared as the suffix in the hash value of object listing result for clients.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":339,"context_line":"        req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR] \u003d symlink_path"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"        # Store info in container listings that this object is a symlink."},{"line_number":342,"context_line":"        # The reason why we use not content-type string, but etag string is"},{"line_number":343,"context_line":"        # that both of symlink information and etag strings are updated only by"},{"line_number":344,"context_line":"        # PUT. This design can cause strange hash values in downgraded Swift"},{"line_number":345,"context_line":"        # scenario, but we accept this now and we move this forward."},{"line_number":346,"context_line":"        # This implementation is compatible with encryption, because symlinks"},{"line_number":347,"context_line":"        # are zero-byte objects and encryption middleware doesn\u0027t encrypt"},{"line_number":348,"context_line":"        # zero-byte objects."}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_a8f6a18e","line":345,"range":{"start_line":342,"start_character":0,"end_line":345,"end_character":68},"in_reply_to":"3f4b6375_351dc573","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":345,"context_line":"        # scenario, but we accept this now and we move this forward."},{"line_number":346,"context_line":"        # This implementation is compatible with encryption, because symlinks"},{"line_number":347,"context_line":"        # are zero-byte objects and encryption middleware doesn\u0027t encrypt"},{"line_number":348,"context_line":"        # zero-byte objects."},{"line_number":349,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":350,"context_line":"            \u0027%s; symlink_path\u003d%s\u0027 % (MD5_OF_EMPTY_STRING, symlink_path)"},{"line_number":351,"context_line":""}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_b86c0cce","line":348,"updated":"2017-10-26 12:48:32.000000000","message":"Since encryption middleware doesn\u0027t encrypt a zero-byte object, we can use hard-corded Etag value here as the symlink Etag.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":345,"context_line":"        # scenario, but we accept this now and we move this forward."},{"line_number":346,"context_line":"        # This implementation is compatible with encryption, because symlinks"},{"line_number":347,"context_line":"        # are zero-byte objects and encryption middleware doesn\u0027t encrypt"},{"line_number":348,"context_line":"        # zero-byte objects."},{"line_number":349,"context_line":"        req.headers[\u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027] \u003d \\"},{"line_number":350,"context_line":"            \u0027%s; symlink_path\u003d%s\u0027 % (MD5_OF_EMPTY_STRING, symlink_path)"},{"line_number":351,"context_line":""}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_88f3e59e","line":348,"in_reply_to":"3f4b6375_b86c0cce","updated":"2017-11-13 12:27:45.000000000","message":"Done","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":359,"context_line":"        Clients that POST to symlinks should understand that the POST is not"},{"line_number":360,"context_line":"        redirected to the target object like in a HEAD/GET request. POSTs to a"},{"line_number":361,"context_line":"        symlink will be handled just like a normal object by the object server"},{"line_number":362,"context_line":"        even if symlink middleware will return HTTPTemporaryRedirect. It cannot"},{"line_number":363,"context_line":"        reject it because it may not have symlink state when the POST lands."},{"line_number":364,"context_line":"        The object server has no knowledge of what is a symlink object is. On"},{"line_number":365,"context_line":"        the other hand, on POST requests, the object server returns all sysmeta"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_d8a6a80f","line":362,"range":{"start_line":362,"start_character":8,"end_line":362,"end_character":68},"updated":"2017-10-26 12:48:32.000000000","message":"what does it mean?","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":359,"context_line":"        Clients that POST to symlinks should understand that the POST is not"},{"line_number":360,"context_line":"        redirected to the target object like in a HEAD/GET request. POSTs to a"},{"line_number":361,"context_line":"        symlink will be handled just like a normal object by the object server"},{"line_number":362,"context_line":"        even if symlink middleware will return HTTPTemporaryRedirect. It cannot"},{"line_number":363,"context_line":"        reject it because it may not have symlink state when the POST lands."},{"line_number":364,"context_line":"        The object server has no knowledge of what is a symlink object is. On"},{"line_number":365,"context_line":"        the other hand, on POST requests, the object server returns all sysmeta"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_48c72d14","line":362,"range":{"start_line":362,"start_character":8,"end_line":362,"end_character":68},"in_reply_to":"3f4b6375_d8a6a80f","updated":"2017-11-13 12:27:45.000000000","message":"I intended to explain difference between POSTs to symlinks and normal objects.\nBut now I think this sentence is about object-server\u0027s behavior.\nSo I removed this.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":386,"context_line":"            version, _junk \u003d req.split_path(1, 2, True)"},{"line_number":387,"context_line":"            location_hdr \u003d os.path.join(\u0027/\u0027, version, sym_target.lstrip(\u0027/\u0027))"},{"line_number":388,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":389,"context_line":"            errmsg \u003d \u0027POSTing to a symlink is not allowed. \u0027 + \\"},{"line_number":390,"context_line":"                \u0027Please POST directly to target object\u0027"},{"line_number":391,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":392,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_38ec9c28","line":389,"range":{"start_line":389,"start_character":46,"end_line":389,"end_character":57},"updated":"2017-10-26 12:48:32.000000000","message":"It seems like \"not allowed\" is too much strong message for user clients.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":387,"context_line":"            location_hdr \u003d os.path.join(\u0027/\u0027, version, sym_target.lstrip(\u0027/\u0027))"},{"line_number":388,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":389,"context_line":"            errmsg \u003d \u0027POSTing to a symlink is not allowed. \u0027 + \\"},{"line_number":390,"context_line":"                \u0027Please POST directly to target object\u0027"},{"line_number":391,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":392,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":393,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_d8f468f3","line":390,"range":{"start_line":390,"start_character":17,"end_line":390,"end_character":24},"updated":"2017-10-26 12:48:32.000000000","message":"And if i understand English correctly, we don\u0027t have to add \"Please\" if it\u0027s direction expression. so...\n\n\u003e \"The requested object is a symlink. POST directly to the target object to apply requested metadata\"\n\nHow do you think of?","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":387,"context_line":"            location_hdr \u003d os.path.join(\u0027/\u0027, version, sym_target.lstrip(\u0027/\u0027))"},{"line_number":388,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":389,"context_line":"            errmsg \u003d \u0027POSTing to a symlink is not allowed. \u0027 + \\"},{"line_number":390,"context_line":"                \u0027Please POST directly to target object\u0027"},{"line_number":391,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":392,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":393,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_e87139e2","line":390,"range":{"start_line":390,"start_character":17,"end_line":390,"end_character":24},"in_reply_to":"3f4b6375_d8f468f3","updated":"2017-11-13 12:27:45.000000000","message":"I feel your message is better.\nI updated the message.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"ff344647d2029ba9e26cf80ba3e9e50652cec3a8","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2016 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_88c21be9","line":1,"range":{"start_line":1,"start_character":24,"end_line":1,"end_character":25},"updated":"2017-11-20 06:32:56.000000000","message":"this could be 17 now.. or scarily it could almost be 18 :(","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"d0742ad67fbef03db303eb0e8d2eb04738373b45","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2016 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_fc5e0944","line":1,"range":{"start_line":1,"start_character":24,"end_line":1,"end_character":25},"in_reply_to":"ff82abbf_88c21be9","updated":"2017-11-20 09:14:45.000000000","message":"Done. I update it to 2017, because I want to merge symlink before 2018 :)","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"ab310c5572dcc6da884806ff955f712745f9fe04","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        app_resp \u003d self._app_call(req.environ)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 and is_success(self._get_status_int()):"},{"line_number":174,"context_line":"            app_resp \u003d self._process_json_resp(app_resp)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        start_response(self._response_status, self._response_headers,"},{"line_number":177,"context_line":"                       self._response_exc_info)"}],"source_content_type":"text/x-python","patch_set":69,"id":"1f485f77_f2164349","line":174,"updated":"2017-11-17 00:12:45.000000000","message":"What is going to happen if I do this:\n\ncurl -k -v -H \u0027X-Storage-Token: AUTH_tk41e385002c62486**********\u0027 -H \u0027Accept: application/xml\u0027 https://mpc.lab.eng.bos.redhat.com/v1/AUTH_test/testcont\n\n?\nIn my tests, there\u0027s a ValueError.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"6c35aa800141c99817348e3d61d1daa5fa74e497","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        app_resp \u003d self._app_call(req.environ)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 and is_success(self._get_status_int()):"},{"line_number":174,"context_line":"            app_resp \u003d self._process_json_resp(app_resp)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        start_response(self._response_status, self._response_headers,"},{"line_number":177,"context_line":"                       self._response_exc_info)"}],"source_content_type":"text/x-python","patch_set":69,"id":"1f485f77_0b740afd","line":174,"in_reply_to":"1f485f77_d2d3475f","updated":"2017-11-17 04:17:18.000000000","message":"I want to know detail of the error.\nPete, can you share error log?\nAnd I want to know pipeline setting as Tim said.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c0e6ff254f291bd1bffe0ede6c1d69e747063189","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        app_resp \u003d self._app_call(req.environ)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 and is_success(self._get_status_int()):"},{"line_number":174,"context_line":"            app_resp \u003d self._process_json_resp(app_resp)"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        start_response(self._response_status, self._response_headers,"},{"line_number":177,"context_line":"                       self._response_exc_info)"}],"source_content_type":"text/x-python","patch_set":69,"id":"1f485f77_d2d3475f","line":174,"in_reply_to":"1f485f77_f2164349","updated":"2017-11-17 00:21:58.000000000","message":"Really? Even after https://github.com/openstack/swift/commit/4806434 ?\n\nWhat\u0027s the pipeline look like?","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"ff344647d2029ba9e26cf80ba3e9e50652cec3a8","unresolved":false,"context_lines":[{"line_number":202,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":203,"context_line":"            for key in meta:"},{"line_number":204,"context_line":"                if key \u003d\u003d \u0027symlink_path\u0027:"},{"line_number":205,"context_line":"                    obj_dict[\u0027symlink_path\u0027] \u003d meta[key]"},{"line_number":206,"context_line":"                else:"},{"line_number":207,"context_line":"                    # make sure to add all other (key, values) back in place"},{"line_number":208,"context_line":"                    obj_dict[\u0027hash\u0027] +\u003d \u0027; %s\u003d%s\u0027 % (key, meta[key])"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_ebd961f4","line":205,"range":{"start_line":205,"start_character":29,"end_line":205,"end_character":43},"updated":"2017-11-20 06:32:56.000000000","message":"NIT: This can just be key:\n\n  obj_dict[key] \u003d meta[key]\n\nseeing as you\u0027ve just gone to the effort to make sure it is.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"d0742ad67fbef03db303eb0e8d2eb04738373b45","unresolved":false,"context_lines":[{"line_number":202,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":203,"context_line":"            for key in meta:"},{"line_number":204,"context_line":"                if key \u003d\u003d \u0027symlink_path\u0027:"},{"line_number":205,"context_line":"                    obj_dict[\u0027symlink_path\u0027] \u003d meta[key]"},{"line_number":206,"context_line":"                else:"},{"line_number":207,"context_line":"                    # make sure to add all other (key, values) back in place"},{"line_number":208,"context_line":"                    obj_dict[\u0027hash\u0027] +\u003d \u0027; %s\u003d%s\u0027 % (key, meta[key])"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_9c1edd6e","line":205,"range":{"start_line":205,"start_character":29,"end_line":205,"end_character":43},"in_reply_to":"ff82abbf_ebd961f4","updated":"2017-11-20 09:14:45.000000000","message":"Done","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fc1904b92b7fb9368f9125d457645763ffecd0c2","unresolved":false,"context_lines":[{"line_number":232,"context_line":"            if key.lower() !\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:"},{"line_number":233,"context_line":"                continue"},{"line_number":234,"context_line":"            # tgt_acct and tgt_cont_obj are quoted strings"},{"line_number":235,"context_line":"            tgt_acct, tgt_cont_obj \u003d split_sysmeta_symlink_header_path(val)"},{"line_number":236,"context_line":"            self._response_headers.extend([(\u0027X-Symlink-Target\u0027, tgt_cont_obj)])"},{"line_number":237,"context_line":"            # return value of req.split_path is unquoted"},{"line_number":238,"context_line":"            sym_acct \u003d quote(req.split_path(4, 4, True)[1])"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_81989b6a","line":235,"range":{"start_line":235,"start_character":37,"end_line":235,"end_character":70},"updated":"2017-11-21 06:24:40.000000000","message":"As far as I can see, this method is only used once.. and it\u0027s here. Is it expected to be needed more in the future?\n\nJust wondering why it\u0027s been refactored away, when split_sysmeta_symlink_header_path() is actually only a 1 liner anyway. And that line is shorter then this method name:\n\n  tgt_acct, tgt_cont_obj \u003d split_path(val, 2, 2, True)\n\nEDIT: ok just realised it\u0027s also used in container-sync.. still, it\u0027s only 1 line, and thats just calling split_path, which is something we call all the time, so maybe a refactor like this actually isn\u0027t required? I dunno, what do others think? Maybe seeing as there are two references, maybe its now only a NIT.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"c4ff759c8f736224813e260a027421ab25f93a72","unresolved":false,"context_lines":[{"line_number":232,"context_line":"            if key.lower() !\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:"},{"line_number":233,"context_line":"                continue"},{"line_number":234,"context_line":"            # tgt_acct and tgt_cont_obj are quoted strings"},{"line_number":235,"context_line":"            tgt_acct, tgt_cont_obj \u003d split_sysmeta_symlink_header_path(val)"},{"line_number":236,"context_line":"            self._response_headers.extend([(\u0027X-Symlink-Target\u0027, tgt_cont_obj)])"},{"line_number":237,"context_line":"            # return value of req.split_path is unquoted"},{"line_number":238,"context_line":"            sym_acct \u003d quote(req.split_path(4, 4, True)[1])"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_9470b4de","line":235,"range":{"start_line":235,"start_character":37,"end_line":235,"end_character":70},"in_reply_to":"ff82abbf_81989b6a","updated":"2017-11-22 13:44:21.000000000","message":"OK. I agree with you. I removed the split_sysmeta_symlink_header_path.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fc1904b92b7fb9368f9125d457645763ffecd0c2","unresolved":false,"context_lines":[{"line_number":267,"context_line":"                body\u003derrmsg, request\u003dreq, content_type\u003d\u0027text/plain\u0027)("},{"line_number":268,"context_line":"                    req.environ, self._start_response)"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def _recursive_get_head(self, req):"},{"line_number":271,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        def build_traversal_req():"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_9ceec486","line":270,"updated":"2017-11-21 06:24:40.000000000","message":"Seeing as this is a recursive method, we could actually get rid of the instance variables (self.loop_count and self.last_tgt_path) we are using just to keep track during recursion and only using here in this function. With something like: http://paste.openstack.org/show/626891/\n\nOr are using the instance variables simply easier for people to read?","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"c4ff759c8f736224813e260a027421ab25f93a72","unresolved":false,"context_lines":[{"line_number":267,"context_line":"                body\u003derrmsg, request\u003dreq, content_type\u003d\u0027text/plain\u0027)("},{"line_number":268,"context_line":"                    req.environ, self._start_response)"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def _recursive_get_head(self, req):"},{"line_number":271,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        def build_traversal_req():"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_4ba3629f","line":270,"in_reply_to":"ff82abbf_9ceec486","updated":"2017-11-22 13:44:21.000000000","message":"I like your implementation idea :)\nI updated variables on the basis of your idea.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fc1904b92b7fb9368f9125d457645763ffecd0c2","unresolved":false,"context_lines":[{"line_number":418,"context_line":"            location_hdr \u003d os.path.join(\u0027/\u0027, version, tgt_aco.lstrip(\u0027/\u0027))"},{"line_number":419,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":420,"context_line":"            errmsg \u003d \u0027The requested object is a symlink. POST directly to \u0027 + \\"},{"line_number":421,"context_line":"                \u0027the target object to apply requested metadata.\u0027"},{"line_number":422,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":423,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":424,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_eb670825","line":421,"updated":"2017-11-21 06:24:40.000000000","message":"This error makes me think that my post never landed anywhere. Where is actually landed on the symlink. Which I know we mention in the docs.\n\nSo not sure if there is anything to do here. What if the user wanted to apply the metadata to the symlink. It doesn\u0027t it was it wasn\u0027t applied I guess. Maybe we need some better wording:\n\n The requested POST was applied to a symlink. POST directly to the target to apply requested metadata.\n\nOr something. Maybe I\u0027m being too critical.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"c4ff759c8f736224813e260a027421ab25f93a72","unresolved":false,"context_lines":[{"line_number":418,"context_line":"            location_hdr \u003d os.path.join(\u0027/\u0027, version, tgt_aco.lstrip(\u0027/\u0027))"},{"line_number":419,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":420,"context_line":"            errmsg \u003d \u0027The requested object is a symlink. POST directly to \u0027 + \\"},{"line_number":421,"context_line":"                \u0027the target object to apply requested metadata.\u0027"},{"line_number":422,"context_line":"            return HTTPTemporaryRedirect("},{"line_number":423,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})("},{"line_number":424,"context_line":"                req.environ, self._start_response)"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_b0813d4d","line":421,"in_reply_to":"ff82abbf_eb670825","updated":"2017-11-22 13:44:21.000000000","message":"Done","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"ff344647d2029ba9e26cf80ba3e9e50652cec3a8","unresolved":false,"context_lines":[{"line_number":442,"context_line":"        elif req.method \u003d\u003d \u0027POST\u0027:"},{"line_number":443,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":444,"context_line":"        else:"},{"line_number":445,"context_line":"            # DELETE and OPTION reqs for a symlink behave like any other object"},{"line_number":446,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"        start_response(self._response_status, self._response_headers,"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_ebb0818e","line":445,"range":{"start_line":445,"start_character":14,"end_line":445,"end_character":79},"updated":"2017-11-20 06:32:56.000000000","message":"NIT: and PUT\u0027s without x-symlink-target.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"d0742ad67fbef03db303eb0e8d2eb04738373b45","unresolved":false,"context_lines":[{"line_number":442,"context_line":"        elif req.method \u003d\u003d \u0027POST\u0027:"},{"line_number":443,"context_line":"            resp \u003d self.handle_post(req)"},{"line_number":444,"context_line":"        else:"},{"line_number":445,"context_line":"            # DELETE and OPTION reqs for a symlink behave like any other object"},{"line_number":446,"context_line":"            resp \u003d self._app_call(req.environ)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"        start_response(self._response_status, self._response_headers,"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_977a3686","line":445,"range":{"start_line":445,"start_character":14,"end_line":445,"end_character":79},"in_reply_to":"ff82abbf_ebb0818e","updated":"2017-11-20 09:14:45.000000000","message":"Done","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9146b7449b99a70ba0b051d9f367988c2d7cbd4e","unresolved":false,"context_lines":[{"line_number":55,"context_line":"return only the metadata (and data in the case of GET) that is stored on the"},{"line_number":56,"context_line":"target object. A GET/HEAD request sent to the symlink with the ``?symlink\u003dget``"},{"line_number":57,"context_line":"query string will return only the metadata that is stored on the symlink object"},{"line_number":58,"context_line":"itself."},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"A POST request to a symlink will result in a 307 TemporaryRedirect response."},{"line_number":61,"context_line":"The response will contain a ``Location`` header with the path of the target"}],"source_content_type":"text/x-python","patch_set":71,"id":"ff82abbf_0ebe3ab3","line":58,"updated":"2017-11-29 12:42:55.000000000","message":"nits)\n\nHow about this?\n\n\u003e A HEAD/GET request to a symlink object behaves as a normal HEAD/GET request to the target object. Therefore issuing a HEAD request to the symlink will\nreturn the target metadata, and issuing a GET request to the symlink will return the data and metadata of the target object.\nOnly when a GET/HEAD request sent to a symlink object with the ``?symlink\u003dget``\nquery string will return the symlink metadata with empty body.","commit_id":"696e439e34ab4ff511fad58202a14ec9b9298703"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9146b7449b99a70ba0b051d9f367988c2d7cbd4e","unresolved":false,"context_lines":[{"line_number":190,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":191,"context_line":"            for key in meta:"},{"line_number":192,"context_line":"                if key \u003d\u003d \u0027symlink_path\u0027:"},{"line_number":193,"context_line":"                    obj_dict[key] \u003d meta[key]"},{"line_number":194,"context_line":"                else:"},{"line_number":195,"context_line":"                    # make sure to add all other (key, values) back in place"},{"line_number":196,"context_line":"                    obj_dict[\u0027hash\u0027] +\u003d \u0027; %s\u003d%s\u0027 % (key, meta[key])"}],"source_content_type":"text/x-python","patch_set":71,"id":"ff82abbf_6ed34605","line":193,"updated":"2017-11-29 12:42:55.000000000","message":"I suppose the values in the object listing are /account/container/object format right? Thinking of usability for clients, making it as the full path like /v1/account/container/object could be useful?\n\nThat is because, if we do it as above, users won\u0027t have to build the full path with version number from the result of object listing.","commit_id":"696e439e34ab4ff511fad58202a14ec9b9298703"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9146b7449b99a70ba0b051d9f367988c2d7cbd4e","unresolved":false,"context_lines":[{"line_number":217,"context_line":"        for key, val in self._response_headers:"},{"line_number":218,"context_line":"            if key.lower() !\u003d TGT_OBJ_SYSMETA_SYMLINK_HDR:"},{"line_number":219,"context_line":"                continue"},{"line_number":220,"context_line":"            # tgt_acct and tgt_cont_obj are quoted strings"},{"line_number":221,"context_line":"            tgt_acct, tgt_cont_obj \u003d split_path(val, 2, 2, True)"},{"line_number":222,"context_line":"            self._response_headers.extend([(\u0027X-Symlink-Target\u0027, tgt_cont_obj)])"},{"line_number":223,"context_line":"            # return value of req.split_path is unquoted"}],"source_content_type":"text/x-python","patch_set":71,"id":"ff82abbf_89f6c4d6","line":220,"updated":"2017-11-29 12:42:55.000000000","message":"Probably, it\u0027s not quoted, just a raw value from the client request.\nThis seems to work well. I\u0027ll try to cleanup around here but it should be ok in the separate patch imo.","commit_id":"696e439e34ab4ff511fad58202a14ec9b9298703"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9146b7449b99a70ba0b051d9f367988c2d7cbd4e","unresolved":false,"context_lines":[{"line_number":253,"context_line":"                body\u003derrmsg, request\u003dreq, content_type\u003d\u0027text/plain\u0027)("},{"line_number":254,"context_line":"                    req.environ, self._start_response)"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"    def _recursive_get_head(self, req, loop_count\u003d0, last_tgt_path\u003dNone):"},{"line_number":257,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        def build_traversal_req():"}],"source_content_type":"text/x-python","patch_set":71,"id":"ff82abbf_694100a9","line":256,"updated":"2017-11-29 12:42:55.000000000","message":"Agh, it looks too much changes here from patch set 65?\n\nOh... it\u0027s from Matt\u0027s comment on patch 69. Those recursive change was my work and I like previous one (i.e. keeping the variable as the instance variable for easy to read.","commit_id":"696e439e34ab4ff511fad58202a14ec9b9298703"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"89f58629f3495c37b9a8ed4279aa8fe978da037a","unresolved":false,"context_lines":[{"line_number":100,"context_line":"* POST with the header ``X-Symlink-Target`` will produce a"},{"line_number":101,"context_line":"  400 BadRequest error."},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dget`` traversing more than"},{"line_number":104,"context_line":"  ``symloop_max`` chained symlinks will produce a 409 Conflict error."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"* POSTs will produce a 307 TemporaryRedirect error."}],"source_content_type":"text/x-python","patch_set":72,"id":"df87a7cf_bfd5aebb","line":103,"range":{"start_line":103,"start_character":11,"end_line":103,"end_character":55},"updated":"2017-12-04 12:43:22.000000000","message":"nits) probably we don\u0027t have to say clearly \"without the param\" here because ?symlink\u003dget is the special case rather than normal GET request.","commit_id":"d1c9cee10fd7e8dd95d37aa4f6926eed2c3835c4"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"60d5d2f6e8eb7f46e67907427a8f65f601c93c4a","unresolved":false,"context_lines":[{"line_number":100,"context_line":"* POST with the header ``X-Symlink-Target`` will produce a"},{"line_number":101,"context_line":"  400 BadRequest error."},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"* GET/HEAD without the query parameter ``?symlink\u003dget`` traversing more than"},{"line_number":104,"context_line":"  ``symloop_max`` chained symlinks will produce a 409 Conflict error."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"* POSTs will produce a 307 TemporaryRedirect error."}],"source_content_type":"text/x-python","patch_set":72,"id":"df87a7cf_9e72f510","line":103,"range":{"start_line":103,"start_character":11,"end_line":103,"end_character":55},"in_reply_to":"df87a7cf_bfd5aebb","updated":"2017-12-06 10:02:18.000000000","message":"Done","commit_id":"d1c9cee10fd7e8dd95d37aa4f6926eed2c3835c4"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ae5435c858dce30faecef62989110448caf24c6c","unresolved":false,"context_lines":[{"line_number":96,"context_line":"Once you deployed symlink in your pipeline, you should neither remove the"},{"line_number":97,"context_line":"symlink middleware nor downgrade your swift version earlier than the symlink"},{"line_number":98,"context_line":"supported. Those operations will be able to show weird object listing result"},{"line_number":99,"context_line":"in adition to that the symlink object handled just a normal object."},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"Errors"},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_a6718746","line":99,"range":{"start_line":99,"start_character":3,"end_line":99,"end_character":10},"updated":"2017-12-11 02:50:11.000000000","message":"addition","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9e557e2b2b1c5be1058121d489dc2fe2b0ce4a89","unresolved":false,"context_lines":[{"line_number":132,"context_line":"# Header values for symlink target path strings will be quoted values."},{"line_number":133,"context_line":"TGT_OBJ_SYMLINK_HDR \u003d \u0027x-symlink-target\u0027"},{"line_number":134,"context_line":"TGT_ACCT_SYMLINK_HDR \u003d \u0027x-symlink-target-account\u0027"},{"line_number":135,"context_line":"TGT_OBJ_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027symlink-target\u0027"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"def _check_symlink_header(req):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_f2321b5e","line":135,"updated":"2017-12-07 23:42:46.000000000","message":"I hate this interface, I can ever remember if get_sys_meta_prefix returns the \u0027-\u0027 or not!\n\nWhy don\u0027t we have a function:\n\nget_sys_meta_header(\u003ctype\u003e, \u003cname\u003e)","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"5bb6580a56ecb9800fb3aae7f0ddecbb35ff4ced","unresolved":false,"context_lines":[{"line_number":132,"context_line":"# Header values for symlink target path strings will be quoted values."},{"line_number":133,"context_line":"TGT_OBJ_SYMLINK_HDR \u003d \u0027x-symlink-target\u0027"},{"line_number":134,"context_line":"TGT_ACCT_SYMLINK_HDR \u003d \u0027x-symlink-target-account\u0027"},{"line_number":135,"context_line":"TGT_OBJ_SYSMETA_SYMLINK_HDR \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027symlink-target\u0027"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"def _check_symlink_header(req):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_275d5546","line":135,"in_reply_to":"df87a7cf_f2321b5e","updated":"2017-12-12 05:21:02.000000000","message":"I agree with your opinion and the new function will be helpful.\nHowever, the \"get_sys_meta_prefix\" is used not only in symlink, hence the change for new function will leak to other implementations.\nTherefore, I think the change should be done in another patch.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9e557e2b2b1c5be1058121d489dc2fe2b0ce4a89","unresolved":false,"context_lines":[{"line_number":170,"context_line":"    _junk, req_acc, req_cont, req_obj \u003d req.split_path(4, 4, True)"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"    if not account:"},{"line_number":173,"context_line":"        account \u003d req_acc"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"    # Check if symlink targets the symlink itself or not"},{"line_number":176,"context_line":"    if (account, container, obj) \u003d\u003d (req_acc, req_cont, req_obj):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_9254ef22","line":173,"updated":"2017-12-07 23:42:46.000000000","message":"Is this *required* - it seems like just NOT setting an account could potentially be an \"unbound\" symlink (free?  accountless?) - wouldn\u0027t that make it simpler over in container sync?","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"16d9636cc5126685fead6ece32c0949d7488e446","unresolved":false,"context_lines":[{"line_number":170,"context_line":"    _junk, req_acc, req_cont, req_obj \u003d req.split_path(4, 4, True)"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"    if not account:"},{"line_number":173,"context_line":"        account \u003d req_acc"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"    # Check if symlink targets the symlink itself or not"},{"line_number":176,"context_line":"    if (account, container, obj) \u003d\u003d (req_acc, req_cont, req_obj):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_54db454e","line":173,"in_reply_to":"df87a7cf_9254ef22","updated":"2017-12-13 08:10:37.000000000","message":"This is for the check below to assert if the symlink-target points to itself.\n\nIt can be re-write as:\n\nif (account and (account, container, obj) \u003d\u003d (req_acc, req_cont, req_obj)) ¥\n    or (not account and (container, obj) \u003d\u003d (req_cont, req_obj)):\n   raise HTTPBadRequest(...)\n\nAnyway, it\u0027s far from container-sync issue, imo.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e1668f32aec21e43295255f85df2a6b58cc1032f","unresolved":false,"context_lines":[{"line_number":182,"context_line":"class SymlinkContainerContext(WSGIContext):"},{"line_number":183,"context_line":"    def __init__(self, wsgi_app, logger):"},{"line_number":184,"context_line":"        super(SymlinkContainerContext, self).__init__(wsgi_app)"},{"line_number":185,"context_line":"        self.app \u003d wsgi_app"},{"line_number":186,"context_line":"        self.logger \u003d logger"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    def handle_container(self, req, start_response):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_25623bd9","line":185,"range":{"start_line":185,"start_character":8,"end_line":185,"end_character":27},"updated":"2017-12-13 10:33:20.000000000","message":"nit: the superclass __init__ sets this","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":182,"context_line":"class SymlinkContainerContext(WSGIContext):"},{"line_number":183,"context_line":"    def __init__(self, wsgi_app, logger):"},{"line_number":184,"context_line":"        super(SymlinkContainerContext, self).__init__(wsgi_app)"},{"line_number":185,"context_line":"        self.app \u003d wsgi_app"},{"line_number":186,"context_line":"        self.logger \u003d logger"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    def handle_container(self, req, start_response):"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_12c61618","line":185,"range":{"start_line":185,"start_character":8,"end_line":185,"end_character":27},"in_reply_to":"df87a7cf_25623bd9","updated":"2017-12-14 01:13:05.000000000","message":"good call. done at follow up.\n\nAnd I think we should walk through all middlewares for this. at least, copy middleware is doing same mistake. anyway, follow up is ok.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b1bea3ad8fa4c375f316d52737635aa374c6b637","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                 is a symlink. The new key is symlink_path."},{"line_number":221,"context_line":"        \"\"\""},{"line_number":222,"context_line":"        if \u0027hash\u0027 in obj_dict:"},{"line_number":223,"context_line":"            hash_value, meta \u003d parse_header(obj_dict[\u0027hash\u0027])"},{"line_number":224,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":225,"context_line":"            for key in meta:"},{"line_number":226,"context_line":"                if key \u003d\u003d \u0027symlink_path\u0027:"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_54b2974a","line":223,"range":{"start_line":223,"start_character":31,"end_line":223,"end_character":43},"updated":"2017-12-11 16:08:53.000000000","message":"we ought to be able to re-use or extract some common code w.r.t. parse_content_type [1]\n\nHowever, [1] preserves quotes around values whereas parse_header does not - and RFC iplies quotes should be preserved in a content_type at least [2]\n\n[1] https://github.com/openstack/swift/blob/93e0287a827c0025c1522517b0e288ec04f12326/swift/common/utils.py#L3759-L3759\n[2] RFC2616 section 3.7 and quoted-string definition","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"16d9636cc5126685fead6ece32c0949d7488e446","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                 is a symlink. The new key is symlink_path."},{"line_number":221,"context_line":"        \"\"\""},{"line_number":222,"context_line":"        if \u0027hash\u0027 in obj_dict:"},{"line_number":223,"context_line":"            hash_value, meta \u003d parse_header(obj_dict[\u0027hash\u0027])"},{"line_number":224,"context_line":"            obj_dict[\u0027hash\u0027] \u003d hash_value"},{"line_number":225,"context_line":"            for key in meta:"},{"line_number":226,"context_line":"                if key \u003d\u003d \u0027symlink_path\u0027:"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_3920fab0","line":223,"range":{"start_line":223,"start_character":31,"end_line":223,"end_character":43},"in_reply_to":"df87a7cf_54b2974a","updated":"2017-12-13 08:10:37.000000000","message":"It would be possible to generalize the code to parse semi-colon based parsable string. I checked the RFC and it seems true reading the section 3.7.\n\nOn the other hand, swift.common.middleware.crypt_utils also uses cgi.parse_header to parse the object_listing result so AFAIK no other staffs using the hash space like as content-type and the users all are depending non quoted-string. Therefore current implementation is SAFE for now.\n\nExactly, we should consider about the format and parse but I\u0027d like to make it later because it affects also encryption staff cleanup.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6d85989c945dd07cad74207eca6a66944a7be62d","unresolved":false,"context_lines":[{"line_number":230,"context_line":"                        \u0027/\u0027, _swift_version, meta[key].lstrip(\u0027/\u0027))"},{"line_number":231,"context_line":"                else:"},{"line_number":232,"context_line":"                    # make sure to add all other (key, values) back in place"},{"line_number":233,"context_line":"                    obj_dict[\u0027hash\u0027] +\u003d \u0027; %s\u003d%s\u0027 % (key, meta[key])"},{"line_number":234,"context_line":"        return obj_dict"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":""}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_55495a2e","line":233,"updated":"2017-12-08 20:25:30.000000000","message":"so one side effect of this implementation shows up if you remove the middleware after creating a symlink...\n\n    ubuntu@saio:~$ curl -s \"http://saio:8090/v1/AUTH_test/test?format\u003djson\" | python -m json.tool\n    [\n        {\n            \"bytes\": 0,\n            \"content_type\": \"text/x-python\",\n            \"hash\": \"d41d8cd98f00b204e9800998ecf8427e; symlink_path\u003d/AUTH_test/test/pete_test.py\",\n            \"last_modified\": \"2017-12-08T19:21:06.736390\",\n            \"name\": \"magic\"\n        },\n        {\n            \"bytes\": 1172,\n            \"content_type\": \"text/x-python\",\n            \"hash\": \"74b7050a8ede8b8a3a68e7657e4afddb\",\n            \"last_modified\": \"2017-12-08T19:19:20.423360\",\n            \"name\": \"pete_test.py\"\n        }\n    ]","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ae5435c858dce30faecef62989110448caf24c6c","unresolved":false,"context_lines":[{"line_number":230,"context_line":"                        \u0027/\u0027, _swift_version, meta[key].lstrip(\u0027/\u0027))"},{"line_number":231,"context_line":"                else:"},{"line_number":232,"context_line":"                    # make sure to add all other (key, values) back in place"},{"line_number":233,"context_line":"                    obj_dict[\u0027hash\u0027] +\u003d \u0027; %s\u003d%s\u0027 % (key, meta[key])"},{"line_number":234,"context_line":"        return obj_dict"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":""}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_060dd38e","line":233,"in_reply_to":"df87a7cf_55495a2e","updated":"2017-12-11 02:50:11.000000000","message":"My brother, that\u0027s actually what I concerned about in my first look of this patch. However, I could not find better solution rather than using the hash space of container entry.\n\nThe reason we need the space is to save the symlink as persistent. I had thought we could have a couple of ways A) add new column  B) use content_type but neither is fine that requires more side-effect and code change. on the idea A, it obviously requires migration cost from current db to the new one and it leaks a lot of changes outside of symlinks. on the idea B,  the content_type is NOT immutable so that users can change (or can even remove) the path in the content-type via another POST request. To simplify, we had the design decision, we can POST any metadata (except X-Symlink-Target) to symlink  and just return 307 TemporaryRedirect, i.e. the content_type can be overwritten under the semantics. Hence, the hash is the only place we can keep the path info as persistent. Fortunately encryption uses it as similar way that means we can maintains as well.\n\nFrom the reason, I added the note at https://review.openstack.org/#/c/232162/75/swift/common/middleware/symlink.py@95.\n\nPerhaps, we could improve to remove the latter from semicolons at.... the gatekeeper? I\u0027m not sure if it would be overkill or not.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e1668f32aec21e43295255f85df2a6b58cc1032f","unresolved":false,"context_lines":[{"line_number":238,"context_line":""},{"line_number":239,"context_line":"    def __init__(self, wsgi_app, logger, symloop_max):"},{"line_number":240,"context_line":"        super(SymlinkObjectContext, self).__init__(wsgi_app)"},{"line_number":241,"context_line":"        self.app \u003d wsgi_app"},{"line_number":242,"context_line":"        self.symloop_max \u003d symloop_max"},{"line_number":243,"context_line":"        self.logger \u003d logger"},{"line_number":244,"context_line":"        # N.B. _loop_count and _last_target_path are used to keep"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_c5710faa","line":241,"range":{"start_line":241,"start_character":8,"end_line":241,"end_character":27},"updated":"2017-12-13 10:33:20.000000000","message":"nit: the superclass __init__ sets this","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":238,"context_line":""},{"line_number":239,"context_line":"    def __init__(self, wsgi_app, logger, symloop_max):"},{"line_number":240,"context_line":"        super(SymlinkObjectContext, self).__init__(wsgi_app)"},{"line_number":241,"context_line":"        self.app \u003d wsgi_app"},{"line_number":242,"context_line":"        self.symloop_max \u003d symloop_max"},{"line_number":243,"context_line":"        self.logger \u003d logger"},{"line_number":244,"context_line":"        # N.B. _loop_count and _last_target_path are used to keep"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_b2516a65","line":241,"range":{"start_line":241,"start_character":8,"end_line":241,"end_character":27},"in_reply_to":"df87a7cf_c5710faa","updated":"2017-12-14 01:13:05.000000000","message":"ditto","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6d85989c945dd07cad74207eca6a66944a7be62d","unresolved":false,"context_lines":[{"line_number":439,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":440,"context_line":"            errmsg \u003d \u0027The requested POST was applied to a symlink. POST \u0027 +\\"},{"line_number":441,"context_line":"                     \u0027directly to the target to apply requested metadata.\u0027"},{"line_number":442,"context_line":"            raise HTTPTemporaryRedirect("},{"line_number":443,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})"},{"line_number":444,"context_line":"        else:"},{"line_number":445,"context_line":"            return resp"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_d5956a34","line":442,"updated":"2017-12-08 20:25:30.000000000","message":"a comment on the relevant RFC section to justify this status code would be *amazingly* useful addition\n\nhttps://tools.ietf.org/html/rfc7231#section-6.4.7 maybe?\n\nOMG requests is magic!?\n\n    ubuntu@saio:~$ swift list test --lh\n       0 2017-12-08 19:51:19            text/x-python magic\n    1.1K 2017-12-08 19:19:20            text/x-python pete_test.py\n    1.1K\n    ubuntu@saio:~$ swift post test magic -H \u0027content-type: text/plain\u0027\n    ubuntu@saio:~$ swift list test --lh\n       0 2017-12-08 19:57:12               text/plain magic\n    1.1K 2017-12-08 19:57:12               text/plain pete_test.py\n    1.1K\n\nYup...\n\n    DEBUG:swiftclient:REQ: curl -i http://saio:8080/v1/AUTH_test/test/magic -X POST -H \"Content-Type: text/x-python\" -H \"X-Auth-Token: AUTH_tk3e6082e2648f490987d8f2feb39f9b94\"\n    DEBUG:swiftclient:RESP STATUS: 202 Accepted\n\n^ requests *magic*\n\n    ubuntu@saio:~$ curl -i http://saio:8080/v1/AUTH_test/test/magic -X POST -H \"Content-Type: text/plain\" -H \"X-Auth-Token: AUTH_tk3e6082e2648f490987d8f2feb39f9b94\"\n    HTTP/1.1 307 Temporary Redirect\n\n^ reality!\n\nhard to argue with success...","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ae5435c858dce30faecef62989110448caf24c6c","unresolved":false,"context_lines":[{"line_number":439,"context_line":"            req.environ[\u0027swift.leave_relative_location\u0027] \u003d True"},{"line_number":440,"context_line":"            errmsg \u003d \u0027The requested POST was applied to a symlink. POST \u0027 +\\"},{"line_number":441,"context_line":"                     \u0027directly to the target to apply requested metadata.\u0027"},{"line_number":442,"context_line":"            raise HTTPTemporaryRedirect("},{"line_number":443,"context_line":"                body\u003derrmsg, headers\u003d{\u0027location\u0027: location_hdr})"},{"line_number":444,"context_line":"        else:"},{"line_number":445,"context_line":"            return resp"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_0682b3c8","line":442,"in_reply_to":"df87a7cf_d5956a34","updated":"2017-12-11 02:50:11.000000000","message":"Yup, exactly, we should add the section.\n\nOn the swift client, hmm... we could fix the auto-redirection behavior in the swift-client because the rfc says as \"The user agent MAY use the Location field value for automatic redirection.\" so it\u0027s client problem imo.","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6d85989c945dd07cad74207eca6a66944a7be62d","unresolved":false,"context_lines":[{"line_number":452,"context_line":"            # if GET request came from versioned writes, then it should get"},{"line_number":453,"context_line":"            # the symlink only, not the referenced target"},{"line_number":454,"context_line":"            if req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":455,"context_line":"                    req.environ.get(\u0027swift.source\u0027) \u003d\u003d \u0027VW\u0027:"},{"line_number":456,"context_line":"                resp \u003d self.handle_get_head_symlink(req)"},{"line_number":457,"context_line":"            else:"},{"line_number":458,"context_line":"                resp \u003d self.handle_get_head(req)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_357ff615","line":455,"updated":"2017-12-08 20:25:30.000000000","message":"ouch... seems a little coupled","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"16d9636cc5126685fead6ece32c0949d7488e446","unresolved":false,"context_lines":[{"line_number":337,"context_line":"                TGT_ACCT_SYSMETA_SYMLINK_HDR) or account"},{"line_number":338,"context_line":"            target_path \u003d os.path.join("},{"line_number":339,"context_line":"                \u0027/\u0027, version, account,"},{"line_number":340,"context_line":"                symlink_target.lstrip(\u0027/\u0027))"},{"line_number":341,"context_line":"            self._last_target_path \u003d target_path"},{"line_number":342,"context_line":"            new_req \u003d make_subrequest("},{"line_number":343,"context_line":"                req.environ, path\u003dtarget_path, method\u003dreq.method,"}],"source_content_type":"text/x-python","patch_set":78,"id":"df87a7cf_b42e51f8","line":340,"range":{"start_line":340,"start_character":31,"end_line":340,"end_character":42},"updated":"2017-12-13 08:10:37.000000000","message":"Perhaps, we don\u0027t have to call lstrip anymore because current impl asserts the symlink format as \"\u003ccontainer\u003e/\u003cobject\u003e\". The leading slash will result in an error on PUT symlink.","commit_id":"05fe5f2775e2085219ead5fc912187de1c9d0f2b"}],"swift/common/middleware/tempurl.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"89f58629f3495c37b9a8ed4279aa8fe978da037a","unresolved":false,"context_lines":[{"line_number":222,"context_line":"    register_swift_info, get_hmac, streq_const_time, quote"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":""},{"line_number":225,"context_line":"DISALLOWED_INCOMING_HEADERS \u003d \u0027x-object-manifest x-symlink-target\u0027"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"#: Default headers to remove from incoming requests. Simply a whitespace"},{"line_number":228,"context_line":"#: delimited list of header names and names can optionally end with \u0027*\u0027 to"}],"source_content_type":"text/x-python","patch_set":72,"id":"df87a7cf_3ffafe41","line":225,"range":{"start_line":225,"start_character":49,"end_line":225,"end_character":65},"updated":"2017-12-04 12:43:22.000000000","message":"OK, FWIW, func tests asserted this one. I suppose this is from similar reason to dlo (maybe security issue) and that makes us safe strongly. If we want to mitigate the constraint, we can discuss later.","commit_id":"d1c9cee10fd7e8dd95d37aa4f6926eed2c3835c4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6d85989c945dd07cad74207eca6a66944a7be62d","unresolved":false,"context_lines":[{"line_number":222,"context_line":"    register_swift_info, get_hmac, streq_const_time, quote"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":""},{"line_number":225,"context_line":"DISALLOWED_INCOMING_HEADERS \u003d \u0027x-object-manifest x-symlink-target\u0027"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"#: Default headers to remove from incoming requests. Simply a whitespace"},{"line_number":228,"context_line":"#: delimited list of header names and names can optionally end with \u0027*\u0027 to"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_d566cac1","line":225,"updated":"2017-12-08 20:25:30.000000000","message":"x-symlink-target-account ???\n\nDoesn\u0027t seem needed...","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"swift/common/request_helpers.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4e654f3cf222295ad9425672c78cc50d3f485ff6","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    :raise: HTTPPreconditionFailed if header value"},{"line_number":297,"context_line":"            is not well formatted."},{"line_number":298,"context_line":"    \"\"\""},{"line_number":299,"context_line":"    src_header \u003d unquote(req.headers.get(name))"},{"line_number":300,"context_line":"    if not src_header.startswith(\u0027/\u0027):"},{"line_number":301,"context_line":"        src_header \u003d \u0027/\u0027 + src_header"},{"line_number":302,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_8c6b44ef","line":299,"range":{"start_line":299,"start_character":4,"end_line":299,"end_character":7},"updated":"2017-10-03 11:08:39.000000000","message":"this is not src because it\u0027s already generalized so that something like \"path_header\" seems correct.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"6d91d5b6b19a15320c0b2bb519f9db77bea46582","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    :raise: HTTPPreconditionFailed if header value"},{"line_number":297,"context_line":"            is not well formatted."},{"line_number":298,"context_line":"    \"\"\""},{"line_number":299,"context_line":"    src_header \u003d unquote(req.headers.get(name))"},{"line_number":300,"context_line":"    if not src_header.startswith(\u0027/\u0027):"},{"line_number":301,"context_line":"        src_header \u003d \u0027/\u0027 + src_header"},{"line_number":302,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":59,"id":"5f4e5783_d2ec9590","line":299,"range":{"start_line":299,"start_character":4,"end_line":299,"end_character":7},"in_reply_to":"7f515b1d_8c6b44ef","updated":"2017-10-13 20:49:00.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"}],"swift/common/wsgi.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"22a481da519b1d491d4f7c4ddc6e4e856b85ed73","unresolved":false,"context_lines":[{"line_number":1116,"context_line":"                 \u0027swift.trans_id\u0027, \u0027swift.authorize_override\u0027,"},{"line_number":1117,"context_line":"                 \u0027swift.authorize\u0027, \u0027HTTP_X_USER_ID\u0027, \u0027HTTP_X_PROJECT_ID\u0027,"},{"line_number":1118,"context_line":"                 \u0027HTTP_REFERER\u0027, \u0027swift.orig_req_method\u0027, \u0027swift.log_info\u0027,"},{"line_number":1119,"context_line":"                 \u0027swift.infocache\u0027, \u0027swift.post_as_copy\u0027):"},{"line_number":1120,"context_line":"        if name in env:"},{"line_number":1121,"context_line":"            newenv[name] \u003d env[name]"},{"line_number":1122,"context_line":"    if method:"}],"source_content_type":"text/x-python","patch_set":43,"id":"1a6eadb0_cce6ae14","line":1119,"updated":"2016-12-17 00:31:46.000000000","message":"This is probably a good idea, but what prompted it? Will it have other implications for middlewares typically after copy? Say, versioned_writes?","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"87c2dd037edc7c05d5ee9a7f8b42f21b3017016c","unresolved":false,"context_lines":[{"line_number":1116,"context_line":"                 \u0027swift.trans_id\u0027, \u0027swift.authorize_override\u0027,"},{"line_number":1117,"context_line":"                 \u0027swift.authorize\u0027, \u0027HTTP_X_USER_ID\u0027, \u0027HTTP_X_PROJECT_ID\u0027,"},{"line_number":1118,"context_line":"                 \u0027HTTP_REFERER\u0027, \u0027swift.orig_req_method\u0027, \u0027swift.log_info\u0027,"},{"line_number":1119,"context_line":"                 \u0027swift.infocache\u0027, \u0027swift.post_as_copy\u0027):"},{"line_number":1120,"context_line":"        if name in env:"},{"line_number":1121,"context_line":"            newenv[name] \u003d env[name]"},{"line_number":1122,"context_line":"    if method:"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_983d20be","line":1119,"in_reply_to":"1a6eadb0_cce6ae14","updated":"2017-01-09 20:13:28.000000000","message":"removed it.","commit_id":"28726b714951a35da6e456a8ebbda4fc7764ef27"}],"swift/container/sync.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"24b5f8c74d67ef2f7cb09d76fc76d198dc72a1e0","unresolved":false,"context_lines":[{"line_number":73,"context_line":"# log_statsd_metric_prefix \u003d"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"[pipeline:main]"},{"line_number":76,"context_line":"pipeline \u003d catch_errors proxy-logging cache symlink proxy-server"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"[app:proxy-server]"},{"line_number":79,"context_line":"use \u003d egg:swift#proxy"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_8e1d2611","line":76,"range":{"start_line":76,"start_character":43,"end_line":76,"end_character":51},"updated":"2017-10-05 09:04:37.000000000","message":"I didn\u0027t get why we need symlink middleware should be in the internal client pipeline specially. I thought the container-sync could requires to copy the symlink itself to another cluster. However, it\u0027s same context with SLO manifest ins\u0027t it?","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"7440ba66bf548d625bb886728a53ac5eaad263cf","unresolved":false,"context_lines":[{"line_number":73,"context_line":"# log_statsd_metric_prefix \u003d"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"[pipeline:main]"},{"line_number":76,"context_line":"pipeline \u003d catch_errors proxy-logging cache symlink proxy-server"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"[app:proxy-server]"},{"line_number":79,"context_line":"use \u003d egg:swift#proxy"}],"source_content_type":"text/x-python","patch_set":59,"id":"7f515b1d_b15f22e4","line":76,"range":{"start_line":76,"start_character":43,"end_line":76,"end_character":51},"in_reply_to":"7f515b1d_8e1d2611","updated":"2017-10-05 11:25:05.000000000","message":"The reason why I added this is because I want to convert X-Object-Sysmeta-Symlink-Target into X-Symlink-Target and X-Symlnk-Target-Account.\n\nThe context difference between SLO and Symlink is special header. (i.e. X-Static-Large-Object and X-Object-Sysmeta-Symlink-Target)\n\nIn SLO context, container-sync daemon will GET slo manifest (\u003dsource object) with X-Static-Large-Object header and PUT it to another swift cluster without any conversion. Then, the other swift cluster receive the manifest. In normal PUT case, objects with X-Static-Large-Object will be rejected by slo middleware. But in this Container-Sync case, container_sync middleware will set req.environ[swift.slo.override] \u003d True and slo middleware skip handling.\n\nHowever, In symlink context, we cannot use same method, because gatekeeper middleware will reject PUT request without conversion because X-Object-Sysmeta-Symlnk-Target is sysmeta header. Therefore, container-sync need to convert Object-Sysmeta-Symlink-Target into X-Symlink-Target and X-Symlnk-Target-Account.\n\nBut I changed my mind in discussion with kota. Using symlink middleware only to convert header is not simple. I will make a converting function which is shared with symlink middleware, and use the function.","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"db12b6bda65fa9bd71c9aaacc9c117cd09832752","unresolved":false,"context_lines":[{"line_number":73,"context_line":"# log_statsd_metric_prefix \u003d"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"[pipeline:main]"},{"line_number":76,"context_line":"pipeline \u003d catch_errors proxy-logging cache symlink proxy-server"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"[app:proxy-server]"},{"line_number":79,"context_line":"use \u003d egg:swift#proxy"}],"source_content_type":"text/x-python","patch_set":59,"id":"3f4b6375_7f069322","line":76,"range":{"start_line":76,"start_character":43,"end_line":76,"end_character":51},"in_reply_to":"7f515b1d_b15f22e4","updated":"2017-10-25 17:10:40.000000000","message":"Done","commit_id":"824764691cc8ad72e86d33f155832f930d3d0d70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b1bea3ad8fa4c375f316d52737635aa374c6b637","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                if \u0027content-type\u0027 in headers:"},{"line_number":604,"context_line":"                    headers[\u0027content-type\u0027] \u003d clean_content_type("},{"line_number":605,"context_line":"                        headers[\u0027content-type\u0027])"},{"line_number":606,"context_line":"                if TGT_OBJ_SYSMETA_SYMLINK_HDR in headers:"},{"line_number":607,"context_line":"                    tgt_acct, tgt_cont_obj \u003d split_path("},{"line_number":608,"context_line":"                        headers[TGT_OBJ_SYSMETA_SYMLINK_HDR], 2, 2, True)"},{"line_number":609,"context_line":"                    del headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"},{"line_number":610,"context_line":""},{"line_number":611,"context_line":"                    # We should send both X-Symlink-Target and"},{"line_number":612,"context_line":"                    # X-Symlink-Target-Account to the remote container"},{"line_number":613,"context_line":"                    # basically. Only when X-Symlink-Target-Account equals to"},{"line_number":614,"context_line":"                    # the account of this local container, drop the"},{"line_number":615,"context_line":"                    # X-Symlink-Target-Account info expecting the remote"},{"line_number":616,"context_line":"                    # cluster can apply the account info."},{"line_number":617,"context_line":"                    # This may be useful when the symlink object pointed to an"},{"line_number":618,"context_line":"                    # object in a container in the account, and the local"},{"line_number":619,"context_line":"                    # account name is different with the remote cluster."},{"line_number":620,"context_line":"                    #"},{"line_number":621,"context_line":"                    # e.g. Syncing the \"AUTH_acc1\"\u0027s local \"cont\" container to"},{"line_number":622,"context_line":"                    #      the remote \"cont\" container of the \"AUTH_acc2\"."},{"line_number":623,"context_line":"                    # Local:                      Remote:"},{"line_number":624,"context_line":"                    #    AUTH_acc1/cont/obj           AUTH_acc2/cont/obj"},{"line_number":625,"context_line":"                    #            ^                            ^"},{"line_number":626,"context_line":"                    #            |                            |"},{"line_number":627,"context_line":"                    #    AUTH_acc1/cont/symlink       AUTH_acc2/cont/symlink"},{"line_number":628,"context_line":"                    #"},{"line_number":629,"context_line":"                    headers[\u0027X-Symlink-Target\u0027] \u003d tgt_cont_obj"},{"line_number":630,"context_line":"                    if tgt_acct !\u003d quote(info[\u0027account\u0027]):"},{"line_number":631,"context_line":"                        headers[\u0027X-Symlink-Target-Account\u0027] \u003d tgt_acct"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"                self._update_sync_to_headers(row[\u0027name\u0027], sync_to, user_key,"},{"line_number":634,"context_line":"                                             realm, realm_key, \u0027PUT\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_96da6775","line":631,"range":{"start_line":606,"start_character":16,"end_line":631,"end_character":70},"updated":"2017-12-11 16:08:53.000000000","message":"I would prefer this behaviour to not be leaking into the container sync daemon. TGT_OBJ_SYSMETA_SYMLINK_HDR and the structure of its value is an internal implementation detail of symlinks, and these lines duplicate behaviour already implemented in the symlink middleware.\n\nIMHO it would be preferable to require symlink middleware to be added to the container sync internal client pipeline just as we do for encryption middlewares. Although this requires an additional config step when deploying symlinks, it avoids leaking implementation between modules.\n\nI\u0027ll propose a follow-on patch [1]. It looks like an earlier patchset (57) already behaved this way based on [2].\n\n[1] https://review.openstack.org/527126\n[1] https://review.openstack.org/#/c/421669/14","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"b3fce795cd4e67f31f2b2480b161c2862bcfc839","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                if \u0027content-type\u0027 in headers:"},{"line_number":604,"context_line":"                    headers[\u0027content-type\u0027] \u003d clean_content_type("},{"line_number":605,"context_line":"                        headers[\u0027content-type\u0027])"},{"line_number":606,"context_line":"                if TGT_OBJ_SYSMETA_SYMLINK_HDR in headers:"},{"line_number":607,"context_line":"                    tgt_acct, tgt_cont_obj \u003d split_path("},{"line_number":608,"context_line":"                        headers[TGT_OBJ_SYSMETA_SYMLINK_HDR], 2, 2, True)"},{"line_number":609,"context_line":"                    del headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]"},{"line_number":610,"context_line":""},{"line_number":611,"context_line":"                    # We should send both X-Symlink-Target and"},{"line_number":612,"context_line":"                    # X-Symlink-Target-Account to the remote container"},{"line_number":613,"context_line":"                    # basically. Only when X-Symlink-Target-Account equals to"},{"line_number":614,"context_line":"                    # the account of this local container, drop the"},{"line_number":615,"context_line":"                    # X-Symlink-Target-Account info expecting the remote"},{"line_number":616,"context_line":"                    # cluster can apply the account info."},{"line_number":617,"context_line":"                    # This may be useful when the symlink object pointed to an"},{"line_number":618,"context_line":"                    # object in a container in the account, and the local"},{"line_number":619,"context_line":"                    # account name is different with the remote cluster."},{"line_number":620,"context_line":"                    #"},{"line_number":621,"context_line":"                    # e.g. Syncing the \"AUTH_acc1\"\u0027s local \"cont\" container to"},{"line_number":622,"context_line":"                    #      the remote \"cont\" container of the \"AUTH_acc2\"."},{"line_number":623,"context_line":"                    # Local:                      Remote:"},{"line_number":624,"context_line":"                    #    AUTH_acc1/cont/obj           AUTH_acc2/cont/obj"},{"line_number":625,"context_line":"                    #            ^                            ^"},{"line_number":626,"context_line":"                    #            |                            |"},{"line_number":627,"context_line":"                    #    AUTH_acc1/cont/symlink       AUTH_acc2/cont/symlink"},{"line_number":628,"context_line":"                    #"},{"line_number":629,"context_line":"                    headers[\u0027X-Symlink-Target\u0027] \u003d tgt_cont_obj"},{"line_number":630,"context_line":"                    if tgt_acct !\u003d quote(info[\u0027account\u0027]):"},{"line_number":631,"context_line":"                        headers[\u0027X-Symlink-Target-Account\u0027] \u003d tgt_acct"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"                self._update_sync_to_headers(row[\u0027name\u0027], sync_to, user_key,"},{"line_number":634,"context_line":"                                             realm, realm_key, \u0027PUT\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_e7df6d63","line":631,"range":{"start_line":606,"start_character":16,"end_line":631,"end_character":70},"in_reply_to":"df87a7cf_96da6775","updated":"2017-12-12 01:54:43.000000000","message":"Could you check https://review.openstack.org/#/c/526615 too?\n\nThat\u0027s what I was trying to avoid code leaking from symlink. I thought the additional step adding symlink in the internal client pipeline could be troubled for operators when looking at patch 421669 solution that is not documented the step.\n\nFor now, you added great deployment doc string so my concern was resolved with that... I\u0027m not sure which is suitable...","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"swift/obj/server.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cabd029d30f7f182030183cc2a7eee160f6be447","unresolved":false,"context_lines":[{"line_number":612,"context_line":"            \u0027PUT\u0027, account, container, obj, request, update_headers,"},{"line_number":613,"context_line":"            device, policy)"},{"line_number":614,"context_line":""},{"line_number":615,"context_line":"        # check if object is symlink, if so, add headers to response"},{"line_number":616,"context_line":"        # this is the only knowledge the object server has about symlinks"},{"line_number":617,"context_line":"        # the symlinks proxy middleware checks for these headers on a POST"},{"line_number":618,"context_line":"        # response and returns an error to the client."}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_5fc60f17","line":615,"updated":"2016-07-22 19:35:18.000000000","message":"Should we make this symlink-agnostic and just return *all* sysmeta headers? This may enable other interesting third-party middleware.","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"8c27b322dbe0a9e68241f445423319d6a8a1441c","unresolved":false,"context_lines":[{"line_number":612,"context_line":"            \u0027PUT\u0027, account, container, obj, request, update_headers,"},{"line_number":613,"context_line":"            device, policy)"},{"line_number":614,"context_line":""},{"line_number":615,"context_line":"        # check if object is symlink, if so, add headers to response"},{"line_number":616,"context_line":"        # this is the only knowledge the object server has about symlinks"},{"line_number":617,"context_line":"        # the symlinks proxy middleware checks for these headers on a POST"},{"line_number":618,"context_line":"        # response and returns an error to the client."}],"source_content_type":"text/x-python","patch_set":31,"id":"dada55a8_35c30559","line":615,"in_reply_to":"dada55a8_5fc60f17","updated":"2016-07-27 16:27:16.000000000","message":"Done","commit_id":"1cd47fe2bddce0120c7dd79fc386f7ceeb636899"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4ef2d5b7048c101418cae75242e4e4593bc26b7a","unresolved":false,"context_lines":[{"line_number":627,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":628,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":629,"context_line":"                    is_object_transient_sysmeta(key) or"},{"line_number":630,"context_line":"                    key.lower() in self.allowed_headers):"},{"line_number":631,"context_line":"                resp_headers[key] \u003d value"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_dd3a07cd","line":630,"range":{"start_line":630,"start_character":40,"end_line":630,"end_character":55},"updated":"2016-08-08 20:56:47.000000000","message":"This can change the semantics of the response, by adding things like Content-Disposition or Content-Encoding. I think we can only do this for headers we *know* have no HTTP meaning (like sysmeta, transient-sysmeta, and user meta).\n\nSpeaking of: should we include user meta?","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"cf9216d4458a37953335df52c819ddc59150236e","unresolved":false,"context_lines":[{"line_number":627,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":628,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":629,"context_line":"                    is_object_transient_sysmeta(key) or"},{"line_number":630,"context_line":"                    key.lower() in self.allowed_headers):"},{"line_number":631,"context_line":"                resp_headers[key] \u003d value"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"}],"source_content_type":"text/x-python","patch_set":34,"id":"fa7ab95a_031e885e","line":630,"range":{"start_line":630,"start_character":40,"end_line":630,"end_character":55},"in_reply_to":"1ac06dbe_4d3af6e8","updated":"2016-08-29 19:21:30.000000000","message":"I guess the reason I didn\u0027t include the user metadata initially is because I wasn\u0027t sure how correct it would be to return that to users for a POST/PUT request.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b0298db24bc441920e01510cbe865f58324503db","unresolved":false,"context_lines":[{"line_number":627,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":628,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":629,"context_line":"                    is_object_transient_sysmeta(key) or"},{"line_number":630,"context_line":"                    key.lower() in self.allowed_headers):"},{"line_number":631,"context_line":"                resp_headers[key] \u003d value"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1ac06dbe_4d3af6e8","line":630,"range":{"start_line":630,"start_character":40,"end_line":630,"end_character":55},"in_reply_to":"9ad45d7e_53e970e5","updated":"2016-08-24 19:07:18.000000000","message":"FWIW, the reason I included it in https://review.openstack.org/#/c/357559 was that it seemed awkward to include transient sysmeta but not user meta (since the only ocassion we have to include transient sysmeta currently is to encrypt user meta). And I wanted the transient sysmeta for https://review.openstack.org/#/c/348603","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"08ff1b642d153bc149d1f3dad72a58f90072c65e","unresolved":false,"context_lines":[{"line_number":627,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":628,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":629,"context_line":"                    is_object_transient_sysmeta(key) or"},{"line_number":630,"context_line":"                    key.lower() in self.allowed_headers):"},{"line_number":631,"context_line":"                resp_headers[key] \u003d value"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"}],"source_content_type":"text/x-python","patch_set":34,"id":"9ad45d7e_53e970e5","line":630,"range":{"start_line":630,"start_character":40,"end_line":630,"end_character":55},"in_reply_to":"9ad45d7e_dd3a07cd","updated":"2016-08-24 15:15:56.000000000","message":"changing to remove allowed_headers, for now I can\u0027t come up with a reason why user meta should be included.","commit_id":"63b522724321eacc316b72b7fa2d30c158210691"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"df0ebf3ad555432bef0fa82f4f88730cd80edc79","unresolved":false,"context_lines":[{"line_number":625,"context_line":"        # add sysmeta and transient-meta to response"},{"line_number":626,"context_line":"        # these headers might be used by proxy middlewares"},{"line_number":627,"context_line":"        # e.g., symlink middleware"},{"line_number":628,"context_line":"        resp_headers \u003d {}"},{"line_number":629,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":630,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":631,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":632,"context_line":"                resp_headers[key] \u003d value"},{"line_number":633,"context_line":""},{"line_number":634,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"},{"line_number":635,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_5f34b948","line":632,"range":{"start_line":628,"start_character":0,"end_line":632,"end_character":41},"updated":"2016-09-08 10:39:29.000000000","message":"This is probably breaking the following unit test:\n\n\ntest_POST_update_meta (test.unit.obj.test_server.TestObjectController)\n\n\nAs the unit test is directly testing object controller (no gatekeeper for filtering).","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":8542,"name":"Prashanth Pai","email":"ppai@redhat.com","username":"pai"},"change_message_id":"58cdf60acad7654b4e6486a0ce3cfd9f965126dd","unresolved":false,"context_lines":[{"line_number":625,"context_line":"        # add sysmeta and transient-meta to response"},{"line_number":626,"context_line":"        # these headers might be used by proxy middlewares"},{"line_number":627,"context_line":"        # e.g., symlink middleware"},{"line_number":628,"context_line":"        resp_headers \u003d {}"},{"line_number":629,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":630,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":631,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":632,"context_line":"                resp_headers[key] \u003d value"},{"line_number":633,"context_line":""},{"line_number":634,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"},{"line_number":635,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_87434f12","line":632,"range":{"start_line":628,"start_character":0,"end_line":632,"end_character":41},"in_reply_to":"9a89bdaa_5f34b948","updated":"2016-09-08 11:16:22.000000000","message":"Now I noticed that this change is a subset of this patch: https://review.openstack.org/#/c/357559/4\n\n\nThat patch has the fix for the unit test.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"9fc234e6051abe3e444839ff6f8890ecafbc2947","unresolved":false,"context_lines":[{"line_number":625,"context_line":"        # add sysmeta and transient-meta to response"},{"line_number":626,"context_line":"        # these headers might be used by proxy middlewares"},{"line_number":627,"context_line":"        # e.g., symlink middleware"},{"line_number":628,"context_line":"        resp_headers \u003d {}"},{"line_number":629,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":630,"context_line":"            if (is_sys_meta(\u0027object\u0027, key) or"},{"line_number":631,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":632,"context_line":"                resp_headers[key] \u003d value"},{"line_number":633,"context_line":""},{"line_number":634,"context_line":"        return HTTPAccepted(request\u003drequest, headers\u003dresp_headers)"},{"line_number":635,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"9a89bdaa_976cfc9d","line":632,"range":{"start_line":628,"start_character":0,"end_line":632,"end_character":41},"in_reply_to":"9a89bdaa_87434f12","updated":"2016-09-09 19:55:29.000000000","message":"yeah, i\u0027m planning to make this patch depend on 357559. I will do that on patch 40.","commit_id":"a541390860989cef003efcc63db018db51308c60"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":890,"context_line":"                               \u0027X-Storage-Token\u0027 not in request.headers))"},{"line_number":891,"context_line":"                conditional_etag \u003d resolve_etag_is_at_header(request, metadata)"},{"line_number":892,"context_line":"                cr \u003d request.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":893,"context_line":"                    \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in metadata"},{"line_number":894,"context_line":"                response \u003d Response("},{"line_number":895,"context_line":"                    app_iter\u003ddisk_file.reader(keep_cache\u003dkeep_cache),"},{"line_number":896,"context_line":"                    request\u003drequest, conditional_response\u003dcr,"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_363669e8","line":893,"range":{"start_line":893,"start_character":19,"end_line":893,"end_character":54},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, TGT_OBJ_SYSMETA_SYMLINK_HDR.title() is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":956,"context_line":"                                conditional_response\u003dTrue)"},{"line_number":957,"context_line":"        conditional_etag \u003d resolve_etag_is_at_header(request, metadata)"},{"line_number":958,"context_line":"        cr \u003d request.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":959,"context_line":"            \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in metadata"},{"line_number":960,"context_line":"        response \u003d Response(request\u003drequest, conditional_response\u003dcr,"},{"line_number":961,"context_line":"                            conditional_etag\u003dconditional_etag)"},{"line_number":962,"context_line":"        response.headers[\u0027Content-Type\u0027] \u003d metadata.get("}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_b67039a7","line":959,"range":{"start_line":959,"start_character":12,"end_line":959,"end_character":45},"updated":"2017-04-03 09:05:38.000000000","message":"Same as above comment. TGT_OBJ_SYSMETA_SYMLINK_HDR.title() is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9e557e2b2b1c5be1058121d489dc2fe2b0ce4a89","unresolved":false,"context_lines":[{"line_number":920,"context_line":"                    \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in metadata"},{"line_number":921,"context_line":"                response \u003d Response("},{"line_number":922,"context_line":"                    app_iter\u003ddisk_file.reader(keep_cache\u003dkeep_cache),"},{"line_number":923,"context_line":"                    request\u003drequest, conditional_response\u003dcr,"},{"line_number":924,"context_line":"                    conditional_etag\u003dconditional_etag)"},{"line_number":925,"context_line":"                response.headers[\u0027Content-Type\u0027] \u003d metadata.get("},{"line_number":926,"context_line":"                    \u0027Content-Type\u0027, \u0027application/octet-stream\u0027)"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_f238dbee","line":923,"updated":"2017-12-07 23:42:46.000000000","message":"hrm... here it is again...","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":2271,"context_line":"                range_specs, fa_length, obj_length,"},{"line_number":2272,"context_line":"                self.app.logger)"},{"line_number":2273,"context_line":"            cr \u003d req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":2274,"context_line":"                \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in resp_headers"},{"line_number":2275,"context_line":"            resp \u003d Response("},{"line_number":2276,"context_line":"                request\u003dreq,"},{"line_number":2277,"context_line":"                headers\u003dresp_headers,"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_d6ecdd2a","line":2274,"range":{"start_line":2274,"start_character":16,"end_line":2274,"end_character":49},"updated":"2017-04-03 09:05:38.000000000","message":"Same as swift.obj.server, TGT_OBJ_SYSMETA_SYMLINK_HDR.title() is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9e557e2b2b1c5be1058121d489dc2fe2b0ce4a89","unresolved":false,"context_lines":[{"line_number":2339,"context_line":"                range_specs, fa_length, obj_length,"},{"line_number":2340,"context_line":"                self.app.logger)"},{"line_number":2341,"context_line":"            cr \u003d req.params.get(\u0027symlink\u0027) \u003d\u003d \u0027get\u0027 or \\"},{"line_number":2342,"context_line":"                \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in resp_headers"},{"line_number":2343,"context_line":"            resp \u003d Response("},{"line_number":2344,"context_line":"                request\u003dreq,"},{"line_number":2345,"context_line":"                conditional_response\u003dcr,"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_d226f715","line":2342,"updated":"2017-12-07 23:42:46.000000000","message":"this is a conceptual leak","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9e557e2b2b1c5be1058121d489dc2fe2b0ce4a89","unresolved":false,"context_lines":[{"line_number":2342,"context_line":"                \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in resp_headers"},{"line_number":2343,"context_line":"            resp \u003d Response("},{"line_number":2344,"context_line":"                request\u003dreq,"},{"line_number":2345,"context_line":"                conditional_response\u003dcr,"},{"line_number":2346,"context_line":"                app_iter\u003dapp_iter)"},{"line_number":2347,"context_line":"            update_headers(resp, resp_headers)"},{"line_number":2348,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_5280a7c0","line":2345,"updated":"2017-12-07 23:42:46.000000000","message":"why must symlink responses be non-conditional?\n\n    diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py\n    index f9c3e14..a76a238 100644\n    --- a/swift/proxy/controllers/obj.py\n    +++ b/swift/proxy/controllers/obj.py\n    @@ -2342,7 +2342,7 @@ class ECObjectController(BaseObjectController):\n                     \u0027X-Object-Sysmeta-Symlink-Target\u0027 not in resp_headers\n                 resp \u003d Response(\n                     request\u003dreq,\n    -                conditional_response\u003dcr,\n    +                conditional_response\u003dTrue,\n                     app_iter\u003dapp_iter)\n                 update_headers(resp, resp_headers)\n                 try:\n\n^ I couldn\u0027t find a single failing unit or functional test?","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"test/functional/test_symlink.py":[{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"#        def get_parsed_path(url, token, parsed, conn):"},{"line_number":52,"context_line":"#            return parsed.path"},{"line_number":53,"context_line":"#        parsed_path \u003d retry(get_parsed_path)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        def put_ref_obj(url, token, parsed, conn):"},{"line_number":56,"context_line":"            conn.request(\u0027PUT\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_97ff09aa","line":53,"updated":"2015-10-25 12:00:27.000000000","message":"you\u0027ve got some commented-out code here","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"#        def get_parsed_path(url, token, parsed, conn):"},{"line_number":52,"context_line":"#            return parsed.path"},{"line_number":53,"context_line":"#        parsed_path \u003d retry(get_parsed_path)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        def put_ref_obj(url, token, parsed, conn):"},{"line_number":56,"context_line":"            conn.request(\u0027PUT\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_706582df","line":53,"in_reply_to":"3a29b11f_97ff09aa","updated":"2015-10-26 14:48:08.000000000","message":"Done","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7d212f88726d45148cde7e4f43cb22ba00e35731","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def test_symlink_dummy(self):"},{"line_number":144,"context_line":"        if tf.skip:"},{"line_number":145,"context_line":"            raise SkipTest"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"    def test_delayed_symlink_put_get(self):"},{"line_number":148,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_372b9535","line":145,"updated":"2015-10-25 12:00:27.000000000","message":"what\u0027s this for?","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":16550,"name":"Robert Francis","email":"robefran@ca.ibm.com","username":"robefran"},"change_message_id":"da79313fc34fa19de09eae2de77fabd14b689847","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def test_symlink_dummy(self):"},{"line_number":144,"context_line":"        if tf.skip:"},{"line_number":145,"context_line":"            raise SkipTest"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"    def test_delayed_symlink_put_get(self):"},{"line_number":148,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":26,"id":"3a29b11f_30486a5b","line":145,"in_reply_to":"3a29b11f_372b9535","updated":"2015-10-26 14:48:08.000000000","message":"This was dummy test method to make sure I had the mechanics of a new test_symlink.py file working. I\u0027ve removed it.\nDone","commit_id":"b42fd1b3bda98e5b6ca8a90b36af1b7f7a1105b4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":145,"context_line":"        for container in self.containers:"},{"line_number":146,"context_line":"            resp \u003d retry(delete_container, container)"},{"line_number":147,"context_line":"            resp.read()"},{"line_number":148,"context_line":"            self.assertTrue(resp.status in (204, 404))"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _test_put_symlink(self, cont_link, link, tgt_cont, tgt_obj):"},{"line_number":151,"context_line":"        def _put_symlink(url, token, parsed, conn):"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_70eeba23","line":148,"updated":"2016-09-05 08:28:58.000000000","message":"Should use assertIn:\n\n  self.assertIn(resp.status, (204, 404))","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":145,"context_line":"        for container in self.containers:"},{"line_number":146,"context_line":"            resp \u003d retry(delete_container, container)"},{"line_number":147,"context_line":"            resp.read()"},{"line_number":148,"context_line":"            self.assertTrue(resp.status in (204, 404))"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _test_put_symlink(self, cont_link, link, tgt_cont, tgt_obj):"},{"line_number":151,"context_line":"        def _put_symlink(url, token, parsed, conn):"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_75da95e9","line":148,"in_reply_to":"9a89bdaa_70eeba23","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        cls._create_container(cls.tgt_cont)  # use_account\u003d1"},{"line_number":66,"context_line":"        cls._create_container(cls.link_cont)  # use_account\u003d1"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        # container in account 2, same name as ref_count"},{"line_number":69,"context_line":"        cls._create_container(cls.link_cont, use_account\u003d2)"},{"line_number":70,"context_line":"        cls._create_objects()"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"1a430d35_a2a415a6","line":68,"range":{"start_line":68,"start_character":47,"end_line":68,"end_character":56},"updated":"2017-02-07 19:33:54.000000000","message":"? I\u0027m not sure what ref_count means here...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        cls._create_container(cls.tgt_cont)  # use_account\u003d1"},{"line_number":66,"context_line":"        cls._create_container(cls.link_cont)  # use_account\u003d1"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        # container in account 2, same name as ref_count"},{"line_number":69,"context_line":"        cls._create_container(cls.link_cont, use_account\u003d2)"},{"line_number":70,"context_line":"        cls._create_objects()"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_1b582ffa","line":68,"in_reply_to":"1a430d35_a2a415a6","updated":"2017-02-17 18:58:12.000000000","message":"can\u0027t remember :/ \nmust have been a copy/paste error. removed...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    @classmethod"},{"line_number":121,"context_line":"    def tearDown(cls):"},{"line_number":122,"context_line":"        if tf.skip:"},{"line_number":123,"context_line":"            raise SkipTest"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        # get list of objects in container"},{"line_number":126,"context_line":"        def get_object(url, token, parsed, conn, container):"}],"source_content_type":"text/x-python","patch_set":51,"id":"1a430d35_222ca501","line":123,"updated":"2017-02-07 19:33:54.000000000","message":"Is this necessary? I would\u0027ve thought the SkipTest from setUp would be sufficient...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    @classmethod"},{"line_number":121,"context_line":"    def tearDown(cls):"},{"line_number":122,"context_line":"        if tf.skip:"},{"line_number":123,"context_line":"            raise SkipTest"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        # get list of objects in container"},{"line_number":126,"context_line":"        def get_object(url, token, parsed, conn, container):"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_26123663","line":123,"in_reply_to":"1a430d35_222ca501","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":123,"context_line":"            raise SkipTest"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        # get list of objects in container"},{"line_number":126,"context_line":"        def get_object(url, token, parsed, conn, container):"},{"line_number":127,"context_line":"            conn.request("},{"line_number":128,"context_line":"                \u0027GET\u0027, parsed.path + \u0027/\u0027 + container + \u0027?format\u003djson\u0027, \u0027\u0027,"},{"line_number":129,"context_line":"                {\u0027X-Auth-Token\u0027: token})"}],"source_content_type":"text/x-python","patch_set":51,"id":"1a430d35_02d8891c","line":126,"range":{"start_line":126,"start_character":12,"end_line":126,"end_character":22},"updated":"2017-02-07 19:33:54.000000000","message":"Better as get_container, or maybe get_object*s*?","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":123,"context_line":"            raise SkipTest"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        # get list of objects in container"},{"line_number":126,"context_line":"        def get_object(url, token, parsed, conn, container):"},{"line_number":127,"context_line":"            conn.request("},{"line_number":128,"context_line":"                \u0027GET\u0027, parsed.path + \u0027/\u0027 + container + \u0027?format\u003djson\u0027, \u0027\u0027,"},{"line_number":129,"context_line":"                {\u0027X-Auth-Token\u0027: token})"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_46156a47","line":126,"in_reply_to":"1a430d35_02d8891c","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f65dd5e7bf4c0d1b17b841c88d8523a50b28b7e3","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            resp \u003d retry(delete_container, container)"},{"line_number":164,"context_line":"            resp.read()"},{"line_number":165,"context_line":"            # TODO"},{"line_number":166,"context_line":"            # self.assertIn(resp.status, (204, 404))"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"class TestSymlink(unittest2.TestCase):"}],"source_content_type":"text/x-python","patch_set":51,"id":"1a430d35_620dcd8f","line":166,"updated":"2017-02-07 19:33:54.000000000","message":"Can we go ahead and do this? Seems like a reasonable thing to assert...","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"fba66b1e5609eab20a33aebab5ba89b4d68a9045","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            resp \u003d retry(delete_container, container)"},{"line_number":164,"context_line":"            resp.read()"},{"line_number":165,"context_line":"            # TODO"},{"line_number":166,"context_line":"            # self.assertIn(resp.status, (204, 404))"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"class TestSymlink(unittest2.TestCase):"}],"source_content_type":"text/x-python","patch_set":51,"id":"fa31d9ce_7c0cbe42","line":166,"in_reply_to":"1a430d35_620dcd8f","updated":"2017-02-17 18:58:12.000000000","message":"Done","commit_id":"eb1353b2b2e89895dad5d67532b5d327ea035d1d"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        return name"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    @classmethod"},{"line_number":91,"context_line":"    def _create_objects(cls):"},{"line_number":92,"context_line":"        def put_tgt_obj(url, token, parsed, conn):"},{"line_number":93,"context_line":"            conn.request(\u0027PUT\u0027,"},{"line_number":94,"context_line":"                         \u0027%s/%s/%s\u0027 % (parsed.path,"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_f12ecb41","line":91,"range":{"start_line":91,"start_character":8,"end_line":91,"end_character":23},"updated":"2017-04-03 09:05:38.000000000","message":"This method create only one object and the created object is target object.\nSo I think _create_tgt_object is better method name.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        return name"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    @classmethod"},{"line_number":91,"context_line":"    def _create_objects(cls):"},{"line_number":92,"context_line":"        def put_tgt_obj(url, token, parsed, conn):"},{"line_number":93,"context_line":"            conn.request(\u0027PUT\u0027,"},{"line_number":94,"context_line":"                         \u0027%s/%s/%s\u0027 % (parsed.path,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_5e5c884a","line":91,"range":{"start_line":91,"start_character":8,"end_line":91,"end_character":23},"in_reply_to":"dfeb2761_f12ecb41","updated":"2017-05-19 16:29:21.000000000","message":"i\u0027m leaving renames out of this patch for now, we can do that in a future patch","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":153,"context_line":"                raise ResponseError(resp)"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"class TestSymlink(unittest2.TestCase):"},{"line_number":157,"context_line":"    env \u003d TestSymlinkEnv"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_a76da105","line":156,"range":{"start_line":156,"start_character":0,"end_line":156,"end_character":38},"updated":"2017-04-03 09:05:38.000000000","message":"I think there is no test which checks cross account symlink without X-Container-Read.\nIMO, we should confirm that we can\u0027t GET/HEAD cross-account target object without X-Container-Read.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        cls \u003d type(self)"},{"line_number":165,"context_line":"        cls.env.tearDown()"},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"    def _test_put_symlink(self, cont_link, link, tgt_cont, tgt_obj):"},{"line_number":168,"context_line":"        def _put_symlink(url, token, parsed, conn):"},{"line_number":169,"context_line":"            conn.request(\u0027PUT\u0027,"},{"line_number":170,"context_line":"                         \u0027%s/%s/%s\u0027 % (parsed.path, cont_link, link),"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_915d3feb","line":167,"range":{"start_line":167,"start_character":32,"end_line":167,"end_character":49},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, link_cont and link_obj are more readable.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":191,"context_line":"                     \u0027\u0027, {\u0027X-Auth-Token\u0027: token})"},{"line_number":192,"context_line":"        return check_response(conn)"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _test_get_target_object(self, cont_link, link, use_account\u003d1,"},{"line_number":195,"context_line":"                                expect_content_location\u003dTrue):"},{"line_number":196,"context_line":"        resp \u003d retry(self._get_head_symlink_deref, method\u003d\u0027GET\u0027,"},{"line_number":197,"context_line":"                     cont_link\u003dcont_link, link\u003dlink, use_account\u003duse_account)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_ac0fc6df","line":194,"range":{"start_line":194,"start_character":8,"end_line":194,"end_character":31},"updated":"2017-04-03 09:05:38.000000000","message":"This method means that \"GET symlink object as target object\", but this method name looks like \"GET target object directly\".\nIMO, \"_test_get_as_target_object\" is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":208,"context_line":"            self.assertIn(expected_location_hdr,"},{"line_number":209,"context_line":"                          resp.getheader(\u0027content-location\u0027))"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"    def _test_head_target_object(self, cont_link, link, use_account\u003d1):"},{"line_number":212,"context_line":"        resp \u003d retry(self._get_head_symlink_deref, method\u003d\u0027HEAD\u0027,"},{"line_number":213,"context_line":"                     cont_link\u003dcont_link, link\u003dlink, use_account\u003duse_account)"},{"line_number":214,"context_line":"        resp.read()"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_2c1cd610","line":211,"range":{"start_line":211,"start_character":8,"end_line":211,"end_character":33},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \"_test_head_as_target_object\" is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":214,"context_line":"        resp.read()"},{"line_number":215,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":216,"context_line":""},{"line_number":217,"context_line":"    def _test_head_symlink_object(self, cont_link, link, use_account\u003d1):"},{"line_number":218,"context_line":"        resp \u003d retry(self._get_head_symlink_no_deref, method\u003d\u0027HEAD\u0027,"},{"line_number":219,"context_line":"                     cont_link\u003dcont_link, link\u003dlink,"},{"line_number":220,"context_line":"                     use_account\u003duse_account)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_ccbfaace","line":217,"range":{"start_line":217,"start_character":8,"end_line":217,"end_character":33},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \"_test_head_as_symlink_object\" is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":221,"context_line":"        resp.read()"},{"line_number":222,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"    def _test_get_symlink_object(self, cont_link, link, use_account\u003d1):"},{"line_number":225,"context_line":"        resp \u003d retry(self._get_head_symlink_no_deref, method\u003d\u0027GET\u0027,"},{"line_number":226,"context_line":"                     cont_link\u003dcont_link, link\u003dlink,"},{"line_number":227,"context_line":"                     use_account\u003duse_account)"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_4ccb9a71","line":224,"range":{"start_line":224,"start_character":8,"end_line":224,"end_character":33},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, \"_test_get_as_symlink_object\" is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":230,"context_line":"        self.assertEqual(contents, \u0027\u0027)"},{"line_number":231,"context_line":"        self.assertEqual(resp.getheader(\u0027content-length\u0027), str(0))"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def test_symlink_put_get(self):"},{"line_number":234,"context_line":"        if tf.skip:"},{"line_number":235,"context_line":"            raise SkipTest"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"        link \u003d uuid4().hex"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # PUT symlink"},{"line_number":240,"context_line":"        self._test_put_symlink(cont_link\u003dself.env.link_cont, link\u003dlink,"},{"line_number":241,"context_line":"                               tgt_cont\u003dself.env.tgt_cont,"},{"line_number":242,"context_line":"                               tgt_obj\u003dself.env.tgt_obj)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"        # GET target object"},{"line_number":245,"context_line":"        self._test_get_target_object(cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"    def test_symlink_put_get_encoded_chars(self):"},{"line_number":248,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_6c3f7e25","line":245,"range":{"start_line":233,"start_character":1,"end_line":245,"end_character":77},"updated":"2017-04-03 09:05:38.000000000","message":"I think this test is subset of test_symlink_put_head_get.\nAre there any unique assertion in this method?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":230,"context_line":"        self.assertEqual(contents, \u0027\u0027)"},{"line_number":231,"context_line":"        self.assertEqual(resp.getheader(\u0027content-length\u0027), str(0))"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def test_symlink_put_get(self):"},{"line_number":234,"context_line":"        if tf.skip:"},{"line_number":235,"context_line":"            raise SkipTest"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"        link \u003d uuid4().hex"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # PUT symlink"},{"line_number":240,"context_line":"        self._test_put_symlink(cont_link\u003dself.env.link_cont, link\u003dlink,"},{"line_number":241,"context_line":"                               tgt_cont\u003dself.env.tgt_cont,"},{"line_number":242,"context_line":"                               tgt_obj\u003dself.env.tgt_obj)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"        # GET target object"},{"line_number":245,"context_line":"        self._test_get_target_object(cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"    def test_symlink_put_get_encoded_chars(self):"},{"line_number":248,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_33621c40","line":245,"range":{"start_line":233,"start_character":1,"end_line":245,"end_character":77},"in_reply_to":"dfeb2761_6c3f7e25","updated":"2017-05-19 16:29:21.000000000","message":"removed","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":282,"context_line":"        # HEAD target object"},{"line_number":283,"context_line":"        self._test_head_target_object(cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"        resp \u003d retry(self._get_head_symlink_deref, method\u003d\u0027GET\u0027,"},{"line_number":286,"context_line":"                     cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":287,"context_line":"        contents \u003d resp.read()"},{"line_number":288,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":289,"context_line":"        self.assertEqual(contents, TARGET_BODY)"},{"line_number":290,"context_line":"        self.assertEqual(resp.getheader(\u0027content-length\u0027), str(target_length))"},{"line_number":291,"context_line":"        self.assertEqual(resp.getheader(\u0027etag\u0027), target_etag)"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"    def test_symlink_put_head_get(self):"},{"line_number":294,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_4caa7ad2","line":291,"range":{"start_line":285,"start_character":0,"end_line":291,"end_character":61},"updated":"2017-04-03 09:05:38.000000000","message":"Why _test_get_target_object is not used?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":335,"context_line":"                     cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":336,"context_line":"        contents \u003d resp.read()"},{"line_number":337,"context_line":"        self.assertEqual(resp.status, 206)"},{"line_number":338,"context_line":"        self.assertEqual(contents, \u0027body\u0027)"},{"line_number":339,"context_line":""},{"line_number":340,"context_line":"    def test_symlink_head_get_put_head_get(self):"},{"line_number":341,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_2cc6164a","line":338,"range":{"start_line":338,"start_character":34,"end_line":338,"end_character":41},"updated":"2017-04-03 09:05:38.000000000","message":"IMO, TARGET_BODY[7:11] is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":337,"context_line":"        self.assertEqual(resp.status, 206)"},{"line_number":338,"context_line":"        self.assertEqual(contents, \u0027body\u0027)"},{"line_number":339,"context_line":""},{"line_number":340,"context_line":"    def test_symlink_head_get_put_head_get(self):"},{"line_number":341,"context_line":"        if tf.skip:"},{"line_number":342,"context_line":"            raise SkipTest"},{"line_number":343,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_2ce5f6a8","line":340,"range":{"start_line":340,"start_character":8,"end_line":340,"end_character":42},"updated":"2017-04-03 09:05:38.000000000","message":"I think this method name doesn\u0027t explains this test\u0027s meaning.\nIMO, \"test_create_symlink_before_target\" is better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":393,"context_line":"        # HEAD target object"},{"line_number":394,"context_line":"        self._test_head_target_object(cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"        resp \u003d retry(self._get_head_symlink_deref, method\u003d\u0027GET\u0027,"},{"line_number":397,"context_line":"                     cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":398,"context_line":"        contents \u003d resp.read()"},{"line_number":399,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":400,"context_line":"        self.assertEqual(contents, TARGET_BODY)"},{"line_number":401,"context_line":"        self.assertEqual(resp.getheader(\u0027content-length\u0027), str(target_length))"},{"line_number":402,"context_line":"        self.assertEqual(resp.getheader(\u0027etag\u0027), target_etag)"},{"line_number":403,"context_line":""},{"line_number":404,"context_line":"    def test_symlink_chain(self):"},{"line_number":405,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_ec626e3e","line":402,"range":{"start_line":396,"start_character":1,"end_line":402,"end_character":61},"updated":"2017-04-03 09:05:38.000000000","message":"Why _test_get_target_object is not used?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":393,"context_line":"        # HEAD target object"},{"line_number":394,"context_line":"        self._test_head_target_object(cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"        resp \u003d retry(self._get_head_symlink_deref, method\u003d\u0027GET\u0027,"},{"line_number":397,"context_line":"                     cont_link\u003dself.env.link_cont, link\u003dlink)"},{"line_number":398,"context_line":"        contents \u003d resp.read()"},{"line_number":399,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":400,"context_line":"        self.assertEqual(contents, TARGET_BODY)"},{"line_number":401,"context_line":"        self.assertEqual(resp.getheader(\u0027content-length\u0027), str(target_length))"},{"line_number":402,"context_line":"        self.assertEqual(resp.getheader(\u0027etag\u0027), target_etag)"},{"line_number":403,"context_line":""},{"line_number":404,"context_line":"    def test_symlink_chain(self):"},{"line_number":405,"context_line":"        if tf.skip:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_14d7064e","line":402,"range":{"start_line":396,"start_character":1,"end_line":402,"end_character":61},"in_reply_to":"dfeb2761_ec626e3e","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"b60734f50518404bf9c0ceae20cefbee663abb1c","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # HEAD to target object"},{"line_number":425,"context_line":"        self._test_head_target_object(cont_link\u003dself.env.link_cont, link\u003dlink1)"},{"line_number":426,"context_line":""},{"line_number":427,"context_line":"        # HEAD to target object"},{"line_number":428,"context_line":"        self._test_get_target_object(cont_link\u003dself.env.link_cont, link\u003dlink1)"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"    def test_symlink_put_missing_target_container(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"dfeb2761_4cadda2f","line":427,"range":{"start_line":427,"start_character":10,"end_line":427,"end_character":14},"updated":"2017-04-03 09:05:38.000000000","message":"GET","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # HEAD to target object"},{"line_number":425,"context_line":"        self._test_head_target_object(cont_link\u003dself.env.link_cont, link\u003dlink1)"},{"line_number":426,"context_line":""},{"line_number":427,"context_line":"        # HEAD to target object"},{"line_number":428,"context_line":"        self._test_get_target_object(cont_link\u003dself.env.link_cont, link\u003dlink1)"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"    def test_symlink_put_missing_target_container(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_74bf6afb","line":427,"range":{"start_line":427,"start_character":10,"end_line":427,"end_character":14},"in_reply_to":"dfeb2761_4cadda2f","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":922,"context_line":""},{"line_number":923,"context_line":""},{"line_number":924,"context_line":"class TestCrossPolicySymlinkEnv(TestSymlinkEnv):"},{"line_number":925,"context_line":"    multiple_policies_enabled \u003d None"},{"line_number":926,"context_line":""},{"line_number":927,"context_line":"    @classmethod"},{"line_number":928,"context_line":"    def setUp(cls):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_a731170e","line":925,"range":{"start_line":925,"start_character":4,"end_line":925,"end_character":36},"updated":"2017-04-10 06:17:45.000000000","message":"In my understanding, this variable has two roles.\nRole1:\n  This class has been set up or not.\n  If this variable is None, this class has not been set up.\n  If this variable is not None, this class has been set up.\nRole2:\n  Multiple policies are enabled or not.\n  If this variable has boolean value,\n  The value means multiple policies are enabled or not.\nI think each variable should have only one role.\nAs I write as below the role2 is not needed.\nSo I think this variable name should show role1, e.g. \"has_been_set_up\".","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":932,"context_line":"        if cls.multiple_policies_enabled is None:"},{"line_number":933,"context_line":"            try:"},{"line_number":934,"context_line":"                cls.policies \u003d tf.FunctionalStoragePolicyCollection.from_info()"},{"line_number":935,"context_line":"            except AssertionError:"},{"line_number":936,"context_line":"                pass"},{"line_number":937,"context_line":""},{"line_number":938,"context_line":"        if cls.policies and len(cls.policies) \u003e 1:"},{"line_number":939,"context_line":"            cls.multiple_policies_enabled \u003d True"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_aa60bea6","line":936,"range":{"start_line":935,"start_character":11,"end_line":936,"end_character":20},"updated":"2017-04-10 06:17:45.000000000","message":"In this case, cls.policies will not be defined. Is it OK?\nI think there will be troubles in the next if-clause.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":938,"context_line":"        if cls.policies and len(cls.policies) \u003e 1:"},{"line_number":939,"context_line":"            cls.multiple_policies_enabled \u003d True"},{"line_number":940,"context_line":"        else:"},{"line_number":941,"context_line":"            cls.multiple_policies_enabled \u003d False"},{"line_number":942,"context_line":"            return"},{"line_number":943,"context_line":""},{"line_number":944,"context_line":"        cls.containers \u003d []"},{"line_number":945,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_2a6dce31","line":942,"range":{"start_line":941,"start_character":12,"end_line":942,"end_character":18},"updated":"2017-04-10 06:17:45.000000000","message":"I think we can raise SkipTest at this timing.\nIMO, if we raise SkipTest at this timing, TestCrossPolicySymlink.setUp is not needed to check \"self.env_multiple_policies_enabled\".\nSo, mutiple_policies_enabled is not needed.\n\nMy implementation image without mutiple_policies_enabled is \u003chttps://gist.github.com/KazuhiroMiyahara/86460c91d6315b08b822647d459b0978\u003e\n(This code is not tested.)","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":941,"context_line":"            cls.multiple_policies_enabled \u003d False"},{"line_number":942,"context_line":"            return"},{"line_number":943,"context_line":""},{"line_number":944,"context_line":"        cls.containers \u003d []"},{"line_number":945,"context_line":""},{"line_number":946,"context_line":"        cls.link_cont \u003d uuid4().hex"},{"line_number":947,"context_line":"        cls.tgt_cont \u003d uuid4().hex"},{"line_number":948,"context_line":"        cls.tgt_obj \u003d uuid4().hex"},{"line_number":949,"context_line":""},{"line_number":950,"context_line":"        link_policy \u003d cls.policies.select()"},{"line_number":951,"context_line":"        tgt_policy \u003d cls.policies.exclude(name\u003dlink_policy[\u0027name\u0027]).select()"},{"line_number":952,"context_line":"        link_header \u003d {\u0027X-Storage-Policy\u0027: link_policy[\u0027name\u0027]}"},{"line_number":953,"context_line":"        tgt_header \u003d {\u0027X-Storage-Policy\u0027: tgt_policy[\u0027name\u0027]}"},{"line_number":954,"context_line":""},{"line_number":955,"context_line":"        cls._create_container(cls.link_cont, headers\u003dlink_header)"},{"line_number":956,"context_line":"        cls._create_container(cls.tgt_cont, headers\u003dtgt_header)"},{"line_number":957,"context_line":""},{"line_number":958,"context_line":"        # container in account 2"},{"line_number":959,"context_line":"        cls._create_container(cls.link_cont, headers\u003dlink_header,"},{"line_number":960,"context_line":"                              use_account\u003d2)"},{"line_number":961,"context_line":"        cls._create_objects()"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":""},{"line_number":964,"context_line":"class TestCrossPolicySymlink(TestSymlink):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_c5df73d4","line":961,"range":{"start_line":944,"start_character":0,"end_line":961,"end_character":29},"updated":"2017-04-10 06:17:45.000000000","message":"These processes can be shared with TestSymlinkEnv.\n\nMy implementation image is \u003chttps://gist.github.com/KazuhiroMiyahara/07782d5b4b5a0b70621aaa177f46e477\u003e\n(This code is not tested.)","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":996,"context_line":"                (self.env.slo_enabled,))"},{"line_number":997,"context_line":""},{"line_number":998,"context_line":"    def test_symlink_target_slo_manifest(self):"},{"line_number":999,"context_line":"        link \u003d uuid4().hex"},{"line_number":1000,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1001,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1002,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1003,"context_line":"                                      \u0027manifest-abcde\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_b73d97de","line":1000,"range":{"start_line":999,"start_character":2,"end_line":1000,"end_character":52},"updated":"2017-04-10 06:17:45.000000000","message":"This code can be shared with other method in TestSymlinkSlo.\nI think this code should be in setUp method.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":996,"context_line":"                (self.env.slo_enabled,))"},{"line_number":997,"context_line":""},{"line_number":998,"context_line":"    def test_symlink_target_slo_manifest(self):"},{"line_number":999,"context_line":"        link \u003d uuid4().hex"},{"line_number":1000,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1001,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1002,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1003,"context_line":"                                      \u0027manifest-abcde\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_7e03c443","line":1000,"range":{"start_line":999,"start_character":2,"end_line":1000,"end_character":52},"in_reply_to":"bff0334d_b73d97de","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1010,"context_line":"        self.assertEqual(\u0027e\u0027, file_contents[-1])"},{"line_number":1011,"context_line":""},{"line_number":1012,"context_line":"    def test_symlink_target_slo_nested_manifest(self):"},{"line_number":1013,"context_line":"        link \u003d uuid4().hex"},{"line_number":1014,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1015,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1016,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1017,"context_line":"                                      \u0027manifest-abcde-submanifest\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_972613ce","line":1014,"range":{"start_line":1013,"start_character":1,"end_line":1014,"end_character":52},"updated":"2017-04-10 06:17:45.000000000","message":"Same as above.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1010,"context_line":"        self.assertEqual(\u0027e\u0027, file_contents[-1])"},{"line_number":1011,"context_line":""},{"line_number":1012,"context_line":"    def test_symlink_target_slo_nested_manifest(self):"},{"line_number":1013,"context_line":"        link \u003d uuid4().hex"},{"line_number":1014,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1015,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1016,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1017,"context_line":"                                      \u0027manifest-abcde-submanifest\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_3efd3c3a","line":1014,"range":{"start_line":1013,"start_character":1,"end_line":1014,"end_character":52},"in_reply_to":"bff0334d_972613ce","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1024,"context_line":"        self.assertEqual(\u0027e\u0027, file_contents[-1])"},{"line_number":1025,"context_line":""},{"line_number":1026,"context_line":"    def test_slo_get_ranged_manifest(self):"},{"line_number":1027,"context_line":"        link \u003d uuid4().hex"},{"line_number":1028,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1029,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1030,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1031,"context_line":"                                      \u0027ranged-manifest\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_77238fbe","line":1028,"range":{"start_line":1027,"start_character":1,"end_line":1028,"end_character":52},"updated":"2017-04-10 06:17:45.000000000","message":"Same as above.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1024,"context_line":"        self.assertEqual(\u0027e\u0027, file_contents[-1])"},{"line_number":1025,"context_line":""},{"line_number":1026,"context_line":"    def test_slo_get_ranged_manifest(self):"},{"line_number":1027,"context_line":"        link \u003d uuid4().hex"},{"line_number":1028,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1029,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1030,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1031,"context_line":"                                      \u0027ranged-manifest\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_1efa8041","line":1028,"range":{"start_line":1027,"start_character":1,"end_line":1028,"end_character":52},"in_reply_to":"bff0334d_77238fbe","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1042,"context_line":"            (\u0027d\u0027, 1)], grouped_file_contents)"},{"line_number":1043,"context_line":""},{"line_number":1044,"context_line":"    def test_slo_ranged_get(self):"},{"line_number":1045,"context_line":"        link \u003d uuid4().hex"},{"line_number":1046,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1047,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1048,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1049,"context_line":"                                      \u0027manifest-abcde\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_572c0bab","line":1046,"range":{"start_line":1045,"start_character":0,"end_line":1046,"end_character":52},"updated":"2017-04-10 06:17:45.000000000","message":"Same as above.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1042,"context_line":"            (\u0027d\u0027, 1)], grouped_file_contents)"},{"line_number":1043,"context_line":""},{"line_number":1044,"context_line":"    def test_slo_ranged_get(self):"},{"line_number":1045,"context_line":"        link \u003d uuid4().hex"},{"line_number":1046,"context_line":"        file_symlink \u003d self.env.container.file(link)"},{"line_number":1047,"context_line":"        file_symlink.write(hdrs\u003d{\u0027X-Symlink-Target\u0027:"},{"line_number":1048,"context_line":"                           \u0027%s/%s\u0027 % (self.env.container.name,"},{"line_number":1049,"context_line":"                                      \u0027manifest-abcde\u0027)})"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_de99b81f","line":1046,"range":{"start_line":1045,"start_character":0,"end_line":1046,"end_character":52},"in_reply_to":"bff0334d_572c0bab","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1191,"context_line":"        copied_contents \u003d copied.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1192,"context_line":"        self.assertEqual(2 * 1024 * 1024, len(copied_contents))"},{"line_number":1193,"context_line":""},{"line_number":1194,"context_line":"    def test_slo_copy_the_manifest(self):"},{"line_number":1195,"context_line":"        source \u003d self.env.container.file(\"manifest-linkto-ab\")"},{"line_number":1196,"context_line":"        source_contents \u003d source.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1197,"context_line":"        source_json \u003d json.loads(source_contents)"},{"line_number":1198,"context_line":"        source.initialize()"},{"line_number":1199,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, source.content_type)"},{"line_number":1200,"context_line":"        source.initialize(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1201,"context_line":"        source_hash \u003d hashlib.md5()"},{"line_number":1202,"context_line":"        source_hash.update(source_contents)"},{"line_number":1203,"context_line":"        self.assertEqual(source_hash.hexdigest(), source.etag)"},{"line_number":1204,"context_line":""},{"line_number":1205,"context_line":"        self.assertTrue(source.copy(self.env.container.name,"},{"line_number":1206,"context_line":"                                    \"copied-ab-manifest-only\","},{"line_number":1207,"context_line":"                                    parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027}))"},{"line_number":1208,"context_line":""},{"line_number":1209,"context_line":"        copied \u003d self.env.container.file(\"copied-ab-manifest-only\")"},{"line_number":1210,"context_line":"        copied_contents \u003d copied.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1211,"context_line":"        try:"},{"line_number":1212,"context_line":"            copied_json \u003d json.loads(copied_contents)"},{"line_number":1213,"context_line":"        except ValueError:"},{"line_number":1214,"context_line":"            self.fail(\"COPY didn\u0027t copy the manifest (invalid json on GET)\")"},{"line_number":1215,"context_line":"        self.assertEqual(source_json, copied_json)"},{"line_number":1216,"context_line":"        copied.initialize()"},{"line_number":1217,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, copied.content_type)"},{"line_number":1218,"context_line":"        copied.initialize(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1219,"context_line":"        copied_hash \u003d hashlib.md5()"},{"line_number":1220,"context_line":"        copied_hash.update(copied_contents)"},{"line_number":1221,"context_line":"        self.assertEqual(copied_hash.hexdigest(), copied.etag)"},{"line_number":1222,"context_line":""},{"line_number":1223,"context_line":"        # verify the listing metadata"},{"line_number":1224,"context_line":"        listing \u003d self.env.container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":1225,"context_line":"        names \u003d {}"},{"line_number":1226,"context_line":"        for f_dict in listing:"},{"line_number":1227,"context_line":"            if f_dict[\u0027name\u0027] in (\u0027manifest-linkto-ab\u0027,"},{"line_number":1228,"context_line":"                                  \u0027copied-ab-manifest-only\u0027):"},{"line_number":1229,"context_line":"                names[f_dict[\u0027name\u0027]] \u003d f_dict"},{"line_number":1230,"context_line":""},{"line_number":1231,"context_line":"        self.assertIn(\u0027manifest-linkto-ab\u0027, names)"},{"line_number":1232,"context_line":"        actual \u003d names[\u0027manifest-linkto-ab\u0027]"},{"line_number":1233,"context_line":"        self.assertEqual(2 * 1024 * 1024, actual[\u0027bytes\u0027])"},{"line_number":1234,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, actual[\u0027content_type\u0027])"},{"line_number":1235,"context_line":"        self.assertEqual(source.etag, actual[\u0027hash\u0027])"},{"line_number":1236,"context_line":""},{"line_number":1237,"context_line":"        self.assertIn(\u0027copied-ab-manifest-only\u0027, names)"},{"line_number":1238,"context_line":"        actual \u003d names[\u0027copied-ab-manifest-only\u0027]"},{"line_number":1239,"context_line":"        self.assertEqual(2 * 1024 * 1024, actual[\u0027bytes\u0027])"},{"line_number":1240,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, actual[\u0027content_type\u0027])"},{"line_number":1241,"context_line":"        self.assertEqual(copied.etag, actual[\u0027hash\u0027])"},{"line_number":1242,"context_line":""},{"line_number":1243,"context_line":""},{"line_number":1244,"context_line":"class TestSymlinkDlo(Base):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_1a910a48","line":1241,"range":{"start_line":1194,"start_character":1,"end_line":1241,"end_character":53},"updated":"2017-04-10 06:17:45.000000000","message":"I think this test needs more comments.\nIt is hard for me to understand meanings of each assertions.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1191,"context_line":"        copied_contents \u003d copied.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1192,"context_line":"        self.assertEqual(2 * 1024 * 1024, len(copied_contents))"},{"line_number":1193,"context_line":""},{"line_number":1194,"context_line":"    def test_slo_copy_the_manifest(self):"},{"line_number":1195,"context_line":"        source \u003d self.env.container.file(\"manifest-linkto-ab\")"},{"line_number":1196,"context_line":"        source_contents \u003d source.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1197,"context_line":"        source_json \u003d json.loads(source_contents)"},{"line_number":1198,"context_line":"        source.initialize()"},{"line_number":1199,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, source.content_type)"},{"line_number":1200,"context_line":"        source.initialize(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1201,"context_line":"        source_hash \u003d hashlib.md5()"},{"line_number":1202,"context_line":"        source_hash.update(source_contents)"},{"line_number":1203,"context_line":"        self.assertEqual(source_hash.hexdigest(), source.etag)"},{"line_number":1204,"context_line":""},{"line_number":1205,"context_line":"        self.assertTrue(source.copy(self.env.container.name,"},{"line_number":1206,"context_line":"                                    \"copied-ab-manifest-only\","},{"line_number":1207,"context_line":"                                    parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027}))"},{"line_number":1208,"context_line":""},{"line_number":1209,"context_line":"        copied \u003d self.env.container.file(\"copied-ab-manifest-only\")"},{"line_number":1210,"context_line":"        copied_contents \u003d copied.read(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1211,"context_line":"        try:"},{"line_number":1212,"context_line":"            copied_json \u003d json.loads(copied_contents)"},{"line_number":1213,"context_line":"        except ValueError:"},{"line_number":1214,"context_line":"            self.fail(\"COPY didn\u0027t copy the manifest (invalid json on GET)\")"},{"line_number":1215,"context_line":"        self.assertEqual(source_json, copied_json)"},{"line_number":1216,"context_line":"        copied.initialize()"},{"line_number":1217,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, copied.content_type)"},{"line_number":1218,"context_line":"        copied.initialize(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027})"},{"line_number":1219,"context_line":"        copied_hash \u003d hashlib.md5()"},{"line_number":1220,"context_line":"        copied_hash.update(copied_contents)"},{"line_number":1221,"context_line":"        self.assertEqual(copied_hash.hexdigest(), copied.etag)"},{"line_number":1222,"context_line":""},{"line_number":1223,"context_line":"        # verify the listing metadata"},{"line_number":1224,"context_line":"        listing \u003d self.env.container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":1225,"context_line":"        names \u003d {}"},{"line_number":1226,"context_line":"        for f_dict in listing:"},{"line_number":1227,"context_line":"            if f_dict[\u0027name\u0027] in (\u0027manifest-linkto-ab\u0027,"},{"line_number":1228,"context_line":"                                  \u0027copied-ab-manifest-only\u0027):"},{"line_number":1229,"context_line":"                names[f_dict[\u0027name\u0027]] \u003d f_dict"},{"line_number":1230,"context_line":""},{"line_number":1231,"context_line":"        self.assertIn(\u0027manifest-linkto-ab\u0027, names)"},{"line_number":1232,"context_line":"        actual \u003d names[\u0027manifest-linkto-ab\u0027]"},{"line_number":1233,"context_line":"        self.assertEqual(2 * 1024 * 1024, actual[\u0027bytes\u0027])"},{"line_number":1234,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, actual[\u0027content_type\u0027])"},{"line_number":1235,"context_line":"        self.assertEqual(source.etag, actual[\u0027hash\u0027])"},{"line_number":1236,"context_line":""},{"line_number":1237,"context_line":"        self.assertIn(\u0027copied-ab-manifest-only\u0027, names)"},{"line_number":1238,"context_line":"        actual \u003d names[\u0027copied-ab-manifest-only\u0027]"},{"line_number":1239,"context_line":"        self.assertEqual(2 * 1024 * 1024, actual[\u0027bytes\u0027])"},{"line_number":1240,"context_line":"        self.assertEqual(\u0027application/octet-stream\u0027, actual[\u0027content_type\u0027])"},{"line_number":1241,"context_line":"        self.assertEqual(copied.etag, actual[\u0027hash\u0027])"},{"line_number":1242,"context_line":""},{"line_number":1243,"context_line":""},{"line_number":1244,"context_line":"class TestSymlinkDlo(Base):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_cb6c5c0a","line":1241,"range":{"start_line":1194,"start_character":1,"end_line":1241,"end_character":53},"in_reply_to":"bff0334d_1a910a48","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1523,"context_line":"            self.assert_header(\u0027etag\u0027, md5)"},{"line_number":1524,"context_line":""},{"line_number":1525,"context_line":"    def testLastModified(self):"},{"line_number":1526,"context_line":"        file_name \u003d Utils.create_name()"},{"line_number":1527,"context_line":"        content_type \u003d Utils.create_name()"},{"line_number":1528,"context_line":""},{"line_number":1529,"context_line":"        file_item \u003d self.env.container.file(file_name)"},{"line_number":1530,"context_line":"        file_item.content_type \u003d content_type"},{"line_number":1531,"context_line":"        resp \u003d file_item.write_random_return_resp(self.env.file_size)"},{"line_number":1532,"context_line":"        put_last_modified \u003d resp.getheader(\u0027last-modified\u0027)"},{"line_number":1533,"context_line":"        etag \u003d file_item.md5"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_5a055213","line":1530,"range":{"start_line":1526,"start_character":1,"end_line":1530,"end_character":45},"updated":"2017-04-10 06:17:45.000000000","message":"I think \"file_item \u003d self.env.container.file(Utils.create_name())\" and \"file_item.content_type \u003d Utils.crate_name()\" will be more simple.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1523,"context_line":"            self.assert_header(\u0027etag\u0027, md5)"},{"line_number":1524,"context_line":""},{"line_number":1525,"context_line":"    def testLastModified(self):"},{"line_number":1526,"context_line":"        file_name \u003d Utils.create_name()"},{"line_number":1527,"context_line":"        content_type \u003d Utils.create_name()"},{"line_number":1528,"context_line":""},{"line_number":1529,"context_line":"        file_item \u003d self.env.container.file(file_name)"},{"line_number":1530,"context_line":"        file_item.content_type \u003d content_type"},{"line_number":1531,"context_line":"        resp \u003d file_item.write_random_return_resp(self.env.file_size)"},{"line_number":1532,"context_line":"        put_last_modified \u003d resp.getheader(\u0027last-modified\u0027)"},{"line_number":1533,"context_line":"        etag \u003d file_item.md5"}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_0bdda413","line":1530,"range":{"start_line":1526,"start_character":1,"end_line":1530,"end_character":45},"in_reply_to":"bff0334d_5a055213","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"70a1d978767ebd5e989d7334184dd66c2d285037","unresolved":false,"context_lines":[{"line_number":1561,"context_line":"    def setUp(self):"},{"line_number":1562,"context_line":"        super(TestSymlinkComparison, self).setUp()"},{"line_number":1563,"context_line":""},{"line_number":1564,"context_line":"    def testLastModified(self):"},{"line_number":1565,"context_line":"        file_name \u003d Utils.create_name()"},{"line_number":1566,"context_line":"        content_type \u003d Utils.create_name()"},{"line_number":1567,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_0d9d56bb","line":1564,"range":{"start_line":1564,"start_character":3,"end_line":1564,"end_character":31},"updated":"2017-04-10 06:17:45.000000000","message":"In this method, \"self.env.parms\" is used, but \"self.env.expect._empty_etag\" is not used. MD5_OF_EMPTY_ETAG is used directly.\nIMO, If  you use MD5_OF_EMPTY_ETAG directly, you should use \"{\u0027symlink\u0027: \u0027get\u0027}\" directly instead of \"self.env.parms\".","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":1561,"context_line":"    def setUp(self):"},{"line_number":1562,"context_line":"        super(TestSymlinkComparison, self).setUp()"},{"line_number":1563,"context_line":""},{"line_number":1564,"context_line":"    def testLastModified(self):"},{"line_number":1565,"context_line":"        file_name \u003d Utils.create_name()"},{"line_number":1566,"context_line":"        content_type \u003d Utils.create_name()"},{"line_number":1567,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1f013ff3_ebbcb8bc","line":1564,"range":{"start_line":1564,"start_character":3,"end_line":1564,"end_character":31},"in_reply_to":"bff0334d_0d9d56bb","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4b008187628e5ef24daa71f74e46cedca3a71a34","unresolved":false,"context_lines":[{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    def setUp(self):"},{"line_number":160,"context_line":"        cls \u003d type(self)"},{"line_number":161,"context_line":"        cls.env.setUp()"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def tearDown(self):"},{"line_number":164,"context_line":"        cls \u003d type(self)"}],"source_content_type":"text/x-python","patch_set":56,"id":"5f2577a7_1074c134","line":161,"updated":"2017-09-11 19:33:28.000000000","message":"I LOVE that we have these tests, but somewhere in here we need to check for a \u0027symlink\u0027 key in /info and raise a SkipTest if we don\u0027t find it.","commit_id":"52d8b080345426e61b9b911f9d281b6be4399eb3"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"7ca67693dd235d86b10b33e4f96b0185d1c42577","unresolved":false,"context_lines":[{"line_number":255,"context_line":"            raise SkipTest"},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"        # makes sure to test encoded characters as symlink target"},{"line_number":258,"context_line":"        target_obj \u003d urllib.parse.quote("},{"line_number":259,"context_line":"            \u0027dealde%2Fl04 011e%204c8df|7Cflash.png\u0027)"},{"line_number":260,"context_line":"        link_obj \u003d uuid4().hex"},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"        # Now let\u0027s write target object and symlink will be able to return"}],"source_content_type":"text/x-python","patch_set":65,"id":"3f4b6375_c9013c6c","line":259,"range":{"start_line":258,"start_character":0,"end_line":259,"end_character":52},"updated":"2017-10-26 12:48:32.000000000","message":"Oops? This looks what I\u0027m not sure on the follow up.\n\nAgh, don\u0027t do that. I think the old test was correct because the encoded values in the object name the ones that can not be re-quote. If we quote here, the test intention was changed.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"45b3e8c7f909789e271cd8e2e51722559ffc258a","unresolved":false,"context_lines":[{"line_number":255,"context_line":"            raise SkipTest"},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"        # makes sure to test encoded characters as symlink target"},{"line_number":258,"context_line":"        target_obj \u003d urllib.parse.quote("},{"line_number":259,"context_line":"            \u0027dealde%2Fl04 011e%204c8df|7Cflash.png\u0027)"},{"line_number":260,"context_line":"        link_obj \u003d uuid4().hex"},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"        # Now let\u0027s write target object and symlink will be able to return"}],"source_content_type":"text/x-python","patch_set":65,"id":"1f485f77_f65b5384","line":259,"range":{"start_line":258,"start_character":0,"end_line":259,"end_character":52},"in_reply_to":"3f4b6375_c9013c6c","updated":"2017-11-13 12:27:45.000000000","message":"I see. I made it to un-requotable value again.","commit_id":"812bf2c9d18c0ae00e6d7d809f26a19c6bfb3dd5"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fc1904b92b7fb9368f9125d457645763ffecd0c2","unresolved":false,"context_lines":[{"line_number":661,"context_line":"        self.assertEqual(resp.status, 400)"},{"line_number":662,"context_line":""},{"line_number":663,"context_line":"    def test_symlink_loop(self):"},{"line_number":664,"context_line":"        # TODO: We should probably keep user from linking to itself, return"},{"line_number":665,"context_line":"        # an error on PUT"},{"line_number":666,"context_line":"        if tf.skip:"},{"line_number":667,"context_line":"            raise SkipTest"},{"line_number":668,"context_line":""}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_81cbb851","line":665,"range":{"start_line":664,"start_character":10,"end_line":665,"end_character":25},"updated":"2017-11-21 06:24:40.000000000","message":"Is this something we want to have implemented in this patch. I mean we do have symlink loop to we can\u0027t have a never ending loops. but it kind of makes sense to have this check, because it\u0027s something that should never be allowed.","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"c4ff759c8f736224813e260a027421ab25f93a72","unresolved":false,"context_lines":[{"line_number":661,"context_line":"        self.assertEqual(resp.status, 400)"},{"line_number":662,"context_line":""},{"line_number":663,"context_line":"    def test_symlink_loop(self):"},{"line_number":664,"context_line":"        # TODO: We should probably keep user from linking to itself, return"},{"line_number":665,"context_line":"        # an error on PUT"},{"line_number":666,"context_line":"        if tf.skip:"},{"line_number":667,"context_line":"            raise SkipTest"},{"line_number":668,"context_line":""}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_481125ac","line":665,"range":{"start_line":664,"start_character":10,"end_line":665,"end_character":25},"in_reply_to":"ff82abbf_81cbb851","updated":"2017-11-22 13:44:21.000000000","message":"Done","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fc1904b92b7fb9368f9125d457645763ffecd0c2","unresolved":false,"context_lines":[{"line_number":990,"context_line":"        resp \u003d retry(get, self.env.link_cont, link_obj)"},{"line_number":991,"context_line":"        resp.read()"},{"line_number":992,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":993,"context_line":"        self.assertEqual(resp.getheader(\u0027X-Object-Meta-Test\u0027), value1)"},{"line_number":994,"context_line":""},{"line_number":995,"context_line":"    def test_update_symlink_target(self):"},{"line_number":996,"context_line":"        link_obj \u003d uuid4().hex"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_614c74c7","line":993,"updated":"2017-11-21 06:24:40.000000000","message":"The symlink itself should have Alfa\u003dapple metadata applied. Which might be what people want (extra metadata on a symlink), so we probably should test for it","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"c4ff759c8f736224813e260a027421ab25f93a72","unresolved":false,"context_lines":[{"line_number":990,"context_line":"        resp \u003d retry(get, self.env.link_cont, link_obj)"},{"line_number":991,"context_line":"        resp.read()"},{"line_number":992,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":993,"context_line":"        self.assertEqual(resp.getheader(\u0027X-Object-Meta-Test\u0027), value1)"},{"line_number":994,"context_line":""},{"line_number":995,"context_line":"    def test_update_symlink_target(self):"},{"line_number":996,"context_line":"        link_obj \u003d uuid4().hex"}],"source_content_type":"text/x-python","patch_set":69,"id":"ff82abbf_06e78f42","line":993,"in_reply_to":"ff82abbf_614c74c7","updated":"2017-11-22 13:44:21.000000000","message":"Done","commit_id":"698c327e26fa633022299cf343a4756bf35f3199"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"cee981a6511987ccb5527227da3d67eeb1527a41","unresolved":false,"context_lines":[{"line_number":163,"context_line":"        pass"},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"    def setUp(self):"},{"line_number":166,"context_line":"        # super(TestSymlink, self).setUp()"},{"line_number":167,"context_line":"        self.env.setUp()"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"        def object_name_generator():"}],"source_content_type":"text/x-python","patch_set":73,"id":"df87a7cf_def4fdd1","line":166,"updated":"2017-12-06 05:22:09.000000000","message":"unnecessary comment out.","commit_id":"5cc5acc12b43ca3aed60954bf633fc1614d71cbc"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"cee981a6511987ccb5527227da3d67eeb1527a41","unresolved":false,"context_lines":[{"line_number":414,"context_line":"                     container\u003dcontainer,"},{"line_number":415,"context_line":"                     obj\u003dtoo_many_chain_link)"},{"line_number":416,"context_line":"        self.assertEqual(resp.status, 409)"},{"line_number":417,"context_line":"        # N.B. This error message is from slo middleware that uses default."},{"line_number":418,"context_line":"        self.assertEqual("},{"line_number":419,"context_line":"            resp.content,"},{"line_number":420,"context_line":"            \u0027Too many levels of symbolic links, maximum allowed is %d\u0027 %"}],"source_content_type":"text/x-python","patch_set":73,"id":"df87a7cf_7e1cd111","line":417,"updated":"2017-12-06 05:22:09.000000000","message":"wrong comment.","commit_id":"5cc5acc12b43ca3aed60954bf633fc1614d71cbc"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"cee981a6511987ccb5527227da3d67eeb1527a41","unresolved":false,"context_lines":[{"line_number":744,"context_line":"                     container\u003dself.env.tgt_cont, obj\u003dobj2)"},{"line_number":745,"context_line":"        self.assertEqual(resp.status, 200)"},{"line_number":746,"context_line":"        self.assertNotIn(\u0027Content-Location\u0027, resp.headers)"},{"line_number":747,"context_line":"        # GET to target object via symlink"},{"line_number":748,"context_line":"        # This is raw object (not symlink)"},{"line_number":749,"context_line":"        resp \u003d retry(self._make_request, method\u003d\u0027GET\u0027,"},{"line_number":750,"context_line":"                     container\u003dself.env.tgt_cont, obj\u003dobj2)"}],"source_content_type":"text/x-python","patch_set":73,"id":"df87a7cf_5ed78d24","line":747,"range":{"start_line":747,"start_character":17,"end_line":747,"end_character":42},"updated":"2017-12-06 05:22:09.000000000","message":"the copied object.","commit_id":"5cc5acc12b43ca3aed60954bf633fc1614d71cbc"}],"test/probe/test_container_sync.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"89f58629f3495c37b9a8ed4279aa8fe978da037a","unresolved":false,"context_lines":[{"line_number":419,"context_line":"            target_body)"},{"line_number":420,"context_line":""},{"line_number":421,"context_line":"        # Note that this tests when the target object is in the same account"},{"line_number":422,"context_line":"        target_path \u003d \u0027/%s/%s\u0027 % (tgt_container, target_name)"},{"line_number":423,"context_line":"        symlink_name \u003d \u0027symlink-%s\u0027 % uuid.uuid4()"},{"line_number":424,"context_line":"        put_headers \u003d {\u0027X-Symlink-Target\u0027: target_path}"},{"line_number":425,"context_line":""}],"source_content_type":"text/x-python","patch_set":72,"id":"df87a7cf_bae93c81","line":422,"range":{"start_line":422,"start_character":23,"end_line":422,"end_character":24},"updated":"2017-12-04 12:43:22.000000000","message":"this will be failed because of slash prefix.","commit_id":"d1c9cee10fd7e8dd95d37aa4f6926eed2c3835c4"}],"test/unit/common/middleware/test_symlink.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":123,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":124,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":125,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) in headers)"},{"line_number":126,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) in headers)"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    def test_get_target_object(self):"},{"line_number":129,"context_line":"        self.app.register(\u0027GET\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_10e80e10","line":126,"updated":"2016-09-05 08:28:58.000000000","message":"Use assertIn here","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":123,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":124,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":125,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) in headers)"},{"line_number":126,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) in headers)"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    def test_get_target_object(self):"},{"line_number":129,"context_line":"        self.app.register(\u0027GET\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_b57c1db6","line":126,"in_reply_to":"9a89bdaa_10e80e10","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":136,"context_line":"        self.assertEqual(body, \u0027resp_body\u0027)"},{"line_number":137,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) not in headers)"},{"line_number":138,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) not in headers)"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def test_head_symlink(self):"},{"line_number":141,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_30e51237","line":138,"updated":"2016-09-05 08:28:58.000000000","message":"Use assertNotIn","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":136,"context_line":"        self.assertEqual(body, \u0027resp_body\u0027)"},{"line_number":137,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) not in headers)"},{"line_number":138,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) not in headers)"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def test_head_symlink(self):"},{"line_number":141,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_1055d7f8","line":138,"in_reply_to":"9a89bdaa_30e51237","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":148,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) in headers)"},{"line_number":149,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) in headers)"},{"line_number":150,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027) in headers)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    def test_head_target_object(self):"},{"line_number":153,"context_line":"        # this test is also validating that the symlink metadata is not"},{"line_number":154,"context_line":"        # returned, but the target object metadata does return"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_50d0d653","line":151,"updated":"2016-09-05 08:28:58.000000000","message":"Same here","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":148,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) in headers)"},{"line_number":149,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) in headers)"},{"line_number":150,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027) in headers)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    def test_head_target_object(self):"},{"line_number":153,"context_line":"        # this test is also validating that the symlink metadata is not"},{"line_number":154,"context_line":"        # returned, but the target object metadata does return"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_d04e0f6e","line":151,"in_reply_to":"9a89bdaa_50d0d653","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) not in headers)"},{"line_number":165,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) not in headers)"},{"line_number":166,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027) not in headers)"},{"line_number":167,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027) in headers)"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"    def test_symlink_too_deep(self):"},{"line_number":170,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_70d5da41","line":167,"updated":"2016-09-05 08:28:58.000000000","message":"And here.. you get the picture.","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Object\u0027, \u0027c1/o\u0027) not in headers)"},{"line_number":165,"context_line":"        self.assertTrue((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027) not in headers)"},{"line_number":166,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027) not in headers)"},{"line_number":167,"context_line":"        self.assertTrue((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027) in headers)"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"    def test_symlink_too_deep(self):"},{"line_number":170,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_b02fcb86","line":167,"in_reply_to":"9a89bdaa_70d5da41","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"5c1cdaa16313d80faaf9d533e617745263e5a28b","unresolved":false,"context_lines":[{"line_number":211,"context_line":"                            headers\u003d{\u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":212,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":213,"context_line":"        self.assertEqual(status, \u0027202 Accepted\u0027)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"class SymlinkCopyingTestCase(TestSymlinkMiddlewareBase):"},{"line_number":217,"context_line":"    # verify interaction of copy and versioned_writes middlewares"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_90ca5ea0","line":214,"updated":"2016-09-05 08:28:58.000000000","message":"We should probably have at least a simple test where we change the symloop_max.","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d918a65ea84a26b508305b5e39585c1ad8afed5d","unresolved":false,"context_lines":[{"line_number":211,"context_line":"                            headers\u003d{\u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":212,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":213,"context_line":"        self.assertEqual(status, \u0027202 Accepted\u0027)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"class SymlinkCopyingTestCase(TestSymlinkMiddlewareBase):"},{"line_number":217,"context_line":"    # verify interaction of copy and versioned_writes middlewares"}],"source_content_type":"text/x-python","patch_set":37,"id":"9a89bdaa_90d9e724","line":214,"in_reply_to":"9a89bdaa_90ca5ea0","updated":"2016-09-07 20:02:37.000000000","message":"Done","commit_id":"4b951cdd00b73ad4b0050789aa5b987de59958d4"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"25ab807c622aad4517aa26d72c9afb3e10c81991","unresolved":false,"context_lines":[{"line_number":235,"context_line":""},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"class SymlinkCopyingTestCase(TestSymlinkMiddlewareBase):"},{"line_number":238,"context_line":"    # verify interaction of copy and versioned_writes middlewares"},{"line_number":239,"context_line":""},{"line_number":240,"context_line":"    def setUp(self):"},{"line_number":241,"context_line":"        self.app \u003d FakeSwift()"}],"source_content_type":"text/x-python","patch_set":42,"id":"3a71b18c_e8289435","line":238,"range":{"start_line":238,"start_character":38,"end_line":238,"end_character":53},"updated":"2016-12-06 18:28:32.000000000","message":"update comment","commit_id":"789202e84f1b0c9a0d8cebdd6f044810973813e9"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        })(self.app)"},{"line_number":35,"context_line":"        self.sym.logger \u003d self.app.logger"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def call_app(self, req, app\u003dNone, expect_exception\u003dFalse):"},{"line_number":38,"context_line":"        if app is None:"},{"line_number":39,"context_line":"            app \u003d self.app"},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_8badceea","line":37,"range":{"start_line":37,"start_character":36,"end_line":37,"end_character":60},"updated":"2017-04-10 09:30:11.000000000","message":"In my understanding, this variable is always False, because call_app is not called with expcet_exception\u003dTrue.\nTherefore, this variable should be removed.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        })(self.app)"},{"line_number":35,"context_line":"        self.sym.logger \u003d self.app.logger"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def call_app(self, req, app\u003dNone, expect_exception\u003dFalse):"},{"line_number":38,"context_line":"        if app is None:"},{"line_number":39,"context_line":"            app \u003d self.app"},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_860ae787","line":37,"range":{"start_line":37,"start_character":36,"end_line":37,"end_character":60},"in_reply_to":"bff0334d_8badceea","updated":"2017-05-19 16:29:21.000000000","message":"we have been copying this method throughtout many test files (e.g., slo, dlo, copy, versioning) and now here. We should come up with a common code that can be shared. For now, I\u0027m going to leave as is, and we can refactor that in a separate patch. I\u0027m trying to keep the number of changes small for now","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.sym.logger \u003d self.app.logger"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def call_app(self, req, app\u003dNone, expect_exception\u003dFalse):"},{"line_number":38,"context_line":"        if app is None:"},{"line_number":39,"context_line":"            app \u003d self.app"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        self.authorized \u003d []"},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_10f20971","line":39,"range":{"start_line":38,"start_character":1,"end_line":39,"end_character":26},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, \"app \u003d app if app else self.app\" will be more simple.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        if app is None:"},{"line_number":39,"context_line":"            app \u003d self.app"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        self.authorized \u003d []"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"        def authorize(req):"},{"line_number":44,"context_line":"            self.authorized.append(req)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        if \u0027swift.authorize\u0027 not in req.environ:"},{"line_number":47,"context_line":"            req.environ[\u0027swift.authorize\u0027] \u003d authorize"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        req.headers.setdefault(\"User-Agent\", \"Mozzarella Foxfire\")"},{"line_number":50,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_a199d1c4","line":47,"range":{"start_line":41,"start_character":0,"end_line":47,"end_character":54},"updated":"2017-04-10 09:30:11.000000000","message":"In my understanding, \u0027swift.authorize\u0027 is used only in tests with copy middleware or versioning middleware.\nAs I wrote at SymlinkCopyingTestCase and SymlinkVersioningTestCase, I think these combinative tests should be moved to functional tests.\nIf these tests moved to functional tests, codes for authorize in this call_app can be removed.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        if \u0027swift.authorize\u0027 not in req.environ:"},{"line_number":47,"context_line":"            req.environ[\u0027swift.authorize\u0027] \u003d authorize"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        req.headers.setdefault(\"User-Agent\", \"Mozzarella Foxfire\")"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        status \u003d [None]"},{"line_number":52,"context_line":"        headers \u003d [None]"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_a1de716a","line":49,"range":{"start_line":49,"start_character":1,"end_line":49,"end_character":66},"updated":"2017-04-10 09:30:11.000000000","message":"Is this header used?","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        req.headers.setdefault(\"User-Agent\", \"Mozzarella Foxfire\")"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        status \u003d [None]"},{"line_number":52,"context_line":"        headers \u003d [None]"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        def start_response(s, h, ei\u003dNone):"},{"line_number":55,"context_line":"            status[0] \u003d s"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_700cb540","line":52,"range":{"start_line":51,"start_character":1,"end_line":52,"end_character":24},"updated":"2017-04-10 09:30:11.000000000","message":"Why are these variables list?\nIMO, \"status \u003d headers \u003d None\" will be more simple.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":52,"context_line":"        headers \u003d [None]"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        def start_response(s, h, ei\u003dNone):"},{"line_number":55,"context_line":"            status[0] \u003d s"},{"line_number":56,"context_line":"            headers[0] \u003d h"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"        body_iter \u003d app(req.environ, start_response)"},{"line_number":59,"context_line":"        body \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_0b2f7e8e","line":56,"range":{"start_line":55,"start_character":1,"end_line":56,"end_character":26},"updated":"2017-04-10 09:30:11.000000000","message":"status \u003d s\nheaders \u003d h","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return self.call_app(req, app\u003dself.sym, **kwargs)"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"class TestSymlinkMiddleware(TestSymlinkMiddlewareBase):"},{"line_number":80,"context_line":"    def test_symlink_simple_put(self):"},{"line_number":81,"context_line":"        self.app.register(\u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated, {})"},{"line_number":82,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_e1b35909","line":79,"range":{"start_line":79,"start_character":0,"end_line":79,"end_character":55},"updated":"2017-04-10 09:30:11.000000000","message":"I think tests about SymlinkContainerContext should be added.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"class TestSymlinkMiddleware(TestSymlinkMiddlewareBase):"},{"line_number":80,"context_line":"    def test_symlink_simple_put(self):"},{"line_number":81,"context_line":"        self.app.register(\u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated, {})"},{"line_number":82,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":83,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_6b460ac3","line":80,"range":{"start_line":80,"start_character":4,"end_line":80,"end_character":38},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check \u0027X-Object-Sysmeta-Symlink-Target\u0027 contains \u0027/a/c1/o\u0027 to ensure that default target account is symlink\u0027s account.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"class TestSymlinkMiddleware(TestSymlinkMiddlewareBase):"},{"line_number":80,"context_line":"    def test_symlink_simple_put(self):"},{"line_number":81,"context_line":"        self.app.register(\u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated, {})"},{"line_number":82,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":83,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_48d05df8","line":80,"range":{"start_line":80,"start_character":4,"end_line":80,"end_character":38},"in_reply_to":"bff0334d_6b460ac3","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":84,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":85,"context_line":"        self.assertEqual(status, \u0027201 Created\u0027)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    def test_symlink_put_different_account(self):"},{"line_number":88,"context_line":"        self.app.register(\u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated, {})"},{"line_number":89,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":90,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_2b16c2a9","line":87,"range":{"start_line":87,"start_character":4,"end_line":87,"end_character":49},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check \u0027X-Object-Sysmeta-Symlink-Target\u0027 contains \u0027/a1/c1/o\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":84,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":85,"context_line":"        self.assertEqual(status, \u0027201 Created\u0027)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    def test_symlink_put_different_account(self):"},{"line_number":88,"context_line":"        self.app.register(\u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated, {})"},{"line_number":89,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":90,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_08da6516","line":87,"range":{"start_line":87,"start_character":4,"end_line":87,"end_character":49},"in_reply_to":"bff0334d_2b16c2a9","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        val \u003d hdrs.get(\u0027X-Object-Sysmeta-Symlink-Target\u0027)"},{"line_number":103,"context_line":"        self.assertEqual(val, \u0027/a/c1/o\u0027)"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"    def test_symlink_put_non_zero_length(self):"},{"line_number":106,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027, body\u003d\u0027req_body\u0027,"},{"line_number":107,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027})"},{"line_number":108,"context_line":"        status, headers, body \u003d self.call_sym(req)"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_2b7b62f5","line":105,"range":{"start_line":105,"start_character":4,"end_line":105,"end_character":47},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check that response body is \u0027Symlink requests require a zero byte body.\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        val \u003d hdrs.get(\u0027X-Object-Sysmeta-Symlink-Target\u0027)"},{"line_number":103,"context_line":"        self.assertEqual(val, \u0027/a/c1/o\u0027)"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"    def test_symlink_put_non_zero_length(self):"},{"line_number":106,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027, body\u003d\u0027req_body\u0027,"},{"line_number":107,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027})"},{"line_number":108,"context_line":"        status, headers, body \u003d self.call_sym(req)"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_880d5592","line":105,"range":{"start_line":105,"start_character":4,"end_line":105,"end_character":47},"in_reply_to":"bff0334d_2b7b62f5","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":108,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":109,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"    def test_symlink_put_bad_object_header(self):"},{"line_number":112,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":113,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027o\u0027})"},{"line_number":114,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_cb8516d1","line":111,"range":{"start_line":111,"start_character":4,"end_line":111,"end_character":49},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check that response body is \u0027X-Symlink-Target header must be of the form \u003ccontainer name\u003e/\u003cobject name\u003e\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":108,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":109,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"    def test_symlink_put_bad_object_header(self):"},{"line_number":112,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":113,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027o\u0027})"},{"line_number":114,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_11fdf039","line":111,"range":{"start_line":111,"start_character":4,"end_line":111,"end_character":49},"in_reply_to":"bff0334d_cb8516d1","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        else:"},{"line_number":119,"context_line":"            self.fail(\"Expecting HTTPException.\")"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    def test_symlink_put_bad_account_header(self):"},{"line_number":122,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":123,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027,"},{"line_number":124,"context_line":"                                     \u0027X-Symlink-Target-Account\u0027: \u0027a1/c1\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_6b4deac2","line":121,"range":{"start_line":121,"start_character":4,"end_line":121,"end_character":50},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check that response body is \u0027Account name cannot contain slashes\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        else:"},{"line_number":119,"context_line":"            self.fail(\"Expecting HTTPException.\")"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    def test_symlink_put_bad_account_header(self):"},{"line_number":122,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027PUT\u0027,"},{"line_number":123,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027c1/o\u0027,"},{"line_number":124,"context_line":"                                     \u0027X-Symlink-Target-Account\u0027: \u0027a1/c1\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_4b05d0c1","line":121,"range":{"start_line":121,"start_character":4,"end_line":121,"end_character":50},"in_reply_to":"bff0334d_6b4deac2","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":146,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":147,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":148,"context_line":"        self.assertEqual(body, \u0027resp_body\u0027)"},{"line_number":149,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target\u0027, \u0027c1/o\u0027), headers)"},{"line_number":150,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027), headers)"},{"line_number":151,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def test_head_symlink(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_cb487688","line":150,"range":{"start_line":149,"start_character":1,"end_line":150,"end_character":69},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check special header keys, \u0027X-Symlink-Target\u0027, and \u0027X-Symlink-Target-Account\u0027 are not in the headers.\nBut, these assertion check pairs with special keys are not in the headers.\nFor example, (\u0027X-Symlink-Target\u0027, \u0027c/o\u0027) can be in the headers.\nSo, \"self.assertNotIn(\u0027X-Symlink-Target\u0027, dict(headers))\" and \"self.assertNotIn(\u0027X-Symlink-Target-Account\u0027, dict(headers))\" will be better.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":146,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":147,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":148,"context_line":"        self.assertEqual(body, \u0027resp_body\u0027)"},{"line_number":149,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target\u0027, \u0027c1/o\u0027), headers)"},{"line_number":150,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027), headers)"},{"line_number":151,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def test_head_symlink(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_d9c53d90","line":150,"range":{"start_line":149,"start_character":1,"end_line":150,"end_character":69},"in_reply_to":"bff0334d_cb487688","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":173,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":174,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":175,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target\u0027, \u0027c1/o\u0027), headers)"},{"line_number":176,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027), headers)"},{"line_number":177,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027), headers)"},{"line_number":178,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":179,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_26015706","line":176,"range":{"start_line":175,"start_character":1,"end_line":176,"end_character":69},"updated":"2017-04-10 09:30:11.000000000","message":"Same as test_get_target_object.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":173,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":174,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":175,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target\u0027, \u0027c1/o\u0027), headers)"},{"line_number":176,"context_line":"        self.assertNotIn((\u0027X-Symlink-Target-Account\u0027, \u0027a2\u0027), headers)"},{"line_number":177,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027), headers)"},{"line_number":178,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":179,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_b9c28984","line":176,"range":{"start_line":175,"start_character":1,"end_line":176,"end_character":69},"in_reply_to":"bff0334d_26015706","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":178,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":179,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    def test_symlink_too_deep(self):"},{"line_number":182,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"},{"line_number":183,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/sym1\u0027})"},{"line_number":184,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/sym1\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_4630dbe8","line":181,"range":{"start_line":181,"start_character":4,"end_line":181,"end_character":36},"updated":"2017-04-10 09:30:11.000000000","message":"This method checks only HEAD.\nIMO, same pattern should be checked with GET.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":178,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":179,"context_line":"        self.assertIn((\u0027Content-Location\u0027, \u0027/v1/a2/c1/o\u0027), headers)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    def test_symlink_too_deep(self):"},{"line_number":182,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"},{"line_number":183,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/sym1\u0027})"},{"line_number":184,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/sym1\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_c6598b35","line":181,"range":{"start_line":181,"start_character":4,"end_line":181,"end_character":36},"updated":"2017-04-10 09:30:11.000000000","message":"This method should check reponse body is \"Too many levels of symbolic links, maximum allowed is 2\".","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":201,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/sym2\u0027})"},{"line_number":202,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/sym2\u0027, swob.HTTPOk,"},{"line_number":203,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/o\u0027,"},{"line_number":204,"context_line":"                           \u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":205,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/o\u0027, swob.HTTPOk,"},{"line_number":206,"context_line":"                          {\u0027X-Object-Meta-Color\u0027: \u0027Green\u0027})"},{"line_number":207,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027HEAD\u0027)"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_2686f767","line":204,"range":{"start_line":204,"start_character":26,"end_line":204,"end_character":55},"updated":"2017-04-10 09:30:11.000000000","message":"I think this method checks symloop_max is effective or not.\nSo \u0027X-Object-Meta-Color\u0027 is not target of this method.\nIMO, this metadata should be removed.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":201,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/sym2\u0027})"},{"line_number":202,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/sym2\u0027, swob.HTTPOk,"},{"line_number":203,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/o\u0027,"},{"line_number":204,"context_line":"                           \u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":205,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/o\u0027, swob.HTTPOk,"},{"line_number":206,"context_line":"                          {\u0027X-Object-Meta-Color\u0027: \u0027Green\u0027})"},{"line_number":207,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027HEAD\u0027)"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_dcd66ff2","line":204,"range":{"start_line":204,"start_character":26,"end_line":204,"end_character":55},"in_reply_to":"bff0334d_2686f767","updated":"2017-05-19 16:29:21.000000000","message":"i\u0027m going to leave it, it is also testing that the correct metadata was returned. I will add a comment to point that out.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":203,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c/o\u0027,"},{"line_number":204,"context_line":"                           \u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":205,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/o\u0027, swob.HTTPOk,"},{"line_number":206,"context_line":"                          {\u0027X-Object-Meta-Color\u0027: \u0027Green\u0027})"},{"line_number":207,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027HEAD\u0027)"},{"line_number":208,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":209,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_c6806b49","line":206,"range":{"start_line":206,"start_character":25,"end_line":206,"end_character":59},"updated":"2017-04-10 09:30:11.000000000","message":"Same as above.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027), headers)"},{"line_number":211,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"    def test_sym_to_sym_to_target(self):"},{"line_number":214,"context_line":"        # this test is also validating that the symlink metadata is not"},{"line_number":215,"context_line":"        # returned, but the target object metadata does return"},{"line_number":216,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_8672637a","line":213,"range":{"start_line":213,"start_character":4,"end_line":213,"end_character":40},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, \u0027Content-Location\u0027 should be checked\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Red\u0027), headers)"},{"line_number":211,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"    def test_sym_to_sym_to_target(self):"},{"line_number":214,"context_line":"        # this test is also validating that the symlink metadata is not"},{"line_number":215,"context_line":"        # returned, but the target object metadata does return"},{"line_number":216,"context_line":"        self.app.register(\u0027HEAD\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_7c276366","line":213,"range":{"start_line":213,"start_character":4,"end_line":213,"end_character":40},"in_reply_to":"bff0334d_8672637a","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":230,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Yellow\u0027), headers)"},{"line_number":231,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def test_symlink_post_no_queryparam(self):"},{"line_number":234,"context_line":"        self.app.register(\u0027POST\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPAccepted,"},{"line_number":235,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c1/o\u0027})"},{"line_number":236,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027POST\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_0691b34e","line":233,"range":{"start_line":233,"start_character":4,"end_line":233,"end_character":46},"updated":"2017-04-10 09:30:11.000000000","message":"In my understanding, symlink\u0027s metadata will be updated by POST request without queryparam and this behavior is specification of symlink.\nIMO, this method should check POST requiests will be applied or not.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":230,"context_line":"        self.assertNotIn((\u0027X-Object-Meta-Color\u0027, \u0027Yellow\u0027), headers)"},{"line_number":231,"context_line":"        self.assertIn((\u0027X-Object-Meta-Color\u0027, \u0027Green\u0027), headers)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def test_symlink_post_no_queryparam(self):"},{"line_number":234,"context_line":"        self.app.register(\u0027POST\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPAccepted,"},{"line_number":235,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c1/o\u0027})"},{"line_number":236,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027POST\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_bce85b16","line":233,"range":{"start_line":233,"start_character":4,"end_line":233,"end_character":46},"in_reply_to":"bff0334d_0691b34e","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":235,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c1/o\u0027})"},{"line_number":236,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027POST\u0027,"},{"line_number":237,"context_line":"                            headers\u003d{\u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":238,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":239,"context_line":"        self.assertEqual(status, \u0027307 Temporary Redirect\u0027)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def test_symlink_post_queryparam(self):"},{"line_number":242,"context_line":"        self.app.register(\u0027POST\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPAccepted,"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_e696cf3e","line":239,"range":{"start_line":238,"start_character":8,"end_line":239,"end_character":58},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check response body is \u0027POST to symlink is not allowed. POST directly to target object\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":235,"context_line":"                          {\u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027/a/c1/o\u0027})"},{"line_number":236,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/symlink\u0027, method\u003d\u0027POST\u0027,"},{"line_number":237,"context_line":"                            headers\u003d{\u0027X-Object-Meta-Color\u0027: \u0027Red\u0027})"},{"line_number":238,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":239,"context_line":"        self.assertEqual(status, \u0027307 Temporary Redirect\u0027)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def test_symlink_post_queryparam(self):"},{"line_number":242,"context_line":"        self.app.register(\u0027POST\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPAccepted,"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_7ca40309","line":239,"range":{"start_line":238,"start_character":8,"end_line":239,"end_character":58},"in_reply_to":"bff0334d_e696cf3e","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":254,"context_line":"        self.assertEqual(status, \u0027202 Accepted\u0027)"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"    def test_set_symlink_POST_fail(self):"},{"line_number":257,"context_line":"        # Setting a link with a POST request is not allowed"},{"line_number":258,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027POST\u0027,"},{"line_number":259,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027/a/c1/regular_obj\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_267b97f5","line":256,"range":{"start_line":256,"start_character":4,"end_line":256,"end_character":41},"updated":"2017-04-10 09:30:11.000000000","message":"IMO, this method should check response body is \u0027A PUT request is required to set a symlink target\u0027.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        status, headers, body \u003d self.call_sym(req)"},{"line_number":254,"context_line":"        self.assertEqual(status, \u0027202 Accepted\u0027)"},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"    def test_set_symlink_POST_fail(self):"},{"line_number":257,"context_line":"        # Setting a link with a POST request is not allowed"},{"line_number":258,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027POST\u0027,"},{"line_number":259,"context_line":"                            headers\u003d{\u0027X-Symlink-Target\u0027: \u0027/a/c1/regular_obj\u0027})"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_5c749f99","line":256,"range":{"start_line":256,"start_character":4,"end_line":256,"end_character":41},"in_reply_to":"bff0334d_267b97f5","updated":"2017-05-19 16:29:21.000000000","message":"Done","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"class SymlinkCopyingTestCase(TestSymlinkMiddlewareBase):"},{"line_number":265,"context_line":"    # verify interaction of copy and symlink middlewares"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_06f77361","line":264,"range":{"start_line":264,"start_character":0,"end_line":264,"end_character":56},"updated":"2017-04-10 09:30:11.000000000","message":"I think tests for combination of symlink middleware and copy middleware should be implemented as functional tests.\nBecause these tests are not UNIT test.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":""},{"line_number":264,"context_line":"class SymlinkCopyingTestCase(TestSymlinkMiddlewareBase):"},{"line_number":265,"context_line":"    # verify interaction of copy and symlink middlewares"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_fc3493e0","line":264,"range":{"start_line":264,"start_character":0,"end_line":264,"end_character":56},"in_reply_to":"bff0334d_06f77361","updated":"2017-05-19 16:29:21.000000000","message":"we do have similar tests in functional tests, but swift unit tests are a little different where we typically do some of these more aggregate tests too","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":320,"context_line":"        self.assertEqual(val, \u0027/new_acct/new_cont/new_obj\u0027)"},{"line_number":321,"context_line":""},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"class SymlinkVersioningTestCase(TestSymlinkMiddlewareBase):"},{"line_number":324,"context_line":"    # verify interaction of versioned_writes and symlink middlewares"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_468d7bd1","line":323,"range":{"start_line":323,"start_character":0,"end_line":323,"end_character":59},"updated":"2017-04-10 09:30:11.000000000","message":"Same as SymlinkCopyingTestCase.\nThese tests should be implemented as functional tests.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"a3ac578cb347215ce181dce33fd1ea3d9ab53db7","unresolved":false,"context_lines":[{"line_number":320,"context_line":"        self.assertEqual(val, \u0027/new_acct/new_cont/new_obj\u0027)"},{"line_number":321,"context_line":""},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"class SymlinkVersioningTestCase(TestSymlinkMiddlewareBase):"},{"line_number":324,"context_line":"    # verify interaction of versioned_writes and symlink middlewares"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":53,"id":"ff0f0b1f_fc1b7370","line":323,"range":{"start_line":323,"start_character":0,"end_line":323,"end_character":59},"in_reply_to":"bff0334d_468d7bd1","updated":"2017-05-19 16:29:21.000000000","message":"functional tests do have versioning tests, but I think it\u0027s a good idea to keep these too","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":14766,"name":"Kazuhiro MIYAHARA","email":"miyahara.kazuhiro@lab.ntt.co.jp","username":"miyahara"},"change_message_id":"82f318c4cec02009dd57df18165d09358048eea7","unresolved":false,"context_lines":[{"line_number":425,"context_line":"            req_headers[\u0027X-Object-Sysmeta-Symlink-Target\u0027])"},{"line_number":426,"context_line":""},{"line_number":427,"context_line":""},{"line_number":428,"context_line":"class TestSymlinkConfiguration(unittest.TestCase):"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"    def setUp(self):"},{"line_number":431,"context_line":"        self.tmpdir \u003d tempfile.mkdtemp()"}],"source_content_type":"text/x-python","patch_set":53,"id":"bff0334d_662cffab","line":428,"range":{"start_line":428,"start_character":0,"end_line":428,"end_character":50},"updated":"2017-04-10 09:30:11.000000000","message":"I think symloop_max in config is effective or not should be checked.","commit_id":"54774b19879d8d2666d9ef3037449420a3b45d75"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6d85989c945dd07cad74207eca6a66944a7be62d","unresolved":false,"context_lines":[{"line_number":782,"context_line":"            \u0027\u003cobject\u003e\u003cname\u003enormal_obj\u003c/name\u003e\u003chash\u003eetag2\u003c/hash\u003e\u0027"},{"line_number":783,"context_line":"            \u0027\u003cbytes\u003e32\u003c/bytes\u003e\u003ccontent_type\u003etext/plain\u003c/content_type\u003e\u0027"},{"line_number":784,"context_line":"            \u0027\u003clast_modified\u003e2014-11-21T14:14:27.409100\u003c/last_modified\u003e\u0027"},{"line_number":785,"context_line":"            \u0027\u003c/object\u003e\u003c/container\u003e\u0027])"}],"source_content_type":"text/x-python","patch_set":75,"id":"df87a7cf_b596a6ef","line":785,"updated":"2017-12-08 20:25:30.000000000","message":"I *really* like this test suite - everytime I drop a NameErorr in the middleware and run these tests it I get a very quick failure in a test named like\n\n    \"test_the_code_you_just_broke_works\"\n\nthat\u0027s *awesome*","commit_id":"f1d0457ac0309961c0c85632d22a290e2a769c8b"}],"test/unit/common/test_internal_client.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":337,"context_line":"        actual_params \u003d dict(parse_qsl(captured_envs[0][\u0027QUERY_STRING\u0027],"},{"line_number":338,"context_line":"                                       keep_blank_values\u003dTrue,"},{"line_number":339,"context_line":"                                       strict_parsing\u003dTrue))"},{"line_number":340,"context_line":"        self.assertEqual(params, actual_params)"},{"line_number":341,"context_line":""},{"line_number":342,"context_line":"    def test_make_request_retries(self):"},{"line_number":343,"context_line":"        class InternalClient(internal_client.InternalClient):"}],"source_content_type":"text/x-python","patch_set":79,"id":"df87a7cf_52ab3e74","line":340,"updated":"2017-12-14 01:13:05.000000000","message":"ok, those changed (and new added) tests failed if i commented out the param change.","commit_id":"99b89aea1051208e3d71afa35fcd62035e702628"}],"test/unit/container/test_sync.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"50fc246fd0bbffc63fe0658cac8c7517513a2eaf","unresolved":false,"context_lines":[{"line_number":1148,"context_line":"            self.assertEqual(str(exc[-1]), \u0027test client exception\u0027)"},{"line_number":1149,"context_line":""},{"line_number":1150,"context_line":"            def fake_get_object(acct, con, obj, headers, acceptable_statuses,"},{"line_number":1151,"context_line":"                                params\u003dNone):"},{"line_number":1152,"context_line":"                self.assertEqual({\u0027symlink\u0027: \u0027get\u0027}, params)"},{"line_number":1153,"context_line":"                self.assertEqual(headers[\u0027X-Newest\u0027], True)"},{"line_number":1154,"context_line":"                self.assertEqual(headers[\u0027X-Backend-Storage-Policy-Index\u0027],"},{"line_number":1155,"context_line":"                                 \u00270\u0027)"}],"source_content_type":"text/x-python","patch_set":79,"id":"df87a7cf_d2e50ede","line":1152,"range":{"start_line":1151,"start_character":0,"end_line":1152,"end_character":60},"updated":"2017-12-14 01:13:05.000000000","message":"if the `param` should be {\u0027symlink\u0027: \u0027get\u0027} always, the `param` should be required argument instead of defaults None? When I turn it to a required args, no tests failed.","commit_id":"99b89aea1051208e3d71afa35fcd62035e702628"}]}
