この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Nodeで AWS SDK を使っていてもう少し便利だと良いのになと思ったので、どうしたら便利になるかを考えてみました。
まずは誰もが使って分かりやすそうな「S3」を対象にしてみます。
ちなみに「CoffeeScript」を利用しています。
S3
バケットの作成 - (AWS.Request) createBucket(params = {}, callback)
そのまま利用すると以下のようになります。
s3.createBucket params, (err, data) ->
if err
console.log err
else
console.log data
単純に作成するだけなら別に問題はないのですが、作成しようとしたバケット名が既にある時には以下のようなエラーが発生してしまいます。
- BucketAlreadyExists
- BucketAlreadyOwnedByYou
バケットが存在しない時だけに作成できればいいのにと思うので、バケットが存在しない時にだけバケット作成を行うようにしてみます。
create_bucket = (bucket, callback, params = {}) ->
params.Bucket = bucket if bucket?
params.Key = key if key?
head_bucket bucket, (err, data) =>
if err?.statusCode is 404
s3.createBucket params, (err, data) ->
console.log "create_bucket"
callback err, data
else
callback err, data
head_bucket = (bucket, callback) ->
params = {}
params.Bucket = bucket if bucket?
s3.headBucket params, (err, data) =>
console.log "headBucket"
callback err, data
「headBucket」メソッドを利用することでバケットの存在チェックを行うことができます。
(AWS.Request) headBucket(params = {}, callback)
エラーの場合
"statusCode"が "404"だったらバケットが存在しない。
"statusCode"が "301"だったらバケットが存在する(他人が作成したバケット)。
正常の場合
バケットが存在する(自分が作成したバケット)。
よって、"statusCode"が "404"の時だけバケットを作成するようにしてみました。
"statusCode"が "301"の時にはそのままエラーとして、正常だったら何もしないのが良いかなと。
「createBucket」メソッドには他にもいろいろオプションはありますが、指定できるようにだけしておきます。
(何か便利な指定の仕方ありませんかね)
バケットの削除 - (AWS.Request) deleteBucketCors(params = {}, callback)
そのまま利用すると以下のようになります。
s3.deleteBucket params, (err, data) ->
if err
console.log err
else
console.log data
バケットの作成と同様に自分のバケットがある時だけ削除するようにしてみます。
delete_bucket = (bucket, callback) ->
params = {}
params.Bucket = bucket if bucket?
head_bucket bucket, (err, data) =>
if err?.statusCode is 404
callback null, data
else if err?.statusCode is 403
callback err, data
else if err?.statusCode is 301
callback err, data
else
s3.deleteBucket params, (err, data) ->
console.log "delete_bucket"
callback err, data
head_bucket = (bucket, callback) ->
params = {}
params.Bucket = bucket if bucket?
s3.headBucket params, (err, data) =>
console.log "headBucket"
callback err, data
同じく「headBucket」メソッドを利用してバケットの存在チェックを行なって、正常の時のみ削除するようにしてみました。
バケットの削除は、バケット内に一つでもオブジェクトがあると削除できないも不便ですね。
オブジェクトをすべて削除してからバケットを削除できるようなメソッドも作ってみました。
delete_bucket_force = (bucket, callback) ->
head_bucket bucket, (err, data) =>
if err?.statusCode is 404
callback null, data
else if err?.statusCode is 403
callback err, data
else
list_objects bucket, (err, data) =>
if err
callback err, data
else
console.log data.Contents
unless data.Contents.length is 0
delete_objects bucket, data.Contents, (err, data) =>
if err
callback err, data
else
params = {}
params.Bucket = bucket if bucket?
s3.deleteBucket params, (err, data) ->
console.log "delete_bucket_force"
callback err, data
else
params = {}
params.Bucket = bucket if bucket?
s3.deleteBucket params, (err, data) ->
console.log "delete_bucket_force"
callback err, data
head_bucket = (bucket, callback) ->
params = {}
params.Bucket = bucket if bucket?
s3.headBucket params, (err, data) =>
console.log "headBucket"
callback err, data
list_objects = (bucket, callback, params = {}) ->
params.Bucket = bucket if bucket?
s3.listObjects params, (err, data) =>
console.log "list_objects"
console.log data.Contents if data?
callback err, data
delete_objects = (bucket, deletes, callback, params = {}) ->
params.Bucket = bucket if bucket?
keys = []
for key in deletes
keys.push { Key: key.Key }
params.Delete = {
Objects: keys
}
s3.deleteObjects params, (err, data) ->
console.log "delete_objects"
callback err, data
「listObjects」メソッドでオブジェクトの一覧を取得して、「deleteObjects」で取得した一覧すべてを削除しています。
クラス化
バケットの作成と削除はちょっと便利になった気がしますが、その他のメソッドはそのままでもそんなに問題ありませんでした。
そこでせっかく「CoffeeScript」を利用しているので、クラス化して便利に使えるようにしてみます。
(全メソッドは用意していませんが、今回紹介した以外のメソッドも用意していたりもします)
class S3
AWS = require 'aws-sdk'
path = require 'path'
constructor: (file) ->
AWS.config.loadFromPath path.normalize file
@s3 = new AWS.S3()
create_bucket: (bucket, callback, params = {}) ->
params = @create_params bucket, null, params
@head_bucket bucket, (err, data) =>
if err?.statusCode is 404
@s3.createBucket params, (err, data) ->
console.log "create_bucket"
callback err, data
else
callback err, data
delete_bucket: (bucket, callback) ->
params = @create_params bucket, null
@head_bucket bucket, (err, data) =>
if err?.statusCode is 404
callback null, data
else if err?.statusCode is 403
callback err, data
else if err?.statusCode is 301
callback err, data
else
@s3.deleteBucket params, (err, data) ->
console.log "delete_bucket"
callback err, data
delete_bucket_force: (bucket, callback) ->
@head_bucket bucket, (err, data) =>
if err?.statusCode is 404
callback null, data
else if err?.statusCode is 403
callback err, data
else
@list_objects bucket, (err, data) =>
if err
callback err, data
else
unless data.Contents.length is 0
@delete_objects bucket, data.Contents, (err, data) =>
if err
callback err, data
else
params = @create_params bucket, null
@s3.deleteBucket params, (err, data) ->
console.log "delete_bucket_force"
callback err, data
else
params = @create_params bucket, null
@s3.deleteBucket params, (err, data) ->
console.log "delete_bucket_force"
callback err, data
delete_object: (bucket, key, callback) ->
params = @create_params bucket, key
@head_object bucket, key, (err, data) =>
if err?.statusCode is 404
callback null, data
else if err?.statusCode is 403
callback err, data
else
@s3.deleteObject params, (err, data) ->
console.log "delete_object"
callback err, data
delete_objects: (bucket, deletes, callback, params = {}) ->
params = @create_params bucket, null, params
keys = []
for key in deletes
keys.push { Key: key.Key }
params.Delete = {
Objects: keys
}
@s3.deleteObjects params, (err, data) ->
console.log "delete_objects"
callback err, data
getBucketVersioning: (bucket, callback) ->
params = @create_params bucket, null
@s3.getBucketVersioning params, (err, data) =>
console.log "getBucketVersioning"
callback err, data
get_acl: (params, callback) ->
@s3.getBucketAcl params, (err, data) ->
console.log "get_acl"
console.log data.Grants if data?
callback err, data
get_object: (params, callback) ->
@s3.getObject params, (err, data) ->
console.log "get_object"
callback err, data
head_bucket: (bucket, callback) ->
params = @create_params bucket, null
@s3.headBucket params, (err, data) =>
console.log "headBucket"
callback err, data
head_object: (bucket, key, callback) ->
params = @create_params bucket, key
@s3.headObject params, (err, data) =>
console.log "head_object"
callback err, data
put_object: (bucket, key, callback, params = {}) ->
params = @create_params bucket, key, params
@s3.putObject params, (err, data) ->
console.log "put_object"
callback err, data
list_buckets: (callback) ->
@s3.listBuckets null, (err, data) ->
console.log "list_buckets"
console.log data.Buckets if data?
callback err, data
list_objects: (bucket, callback, params = {}) ->
params = @create_params bucket, null, params
@s3.listObjects params, (err, data) =>
console.log "list_objects"
console.log data.Contents if data?
callback err, data
create_params: (bucket, key, params = {}) ->
params.Bucket = bucket if bucket?
params.Key = key if key?
return params
module.exports = S3
利用例
async = require 'async'
S3 = require './S3'
s3 = new S3('../config/config.json')
bucket_name = "classmethod-hoge"
key_name = ""
delete_bucket_force = (callback) ->
s3.delete_bucket_force bucket_name, callback
delete_bucket = (callback) ->
s3.delete_bucket bucket_name, callback
create_bucket = (callback) ->
params =
ACL: "public-read"
CreateBucketConfiguration: {
LocationConstraint: "ap-northeast-1"
}
s3.create_bucket bucket_name, callback, params
put_object = (callback) ->
params =
Body: "Hello world!"
key_name = "Key"
s3.put_object bucket_name, key_name, callback, params
get_object = (callback) ->
s3.get_object bucket_name, key_name, callback, params
delete_object = (callback) ->
s3.delete_object bucket_name, key_name, callback
list_buckets = (callback) ->
s3.list_buckets callback
list_objects = (callback) ->
s3.list_objects bucket_name, callback
tasks = []
tasks.push list_buckets
tasks.push create_bucket
tasks.push put_object
tasks.push delete_object
tasks.push delete_bucket
async.series tasks, (err, results) ->
if err
console.log err
else
console.log results
パラメータをもう少し便利に使う方法があれば、もっと良くなる気がするんですが・・・
なお、今回のソースはgithubに公開してあります
https://github.com/jun116/aws-sdk-coffee