SPDYも廃止されたのでnginxでhttp2使いたいけど、そもそもhttp2ってなに?っていうお話
こんにちは、高橋です。最近はnginxとrailsとswiftをぐるぐるしています。
nginxは非常にパワフルなwebサーバーで、アクセス数が増大した時した時でも非常に安定してトラフィックを捌いてくれています。
Ruby on Railsを使用する場合には、unicornやpumaなどのアプリケーションサーバーと併用して使うことが多いかと思いますが、どうしてもアプリケーションサーバーの方がボトルネックになってしまいます。nginxの処理能力をどれだけ極限まで高めても、結局はアプリケーションサーバーの方で処理しきれずに503が返ってきてしまうので、どうやってアプリケーションサーバーの方を安定的に処理能力をあげるか最近は悩むところです。。
最近ではAWSのEC2などでautoscalingもよく使われているので、1台あたりのトラフィックの処理能力はそれほどカリカリにまで高める必要はないのかもしれません。
ということで前置きはこんな所で、今回は(僕が勝手に)社内にもhttp2を取り入れたいなーと思い、色々調べてサーバー上で試験的に試してみたので、まとめてみました。
nginxでHTTP/2を使用する
Googleが提唱していたSPDYを取り込んだ形でhttp/2が標準化される流れとなり、これから本格的に広まって行きそうですが、nginxではバージョン1.9.5からhttp/2をサポートするようになりました。
HTTP/2とは
http/2は、http/1.1でプロトコルレベルでの問題となっていたデータ送受信における効率の悪さを克服する形で、http/1.1ではクライアントとサーバーがシングルシーケンスでデータをやりとりを行なっていたのが、http/2ではmultipleにシーケンスのやりとりを行うことができるようになりました。これによってデータ転送と処理の効率が上がりwebページを表示するまでのスピードが上がるというわけです。
http/1.1の場合 http/1.1ではブラウザのTCP同時接続は最大4~6に制限されています。 HTTP Head of Line Blockingによりブラウザのネットワークはこんな感じに、ひとつのファイルの読み込みが終わるまでは、それ以降のファイルの読み込みはブロックされます。
http/2を使用した場合 同時に複数のファイルの読み込みを行うようになります。http/2ではブラウザの最大同時リクエスト数は100以上が可能とされていています。
webブラウザのHTTP/2対応状況
2016年9月現在のブラウザの対応状況はこんな感じです。ChromeやFirefoxなどのメジャーなブラウザではほぼほぼ対応していますが、IEやsafariなどでは一部対応といった感じのようです。
Can I use... Support tables for HTML5, CSS3, etc
HTTP/1.1からHTTP/2への主な変更点
- 根本となる部分はhttp/1.1と同じ
- http/1.1のセマンティックスは変更しない
- サーバーへのTCP接続数を1つに限定
- TLSの機構を使用してプロトコルを自動選択
- バイナリープロトコル
- 多重化送信
などといったことが挙げられます。
HTTP/2を使用すると現在のTLSは一部機能が使用できない
よりセキュアな通信を確立するために、http/2は現在のTLSの一部機能を制限することで、セキュアなプロトコルとして現在は使用されています。今後http/2に対応した形の新しいTLS、もしくはそれに替わるものが出てくるかと思います。
制限される内容はこちら
- プロトコル選択にはNPNではなくALPNを使用
- サーバー認証を共有できる接続は接続共有が可能
- TLSプロトコルは1.2以上のみが使用可能
- TLS Compressionの禁止
- Renegotiationの禁止
- DH鍵は2048bit以上を使用
- AEAD(認証付き暗号)のうち、GCMとCCM以外の暗号方式は利用できない
NPN (Next Protocol Negotiation) からALPN (Applicaiton-Layer Protocol Negotiation) へ
http/2に先行して、NPN (Next Protocol Negotiation) はTLS false start方式の次の規格としてgoogleが提唱し、SPDYを支える次期アプリケーション層プロトコルネゴシエーションとして2010年ごろに登場しました。
背景的にはwebサイトの表示速度にはネットワークの回線速度よりもRTTの影響が大きく関わっており、TCP接続のハンドシェイクを毎回行うところに非効率さがあったと判断したのかと思います。
これに関しては2011年にAkamaiが行なった調査を簡単にまとめた2012年の記事があるので、下記の引用画像を見ていただくとwebサイトの表示速度がRTT依存というのがよりわかりやすいかと思います。
引用元: Latency: The New Web Performance Bottleneck - igvita.com
これまではNPNが使用されていましたが、今後の流れとしてはhttp/2での後押しもありALPNが一般的となりそうです。
NPNとALPNの簡単な違いは、サーバーとクライアントのどちらが使用するアプリケーションプロトコルの決定を行うかというところで、NPNではクライアント側によるプロトコルの選択が行われていましたが、ALPNではサーバー側がクライアントの使用できるアプリケーションプロトコルの中から使用するプロトコルを選択するという形になります。
ALPNを使用するにはOpenSSLのバージョン1.0.2以上が必要となりますが、サーバーのOSによっては最新のOpenSSLを入れてもALPNを使用できないこともあります。
CentOSでHTTP/2とALPNを使う
CentOSでhttp/2とALPNが使用できるのはCentOS 7 以上のバージョンとなります。
UbuntuでALPNを使う
Ubuntuでhttp/2とALPNを使用する場合は、今年リリースされた Ubuntu 16.04 LTS (Xenial) 以上のバージョンになります。
nginxでのhttp2を設定
現在、nginxでhttp/2を使うには、ngx_http_v2_moduleが必要となります。
再ビルドなどに関しては他にも記事があるので割愛しますが、 サーバーのOSとOpenSSLのバージョンがhttp/2に対応していれば、nginxで使用するのは非常に簡単かと思います。
最後の最後で、もはやおまけみたいな感じになってしまいますが、listenディレクティブにhttp2と入れるだけで、基本的には完了です。
server { listen 443 ssl http2; # ~~~~~ }
付け加えるとしたら、SSLのプロトコルの設定や、ssl_ciphersなどの設定などでしょうか。その辺りに関しましては、こちらの記事を流し読み程度にご参考にしていただけると嬉しいです。
googleはもちろんのこと、facebookやtwitterといった名だたるwebサービスで既にproductionへ導入されているhttp/2で、 徐々に様々なwebサービスで導入され始めていますが、本格的に普及するまではもうしばらく時間がかかりそうな気もします。
また進展があったら、記事にしたいと思います!
Cluexではエンジニアの方を探しています!
AWS Lambdaを使用し、CloudfrontのInvalidationを走らせる
こんにちは。エンジニアの志村です。
先日assets on S3についての実装を行いました。
その際の記事は下記になります。
今回はasset_syncにより、S3にassetファイルがアップロードされた段階でCloudfrontのInvalidationをLambdaを使用して走らせるという処理を実装したいと思います!
Invalidationとは
Cloudfrontのキャッシュを明示的に消す機能です。
クラスメソッドさんの上記の記事が非常に分かりやすいかと思います。
キャッシュを使用するのに重要なポイントは適切なキャッシュ期間を設けることです。それを行わないと古いファイルがいつまで経っても配信され続けてしまいます。
特にassets on S3を使用する場合には、明示的にファイルをInvalidationしないといつまで経っても最新のassetsファイルがユーザーに配信されなくなります。
このような状況を防ぐために、S3にファイルが転送された段階で、assetsのキャッシュを消去する必要があります。
Lambdaの実装
ではLambdaの実装を始めていきます。
AWSコンソールからLambdaを選択します
「Create Lambda Function」を選択します
今回はBlueprintは使用しないので「Skip」を選択します
S3を選択します。
項目 | 説明 |
---|---|
Bucket | assets用のBucketを選択 |
Event Type | S3にassetsファイルがCreateされた段階でInvalidationを走らせたいので「Object Created(All)」を選択 |
Enable Trigger | チェックを入れると、設定したイベントが走るようになります(production等で設定する場合は注意!) |
※Prefix, Suffixは必要であれば入力して下さい。
LambdaFunctionを作成します
項目 | 説明 |
---|---|
Name | 適当な名前を入力 |
Description | 分かりやすい説明を入力 |
Runtime | 今回はPythonにします |
コードは下記のコードが非常に分かりやすかったのでそれを使用します。
※DistributionIDは自身のCloudfrontディストリビューションのIDを入力して下さい
from __future__ import print_function import boto3 import time def lambda_handler(event, context): for items in event["Records"]: path = "/" + items["s3"]["object"]["key"] print(path) client = boto3.client('cloudfront') invalidation = client.create_invalidation(DistributionId='ディストリビューションID', InvalidationBatch={ 'Paths': { 'Quantity': 1, 'Items': [path] }, 'CallerReference': str(time.time()) })
因みにですが、boto3はPython用のAWS SDKです。 Lambda FunctionをPythonで書く際には必ずと言って良いほど良く使用します。 ドキュメントも充実しているので非常に使い勝手が良いと思います。
Boto 3 Documentation — Boto 3 Docs 1.4.0 documentation
ロールやその他の設定をします
「Lambda function handler and role」のRole→「Create a custom role」を選択します。
そうすると下記のような画面が現れるので、下記のCloudfrontのInvalidationを許可するロールを作成します。
下記のようなポリシードキュメントになります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation" ], "Resource": [ "*" ] } ] }
最後に「Create function」を押下すれば完成です!
使い方
asset_syncでデプロイすると勝手にInvalidationが走ってくれます。 下記の画面で確認が出来ます。
AWSコンソールからCloudfrontを選択します
該当するディストリビューションのIDを選択します
「Invalidations」タブを選択すると、Invalidationsの状態が閲覧出来ます。ここでデプロイ直後にStatusがProgressとなっていればトリガーがきちんと走っています。
以上になります。 キャッシュの扱いって本当難しいなーと感じますが、この様に自動化してしまえば特に意識することも少なくなって、よりCloudfrontが使いやすくなりますね。
Rackの基礎
こんにちは!! エンジニアとしてインターンしている村田です。
今回はズバリRackについて書いていきたいと思います。
Rackに関しては日本語の資料もあまり多くないため、特にRailsの初心者の方はよく分からないまま見過ごしていることも多いかもしれません。
私も初心者なので探すのに苦労しました。。
そこで自分もまだまだではありますが、これを読んで自分と同じような初心者の方々がRackのぼんやりとしたイメージをつかんでいただけるように書いていきたいと思います。
それでは早速ですがやっていきましょう!
Rackが誕生した背景
まず何故Rackが必要なのか? ここがわからないと、話が頭に入ってこないですよね。
これはPSGIというPythonのインターフェースの仕様に影響を受けました。
以前のPythonフレームワーク界は、様々フレームワークが開発されたものの、そのフレームワークが特定のWebサーバーに依存した状態でした。 ただし、これではサーバーの乗り換え時の負担が大きかったりして、開発者も頭を悩ませることが多かったようです。 そこで、ある特定のルールを定めて(インターフェース)、そのルールのもとフレームワークとWebサーバーの開発を進めることにしました。
これがPSGIの正体です。
RubyのフレームワークもRailsとSinatraを筆頭に多様性に富みますし、WebサーバーもWebrickをはじめとして様々な独自のデプロイ方法を持っています。
すると、当然PSGIの代わりとなるシステムが必要になりまして、そうやって検討されていった結果現在のRackが誕生していくことになります。
Rackってなに??
さていよいよ本題にいきましょう。
Rackとは、rackup
というコマンドを打つことで指定したファイルを参照しながらWebサーバーを立ち上げられるようにしているライブラリ(gem)です。 もう少し機能自体の説明をするならば、HTTPの送受信処理を担当するモジュールです。
指定したファイル(デフォルトではconfig.ru。ちなみにruはruckupの略。)には独自のRuby DSLで様々なミドルウェアやアプリケーションを参照するように書かれています。 これをもとにWebサーバーを立ち上げていくことになります。
ビジュアル的に説明をするとこんな感じになっています。
このようにミドルウェアを介して、RailsなどのRackアプリケーションに対してWebサーバーから来たHTTPをパースしたりしています。
試しにbundle exec rake middlewareと打ってみましょう。 例えばこのような感じになって出てくると思います。
use Raven::Rack use ActionDispatch::Static use Rack::Lock use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fd239f96d58> use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use BetterErrors::Middleware use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActiveRecord::Migration::CheckPending use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache use ActionDispatch::Cookies use ActionDispatch::Session::CacheStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use Remotipart::Middleware use Rack::Head use Rack::ConditionalGet use Rack::ETag use Warden::Manager use ExceptionNotification::Rack use Bullet::Rack use OmniAuth::Strategies::Facebook run Rails::Application.routes
ここに書いてあるuse
の対象がRackミドルウェアです。
そして最後に書いてあるrun
の対象はRackアプリケーション(Rails)になります。
ちなみにuse
やrun
はRack DSLなのですが、今回は詳しく触れませんので興味がある方は調べてみてください。
ruckupの正体
こちらをご覧いただければお分かり頂けると思いますが、実はrackupコマンドがやっているのはRack::Server.start
をしているだけなんですよね。
と言われてもRack::Server
とかよく知らないって方がこの記事を読んでくださっていると思いますので、説明します。
Railsで開発をしているとrails s
、省略しないで書くと、rails server
というコマンドを打つことがあると思います。 このrails server
というコマンドも実は省略形でして、正確にはRails::Server.start
というコマンドを打っています。
何か先ほどとても似ているコマンドを見ましたよね? そうRack::Server.startです。
もちろんこの二つは関係がないわけではなく、Rails::ServerはRack::Serverのサブクラスになっているのです。
継承する中で、ポートを3000番にするなど様々な違いを作っているようですが基本的な動きの部分は引き継いでいることがわかっていただけたと思います。
Rackミドルウェアの話
Rackミドルウェアはもちろん自分で追加することもできますが、そのためには簡単なルールを幾つか覚えなくてはなりません。
1つのHashオブジェクトを引数に取る「call」メソッドが実装されていること callメソッドは「ステータスコード」、「ヘッダーを表現したHash」、「eachに反応するオブジェクト」の3つの要素を持った配列を返すこと
上にある2つがそのルールになります。
また慣習的にcallメソッドの引数にはenv
を用いることも覚えておくと得をするかもしれません。
詳しく話を始めるとDSLの説明やその他いろいろな話を書かないといけないので割愛しますが、Railsのようなアプリケーションも最後はcallで呼ばれるので
lamda do |env| [200, {"Content-Type" => "text/html"}, ["Hello, world!"]] end
簡単に言ってしまえばこのような形で動いていることになります。 これは先ほどの条件を満たしていますよね。
最後に
私の説明では物足りなかった部分も多かったと思います。 でもこれをきっかけにしてRackのイメージを掴めた方が一人でもいらっしゃればとても嬉しいです。
私もわからないことだらけなのでもっと勉強していこうと思いますが、最後にこの記事を作る上で参考にさせていただいた記事を載せておこうと思います。
それでは失礼いたします。
vertical-alignの使い方と別の実装方法について
こんにちは、エンジニアの井戸田です。
先日 vertical-align
ではまり、検索してみると予測変換で vertical-aling 効かない
と出てくるので、結構皆さんもはまっているんだなと感じました。
なので今回は僕もはまったcssのプロパティである、 vertical-align
の値・使い方や、垂直方向の調整の別の実装方法を紹介したいと思います。
コードについて、htmlはslim、cssはscssを使用しているので注意してください。
vertical-alignの説明
vertical-align
は行内のテキスト、画像の垂直方向の揃え位置を指定するプロパティです。
vertical-align
は適用できるのが、 inline要素
と テーブルセル
です。なので divタグ
や pタグ
などの ブロック要素
に対して vertical-align
を指定してもうまくいきません。
divタグ
や pタグ
に vertical-align
を指定したい時は diplay: inline
や, display: table-cell
, diplay: inline-block
を指定し、要素自体を変更する必要があります。
値 | 説明 |
---|---|
baseline | 適当した要素のベースラインを親要素のベースラインに合わせる(初期値) |
top | 適用した要素の上端を、行ボックスの上端に合わせる |
middle | 適用した要素の中心を、親要素の中心に揃える |
bottom | 適用した要素の下端を、行ボックスの下端に合わせる |
text-top | 適用した要素の上端を、親要素の文字の上端に合わせる (テーブルセルへの指定はできない) |
text-bottom | 適用した要素の上端を、親要素の文字の下端に合わせる (テーブルセルへの指定はできない) |
super | 上付き文字 (テーブルセルへの指定はできない) |
sub | 下付き文字 (テーブルセルへの指定はできない) |
pxなどの単位 | px, emなどの単位を使用しての指定(ベースラインが揃った状態を0、正の値は上方向、負の値はした方向になる) |
- 初期値が
baseline
なのですが、画像などはbaseline
を持たないため、下端が親要素のベースラインに揃えられます。 - middleとは、フォントの場合
0.5ex
。小文字の「x」の半分高さです。
top
と text-top
、 bottom
と text-bottom
、 baseline
と text-bottom
の違いについて、勘違いしやすいので下記にまとめておきます。
top と text-topの違い
.verticalAlign.verticalAlign-top span.example | Example span.parent | parent span.child | top .verticalAlign.verticalAlign-textTop span.example | Example span.parent | parent span.child | text-top
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-top { .child { vertical-align: top; } } &-textTop { .child { vertical-align: text-top; } } } .example { background-color: #fd7c79; font-size: 5rem; } .parent { background-color: #33cfff; font-size: 2.5rem; } .child { background-color: #24ff18; font-size: 1rem; }
上が top
で 下が text-top
になります。
text-top
は親要素の文字の上端(一番高い場所)を基準とします。なので上端を基準として配置することが可能です。
又 top
は適用した要素の上端を、行ボックスの上端に合わせるため上記のような表示になります。
bottom と text-bottomの違い
.verticalAlign.verticalAlign-bottom span.example | Example span.parent | parent span.child | bottom .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-bottom { .child { vertical-align: bottom; } } &-textTop { .child { vertical-align: text-bottom; } } } // 省略 以下はtopとtext-topと指定の仕方は同じです。
上が bottom
で下が text-bottom
になります。
text-bottom
は親要素の文字の下端(ディセンター文字の下端)を基準として配置することが可能です。
また bottom
は適用した要素の下端を、行ボックスの下端に合わせるため上記のような表示になります。
baseline と text-bottom
次は baseline
と bottom-text
に対してどのような違いがあるのか、説明します。
.verticalAlign.verticalAlign-baseline span.example | Example span.parent | parent span.child | baseline .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-baseline { .child { vertical-align: baseline; } } &-textBottom { .child { vertical-align: text-bottom; } } } // 省略 以下はtopとtext-topと指定の仕方は同じです。
上記を見てみるとどのような違いがあるのか迷うと思うのですが、親要素( .parent
)を対して line-height
を入れてみると違いが良く分かります。
.verticalAlign.verticalAlign-baseline span.example | Example span.parent | parent span.child | baseline .verticalAlign.verticalAlign-textBottom span.example | Example span.parent | parent span.child | text-bottom
.verticalAlign { margin: 0 0 8px 0; background-color: #f93; &-baseline { .child { vertical-align: baseline; } } &-textBottom { .child { vertical-align: text-bottom; } } } .example { background-color: #fd7c79; font-size: 5rem; } .parent { background-color: #33cfff; font-size: 2.5rem; line-height: 2; // ← 追加 } .child { background-color: #24ff18; font-size: 1rem; }
.parent
に対して line-height: 2;
を指定すると、 baseline
は親のフォントのベースライン(基準線)に合わせるので、ズレは生じません。ただ text-bottom
は親の要素の文字の下端に合わせるので、ズレが生じてしまいます。
上記の例の様に親の要素で line-height
(や height
などの縦幅調整をするプロパティ)を指定している時は注意が必要です。
(実際に実装する時には 初期値が baseline
なので、 vertical-aling: baseline;
の指定は必要ありません。)
ブロック要素への対応
テーブルセルとdisplay: table-cellの使い方
テーブルセルとは tableタグ
で使用する tdタグ
, thタグ
のことです。こちらの要素に対しても vertical-align
を使用すことができます。但し text-top
, text-bottom
, super
, sub
は指定することができません。
display: table-cell
での実装方法は下記の様になります。下記の例では .block
を垂直方向に中央揃えにしています。
.tableCell .block | block
.tableCell { display: table-cell; height: 100px; background-color: #f93; vertical-align: middle; }
block要素
に対して vertical-align
を使用する場合には、垂直方向の調整をしたいタグの親要素に対して display: table-cell
, vertical-align: ◯◯
を指定することで、使用することができます。
ただ表に関係ない要素に display: table-cell
を指定するのはバットな気がしますね。
display: inline-block
display: table-cell
を使用しないで display: inline-block
を使用する方法もあります。inline-block要素
とは inline要素
と block要素
を兼ね備えた要素です。下記の例では2つの inline-block要素
を垂直方向に中央揃えにしています。
.block .inlineBlock1 | inlineBlock1 .inlineBlock2 | inlineBlock2
.inlineBlock1 { display: inline-block; height: 8rem; background-color: #fd7c79; font-size: 2rem; vertical-align: middle; } .inlineBlock2 { display: inline-block; background-color: #33cfff; font-size: 2rem; vertical-align: middle; }
block要素
に対して display: inline-block
、 vertical-align: ◯◯
を指定することで、使用することができます。
inline-block要素
と inline要素
で異なるのが、 inline-block要素
の場合は横幅・縦幅が指定が可能なので、その分 inline要素
より使い易いかも知れません。
block
inline
inline-block
の違いについては、また別の機会に詳しく話したいと思います!
vertical-alingを使用しないで垂直方向を調整する方法として
- line-height
line-height
を使用して、親要素のheightに調整する。なんとなくバットな調整方法だと思います・・・。 - position
親のblock要素に対してposition: relative
、子要素に対してpostion: absolute
を指定する。
ただ垂直方向の中央揃えにしたいと思っていても、postion:absolute
は指定した要素の本来の位置からの相対位置なのでtop: 50%
という指定をしていても、その要素の上端が真ん中にきてしまうので、top: 50%
ではなく調整する必要があります。
上記2つを挙げましたが、それぞれ調整が難しいと思います。そこで僕個人がおすすめしたいのが FlexBox
を使用する方法です。
FlexBoxを使用し垂直方向を調整する
FlexBox
とは「Flexible Box Layout Module(フレキシブルボックスレイアウトモジュール)」のことで、要素をFlexコンテナというボックス内にフレキシブルで簡単に整列する方法です。
FlexBoxに対応しているブラウザは下記のようになります。
参考) Can I use... Support tables for HTML5, CSS3, etc
- IE11から正式対応。
- safariには
-webkit-
のベンダープレフィックス必要のようです。
垂直方向の調整をするために align-items
又は align-self
というプロパティを使用します。
align-items と align-self
- align-items
flexコンテナに対して指定することで、コンテナ内のすべてflexアイテム(子要素)に対して、同じ位置に調整します。 - align-self
flexアイテムに対して指定することで、個別に位置を調整します。
値 | 説明 |
---|---|
baseline | flexアイテム内の文字のベースラインを揃える。 最初のflexアイテムのbaselineに揃うようです。 |
flex-start | flexアイテムの上端を揃える( flex-direction が column や column-reverse の場合は右側を揃える) |
flex-end | flexアイテムの下端を揃える( flex-direction が column や column-reverse の場合は右側を揃える) |
center | 適用した要素の中心を、親要素の中心に揃える( flex-direction が column や column-reverse の場合は横幅の中央を揃える) |
stretch | フレックスアイテムの高さを揃える( flex-direction が column や column-reverse の場合は横幅を揃える) |
下記の例では、 align-items: center
を使用して実装してます。
.flexBox .flexItem1 | flexItem1 .flexItem2 | flexItem2 span.flexItem3 | flexItem3
.flexBox { display: flex; align-items: center; } .flexItem1 { background-color: #fd7c79; height: 200px; } .flexItem2 { background-color: #33cfff; height: 80px; } .flexItem3 { background-color: #24ff18; height: 160px; }
.flexBox
に対して display: flex
, align-items: center
を指定することで、flexコンテナ内の全てのflexアイテムが垂直方向に中央揃えになります。
このように簡単に垂直方向を調整することができるので、ブラウザの対応に気をつけなければいけませんが、 FlexBox
はとても便利です。
もし vertical-align
での調整が難しい場合には、 FlexBox
の導入をぜひ検討してみてください。弊社が運用しているmamanokoでも flex
を多用してます。
余談
株式会社Cluexではエンジニアの方を探しています!
GeocoderとGeokitを使用して、現在地周辺検索を行う機能を実装してみた
こんにちは、エンジニアの神山です。最近大豆製品ばっかり食べています。
今回はWebサービスでよく見かける、現在地周辺検索を行う機能の実装について書きました。
例えば現在地から半径2km内にあるレストランを検索したり、現在地より最寄りの駅を探したりできる機能です。
今回使用したGemは、 geocoder と geokit-rails です。
まずこの2つのGemにフォーカスして話を進めていきます。
GeocoderとGeokit
これらのGemは住所から緯度経度を割り出したり、緯度経度を用いた検索ロジックを提供しております。
具体的には以下の様な事ができます。
- 住所から緯度経度を割り出す
- 緯度経度から住所を割り出す
- IPアドレスから緯度経度を割り出す
- 指定したオブジェクトまたは緯度経度を中心に、指定した距離内や範囲(ex: 2km~5km)にある施設を検索する
- 2点間の距離を算出する
- あるオブジェクトに対して指定したオブジェクトが位置する方角を示す
- 指定したオブジェクトまたは緯度経度を中心に、長方形状に指定した範囲内ある検索する
住所から緯度経度を割り出すとは、「東京都中央区◯◯」という文字列を判別し、北緯35度、東経139度というように緯度経度に直すことです。
GeocoderとGeokitの比較
Geocoderの利点
Geocoderを使うメリットは、住所から緯度経度を割り出す機能が優秀という点です。
GeocoderはGeokitより多くのAPIを網羅しております。
GeokitはGoogle・Yahoo・Bing・FCC・MapQuest・Mapbox・OpenCageの7つに対して、 Geocoderは上のFCCを除いたものに加えて、Google Maps API for Work・Google Maps API for Work・Nominatim・Yandex・Geocoder.ca・Geocoder.us・Ovi/Nokia・Here/Nokia・ESRI・Mapzen・Pelias・Data Science Toolkit・Geocodio・SmartyStreets・OKF Geocoder・Geoportail.lu・PostcodeAnywhere Uk・LatLon.ioの25個網羅しています。
使用できるAPIの数が多いほうが、最適なものを選べるので使い勝手がいいですね。
Geokitの利点
一方、Geokitを使うメリットは、オブジェクトを絞るメソッドを使用する際メソッドチェーンが使えるという点です。
Geocoderだと可能な場合と不可能な場合があるようです。
例えば、Geokitのメソッドであるwithin
を使うとき、
prefecure_id = 1 shop_type = restaurant latitude = 33.33 longitude = 140.44 Shop.within(2, [latitude, longitude]).tap do |scoped| scoped.where!(prefecure_id: prefecure_id) if prefecure_id scoped.where!(shop_type: shop_type) if shop_type end
のようなことが出来ます。 例えば絞込を行う等、メソッドチェーンを使用したい場面を想定するとGeokitのほうが使い勝手が良いですね。
上記の理由により今回は、
- Geocoder: 緯度経度の割り出しを行う
- Geokit: 現在地周辺検索を行う
の様な使い分けをしました。
ちなみにgeocoder
とgeokit
の人気を比較しているサイトがあったので載せておきます。
Geocoderの使い方
住所から緯度経度を割り出すことを geocoding
といいます。
geocoding
を行いたいカラムがあるモデルに以下のように記述します。
geocoded_by :address after_validation :geocode, if: :address_changed?
geocoded_by
はgeocoding
を行いたいカラムを指定します。
address
というカラムに住所(ex: 東京都港区〇〇)が入っており、その住所を基に検索を行いたいような場面です。
after_validation
は geocoding
するタイミングを指定します。
上のように書くと、address
カラムに変更があった際に、自動でgeocoding
されるようになります。
Geokitの使い方
緯度経度を使って出来ることを、GitHubより抜粋しました。
# 指定した緯度経度から半径5km内のオブジェクトを検索 Shop.within(5, origin: [33.33, 140.33]) # 指定した緯度経度から半径5km外のオブジェクトを検索 Shop.beyond(5, origin: [33.33, 140.33]) # 指定した緯度経度から2km~5km内のオブジェクトを検索 Shop.in_range(2..5, origin: [33.33, 140.33]) # 緯度が30.33~35.55内でかつ、経度が135.55度~145.55度内にあるオブジェクトを検索 Shop.in_bound([[30.33, 135.55], [35.55, 145.55]]) # 指定した緯度経度から一番近いオブジェクトを検索 Shop.closest(origin: [33.33, 140.33])
様々な検索方法がありますね。 因みにGeocoderでも同じようなこと検索は可能です。
現在地の検索機能
では、現在地より半径2km以内にある店を検索する機能を実装していきます。 「現在地から探す」ボタンを押した時に、上記の条件で検索が行われるような実装です。
「現在地から探す」ボタン押下後の挙動としては、 Javascriptを用いて現在地の緯度経度情報を取得→Geokitのメソッドを用いて緯度経度付近にある施設を検索して、Viewに表示させる という流れになります。
Model
Shopモデルのaddress
カラムをgeocodingします。
- models/shop.rb
geocoded_by :address after_validation :geocode, if: :address_changed?
address_changed?
というメソッドはActiveRecord::Dirtyの機能です。
{column_name}_changed?で該当するカラムが変更された時に
true`を返します。
詳しくは下記を御覧ください。
Controller
Geokitのwithin
メソッドを用いることにより、現在地から2km以内の店が@placesに渡されます。
- shops_controller
def search latitude = params[:latitude] longitude = params[:longitude] @places = Shop.all.within(2, origin: [latitude, longitude]) end
View
- shops/index
「現在地から探す」ボタン部分になります。
.currentLocation = button_tag ‘現在地から探す’, type: ‘button’
Javascript
現在地の取得には、HTML5のGeolocation API
を使用します。
以下の様なコードになります。
class @CurrentLocations @getCurrentLocation: -> $('.currentLocation').on 'click', -> if navigator.geolocation navigator.geolocation.getCurrentPosition(successGetPosition, failGetPosition, options) else message = 'ご使用中のブラウザは現在地検索に対応されておりません。' Alert.set('warning', message) successGetPosition = (position) -> window.location.href = "/shops/searches?latitude=#{position.coords.latitude}&longitude=#{position.coords.longitude}" options = enableHighAccuracy: true failGetPosition = (error) -> switch error.code when 1 message = '位置情報の提供を許可してください。' when 2 message = '位置情報の取得に失敗しました。' Alert.set('warning', message)
では上から見ていきます。
@getCurrentLocation: -> $('.currentLocation').on 'click', -> if navigator.geolocation navigator.geolocation.getCurrentPosition(successGetPosition, failGetPosition, options) else message = 'ご使用中のブラウザは現在地検索に対応されておりません。' Alert.set('warning', message)
@getCurrentLocation
が現在地を取得する関数です。
navigator
はブラウザの情報を取得するオブジェクトです。
そして.geolocation
でブラウザが Geolocation API
に対応しているか調べています。
対応していないブラウザもあるので注意して下さい。(IE8.0など)
ブラウザが Geolocation API
に対応している時、 geoCurrentPosition
で現在地の取得を試みます。
geoCurrentPosition
の第一引数は現在地の取得に成功した時に実行され、第二引数は失敗した時に実行されます。
第三引数は現在地の取得の際のオプション設定をしております。
ちなみにブラウザが Geolocation API
に対応していてもユーザーが位置情報の提供を許可していない状況も考えられます。
そのような場合、 geoCurrentPosition
が呼ばれると自動で許可するか否かのポップアップが出るようになっております。これまた便利ですね。
ブラウザが Geolocation API
に未対応である場合は、 else
の部分が実行されます。
ここでは「対応していません」というアラートを出すようにしています。
successGetPosition = (position) -> window.location.href = "/places/searches?latitude=#{position.coords.latitude}&longitude=#{position.coords.longitude}"
successGetPosition
は現在地の取得に成功した時の関数です。
position
オブジェクトに現在地の情報が入っており、position.coords
で様々な情報を取り出せます。
例えば、 position.coords.latitude
で緯度を取得できたり、 position.coords.logitude
で経度を取得できます。
そして現在地の取得に成功した時に、現在地周辺の店の一覧ページに移動します。 またControllerに緯度経度の値を渡しております。
options = enableHighAccuracy: true
options
はその名のとおり、現在地取得の際のオプション設定です。
enableHighAccuracy
はGPSなどを使った高精度な現在地の取得を可能にします。
他にもタイムアウト設定やキャッシュの設定なども可能です。
failGetPosition = (error) -> switch error.code when 1 message = '位置情報の提供を許可してください。' when 2 message = '位置情報の取得に失敗しました。' Alert.set('warning', message)
failGetPosition
は現在地の取得に失敗した時に実行される関数です。
error
というオブジェクトに失敗の原因が入っております。
今回は、エラーの原因ごとに別々のアラートを出したいので、 error.code
ごとに条件分岐をしております。
error.code = 1
はユーザーが位置情報の許可をしていない時を指しております。
error.code = 2
は現在地の取得に失敗した時を指しております。
Geolocation API
の詳しい情報は以下のリンク先にも書かれているので参考にしてみてください。
以上が現在地周辺の施設を検索する機能の解説でした。 非常に便利なGemですね。
改良点等アドバイスいただけたら大変幸いです。
参考
今のうちに見直しておきたいnginx設定集 【セキュリティ編】
こんにちは、Cluexの高橋です。
先日EC2サーバーのOSを新しいものにしまして、その時にサーバーのテストを簡単に行ってくれるQualys SSL Labsで移行前のサーバーをテストしてみたところ、C判定が出てしまったので、nginxの設定も全体的に見直してみました。
イメージはこんな感じです
テストしたのはこちら「Qualys SSL Labs」 www.ssllabs.com
ということで今回はnginxの設定に関してセキュリティ関連でやっておくべき設定集をまとめました。
nginxのバージョン情報を隠す
nginxのバーション情報を隠蔽します。
server { # ~~ server_tokens off; # ~~ }
SSL通信に使用するプロトコルを指定する
SSLv2やSSLv3はダウングレード攻撃やPOODLEなどへの脆弱性があるのでTLSのみ許可します。
server { # ~~ ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ~~ }
暗号化スイートの設定
SSLの暗号化にする暗号化スイートを明示的に指定し、クライアントサイドで指定した暗号化をしないようにすることで、通信をよりセキュアにすることができます。 ちなみにssl_ciphersの設定方法としては、「:」をデリミタとして使用し、「!」をプレフィックスでつけることで除外対象となります。
詳細な暗号化スイートの設定内容はこちらのサイトを参考にさせていただきました。
Strong SSL Security on nginx - Raymii.org
おすすめの設定がこちら。
server { # ~~ ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; # ~~ }
IE6/WinXP などにも対応したいと言う方にはこちらの設定がおすすめとのことですが、SSL3.0などを使用できない設定にしているので今回は特にIE6を気にする必要はないかと思います。
server { # ~~ ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; # ~~ }
サーバーの暗号化設定の優先
先ほどのサーバー側で指定した暗号化スイートを優先して使用するようにします。
server { # ~~ ssl_prefer_server_ciphers on; # ~~ }
Http Strinct Transport Security(HSTS)ヘッダの追加
サーバーからStrict Transport Securityヘッダを返すことで常にHTTPSで通信を行うようにし、中間者攻撃を防ぎます。これを使用するには Nginxのngx_http_headers_moduleが必要になります。
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';
ちなみにpreloadオプションを使用したい場合は、こちらでドメインを登録しておくと宜しいかと思います。
こちらに登録するには下記の要件を満たす必要があります。
Submission Requirements
If a site sends the preload directive in an HSTS header, it is considered be requesting inclusion in the preload list and may be submitted via the form on this site.
In order to be accepted to the HSTS preload list through this form, your site must satisfy the following set of requirements:
Serve a valid certificate.
Redirect from HTTP to HTTPS on the same host.
Serve all subdomains over HTTPS.
・In particular, you must support HTTPS for the www subdomain if a DNS record for that subdomain exists.
- Serve an HSTS header on the base domain for HTTPS requests:
・The max-age must be at least eighteen weeks (10886400 seconds).
・The includeSubDomains directive must be specified.
・The preload directive must be specified.
If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (rather than the page it redirects to).
preloadを指定する場合はこんな感じです。
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;preload';
DH鍵交換時のKeyの強化
TLSプロトコルで採用されているDiffie-Hellman鍵交換は512bitもしくは1024bit以下のDHパラメータにおいてLogjam攻撃を受ける可能性があり、これを防ぐにはDHパラメータに2048bitのものを使用することが望ましいとされています。
Diffie-Hellman鍵交換による暗号化時にnginxのデフォルトでは1024ビットの鍵を使用しますが、Google ChromeやMozilla Firefoxなどの主要なブラウザでは「最低でも」1024ビット以上のものを使用するよう推奨しており、できれば2048bitのものを独自生成して使用するのが好ましいかと思います。
一般的なwebサイトでは2048bitもしくは4096bitでpemを作っておくといいようです。
まずはpemファイルの作成
$ cd /etc/ssl/certs $ openssl dhparam -out dhparam.pem 4096
こちらがnginxのconfファイルに追加する内容。
server { # ~~ ssl_dhparam /etc/ssl/certs/dhparam.pem; # ~~ }
OCSPステープリング(OCSP Stapling)の設定
OCSP(Online Certificate Status Protocol)はSSL/TLS通信の時に証明書が失効していないかを確認するために使用されています。 通常はSSL通信を行う際はクライアント側がこのOSCPを使用してサーバー証明書の正当性を確認する必要がありますが、サーバー側で事前にこの処理を行うことでクライアント側で行う必要がなくなるのでHTTPS通信の開始を高速化できます。
具体的にはOCSPステープリングによってクライアント側ではなくサーバー側でOCSPによるサーバー署名書の確認を行い、その結果をクライアントへのレスポンスと一緒に送るようにすることで、これを実現しています。
ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/cert/trustchain.crt; resolver 8.8.8.8 8.8.4.4 valid=300s
ssl_staplingを使用するにはDNSリゾルバを resolverディレクティブにて指定する必要があります。googleのパブリックDNSサーバーが使用されることが多いようです。
X-Frame-Options
レスポンスヘッダにX-Frame-Optionsを設定することでブラウザがiframeなどの内部に自身のサイトを表示を許可するかを設定できます。DENYもしくはSAMEORIGINを指定することで自分のサイトのコンテンツが他のサイトに埋め込まれないように設定でき、クリックジャッキング攻撃を防ぐことができます。
add_header X-Frame-Options SAMEORIGIN;
X-XSS-Protection
XSSに対するフィルタ機能を有効化
add_header X-XSS-Protection "1; mode=block";
X-Content-Type-Options
Content-Typeに一致しない処理は行わないようにさせることでXSSなどを防ぎます。
add_header X-Content-Type-Options nosniff;
これが設定されていない場合、例えば Content-type="text/plain"
のファイルでも、その中にjavascriptのソースがあるとブラウザによって実行される可能性があります。
再度テストした結果は・・・
当時の設定では上記の幾つかはまだ設定していないものもあるのでA+の評価をとることができなかったので、今回あげたものも含めてさらにサーバー周りを強化していきたいなと思います。
ちなみにMozilla Foundationが公開しているwebサーバーのConfig Generatorがあるので、そちらで基本的な設定を確認できるので、気になる方はお使いになってみるいいかと思います。
Generate Mozilla Security Recommended Web Server Configuration Files
余談)Cluexではエンジニアの方を探しています!
See more at cluex.co.jp
assets on S3の導入
こんにちは。エンジニアの志村です。 最近暑くて参りますね…。アイスばっかり食べてます。
さて今回ですが、Assets on S3を導入しましたのでその際のメモです。
結構この形でassetsを配信しているサービスは多いですよね。
今回は、Cloudfront+S3 / asset_sync+capistranoという定番のパターンで実装しております。
assets on S3とは
デプロイ時にassetsファイルをS3に配置し、CDN経由で配信する方法です。
通常であればnginxやApache等のWebサーバーを介して静的ファイルは配信されています。
assets on S3はassetsファイルをS3に配置し、CloudfrontやAkamai等のCDN経由で配信します。
Webサーバー負担軽減やCDNを噛ませることによる高速化を目的として用いられることが多いかと思います。
仕組み
下記のような流れになります。
- デプロイ時に
rake assets:precompile
を走らせる。その際にasset_syncを使用し、S3にassetsファイルをアップロードする。 - manifestファイルをEC2にアップロードする。
rake assets:precompile
時に作成されるassetファイルを削除する(public/assetsに格納されている)
こんな感じでしょうか。 他にもCloudfrontやS3の設定があるので、下記に記していきます。
Rails側の設定
ではまずasset_syncを導入し、bundle install
をします。
asset_syncの導入
gem 'asset_sync'
次にasset_syncのconfigファイルを生成します。
$ rails g asset_sync:install --provider=AWS
今回はAWSを使用するのでproviderオプションにはAWSを設定します。
そうするとasset_sync.rb
という設定ファイルが生成されます。
- config/initializers/asset_sync.rb
AssetSync.configure do |config| # fogを使用するサービス config.fog_provider = 'AWS' # S3の存在するリージョン config.fog_region = 'ap-northeast-1' # S3のバケット名 config.fog_directory = 'assets' # IAMのアクセスキー config.aws_access_key_id = 'xxxx' # IAMのシークレットアクセスキー config.aws_secret_access_key = 'xxxx' # 既にS3上に存在しているファイルの扱い keep, delete, ignoreから選択 config.existing_remote_files = 'keep' # gzip圧縮をするかどうか config.gzip_compression = true end if defined?(AssetSync)
上記で使用してるIAMに関しては、次の章のS3の部分で説明します。 これでasset_sync自体の設定は完了しました!
assetsのURLをCloudfrontにする
assetsファイルはCloudfrontより配信されます。
通常の設定では、http://domain/assets/
配下のファイルが配信されますが、これをhttps://Cloudfrontのエンドポイント/assets
に変更し、Cloudfrontから配信するように設定します。
- config/environments/production.rb
〜中略〜 # Enable serving of images, stylesheets, and JavaScripts from an asset server. config.action_controller.asset_host = '//xxxxx.cloudfront.net' 〜中略〜
これでassetsファイルがCloudfrontより配信されるようになりました!
次はcapistranoの設定を行います
capistranoの設定
流れとして、
cap 〜 deploy
コマンドを叩いた時に、ローカルにてrake assets:precompile
を走らせる(asset_syncが自動的にS3にアップロードしてくれる)- manifestファイルをサーバの
public/assets
ディレクトリに転送する - ローカルで生成されたpublic/assetsディレクトリを消去する
この中で特に大切なのは2.かと思います。
railsは、productionにデプロイされる際にprecompileを行います。
その際にdigestを付与してファイル名-digest.scss
のようなファイル名に変更します。
このdigestはprecompile時にランダムに設定されるのでrails側で管理が必要になります。
そのファイル名を管理するのがmanifestファイルです。これが存在しないと、railsはassetのパスを正しく指定出来ません。
ではcapistranoの設定に移っていきます。 こちらのコードを参考にさせて頂きました。
- config/deploy.rb
〜中略〜 namespace :deploy do # rake db:assets:precompileを実行する task :asset_sync do run_locally do Bundler.with_clean_env do execute :rake, 'assets:precompile' end end end # manifestファイルをアップロードする task :upload_manifest do on roles(:app) do |host| if test "[ ! -d #{release_path}/public/assets ]" execute "mkdir -p #{release_path}/public/assets" end file_path = Dir::glob('public/assets/.sprockets-manifest*').first upload!(file_path, "#{release_path}/public/assets") end end # ローカルに残されたprecompile後のassetsファイルを削除する task :assets_cleanup do run_locally do Bundler.with_clean_env do execute :rake, 'assets:clobber' end end end task :restart do invoke 'unicorn:restart' end end before 'deploy:starting', 'deploy:asset_sync' after 'deploy:publishing', 'deploy:upload_manifest' after 'deploy:publishing', 'deploy:assets_cleanup' after 'deploy:publishing', 'deploy:restart' 〜中略〜
上記のようになります。
rakeタスクに関しては新しくファイルに切り分けても良いかと思いますが、そんなにデプロイスクリプトが多いわけでも無かったので僕はそのままdeploy.rbに書いてしまっています。
release_path
の部分はそれぞれの環境に合わせたpathを指定すればOKです。
developmentではsprocketsを使用しているのでそれをそのままuploadしております。
AWS側の設定
S3の設定
S3はバケットを作成し、CORSの設定を行います。 CORSの設定をしないと、Font Awesomeが正しく表示されません。 詳しくは
を御覧ください。
AWSコンソールの「S3」を選択
「バケットの作成」を選択
バケット名、リージョンを設定
作成したバケットを選択し、「プロパティ」→「アクセス許可」→「CORS設定の編集」を選択
ここに下記のコードを貼り付け、「保存」をします 下記のコードを使用させて頂きました。
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration>
Cloudfrontの設定
基本設定
assets用のディストリビューションを作成します。
AWSコンソールの「Cloudfront」を選択
「Web」を選択
Origin Settingsを入力する
項目 | 設定 | 説明 |
---|---|---|
Origin Domain Name | 先ほど作成したS3バケット名 | オブジェクトの取得先 |
Origin Path | 空のまま | S3のルートディレクトリの設定 |
Origin-ID | 分かりやすい名前 | オリジンを区別する一意のID |
Restrict Bucket Access | Yes | CloudfrontのURLからのみS3のオブジェクトにアクセス出来る |
Comment | 分かりやすい名前 | identityを区別するIDのようなもの |
Grant Read Permissions on Bucket | Yes | バケット内のオブジェクトの読み取り許可 |
Origin Custom Headers | 空のまま | リクエストをオリジンに転送する際にカスタムヘッダーを含めるかどうか |
※ Default Cache Behavior Settings, Distribution Settingsに関しては環境に応じて入力して下さい。今回は特にいじらずに行きます。
「Create Distributions」を選択するとCloudfrontのDistributionが作成されます。
Behaviorの設定
さて、Behaviorの設定を行っていきましょう。
Behaviorは振り分けのルールです。
例えば、
https://xxxx.cloudfront.net/assets
にリクエストが来た場合にはassetsバケットに転送https://xxxx.cloudfront.net/images
にリクエストが来た場合にはimagesバケットに転送
のようなことが可能になります。
「Behavior」タブの「Create Behavior」を選択
Settingsを入力
項目 | 設定 | 説明 |
---|---|---|
Path Pattern | /assets/* | 振り分けパターン。今回は/assets配下のオブジェクト全てをS3から配信したいので/assets/*とする |
Origin | 先ほど設定したOrigin-ID | どのオリジンからオブジェクトを取得するかを選択 |
Viewer Protocol Policy | 環境によって選択 | アクセスする際のプロトコルの選択 |
Allowed HTTP Methods | GET, HEAD | オリジンに転送するHTTPメソッド。今回は取得のみなのでGET, HEADを選択 |
Forward Headers | Whitelist -> Origin | どのヘッダを転送するか 今回CORSの設定を行っているので、OriginをAddする |
Grant Read Permissions on Bucket | Yes | バケット内のオブジェクトの読み取り許可 |
Object Caching | Use Origin Cache Headers | MaximumTTL等を変更しないのであればUse Origin Cache Headersのままで良い |
「Create」を選択すると、このBehaviorが有効になります。
設定の反映までは10分〜20分ぐらいかかるので気長に待ちましょう!
以上です。 asset_syncのおかげでそこまで多くの手順を踏むこと無く、assets on S3の導入が出来ました。 次回はLambdaを使用してInvalidationを走らせる処理について書きたいと思います。