プログラマでありたい

おっさんになっても、プログラマでありつづけたい

AWS SDK for iOSでリージョンを指定する

 AWS SDK for iOSを使ってみました。とりあえずS3が使いたいので、サンプル見ながらコーディング。サンプルには、およそS3を使う上で必要なものは殆ど網羅しています。余り困ることは無かったのですが、ダウンロードをするとエラーメッセージが出てくるバケットがありました。エラーの内容は次のとおりです。

The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.


 Rubyでも何回か見たような気がしますが、デフォルト以外のリージョンを使う場合はエンドポイントを指定せよとのことだと思います。では、エンドポイントをどうやって指定したら良いのか?メソッドを見てみると、setEndpointというモノが用意されていました。AmazonS3ClientとS3GetObjectRequestのどちらで指定しても良さそうです。オブジェクトのリクエストなので、S3GetObjectRequestのタイミングごとに指定するのが良いのかなぁと思います。EndPointのリストは、次のページでまとまっています。
Regions and Endpoints - Amazon Web Services Glossary


 次のようなソースを書きました。

    NSString *bucketName = [NSString stringWithFormat:@"your backet name"];
    NSString *keyName    = [NSString stringWithFormat:@"hoge.txt"];

    // Puts the file as an object in the bucket.
    S3GetObjectRequest *getObjectRequest = [[[S3GetObjectRequest alloc] initWithKey:keyName withBucket:bucketName] autorelease];
    [getObjectRequest setEndpoint:@"s3-ap-northeast-1.amazonaws.com"];


 そうすると、次のようなエラーが

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSCFConstantString substringFromIndex:]: Range or index out of bounds'
First throw call stack:

(0x17bf022 0x14becd6 0x1767a48 0x17679b9 0xd27c2 0x24875 0x246fe 0x24132 0x1f567 0x1c933 0x1c07b 0x1b2ee 0x2308 0x17c0e42 0xe69df 0x179394f 0x16f6b43 0x16f6424 0x16f5d84 0x16f5c9b 0x1eb67d8 0x1eb688a 0x41e626 0xdc7d 0x1ef5)


 何故、NSRangeExceptionが???悩むこと1時間以上。
S3/S3Constants.hを見たら、全ての謎が解けました。

// Endpoint
#define kS3ServiceEndpoint                   @"http://s3.amazonaws.com"

http://から始めないと駄目なのです。(もしくはhttps://)
ですので、正しくは下記のソースになります。

    [getObjectRequest setEndpoint:@"https://s3-ap-northeast-1.amazonaws.com"];


 ついでに言うと、単純にS3の東京リージョン使っている場合は、上記のような指定は特に必要ない模様です。 Hosting Websites on Amazon S3を使っている場合のみ、ちゃんと指定が必要な模様です。(付けておくことに越した事はないと思います。)


 こんな些細なことでも、ハマると時間掛かりますよという話でした。