LEGOスクラムに参加した!(座学編)
この記事なに?
12/14(木) に行われたLEGOスクラムのレポートです!
イベントの詳細についてはこちら↓
参加の理由としては、「今のチームでやってる手法がちゃんとアジャイルのレールに乗っているか?」「体系的に一回知識を入れてる一貫として、先輩におすすめされたから」
といった感じでした。
チーム決めでは、スクラムについて詳しい順に並んでくださいということで、まさかのプロジェクトでやってる方が私しかおらず、参加者の中で1番詳しい人となりましたw
この記事では座学で学んだ部分についてまとめます。
ちなみに、メモは会社の slack で垂れ流ししてました。
アジャイル is 何? スクラム is 何?
まずは、なんでもかんでもアジャイルを適用すればいいのか? いわゆる銀の弾丸なのか?という話です。
大前提アジャイルに定義はない!!
あえてあげるとすれば、態度や概念。
スクラムやカンバンといった方法論を身につけることで、アジャイルが習得されるでいいということです。
では、スクラムとは何なのか?
スクラム=複雑で変化の激しい問題に対応するためのフレームワーク。可能な限り価値の高いプロダクトを生産的かつ創造的に届けるためのもの。
複雑で変化の激しいとはどんな状況なのか?
何を作ればいいか・どうやって作ればいいかが中途半端なものをここでは、複雑(Complex)なものとして定義します。
例えば、夏休みの宿題のようなものは、スクラムに向いていません。
なぜなら、何をするかも、どうやるかも明確で、各教科を1つずつ終わらせていけば全ての作業が完了するようなものだからです。特に変化が発生する要素がないので、別の方法を適用する方がよいらしい。
セミナーの中では WBS*1 に切ることが出来るものということも仰っていました。
また、漠然としすぎていてもそれはそれで問題だそうで、「世界を良くするものを作る」という、何を作ればいいか・どうやって作ればいいかが難しすぎる(Anarchy)な問題に関してもスクラムを適用することはできません。
これを達成するには、デスマーチしかないとのこと。
これらの真ん中の作業の時にスクラムが有効な手段となりうるそうです。
アジャイル開発は、オブジェクト指向開発を人間に当てはめたもの
オブジェクト指向形のプログラミング言語の特徴として、クラスに生えてるメソッドはどのインスタンスでも同じような振る舞いを行うというものがあります。
その考え方をプロダクトマネージメントにも応用しようと考えたのがアジャイルなチームの始まりで
- 1つ1つのタスクが誰がどの作業をやれる状態となっている
- アサインではなく、サインアップ
- 機能横断型なメンバーでチームを構成する
1つ1つのタスクが誰がどの作業をやれる状態となっている
これは、タスクの粒度や共通認識のレベルの話で、全員が同じ規模感や認識を持つことが重要ということです。
そして、1つ1つのタスクに対して、誰かから当てはめられるのではなく、手が空いた人から「これやります!」というのが大事になっています。
確かに、うちのプロジェクトでもサインアップは意識されている気がする
機能横断型
機能横断型とは、自分の領域を絞らずに全部出来る(しようとする)ゼネラリストのような人が集まった集団が求められるということです。
例えば、「自分はバックエンドだけしかするつもりありません」という人より、「デザインもできますし、インフラもできます」というような感じです。
今まで、スクラムは一手法として捉えていたので、オブジェクト指向を人間に当てはめたものという表現は納得感のあるものでした。
一回で完成品を作ろうとするのは無理
半年がかりで、どかっとした機能を作るのではなく、雪だるまのようにちょっとずつやれることを増やしていく考え方でプロジェクトを進めます。
- 最小の単位で作ってみる
- 製品とプロセスの振り返りを行うこと
特にどのようにこれらを作っていったか?というプロセスまで振り返りができるようにすることで、個人としてではなく、チームとしての成長を狙っています。
座学の中では最高に美味しい焼きそばの作り方というテーマでワークが行われました。
ラグビー型のチームへ
複雑で変化の激しい領域に対応するならば、継続的にちょっとずつ前に進める変化に強いチーム作りを意識しなければならない。
引用:The New New Product Development Game
type A のようなリレー形式のように、引き継ぎ引き継ぎで作業をするのではなく、同じチームで継続的に少しずつ進んでいく type C のようなラグビー型のチームのほうが早く進めることができるという調査。
このラグビー型チームにしていくためには、決まったパターンがあるので一回それに当てはめてみてトライアンドエラーで進めていくことが大事そうに感じました。
基本的に【プロダクトオーナーxスクラムマスターx開発チーム】の構図
ここでいう開発チームは、実際にコードを書く人だけでなく、テスターやデザイナーも含まれるそうです。
そして、プロダクトオーナーは「何を作るかの責任者」であるため、必ずしも技術に長けている必要はない。 顧客からの要求をスキニングしたり、製品の価値として、どこまで求めるかの意思決定を行う。
スクラムマスターは「どうやって作るかの責任者」であるため、そのチームの中で一番技術に長けている人がなるべき。
チーム内で発生したバックログに全く関係のない雑務(例えば会議の調整)もスクラムマスターが行うべきだそうです。
その理由としては、チームとして目標を達成できることが一番なため、個人のスキルを高めるために余裕のある人が「技術的に一番余裕がある人」である点。 また、他の人に目を配る余裕がある点や、何をやっているかが(技術的に)わかる点も1番スキルの高い人がやるべき要因です。
そしてなにより、技術に長けている= Complex な問題を解決する力が強いわけではないということも前提としてあります。
まとめ
ここまで、アジャイルの方法論の一つであるスクラムについて書いてきましたが、最後にまとめると。
- スクラムは適度に複雑(Complex) な問題を解決する方法で簡単すぎても漠然としすぎてもいけない。
- なんども繰り返してチームとして問題解決を行える力を付ける
- そこでは必ずプロダクトとプロセス両方の振り返りを行う
この座学のなかではあまり触れられていなかったのですが、お客さんがアジャイルに積極的かどうか?という点も実際の仕事においてはかなり重要になっていくそうで、お客さんの理解を得る方法については、アジャイルサムライに、確実に動くものを毎週届けることで、少しずつ信頼を得ていくというのが大事という風に書いてありました。
あと、ここや本に書いてあることはあくまでもテンプレートなので、最終的な形は自分たちでカスタマイズして作っていくことが大事になってくるのかなと思いました。
最初から、アジャイルな気持ちで〜と言っても何をすれば?となってしまうので、初めは型にハマって、次第にカスタムしていくというのかな。
特に Web 業界だと、週に1回のリリース頻度だとちょっと遅すぎるので、そこらへんのバランスも必要になってきたりしそうです。
というのが座学の感想です。
後半のレゴ編に続きます
*1:Work Breakdown Structure:作業分解構成図
HHKB を掃除した話 #HHKB20th
この記事はfeedforce Advent Calender 2016 の16日目の記事です!
昨日は同じチームの UX デザイナーよーさんが書いてくれました。
この人、結局君の名は。何回行ったんだろう...7~8回?
みなさん、そろそろ大掃除の時期ですね!
お部屋のお片づけは順調でしょうか?
私は進捗ゼロです!!!!!!!
そんな私がまず取り掛かる場所。 そうキーボードですね!←
というわけで、今日は、私の愛機の HHKB を掃除した話をお届けします!
そもそも HHKB って?
- 出版社/メーカー: PFU
- 発売日: 2006/03/23
- メディア: Personal Computers
- クリック: 192回
- この商品を含むブログ (23件) を見る
↑こちらが今使っている Happy Hacking Keyboard Professional 2です。
矢印キーがないのでとても省スペースである点。 ストロークが深く、打鍵するとコトコトという非常に心地よい音がするのが特徴です。
さらに、無刻印にすることにより、集中力が研ぎ澄まされるという効果もあります(個人差あり)
なお、かなり癖が強いため、慣れるまでに時間がかかるのが難点です。
いわば小柄な体系で、最初はツンだけどそれでもアタックし続けることで、やっとデれてくれるような手のかかる女のk...(ry
HHKB の魅力については、こちらの記事がおすすめです!!
そんな HHKB を掃除開始
準備するものとしては、
- キートップ抜き
- 洗濯ネット
があれば十分な気がします キートップ抜きは、ヨドバシなど電気屋さんで買うとよいかと!
まずは、汚れを確認。
埃がだいぶ溜まってる....
キートップを外していきましょう!
こんな感じでズバズバ抜いていきます!
抜いたら 無くさないように洗濯ネット に入れましょう!
全部抜き終わった写真がこちら↓
あぁ...きちゃない...
スペースキーの部分にバネがついているので、無くさないように注意です!
キートップを洗う
今回は、普通の中性洗剤を使いました。
それをタオルで拭いて、乾かします!
乾くのを待ってる間に、本体のお掃除
こちらには、どこのご家庭にもある精密ピンセットを使いました!
普通ならエアー缶を買って、風でシャーっとしたほうが早いと思います
いざ!キートップの装着
掃除始める前の僕「無刻印やから、キーの配列考えなくていいから楽勝やんけ〜」
パチパチ....パチパチ....パチパチ....
パチパチ....パチパチ....パチパチ....パチパチ....パチパチ....パチパチ....おわった!!!!!!
以上にて、この記事を....
あれ?いつもと感触が違う???????
( ゚д゚) ・・・ (つд⊂)ゴシゴシ (;゚д゚) ・・・ (つд⊂)ゴシゴシゴシ ( ゚д゚)
微妙に高さが違うんですね()
特に左側2つ(´;ω;`)
この後、違和感あるとこ付けては外しを繰り返して 完成しました!!!
高級なキーボードはちゃんと手の形に合うように、湾曲しているそうなので、列ごとで洗濯ネットに入れとくと良いかも知れません!φ(..)
みなさんも、年越しの大掃除リストにキーボードを加えましょう!!!
明日は、新卒同期の有給消化率ナンバーワン tsub 氏です!!!
追記
会社のはてブコメントから、公式さんが教えてくれなかったことを教えてくれた!!!!!!!
突撃!隣のキーボード - Feedforce Developer BlogHHKB無刻印洗濯は考えなしにはじめると紹介記事のごとくハマるんですけど、キートップ裏に書いてある記号で何のキーかわかったりします。
2017/11/15 20:52
下から A→B→C... って振られている感じみたいです! 数字は横の並び順かな?どっちが1番なんだろうw
あなただけの登山ルートがそこにはある『山頂をめざせ』:ボドゲ紹介
この記事何?
この記事は、 2016年ボドゲ紹介02 Advent Calendarの7日目です。
参加を決めてから気づきましたが、ボドゲ紹介01 の7日目は弊社のボドゲ部部長 @kano_e さんが書いていますので、そちらもどうぞ
今日紹介するゲームは、お気に入りなサイコロゲー「山頂をめざせ」です!
Gipfelstürmer: AMIGO - Familienspiel
- 出版社/メーカー: Amigo Spiel + Freizeit
- 発売日: 2015/10/01
- メディア: おもちゃ&ホビー
- この商品を含むブログを見る
まずは簡単にルールから
まずはじめに、1人5匹のヤギとプレートを一枚ずつ持ちます。
このヤギさんを山頂に進めるのがゲームの目的です!
この5匹のヤギを山の麓に並べてゲームスタート!
ターンが回ってくると、サイコロを5個振って各看板に書いてある目をクリアーできれば一歩前に進めます。 サイコロは振り直したいものだけキープして、振り直しは2回まで振り直せます。
例えばこの写真は、3と6のツーペアが揃っているので、
このツーペアの看板が進めるという感じでズンズンヤギさんを進めていきましょう!
自分のヤギさんを押し上げちゃえ
山頂までのルートにはヤギさんが止まる枠があるのですが、それには上限が決まっています。 小さい枠はみんなで1匹、大きい枠は個人で2匹までです。 じゃあ、それ以上は進めないのか?
ここがこのゲームの醍醐味! 自分のヤギを押し上げちゃう事ができるんです!!
上に行けば行くほど、看板の賽の目が難しくなるので、 このようになるべく道に続けるようにヤギを配置して、上に上に押し上げていくのがこの山頂をめざせの醍醐味です!!
相手を押しのけちゃえ
ゲームの中盤になると進む先に他の人のヤギがいる。。。という状況になります
その場合どうするか。。。。
邪魔な敵は押しのけていくのです!!!
上手くいけば、一番下まで突き落とすことができます!!
終了条件
こうして、ヤギさんを押し上げたり、敵を押しのけたりして、一番先に山頂に2匹のヤギさんを山頂に登らせたら勝ちです!!
あなたは白色ヤギさんや黄色ヤギさんみたいに準備万端に用意する派? [
それとも、緑色ヤギさんみたいに5つのぞろ目を気合いで出す派?
- どのルートを進ませるかという戦略
- 自分の力で出す目をコントロールする力
両方がバランス良く必要な、山頂をめざせいかかでしょうかo(・ω・´o) この日は着々とヤギさん並べてる間に6の5個ゾロ出されて負けましたw
おわりに
毎週水曜 19:30~ 弊社ボドゲ部活動中です! ほぼ毎週ゲストさんもいらっしゃっていますので、お時間ありましたらぜひ湯島まで〜
明日はowl_8 - Adventar の今年遊んだボドゲ です!
Webを支える技術を読んでる まとめ5
この記事について
技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。
HTTPヘッダとは
おさらい
Webを支える技術を研修で読んでる まとめ2 - pokotyamu的書きなぐり日記 メッセージヘッダーの部分が今回説明するHTTPヘッダである。
概要
ヘッダには、メッセージボディに対する付加情報(メタデータ)を入れる。 例えば、メディアタイプや言語タグなどである。 また、リソースへのアクセス権を設定する認証や、クライアントとサーバの通信回数と量を減らすキャッシュなどのHTTPの機能はヘッダで実現する。
つまりこのような機能は第7~8章で述べたHTTPメソッドやステータスコードと、本章のHTTPヘッダの組み合わせによって表現される。
本章では、 HTTP1.1で主に使用される頻度の高いものだけに絞って説明する。
歴史的背景
- HTTP0.9の頃には、HTTPヘッダは存在しなかった
- HTTPの仕様がバージョンアップするに連れ、本文のメタデータを表現するために電子メールのメッセージ仕様を使う方式が採用される
- そのため、現在のHTTPヘッダは電子メールのヘッダと同じものもある
- メールのメッセージ仕様は番兵構造である。^1
- メールは一方通行のやり取りだったが、HTTPは双方向にやり取りをするため拡張する必要がある
日時
DateやExpiresで表現する。 メッセージ作成の時間や、PUTやDELETEの時間指定などに使用される。 以下は主要な日時を使用するヘッダである。
利用するメッセージ | ヘッダ | 意味 |
---|---|---|
リクエストとレスポンス | Date | メッセージを作成した日時 |
リクエスト | If-Modified-Since | 条件付きGETでリソースの更新日時の指定 |
リクエスト | If-Unmodified-Since | 条件付きPUTやDELETEでリソースの更新日時の指定 |
レスポンス | Expries | レスポンスをキャッシュ出来る期限 |
レスポンス | Last-Modified | リソースを最後に更新した日時 |
レスポンス | Retry-After | 再度リクエストを送信出来るようになる日時の目安 |
Date: Tue, 06 Jun 2010 03:34:00 GMT
HTTPメソッドで使用する日時は、必ず GMT(グリニッジ標準時)で返さなければならない。
MIMEメディアタイプ
MIME(Multipurpose Internet Mail Extensions)の略。 名前の通り、電子メールのヘッダから採用されたものである。 今後はメディアタイプで示す。
Cotent-Type
メディアタイプの指定を行う。
Content-Type: text/plain
このメッセージボディの中身がどのような形式のものなのかを指定する。
メディアタイプには、以下の表の9つのタイプが存在している。
タイプ | 意味 | 例 |
---|---|---|
text | 人の読めるデータ | text/plain |
image | 画像データ | image/jpeg |
audio | 音声データ | audio/mpeg |
video | 動画データ | video/mp4 |
application | その他のデータ | aplication/pdf |
multipart | 複数データからなる複合データ | multipart/related |
message | 電子メール | message/rfc822 |
model | 複数次元で構成するモデルデータ | model/vrml |
example | 例示用データ | example/foo-bar |
text/plane
の/の左側を「タイプ」、右側を「サブタイプ」と呼ぶ。
タイプは勝手に増やすことは出来ないが、サブタイプは比較的自由に作ることが出来る。
サブタイプ一覧については数が膨大なので、IANAのページを参照する。
IANAは、「Internet Assigned Numbers Authority」の略。
ドメイン名、IPアドレス、プロトコル番号など、インターネット資源のグローバルな管理を行っている南カリフォルニア大学情報科学研究所のプロジェクトチーム。サブタイプの管理もここが行っている。
charset (日本語メッセージの注意)
文字エンコーディングを指定する。
Content-Type: application/xml; charset=utf-8
charsetは省略可能だが、タイプがtextの場合は注意が必要である。 HTTPでのtextタイプのデフォルト文字エンコーディングは、ISO 8859-1と定義されている。 もし、日本語文字列が入っているメッセージに対して、ISO 8859-1と解釈しようとするため、文字化けを引き起こす可能性がある。 さらに、メッセージボディ内で、文字エンコーディングを指定している場合でも、Conttent-Typeヘッダのcharsetが宣言されているならば、こちらが優先される。
文字化けを起こさないように気をつけるためには、必ずcharsetパラメータを付ける事が望ましい。
言語タグ
charsetパラメータは文字エンコーディング方式を指定するが、リソース表現の自然言語を指定する場合は、 Content-Languageを使用する。
Content-Language: ja-JP
言語タグの「-」の左側には、ISO 639が指定する言語コードが入る。 日本語ならば「jp」英語ならば「en」など 右側にはISO 3166が定義する地域コードが入る。 日本ならば「JP」アメリカならば「US」など
言語コードと地域コードの組み合わせにより、1つの国に複数言語ある場合や多数の国で使われる言語にも対応することができる。
コンテントネゴシエーション
メディアタイプや文字エンコーディングや言語タグはサーバが一方的に決定するだけでなく、クライアントと交渉して決めることも出来る。
クライアントが処理出来るメディアタイプを伝える時は、Accept
クライアントが処理できる文字エンコーディングを伝える時は、Accept-Charset
クライアントが処理できる言語を伝える時は、Accept-Language
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Accept-Language: ja,en-us;q=0.7,en=0.3
q=のパラメータは優先度が指定でき、1に近いほど優先される。 省略されている場合は1が入る。
Content-Length
Content-Length
ヘッダを利用して、メッセージボディのサイズを10進数のバイトで示すことが出来る。
静的ファイルなど、あらかじめサイズが分かっているリソースを転送する場合などは、これを利用する。
しかし、動的な画像ファイルなど、すぐにサイズが確定しない場合、Transfer-Encoding
ヘッダを利用して、ボディを複数の塊(チャンク)にして、転送することが出来る。
これにより、最終的なサイズが分からないデータに対しても、ボディを少しずつ転送することが出来る。
次にチャンク転送の例を示す。
POST /test HTTP/1.1 Host: example.jp Transfer-Encoding: chunked Content-Type: text/plain; charset=utf-8 10 The brown fox ju 10 mps quickly over e the lazy dog. 0 <空行>
各チャンクの先頭にはチャンクサイズが16進数で入る。 上記の例において、16バイトで表現する16進数の「10」と14バイトを表現する「e」が登場する。 最後には必ず長さ0の空行を付ける。
なお、HTTP1.1の仕様では、全てのHTTP1.1実装は、チャンクエンコーディングを受信しなければならない。
認証
概要
現在主流のHTTP認証方式には、HTTP1.1が規定しているBasic認証とDigest認証がある。 またWeb APIでWSSEというHTTP認証の拡張仕様を利用する場合もある。
今回は、主流の2つを簡潔に説明する。
そもそも認証について、あるリソースに制御がかかってる場合、401 UnauthorizedとWWW-Authenticate
ヘッダを利用して、クライアントにリソースへのアクセスに必要な認証情報を通知出来る。
DELETE /test HTTP/1.1 Host: example.jp
HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Example.jp"
これは、Basic認証も、Digest認証もどちらも使用する。
Basic認証
最も簡単かつ基本的な方式。 ユーザ名とパスワードを使って認証を行う。
ブラウザから送信される認証情報は、「ユーザ名:パスワード」という形式で「:」区切りで並べ、これをBASE64でエンコーディングした文字列をHTTPヘッダのAuthorizationフィールドに記載する。
古くから使用される方式のため、ほとんどのWebサーバやWebクライアントが対応しているが、認証情報が暗号化やハッシュ化されないため、通信途上で第三者に覗き見られる危険性がある。
そもそも、
$ echo Z3Vlc3Q6VGFrZTU= | base64 -D guest:Take5
このようにbase64をデコードすることによって、簡単に元の文字列を判定することが出来る。
よって、Basic認証を使う時は、それが許される程度のセキュリティ強度でいいのか?SSL(Secure Socket Layer)やTLS(Transport Layer Security)を使ってHTTPS(HTTP over Secure Socket Layer)通信し、通信路上で暗号化するか?を検討する必要がある。
Digest認証
Digest認証は、Basic認証よりもセキュアな認証方式である。 あるメッセージに対して、ハッシュ関数を適用した結果のハッシュ値を使って認証を行う。 ハッシュ関数とは、データからそのデータを代表する数値を求める関数のことで、ハッシュ関数を使って得られた値のことをハッシュ値と呼ぶ。
Basic認証では、
DELETE /test HTTP/1.1 Host: example.jp Authorizaition: Basic dXNlcjpwYXNzd29yZA==
このようなリクエストで送信していたが、Digest認証では、
HTTP/1.1 401 Unauthorized WWW-Authenticate: Digest realm="Example.jp", nonce="1ac421d9e0a4k7q982z966p903372922", qop="auth", opaque="92eb5ffee6ae2fec3ad71c777531578f"
このようにより複雑なレスポンスが返ってくる。
このWWW-Authenticateの値のことをチャレンジと言う。 クライアントはまず認証なしで、リクエストを送信した上で、チャレンジを使って次回のリクエストを組み直す。
nonce
はnumber used onceの略で、リクエストごとに変化する文字列である。
nonceの値は、サーバの実装に依存しているが、基本的には、タイムスタンプやサーバだけが知り得るパスワードから生成する。
qop
はquality of protectionの略で、auth
かauth-init
を指定して使用する。
qopの値はクライアントが送信するダイジェストの作成方法に影響を与える。
authの場合、メソッドとURIからダイジェストを作成する。
auth-initの場合、メソッドとURIに加えてメッセージボディーも利用する。
これにより、POSTやPUTでボディを送信するときは、auth-initを使うとメッセージ全体が改ざんされないことを保証することが出来る。
opaque
は、クライアントには不透明(推測できない)文字列で、同じURI空間へのリクエストえは共通してクライアントからサーバに送る。
これらを以下のような流れで実行する。
- ユーザ名、realm、パスワードを「:」で連結し、MDS(Message Digest Algorithm)ハッシュ値を求める
- メソッドとURIのパスを「:」で連結し、MDSハッシュ値を求める
- 1の値、サーバから得たnonce、クライアントがnonceを送った回数(cnonce)、qopの値2の値を「:」で連結し、MDSハッシュ値を求める
サーバ上にパスワードのハッシュ値を保管し、そのハッシュ値を元に認証を行うため、パスワードそのものをサーバに預けなくて良くなる点から、セキュリティリスクを下げることが出来る。
Basic認証の場合は、同じURI空間のリソースであれば、クライアントは一度認証してしまえば、2回目以降は自動的にユーザ名とパスワードを送れた。しかし、Digest認証では、サーバからのnonceがなければクライアントが側でダイジェスト計算されないため、一度401 Unauthorizedレスポンスを返さなければならない。
また、パスワードを暗号化するだけなので、メッセージを暗号化したい場合は、Basic認証同様HTTPSを利用する方法が考えられる。
さらに、ApacheなどのWebサーバでは、Digest認証がオプション扱いでサポートしておらず、自前で実装しなければならないといった状況が考えられる。
キャシュ
概要
キャッシュとは、サーバから取得したリソースをローカルストレージ(HDDなど)に蓄積し、再利用する手法のことである。 ローカルストレージにキャッシュしたデータそのものをキャッシュと呼ぶも事もある。 クライアントが蓄積したキャッシュは、キャッシュが有効な間、再度そのリソースにアクセスしようとした時に、再利用する。
キャッシュ用ヘッダ
クライアントが、サーバから取得したリソースがキャッシュ可能かどうか? そのリソースのキャッシュに関するメタデータが入るヘッダについて説明する。
Pragma
Pragmaヘッダに指定できる値は、公式にはno-cache
のみ。
この値はリソースをキャッシュしてはならないことを示す。
クライアントは、次回リソースにアクセスする時、必ず再度サーバにアクセスしなければならない。
Expries
Exouresヘッダはキャッシュの有効期限を示す。 指定できる値には、日時をGMTのみである。 リソースを変更することがない場合、永久にキャッシュ可能であることを示したくないが、そのような場合でも、Expriesには、最長で、約1年後の値を入れることが推奨されている。
Cache-Control
HTTP1.1から導入されたヘッダ。 PragmaもExpiresもどちらも、Cache-Controlで代用出来る。
Pragma: no-cache Cache-Control: no-cache
これら2つは同様の意味として使える。
また、有効期限の書き方として、相対時間(あと○○秒有効) といった設定が出来るようになった。
Cache-Control: max-age: 86400
この他にも、様々な細かい設定が行うことが出来る。 詳細については、RFC 2616を参照。
使い分け
以上の3種類の使い分けについては、次の3つの方針がある。
- キャッシュさせない場合は、PragmaとCache-Controlのno-cacheを同時に指定する
- キャッシュの有効期限が明確に決まっている場合は、Expiresを指定する
- キャッシュの有効期限を相対的に指定したい場合は、Cache-Controlのmax-ageで相対時間を指定する
条件付きGET
クライアントがExpiresやCache-Controlヘッダを検証した結果、ローカルキャッシュをそのまま再利用出来ない時でも、条件付きGETを行えば再利用出来る可能性がある。 仕組みとしては、変更されているかを調べる項目をリクエストヘッダに送って、そのレスポンスからそのまま使えるかどうかを検証する。
If-Modified-Since
まず、リクエストの例は次のようになる。
GET /test HTTP1.1 Host: example.jp If-Modified-Since: Thu, 11 May 2010 03:34:00 GMT
これはローカルキャッシュの更新日時が2010年5月11日3時34分ちょうどであることを示している。 これに対して、サーバはこれ以降変更がない場合、以下のレスポンスを返す。
HTTP/1.1 304 Not Modified Content-Type: application/xhtml+xml; charset=utf-8 Last-Modified: Thu, 11 May 2010 03:34:00 GMT
304 Not Modifiedは条件付きGETへのレスポンスで、リソースが変更されていないことを示す。 これにより、レスポンスにボディを含まないため、ネットワーク帯域を節約出来るメリットがある。
If-None-Match
これも、リクエストの例をベースに説明する。
GET /test2 HTTP1.1 Host: example.jp If-None-Match: ab3322028
HTTP/1.1 304 Not Modified Content-Type: application/xhtml+xml; charset=utf-8 ETag: ab3322028
If-Modified-Sinceヘッダによく似ているが、一番の違いはETagというヘッダの値を更新の判定に使用している点である。 ETagはリソースが更新されるたびに新しい値に変わる文字列であり、特に文字列的な意味はない。 このETagはリソースに紐付けているため、たとえETagの文字列が同じでも違うリソース同士では意味が無い。
ETagの生成方法は静的ファイルと動的ページでは異なる。
静的ファイルの場合
Apacheのデフォルトでは、静的ファイルのETagの値はinode番号、ファイルサイズ、更新日時から自動で計算してくれる。 ただし、inode番号は、同一内容のファイルでもファイルシステムが異なれば別の値となる。 例えば、サーバを分散されている時に注意すべきである。 そのため、ファイルサイズと更新日時のみでETagの値を計算させるようにする。
動的ページの場合 ApacheなどのWebサーバは動的に生成されるHTMLやフィードなどは自動的にETagを計算してくれない。 そのため、Webアプリケーション側でETagの値を計算する必要がある。 一般的には、リソースのメタデータ(更新日時、サイズなど)から作成する方法や、リソースの更新カウ
使い分け
それぞれを使い分けるための方針は次のようになる。
- Last-Modifiedヘッダしか分からない場合はIf-Modified-Since
- サーバがETagヘッダを出している場合にはIf-None-Match
- 時計を持っていないサーバに対してはIf-None-Match
- ミリ単位で変更される可能性のあるリソースにはIf-None-Match
持続的接続
HTTP1.1での新機能がこの持続的接続(Persistent Connection)
HTTP1.0までは、サーバがレスポンスを返すたびにTCPコネクションを切断していた。
これを解決するために、Keep-Alive
ヘッダを利用して、まとめて接続し続ける手法が開発された。
これにより、クライアントはレスポンスを待たずに、同じサーバにリクエストを送信することが出来る。
HTTP1.1では、このKeep-Alive
が標準化されている。
コネクションを切断したい場合は、リクエストのConnection
ヘッダにclose
という値を指定すれば良い。
Webを支える技術を研修で読んでる まとめ4
この記事について
技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。
ステータスコードとは
概要
WebサービスでもWebAPIでもリクエストに対するレスポンスの内容を概略的に表したものがステータスコードである。 これらを正しく使うことは、WebAPIを作成する上でのマナーである。 例えば、エラーを表すコードを返さなければならないのに、成功のコードを返してしまったら、受け取った側はそれを正しいものとして認識してしまう。 つまり、ステータスコードが正しく守られていない場合は、専用のクライアントを実装しなければならず、色々なクライアントで使用出来るというWebAPIの利点を活かすことも出来ない。 そのため、誤用することなく、正しい理解をすることが求められる。
Webを支える技術を研修で読んでる まとめ3 - pokotyamu的書きなぐり日記で述べた、レスポンスメッセージの1行目にあるのが、ステータスラインである。
おさらいすると、ステータスラインは、プロトコルバージョン、ステータスコード、テキストフレーズから成る。
例えば
HTTP/1.1 200 OK
といった形のステータスラインがあった場合。
200
がステータスコードである。
ステータスコードは3桁の数字であり、先頭の数字によって5つに分類することが出来る。
ステータスコード | 意味 |
---|---|
1xx | 処理中 |
2xx | 成功 |
3xx | リダイレクト |
4xx | クライアントエラー |
5xx | サーバエラー |
この5つに分けられている理由としては、次の3つが挙げられる。
- どのようなレスポンスであったかの概要を理解することができる
- クライアントとサーバの結びつきを緩やかにすることができ、サーバのバージョンアップやクライアントの置き換えが行いやすくなる
- ステータスコードが新たに追加された場合でも、先頭の数字さえ分かればクライアント側で最低限の処理を行うことができる
以降では、5つの分類それぞれの概要と代表的なものについて説明する。 基本的にRFC2616の原文リンクの和訳と補足の形ですすめる。
1xx
概要
1xx系は、処理が継続していることを示す。 クライアントはそのままリクエストを継続するか、サーバの支持にしたがってプロトコルをアップデートして再送信する。 実際に見かける場は、ほとんどないため、今回は割愛する。
2xx
概要
何かのリクエストが成功したことを示す。
200 OK
リクエストが問題なく受理されて、要求に従ったレスポンスが返る。 ブラウザでページが読み込まれて、表示された時に使用されることから、一番遭遇頻度が高いステータスコードといえる。
201 Created
リクエストが完了し、新たに作成されたデータのURIが返る。 新たに作成されたURIの情報はレスポンスヘッダのLocationで示される。 ※ただし、PUTで作成した場合は、Locationは返らない さらにレスポンスで返されるリソースのタイプはContent-Typeで示される。
この生成処理は、リクエストを返す前には終了していなければならず、もし直ぐに返せない場合は、202 Accepted
を返す。
3xx
概要
他のリソースへのリダイレクトを示す。 クライアントはこのステータスコードを受け取った時、レスポンスメッセージのLocationヘッダを見て新しいリソースへ接続する。
301 Moved Permanently
リクエストで指定したリソースが新しいURIに移動したことを示す。
その時のロケーションはレスポンスヘッダ内のLocationで示される。
もし、301のステータスコードをGET
,HEAD
メソッド以外で受け取ったユーザエージェントは、条件の変更などが発生する場合があるため、ユーザが確認出来るまで、自動的にリダイレクトの要求を受け取るべきではない。
302 Found
リクエストで指定されたURLが一時的に存在せず、別のURLに仮の移転をしているので、移動先のURLに転送したことを示す。
302のステータスコードも301と同様にGET
,HEAD
メソッド以外で受け取ったユーザエージェントは、条件の変更などが発生する場合があるため、ユーザが確認出来るまで、自動的にリダイレクトの要求を受け取るべきではない。
303 See Other
主にPOST後のリダイレクトで用いられる。 フォームからPOSTした後にリダイレクトしてTOPページに戻す場合が考えられる。 最初の処理では、POSTでリクエストしたが、ブラウザはリダイレクト先にはGETを使う。
307 Temporary Redirect
HTTP1.1で追加され、本来の302が持つべきだった内容を再定義している。よって今後の設計においては、302ではなく307を使うことが推奨される。 最初のURLでは実際の処理は行わず、リダイレクト先に改めてリクエストを出し直して欲しい時に使う。 つまり、最初のリクエストがPOSTだった場合、ブラウザはリダイレクト先にもPOSTを使う。 基本的な処理自体は302と変わらないが、元々リクエストに使った動詞をそのまま使って、変更先のURIにリクエストして欲しい場合は307を使うべきである。
参考:HTTPステータスコード – 302 Foundと303 See Otherと307 Temporary Redirectの違いについて
301と307(302)の違い
どちらも、URIの移動を示すステータスコードである。 ユーザ目線からしても、どちらもページが移動する挙動のため意識する必要はない。 しかし、 検索エンジンからすると以下のように挙動が変わる。
- 301の場合は、URLが移転先のものになる
- サイトのリニューアルでURLが変更になった場合
- 307(302)の場合は、URLが元のURLのものになる
- サーバーエラーが発生したときにエラーページへリダイレクトする場合
サイトのURIを変更する時は、これらの違いを意識する設計が求められる。 参考:301リダイレクトと302リダイレクトは離婚と不倫 – SEO例え話
4xx
概要
クライアントエラーを示す。 原因はクライアント側のリクエストにある。 エラーを解消しない限り正常な結果が得られないので、同じリクエストをそのまま再送信することは出来ない。
400 Bad Request
リクエストの文章が間違っている時に発生する。 クライアントは、再度修正して送り返す必要がある。
401 Unauthorized
適切な認証情報を与えずにリクエストを行った時に発生する。
レスポンスのWWW-Authenticate
ヘッダで、クライアントに対して認証方式を伝える。
403 Forbidden
リクエスト自体の処理は受け付けたが、権限がないために実行出来ない時発生する。 ファイルの閲覧や、外部サイトからのアクセスを禁止しているページで発生する。 解消するためには、サーバ側の設定を調整するしかない。
404 Not Found
指定したリソースが存在しない場合に発生する。 既に削除されてしまっていた場合や、URLの入力ミスなどの時に起こる。
403などで外部サイトからのアクセスを禁止している時に、要求が拒否された理由を正確に明らかにしたくない場合や、他の応答が適用されない場合、404が使用されます。
5xx
概要
サーバエラーを示す。 原因はサーバ側にある。 サーバ側の原因が解決すれば、同一のリクエストを再送信して正常な結果が得られる可能性がある。
500 Internal Server Error
サーバ側に何らかの異常が生じていて、正しいレスポンスが返せない時に発生する。 レスポンスボディには、異常の原因が入る。
503 Service Unavailable
サーバがメンテナンスや高負荷に耐え切れずサービスを提供していない時に発生する。 ツイッターのクジラが出たなどが有名どころ。
エラー処理
4xx系と5xx系は、どちらもエラーを表現している。 エラーコードはHTTP仕様が規定しているが、ボディーにどんなメッセージを入れるかは規定していないので、そのページが人間用なのかプログラム用なのかで分けてエラーメッセージを返すとよい。
まとめ
今回のステータスコードを一覧にまとめる。
ステータスコード | 補足文章 | 概略 |
---|---|---|
200 | OK | リクエストが問題なく受理されて、 要求に合わせたレスポンスが返る |
201 | Created | データの作成が行われ、新たに作成されたデータのURIが返る |
301 | Moved Permanently | リクエストで指定したリソースが 新しいURIに移動したことを示す |
302 | Found | リクエストで指定されたURLが一時的に存在せず、 別のURLに仮の移転をしているので、 移動先のURLに転送したことを示す |
303 | See Othoer | 主にPOST後のリダイレクトで用いられる |
307 | Temporary Redirect | 基本302と同じ。 元々リクエストに使った動詞をそのまま使って、 変更先のURIにリクエストして欲しい場合に使用 |
400 | Bad Request | リクエストの文章が間違っている時に発生する |
401 | Unauthorized | 適切な認証情報を与えずにリクエストを行った時に発生する |
403 | Forbidden | リクエスト自体の処理は受け付けたが、 権限がないために実行出来ない時発生する |
404 | Not Found | 指定したリソースが存在しない場合に発生する |
500 | Internal Server Error | サーバ側に何らかの異常が生じていて、 正しいレスポンスが返せない時に発生する |
503 | Service Unavailable | サーバがメンテナンス中や高負荷に耐え切れず サービスを提供していない時に発生する |
Webを支える技術を研修で読んでる まとめ3
この記事について
技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。 前 pokotyamu.hatenablog.com
次
HTTPメソッドの概要
HTTPメソッドには9つの種類がある。
メソッド | 意味 |
---|---|
GET | リソースの取得 |
POST | 子リソースの作成、リソースへのデータの追加、その他処理 |
PUT | リソースの更新、リソースの作成 |
PATCH | リソースの一部更新 |
DELETE | リソースの削除 |
HEAD | リソースのヘッド(メタデータ)の取得 |
OPTION | リソースがサポートしているメソッドの取得 |
TRACE | 自分宛てにリクエスト・メッセージを返す(ループバック)試験 |
CONNECT | プロキシ動作のトンネル接続への変更 |
以降、各メソッドについて見ていく。 また、ステータスコードについては、次の第8章で述べる。 今回説明中で使用するステータスコードは、あくまで実装の一例である。そのため、実装のやり方によっては変化することがある。
各ヘッダの確認方法はGoogle Chromeの場合 以下の参考リンクのレスポンスヘッダのコピーを参照 参考:coliss.com - Chrome デベロッパーツールの使い方: プロのように華麗に使いこなすための20のテクニック
GETメソッド
GETでは、指定したURIの情報を取得する。 Webページの取得、画像の取得、映像の取得、フィードの取得など、実際にブラウザを利用している時に一番使われるメソッドがGETメソッドである。
GET / HTTP/1.1 Host: www.hottomotto.com
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Connection: keep-alive Date: Tue, 26 Apr 2016 03:27:37 GMT Server: Apache Vary: Accept-Encoding X-IIJ-Cache: MISS Transfer-Encoding: chunked <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- 途中略 --> </body> </html>
レスポンス例のレスポンスボディー内に、指定したリクエストのhtmlの情報が返されている。 これを読み込んでWebブラウザ上で表示している。
POSTメソッド
POSTメソッドでは3つの役割が存在する。
子リソースの作成
ブログページを親とした時に、ブログ記事が子リソースに当たる。 つまり、ブログ記事の投稿がこの子リソースの作成に当たる。
POST /list HTTP/1.1 Host: example.jp Content-Type: text/plain; charset=utf-8 こんにちは!
HTTP/1.1 201 Created Content-Type: text/plain; charset=utf-8 Location http://example.jp/list/item5 こんにちは!
201 Created
というステータスコードが返ってきたが、これは正常にリソースの作成が出来たことを示す。
Locationヘッダにその新しいリソースのURIが入っている。
リソースへのデータの追加
ログリソースの追加などがこれに当たる。
POST /log HTTP/1.1 Host: example.jp 2016-04-25T10:13:00Z, GET /log, 200
HTTP/1.1 200 OK
ここではPOSTのレスポンスとして、200
が返ってきたが、これは、リソースの作成ではなく、データの追加を示す。
POSTがデータ作成を意味するか、またはデータ追加を意味するかは実装に依存するため、WebAPIの仕様書などを調べる必要がある。
他のメソッドでは対応出来ない処理
URIの長さにはブラウザの実装上2000文字以内などの制約が入る場面がある。 そのような長いキーワードの場合、URIのクエリにキーワードを入れてGETする方法は利用出来ない。 この時に POSTを利用することで、ボディの中にキーワードを格納することが出来る。
POST /search HTTP/1.1 Content-Type: application/x-www-form-urlencoded q=very+long+keyword+hogehogehoge......
PUTメソッド
PUTは2つの役割が存在する。
リソースの更新
先ほどのPOSTの記事作成で作ったリソースの内容を更新する。
PUT /list/item5 HTTP/1.1 Host: example.jp Content-Type: text/plain; charset=utf-8 こんばんは!
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 こんばんは!
このように、PUTメソッドは、元のリソースを更新するときに使う
リソースの作成
http://example.jp/newitemが存在してないものとする。
POST /newitem HTTP/1.1 Host: example.jp Content-Type: text/plain; charset=utf-8 新しいリソース/newitemの内容
HTTP/1.1 201 Created Content-Type: text/plain; charset=utf-8 新しいリソース/newitemの内容
PUTは存在しないURIへのリクエストのため、サーバはリソースを新しく作成すると解釈し、201 Created
を返す。
/newitemが存在していた場合は、更新として処理される。
PATCHメソッド
2010年のRFC7589で追加された一番新しいメソッド。 リソースの一部更新で使用される。 例えば、ブログ記事のタイトルの更新などに使用される。
PATCH /list/item5 HTTP/1.1 Host: example.jp Content-Type: text/plain; charset=utf-8 ##一部更新内容##
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 ##一部更新が反映##
このように、基本的には、PUTの子リソースの更新となんら変わらない。 それぞれの違いについては後述する。
Github APIでも採用されているほか、Ruby on Rails v4.0から正式に採用された。
DELETEメソッド
名前の通りリソースの削除を行うメソッド。
DELETE /list/item2 HTTP/1.1 Host: example.jp
HTTP/1.1 200 OK
一般にDELETEのレスポンスはボディーを持たない。
そのため、ステータスコードにボディーがないという意味の204 No Content
が使われる場合がある。
POSTでPUT/DELETEを代用する
今現在、一番よく利用されているのが、GETとPOSTメソッドである。 HTMLのフォームで指定出来るのもこの2つだったが、技術の発展とともに、AjaxのXMLHttpRequestというモジュールを利用することで、任意のメソッドを発行できるようになった。 しかし、XMLHttpRequestをサポートしない携帯電話向けブラウザでは2つのメソッドしか利用出来ない。 また、プロキシサーバではPUTによって勝手にサーバーに関する情報をクライアントに追加させたり置き換えさせたりするため、セキュリティの問題で2つのメソッド以外のアクセスを制限する場合がある。
このような状況で、サーバにPUTやDELETEを伝えるためには、
- _methodパラメータ
- フォームの隠しパラメータに_methodというパラメータを入れる
- その中に本来送りたかったメソッドの名前を入れる
- Ruby on Railsが採用している
- X-HTTP-Method-Overrde
HEADメソッド
GETとよく似ていているが、GETはリソースを取得、HEADはリソースのヘッダ(メタデータ)のみを取得するメソッド。
HEAD /list/item1 HTTP/1.1 Host: example.jp
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8
先述した通り、ヘッダのみ返すため、HEADへのレスポンスにはボディーを含まない。 利用用途としては、ネットワークの帯域を節約しつつ、リソースの大きさや、更新日時を調べるために使う。
OPTIONSメソッド
OPTIONSは、そのリソースがサポートしているメソッドの一覧を返す。
OPTIONS /list HTTP/1.1 Host: example.jp
HTTP/1.1 200 OK Allow: GET, HEAD, POST
OPTIONS /list/item1 HTTP/1.1 Host: example.jp
HTTP/1.1 200 OK Allow: GET, HEAD, PUT,DELETE
OPTIONS自体は、Allowヘッダには含めない。 また、OPTIONSメソッドは開発者が独自で実装しなければならない。
主要ではないHTTPメソッド
今まで説明した、7つのメソッドが主にHTTPメソッドとしては使われやすい。 ここからは、少し使用頻度の低い2つのメソッドについて説明していく。
TRACEメソッド
TRACEは、HTTPリクエストを「オウム返しに」HTTPレスポンスとして返す。
ただし、注意すべき点として、リクエストをそのまま返すため、レスポンスの中にCookieヘッダ
やAuthorizationヘッダ
も含まれてしまう。
そのため、Cross-Site Tracing(XST)攻撃に利用された。
XST攻撃とは、XSS^1とTRACEメソッドを組み合わせた攻撃手法である。
以下、徳丸浩の日記 - 実はそんなに怖くないTRACEメソッドから引用
XSS単独では、XSSによりJavaScript等が動いているブラウザ上のレスポンス(ヘッダ及びボディ)は取得出来ますが、リクエストヘッダを取得することはできません。このため通常は、HttpOnly属性の指定されたCookieや、Authorizationヘッダ(Basic認証のIDとパスワード)を取得することはできません。 しかし、TRACEメソッドを実行すると、先に見たようにリクエストヘッダがそのままレスポンスとして返るので、XSS単独ではとることのできないHttpOnly属性の指定されたCookieや、Authorizationヘッダを盗み出すことができます。これがXST攻撃です。とくに、BASIC認証のIDとパスワードを盗むことができると、長期にわたって不正にログインすることができてしまうため、XSSの影響が大きくなります。
CONNECTメソッド
RFC 2817の定義によると
A CONNECT method requests that a proxy establish a tunnel connection on its behalf. The Request-URI portion of the Request-Line is always an 'authority' as defined by URI Generic Syntax [2], which is to say the host name and port number destination of the requested connection separated by a colon:
```レスポンス例 CONNECT server.example.com:80 HTTP/1.1 Host: server.example.com:80
日本語に軽く訳すと、 「CONNECTは、proxyとのトンネル接続を作るために使われる。リクエストURIの中にhostme名、ポート番号、リクエスト元の情報がコロン区切りで記述される。これらは、URIの一般的なシンタックスである。」
べき等性と安全性
べき等とは「ある操作を何回行っても結果は同じという考え方」である。 数学の絶対値、0の乗算(3 * 0 = 0)などがあげられる。
また、安全性とは「操作対象のリソースの状態を変化させないこと」を意味している。
これらを主要メソッドであるGET、POST、PUT、PATCH、DELETE、HEADに当てはめると次のような図に分類出来る
○ | 安全性あり | 安全性なし |
---|---|---|
べき等 | GET、HEAD | PUT、DELETE |
べき等でない | POST,PATCH |
GETとHEADは、値を取ってくるだけなのでべき等かつ安全なのは自明である。 PUTとDELETEは、値を更新や作成、削除する点から変化を与えるため安全性はないが、何度やっても値は同じなのでべき等性はある。 POSTは、リクエストの結果次第で何が起こるか分からないためべき等性はなし。更に、リソースの状態に変化も与えるため安全性もなし。 POSTの例としては、通販サイトでのブラウザの戻るボタンを押してしまった時に、2重注文のような問題が発生する可能性を示している。 PATCHは、更新の時に、べき等でなく、安全性もない更新であると定義されている。
POSTとPUTとPATCHの使い分け
POSTとPUT
どちらも新しいリソースの作成を行えるが、それぞれの使い分ける指針として、 リソースのURI決定権が挙げられる。
POSTでリソースを作成する場合、URIの決定権は サーバ側にある。 なので、レスポンスヘッダー内にLocationが含まれる。 この動作の例としては、TwitterのようにUTIをサーバーが自動的に作成する場合が挙げられる。
PUTでリソースを作成する場合、 クライアントが決めたURIがそのままサーバ側で使用される。 なので、レスポンスヘッダー内でLocationが含まれていない。 この動作の例としては、Wikiのようにクライアントが決めたタイトルがそのままURIになるものが挙げられる。
PUTとPATCH
Ruby on Rails(以下Rails)の導入された経緯から、この2つのメソッドの違いを考える。
元々Railsでは、レコードの更新に対して、PUTメソッドが使われていた。
Railsで使用するレコードの中にはupdate_at
という更新時間の項目が常に含まれている。これは、ユーザが指定していない時でも作成される。
この時、レコード内の別の項目だけを更新した時にupdate_at
も一緒に更新時間が変わってしまう。つまり、同じ更新を行う時に毎回同じ結果が返るという べき等性が失われている。
そこで、最初からべき等性も安全性もない、PATCHメソッドを用いることで、この誤用を解消した。
このように、PUTとPATCHは基本的に処理内容としては、同じだが、べき等性が必要か否かで選ぶと良い。 参考:Edge Rails - PATCH is the new primary HTTP method for updates
メソッドの誤用
先ほど、べき等性と安全性の対応表を出したが、全てがあの表に当てはまるとは限らない。 そのパターンについて述べる。
なお、これらのパターンは開発者の問題であることが多く、前述した図が基本と考えて良い。 そのため、べき等性や安全性を考慮して、適切なメソッドを適切なタイミングで使用することを心がける。
GETが安全でなくなる場合
GET: /resources/1/delete HTTP/1.1 Host: example.jp
このようにGETで要求しているにもかかわらず、example.jp/resources/1 を削除しようとする時、安全性がなくなる。 これを防ぐためには、GETの発行前後でリソースに変化が入っていないか?を考えると良い。 基本的にGETでは参照しか出来ないはずなので、deleteなどの動詞がURIに入ってる段階で矛盾している。
PUTがべき等でなくなる場合
価格の更新に対して、現在の価格の50%増加させるといったように、今の差分から処理を行う時 毎回結果が変わってくるため、べき等性がなくなる。 このようなときには、PATCHを使うか、「+50%」といった相対的な表現を避けるべきである。
DELETEがべき等でなくなる場合
ソフトウェアの最新バージョンがhttp://example.jp/latest
というエイリアスリソースで管理されている時、このURIに対してDELETEを行うとどうなるか?
もし、エイリアスリソースそのものを削除するという処理の場合、http://example.jp/latest
が削除されるだけなので、べき等性は保たれる。
しかし、エイリアス先のリソース(最新バージョンのリソース)を指していた場合、ver2.0が削除された次の削除はver1.9になるため、べき等性がなくなってしまう。
このようにエイリアスリソースを削除するように設計するのもいいが、このような特殊なリソースについては、更新や削除などの操作が出来ないような設計にするのが求められる。
CRUDな設計
これまで、9つのHTTPメソッドの種類をまとめた。
これらのメソッドのうち、GET、POST、PUT、DELETEは4つでCRUD
という性質を満たす。
CRUDとは、
- Create:作成、生成
- Read:読み取り
- Update:更新
- Delete:削除
の4つの頭文字を取ったものである。
それぞれの対応関係は、以下の図のようになっている。
CRUD名 | 意味 | メソッド |
---|---|---|
Create | 作成 | POST、PUT |
Read | 読み込み | GET |
Update | 更新 | PUT |
Delete | 削除 | Delete |
CRUDな設計の代表例は、railsのscaffoldした雛形Webアプリケーションが挙げられる。 参考:TECHSCORE - 4.scaffoldを利用した開発(1)
Webを支える技術を研修で読んでる まとめ2
この記事について
技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。
次
HTTPの概要
HTTPはTCP/IPをベースにしている。 TCP(Transmission Control Protocol) IP(Internet Protocol) 現在のHTTPはバージョン1.1が主流として使われており、10年以上更新されていない。 現代の開発スタイルでは、HTTP1.1を有効に使っていこうという流れになっている。^1 ネットワーク・プロトコルは階層毎にわかれている。
各階層は次のようになっている。
- ネットワークインターフェース層
- 物理的なケーブルやネットワークアダプタに相当する部分
- イーサネット
- インターネット層
- IPを使ってパケット単位でネットワークで実際にやり取りする部分
- この時、最終的にたどり着くかは保証していない
- IP
- IPを使ってパケット単位でネットワークで実際にやり取りする部分
- トランスポート層
- アプリケーション層
階層にすることの特徴は
- 抽象度別に分けることが出来る
- ネットワークインターフェース層のほうが抽象度が低い
- 各階層の実装が独立している
- 下位層の実装に依存しない
- 障害発生時などの問題を各層毎に区切ることが出来る
HTTPの仕組みについて
HTTPはアーキテクチャスタイルに クライアント/サーバ を採用している。 クライアント(Webブラウザ)が情報を提供するサーバ(Webサーバ)に接続し、各種リクエストを出してレスポンスを受け取る。 このようなプロトコルを リクエスト/レスポンス型(Request-Response Style) と呼ぶ。
クライアント/サーバそれぞれの役割
クライアントでは、リクエストの送信から受信する際、次のことを行う。
- リクエストメッセージの構築
- リクエストメッセージの送信
- (レスポンスが返るまで待機)
- レスポンスメッセージの受信
- レスポンスメッセージの解析
- クライアントの目的を達成するために必要な処理
次に、サーバでは次のことを行う
- (リクエストの待機)
- リクエストメッセージの受信
- リクエストメッセージの解析
- 適切なアプリケーション・プログラムへの処理の委譲
- DBから最新記事を取得処理
- 広告へのリンク作成処理
- アプリケーション・プログラムから結果を取得
- レスポンスメッセージの構築
- レスポンスメッセージの送信
HTTPメッセージ
先述した、リクエストメッセージとレスポンスメッセージはまとめて、 HTTPメッセージ と呼ぶ。
リクエストメッセージの構造
リクエストメッセージの構造は以下の図のようになっている。
リクエスト行のURIには、http://example.jp:8080/search?q=test&debug=true#n10
のようなURIフラグメントは、リクエストメッセージには含めない。この場合のリクエスト行は、URIフラグメントを除いた、パス以降の文字列が入る。具体的には/search?q=test&debug=true
が入る。
また、リクエストURIは基本絶対URIでも相対URIでも使用出来る。^2 しかし、プロキシへのリクエストの場合必ず 絶対URI となる。
レスポンスメッセージの構造
レスポンスメッセージの構造は以下のずのようになっている。
参考:ネットワークエンジニアとして TCP/IP - HTTP
HTTPのステートレス性
HTTPはステートレスなプロトコルとして設計されている。 これは、サーバがアプリケーション状態を保存しないということである。
アプリケーション状態とは?
アプリケーション状態は、別名セッション状態とも言う。 システムにログインしてから、ログアウトするまでの一連の操作間の状態をアプリケーション状態と呼ぶ。
もしステートフルなプロトコルだと、アプリケーション毎のやり取りをサーバが記憶する必要がある。 反対にステートレスなプロトコルだと、アプリケーション自身でやり取りを全て記憶する必要がある。
それぞれの概要は次のようになる。
- やり取りについて
- ステートフル:簡潔(サーバが記憶しているから)である。
- ステートレス:冗長(今までの状態を話す必要があるから)である。
- 利点
- ステートフル:送信するデータ量が少なくて済む。
- ステートレス:クライアント数が増えた際にシステムをスケールさせるのが楽になる。
- 欠点
- ステートフル:クライアント数が増えると、サーバが記憶しなければならないデータ量が増えるため負担が増える。
- ステートレス:送信データ量が増える。認証など、サーバに負担がかかる処理を繰り返す。通信エラーの際にリクエストが処理出来ているか分からない。