carrierwaveでS3にアップした画像に有効期限をつけると共にCloud Frontで配信するための手順


# 概要
* carrierwaveでアップロードした画像に有効期限のメタデータをつける
* cdn (cloudfront)で画像を配信するための設定
* 応用編 srcの表示をCloudFrontのドメイン名ではなく、独自のドメイン名を使う

# 環境
* rails 5.1（参考[拙記事](http://qiita.com/junara/items/1899f23c091bcee3b058) ）
* carrierwaveでS3にアップロードできている（参考[拙記事](http://qiita.com/junara/items/1899f23c091bcee3b058) ）
* AWS Route 53でドメインを設定している（参考[拙記事](http://qiita.com/junara/items/62b0e11f71111ef8e4ce)）

# 手順
## carrierwaveでアップロードした画像に有効期限のメタデータをつける
デフォルトの設定では、carrierwaveでアップロードした画像には有効期限を表すメタデータがつけられていないため、以下のメタデータを付与するようにcarrierwaveの設定を修正する。

* （例 一年後までブラウザキャッシュを保持して欲しい場合）に付与するメタデータ
    * cache-control: max-age=315576000
    * expires:Wed, 27 Jun 2018 09:34:29 GMT

### carrierwave設定の修正
Raisアプリを修正する

```config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  省略
  config.fog_attributes = {cache_control: 'max-age=31536000', expires: 1.year.from_now.httpdate}
end
```

この設定の修正により、今後carrierwaveでアップロードされた画像には全てメタデータが付与されます。


### メタデータが付与されたことの確認
メタデータが付与されているかどうかはS3のバケットの実際の画像データにアクセスすればわかます。

実際にS3でアップロードした画像のメタデータは下記のようになります。（expiresはアップロードした日時からの一年後の日時なので、アップロードのタイミングにより異なります。）

[![https://gyazo.com/ed8f58e11232a3afe4e55419ec525409](https://i.gyazo.com/ed8f58e11232a3afe4e55419ec525409.png)](https://gyazo.com/ed8f58e11232a3afe4e55419ec525409)

## cdn (cloudfront)で画像を配信するための設定
AWSにログインし、CloudFrontを選択する

[![https://gyazo.com/7715061ede1dd97927f856c404703dd3](https://i.gyazo.com/7715061ede1dd97927f856c404703dd3.png)](https://gyazo.com/7715061ede1dd97927f856c404703dd3)

Create Distributionを押す

[![https://gyazo.com/77ebe88b392ef2524c8e44c9f31d635d](https://i.gyazo.com/77ebe88b392ef2524c8e44c9f31d635d.png)](https://gyazo.com/77ebe88b392ef2524c8e44c9f31d635d)

Webの方の Get Startedを押す

[![https://gyazo.com/581f2fdd42a2df42d5ff685ad2dbec42](https://i.gyazo.com/581f2fdd42a2df42d5ff685ad2dbec42.png)](https://gyazo.com/581f2fdd42a2df42d5ff685ad2dbec42)

Origin Domain Nameを押して、出てくる選択肢からcarrierwaveがアップロードした先のS3のバケットを選ぶ。

[![https://gyazo.com/8ff1388a09b440b8b921b821c0a09fa0](https://i.gyazo.com/8ff1388a09b440b8b921b821c0a09fa0.png)](https://gyazo.com/8ff1388a09b440b8b921b821c0a09fa0)

Origin IDが自動的に設定されるのを確認する
[![https://gyazo.com/4deffb427e1ab8d4c57c9aee8fa7cac5](https://i.gyazo.com/4deffb427e1ab8d4c57c9aee8fa7cac5.png)](https://gyazo.com/4deffb427e1ab8d4c57c9aee8fa7cac5)

色々設定があるけど無視してページの最下部にあるCreate Distributionボタンを押す

[![https://gyazo.com/91ed1969d168f6d79627f134842c48b0](https://i.gyazo.com/91ed1969d168f6d79627f134842c48b0.png)](https://gyazo.com/91ed1969d168f6d79627f134842c48b0)

これで、画像を配信するためのdistributionが作成がされる。

### CloudFrontのドメインをcarrierwaveに登録する

#### CloudFrontのドメインをコピーする。

作成されたdistributionをクリックする

[![https://gyazo.com/2705091f214fa9f96cc9529125b29bff](https://i.gyazo.com/2705091f214fa9f96cc9529125b29bff.png)](https://gyazo.com/2705091f214fa9f96cc9529125b29bff)

Domain Nameをコピーする

[![https://gyazo.com/f30ea27c0eca54fde4f53b7337ff5270](https://i.gyazo.com/f30ea27c0eca54fde4f53b7337ff5270.png)](https://gyazo.com/f30ea27c0eca54fde4f53b7337ff5270)

#### carrierwaveに登録する

Raisアプリを修正する。config.fog_publicをtrueにし、コピーしたcloudfrontのドメインをconfig.assset_hostに設定する。

```config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  省略
  config.fog_attributes = {cache_control: 'max-age=31536000', expires: 1.year.from_now.httpdate}
  config.fog_public = true
  config.asset_host = 'https://コピーしたcloudfrontのドメイン'
end
```
### 確認する

carrierwaveでアップロードした画像のソースを見てください。 ``<img src="xxxxx">``  の xxxxxの箇所に、CloudFrontのドメインが含まれていれば成功です。

[![https://gyazo.com/38bdd3d6bce8499af29063b7617b00f0](https://i.gyazo.com/38bdd3d6bce8499af29063b7617b00f0.png)](https://gyazo.com/38bdd3d6bce8499af29063b7617b00f0)

# 応用編 srcの表示をCloudFrontのドメイン名ではなく、独自のドメイン名を使う
機能としては、問題ないですがCloudFrontのドメイン名がむき出しなのはちょっとかっこ悪いので __cdn.サイト名__ を使うように設定を修正する。

 __cdn.サイト名__ のCNAMEに __CloudFrontのドメイン名__ を登録して、それらをCloudFrontとcarrierwaveに反映すればいい。
 
 CNAMEの設定はなにでやってもいいですが、今回はRoute53での例を示します。

## Route53でCloudFrontのドメイン名をCNAMEに設定する。

（以下の設定は既に自分のサイトのDomain NameをRoute 53で管理している事が必要です。）

AWSのRoute 53を選択する

[![https://gyazo.com/e5bf2f76d08a27502729e85badfdce00](https://i.gyazo.com/e5bf2f76d08a27502729e85badfdce00.png)](https://gyazo.com/e5bf2f76d08a27502729e85badfdce00)

Hosted zones → 自分のサイトの Domain Nameをクリック後、Create Record Setボタンを押す

[![https://gyazo.com/e791a90e49d1f94da219a9333debd015](https://i.gyazo.com/e791a90e49d1f94da219a9333debd015.png)](https://gyazo.com/e791a90e49d1f94da219a9333debd015)

画面横のウィンドウに独自のドメイン名（例では  __cdn.サイト名__ ）とcloud Frontのドメイン名を入力する。

[![https://gyazo.com/cb30c97e9faa207ab4bba8c2a4ec1f2b](https://i.gyazo.com/cb30c97e9faa207ab4bba8c2a4ec1f2b.png)](https://gyazo.com/cb30c97e9faa207ab4bba8c2a4ec1f2b)

Save Record Setボタンを押す

[![https://gyazo.com/14e9d378deaa5a683c517aa03ec6c299](https://i.gyazo.com/14e9d378deaa5a683c517aa03ec6c299.png)](https://gyazo.com/14e9d378deaa5a683c517aa03ec6c299)

## CloudFrontにcdn.サイト名を設定する

CloudFrontに戻り、 __cdn.サイト名__ を登録する

作成されたdistributionをクリックする

[![https://gyazo.com/2705091f214fa9f96cc9529125b29bff](https://i.gyazo.com/2705091f214fa9f96cc9529125b29bff.png)](https://gyazo.com/2705091f214fa9f96cc9529125b29bff)

Editを押す

[![https://gyazo.com/cbfe1854c0806b201f29f6ae8b31bbf3](https://i.gyazo.com/cbfe1854c0806b201f29f6ae8b31bbf3.png)](https://gyazo.com/cbfe1854c0806b201f29f6ae8b31bbf3)

Alternate Domain NamesにRoute 53で設定したcdn.サイト名を入力する

[![https://gyazo.com/f88109b5bd96ef47ce99bc676c638318](https://i.gyazo.com/f88109b5bd96ef47ce99bc676c638318.png)](https://gyazo.com/f88109b5bd96ef47ce99bc676c638318)

Yes Editを押して保存する。

[![https://gyazo.com/e3e4e0b825dc5daed66fe6e560b87261](https://i.gyazo.com/e3e4e0b825dc5daed66fe6e560b87261.png)](https://gyazo.com/e3e4e0b825dc5daed66fe6e560b87261)

## cdn.サイト名をcarrierwaveに反映

Raisアプリを修正する。config.assset_hostのCloud Frontのドメイン名を入力した箇所を __cdn.サイト名__ に置換する。

```config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  省略
  config.fog_attributes = {cache_control: 'max-age=31536000', expires: 1.year.from_now.httpdate}
  config.fog_public = true
  config.asset_host = 'https://cdn.サイト名'
end
```

## 確認する

carrierwaveでアップロードした画像のソースを見てください。 ``<img src="xxxxx">``  の xxxxxの箇所に、CloudFrontのドメインが含まれていた箇所が __cdn.サイト名__ に置換されて表示されていれば成功です。

[![https://gyazo.com/7383d59a29a78d8ea5a385ad045e9af6](https://i.gyazo.com/7383d59a29a78d8ea5a385ad045e9af6.png)](https://gyazo.com/7383d59a29a78d8ea5a385ad045e9af6)

## 参考
* https://www.algonauti.com/posts/speed-up-ugc-with-cloudfront
* https://stackoverflow.com/questions/22773374/can-carrierwave-upload-to-amazon-s3-but-serve-through-cloudfront