S3 ListObjects APIの新バージョン ListObjectsV2を使おう

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今日弊社内のチャットで「S3のAPIにListObjectsV2っていう見たこと無いものがある!」という話題で盛り上がりました。 調べてみたところ、5/4にリリースされたAPIのようです。

社内での認知度が低かったので、これはもっとこの存在を広めるべきなのでは、と思いこのブログを書いています。

ListObjectsV2とは

名前の通り、元からS3に存在していたListObjects APIのVersion 2として提供されています。本記事では以降、今までのAPIをv1、今回追加されたAPIをv2と呼びます。ドキュメントに以下の記載がある通り、v1のサポートも続けるが、今後の新規開発ではv2を利用することが推奨されています。

This API has been revised. We recommend that you use the newer version, GET Bucket (List Objects) version 2, when developing applications. For more information, see GET Bucket (List Objects) Version 2. For backward compatibility, Amazon S3 continues to support GET Bucket (List Objects) version 1.

主な変更点

以降、私がドキュメントを読んで & SDK for Ruby経由でAPIを叩いてみて知った主な違いを記載していきます。

fetch-ownerパラメータの追加

v2 APIでfetch-ownerというパラメータが追加されています。v2 APIではオブジェクトのOwner情報がレスポンスに含まれなくなったため、Owner情報を取得する場合にはこのパラメータを追加しましょう。

[6] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/') # fetch_ownerなし
{
    :is_truncated => false,
        :contents => [
        [0] {
                      :key => "v2api/",
            :last_modified => 2016-06-14 06:40:10 UTC,
                     :etag => "\"d41d8cd98f00b204e9800998ecf8427e\"",
                     :size => 0,
            :storage_class => "STANDARD"
        },
        [1] {
                      :key => "v2api/sample.txt",
            :last_modified => 2016-06-14 06:40:57 UTC,
                     :etag => "\"14758f1afd44c09b7992073ccf00b43d\"",
                     :size => 7,
            :storage_class => "STANDARD"
        }
    ],
            :name => "sample-bucket",
          :prefix => "v2api/",
        :max_keys => 1000,
       :key_count => 2
}

[7] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/', fetch_owner: true) # fetch_owner: trueを追加
{
    :is_truncated => false,
        :contents => [
        [0] {
                      :key => "v2api/",
            :last_modified => 2016-06-14 06:40:10 UTC,
                     :etag => "\"d41d8cd98f00b204e9800998ecf8427e\"",
                     :size => 0,
            :storage_class => "STANDARD",
                    :owner => {
                :display_name => "owner-of-the-object",
                          :id => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        },
        [1] {
                      :key => "v2api/sample.txt",
            :last_modified => 2016-06-14 06:40:57 UTC,
                     :etag => "\"14758f1afd44c09b7992073ccf00b43d\"",
                     :size => 7,
            :storage_class => "STANDARD",
                    :owner => {
                :display_name => "owner-of-the-object",
                          :id => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        }
    ],
            :name => "sample-bucket",
          :prefix => "v2api/",
        :max_keys => 1000,
       :key_count => 2
}

start-afterパラメータの追加

新たにstart-afterパラメータが追加されました。S3のKeyを指定すると、そのキーよりも後のレンジのオブジェクトを取得できるようになります。

[11] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/').contents.map(&:key)
[
    [0] "v2api/",
    [1] "v2api/a.txt",
    [2] "v2api/b.txt",
    [3] "v2api/c.txt"
]
[12] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/', start_after: 'v2api/a.txt').contents.map(&:key)
[
    [0] "v2api/b.txt",
    [1] "v2api/c.txt"
]

markerがstarting-tokenに変更

v1 APIでは取得されたオブジェクト件数が、リクエストパラメータで指定されたmax-itemsか、デフォルト値(1000)以上存在した場合には、NextMarkerという値がレスポンスで返却されていました。その値を次のAPIコールにmarkerパラメータとして与えることで残りの値を取得することができました。

v2 APIではパラメータの名前がcontinuation-tokenに変更になり、レスポンスの値がnext-continuation-tokenになりました。挙動はMarkerと特に変わらないようです。

[4] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/', max_keys: 2).contents.map(&:key)
[
    [0] "v2api/",
    [1] "v2api/a.txt"
]
[5] pry(main)> continuation_token = s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/', max_keys: 2).next_continuation_token
"1lmOGANa7kmIaew4st0tmj4+U10YPksAuNAqhGEV3CyMCoBYAKsTZnA=="
[61] pry(main)> s3.list_objects_v2(bucket: 'sample-bucket', prefix:'v2api/', max_keys: 2, continuation_token: continuation_token).contents.map(&:key)
[
    [0] "v2api/b.txt",
    [1] "v2api/c.txt"
]sample-bucket

まとめ

ListObjectsV2での変更点について記載しました。記事の最初に記載した通り、V1のサポートが打ち切られるわけではないので急いでV2に切り替える必要はないと思います。新規開発する際には、V2 APIを利用してみてはいかがでしょうか。

個人的にはstart-afterパラメータが良さ気だと思っています。オブジェクトキーにタイムスタンプが含まれる際に、ある特定時刻以降のオブジェクトを取得するために使えそうな気がしています。