眠いので手短にまとめる。
普通にPUTするURL取得する
import AWS from "aws-sdk";
const s3 = new AWS.S3();
async function getPresignedURLForPUT(path){
return new Promise((resolve,reject)=>{
s3.getSignedUrl("putObject", {
Bucket: "example.com",
Key: path,
Expires: 60 * 60 * 24 * 365
}, (err, url) => {
if (err) {
reject(err);
} else {
resolve(url);
}
});
});
}
console.log(await getPresignedURLForPUT("aaa/bbb.jpg");
AWSのアクセスキーやシークレットなどは環境変数に入っている前提。 AWS_DEFAULT_REGION
も環境変数に入っている。
最初の洗礼
この状態でやったら、URLは取得できるものの、送ろうとすると301エラー
が出る。
<Error>
<script/>
<Code>PermanentRedirect</Code>
<Message>
The bucket you are attempting to access must be addressed using the
specified endpoint. Please send all future requests to this endpoint.
</Message>
<Bucket>XXX.COM</Bucket>
<Endpoint>XXX.COM.s3.amazonaws.com</Endpoint>
<RequestId>A82721F2A44XXXX</RequestId><HostId>HPgWeSUk2cKu3AbijEu9+S41bHh7dUxSiwOEEVrS08dsrpJ3AvMP5V2iXXXXXX
</HostId>
</Error>
こんな感じのエラーが出る。検索するとリージョン関連のエラーである様だが、環境変数には入っている。
ダメ元で以下の様にしてもダメ。
const s3 = new AWS.S3();
s3.config.update({region:"ap-northeast-1"});
ところが以下の様にすると問題ないようになった。
AWS.config.update({region:"ap-northeast-1"});
const s3 = new AWS.S3();
弐の壁
先ほどので別のURLが帰って来る様になり、PUTリクエストが送れる様であったが、SignatureDoesNotMatchエラーが出る。
これによると、以下が必要になるらしい。
var s3 = new AWS.S3({
signatureVersion: 'v4'
});
最後の壁
v4だと一週間以上の有効期限のSignatureは作れないらしい。諦めて1週間有効なSignatureを作った。
所感
そもそも設定おかしいなら最初からSigned-URL返して来るなよ。っていう感じではある。