Hit the books!!

プログラミング学習記録

「Webを支える技術」を読んで

よく良書として挙げられている「Webを支える技術 HTTP、URI、HTML、そしてREST」を読んだのでまとめ。

HTMLは学習済なのでとばした。それを言ったらHTTPだって勉強済なんだけど...理解できてないのでまとめました。主な目的はRESTを理解すること。

 

 

 

REST(Representational State Transfer)とは

クライアント/サーバから派生したWebのアーキテクチャスタイル。以下の6つを組み合わせたネットワークシステムのアーキテクチャスタイル。

  • クライアント/サーバ:クライアントとサーバで処理を分離する
  • ステートレスサーバ:クライアントのアプリケーション状態をサーバ側で管理しない
  • キャッシュ(Cache):クライアントとサーバ間の通信量を減らす
  • 統一インターフェース:インターフェースを固定する
  • 階層化システム:システムを階層に分離する
  • コードオンデマンド:プログラムをサーバからクライアントにダウンロードし実行する

 

URI(Uniform Resource Identifier)

URIの構文

例:http://user:pass@blog.example.jp:8000/search?q=test&debug=true#n10
httpURIスキーム
user:pass:ユーザ情報
blog.example.jp:ホスト名
8000:ポート番号
/search:パス
q=test&debug=true:クエリパラメータ
#n10URIフラグメント

ベースURI

相対URIの起点となるURIのことをベースURIという。相対URIを絶対URIに変換することを「相対URIを解決する」という。
ベースURIは直感的に指定する方法と、HTMLやXMLの中で明示的に指定する方法がある。

使用できる文字と%エンコーディング

URIの仕様では、アルファベット・数字・記号のいわゆるASCII文字が使えると定められている。
日本語などのASCII以外の文字をURIに入れるときには、「%16進数」という形になるようUTF-8エンコードされる。(%エンコーディングという)

URIの設計指針

その他設計テクニック

  • URIをやむを得ず変更したいときはリダイレクトすること
  • 言語を指定する拡張子はOK(http://example.jp2020.08/31/.press.enなど)
  • 複数パラメータを表現するにはセミコロンかカンマを使ったマトリクスURIを使う(地図など)

 

HTTPの基本

HTTPとは

RESTの重要な特徴である統一インターフェース、ステートレスサーバ、キャッシュなどを実現しているWebの基盤となるプロトコル

TCP/PIとは

インターネットの基盤を構成する重要なネットワークプロトコル。以下の通り階層型になっている。

f:id:ud_ike:20200901202632p:plain

リクエストとレスポンス

Webサイトにアクセスしたときに行われること

<クライアント側>
①リクエストメッセージの構築
②リクエストメッセージの送信
③(レスポンスが返るまで待機)
④レスポンスメッセージの受信
⑤レスポンスメッセージの解析
⑥クライアントの目的を達成するために必要な処理

<サーバ側>
❶(リクエストの待機)
❷リクエストメッセージの受信
❸リクエストメッセージの解析
❹適切なアプリケーションプログラムへの処理の委譲
❺アプリケーションプログラムから結果を取得
❻レスポンスメッセージの構築
❼レスポンスメッセージの送信

HTTPメッセージ

<構造>

f:id:ud_ike:20200901202651p:plain

◆リクエストメッセージ
<例>

GET /test HTTP/1.1
Host: example.jp
GET search?q=test&debug=true HTTP/1.1
Host: example.jp:8080

1行目:リクエストライン
メソッド(GET)、リクエスURI(/test)、プロトコルバージョン(HTTP/1.1)
リクエスURIは絶対URIになることもある。

2行目:ヘッダ
名前(Host): 値(example.jp)

ヘッダのあとにボディが続くこともある。

◆レスポンスメッセージ
<例>

HTTP/1.1 200 OK
Content-Type: application/xhtml+xml; charset=utf-8

<html xmlns="http://www.w3.org/1999/xhtml">
...
</html>

1行目:ステータスライン
プロトコルバージョン(HTTP/1.1)、ステータスコード(200)、テキストフレーズ(OK)

2行目:ヘッダ

ヘッダ→空行→ボディ となる。

HTTPのステートレス性

HTTPはステートレスなプロトコルである。FTPはステートフルなプロトコルの代表例である。

◆ステートフル

・やりとりが簡潔
・サーバがクライアントのそれまでの注文(セッション状態、アプリケーション状態)を覚えている
・クライアントの数が増えるとセッション状態を覚えておくことが難しくなる

◆ステートレス

・やりとりが冗長
・クライアントは毎回すべての注文(自己記述的メッセージ)を繰り返す
・クライアントが送信するデータ量が多くなる
・認証などのサーバに負荷がかかる処理を繰り返してしまう
・通信トラブルのときにリクエストが処理されたかわからない

HTTPメソッド

8つのメソッド

HTTPで定義されているメソッドは以下の8つ。

メソッド 意味
GET リソースの取得
POST 子リソースの作成、リソースへのデータ追加、その他の処理
PUT リソースの更新、リソースの作成
DELETE リソースの削除
HEAD リソースのヘッダ(メタデータ)の取得
OPTIONS リソースがサポートしているメソッドの取得
TRACE 自分宛にリクエストメッセージを返す(ループバック)試験
CONNECT プロキシ動作のトンネル接続への変更

HTTPメソッドとCRUD

GET, POST, PUT, DELETEはCRUDという性質を満たす代表的なメソッドである。

CRUD メソッド
Create POST/PUT
Read GET
Update PUT
Delete DELETE

POSTとPUTの使い分け

POSTはクライアントはリソースURIを指定できない。URIの決定権はサーバ側にある。Twitter向き。
PUTはクライアントがURIを決める。wikiなどに向く。

POSTでPUT/DELETEを代用する方法

HTMLのフォームで指定できるメソッドがGETとPOSTの2つであることもあり、この2つのメソッドしか使用を許可されていない場合もある。

このような状況の時にサーバにPUTやDELETEを伝える方法が2つある。

  • _methodパラメータを用いる
    フォームの隠しパラメータ(hidden)に_methodというパラメータを用意し、そこに本来送りたかったメソッドの名前を入れる
  • X-HTTP-Method-Overrideヘッダ
    _methodパラメータはPOSTの内容がXMLなどの場合は利用できない。このような場合にはX-HTTP-Method-Overrideヘッダを用いてX-HTTP-Method-Override: PUTと記述する

べき等性と安全性

べき等:ある操作を何回行っても結果が同じこと
安全性:操作対象のリソースの状態を変化させないこと

メソッド 性質
GET, HEAD べき等かつ安全
PUT, DELETE べき等だが安全でない
POST べき等でも安全でもない

使い方によってはべき等でなくなる場合もある。
他のメソッドでできることをPOSTで実現しようとしないこと。

ステータスコード

ステータスコードの分類

ステータスコードは3桁の数字で、先頭の数字によって5つに分類される。

分類 意味
1xx 処理中
2xx 成功
3xx リダイレクト
4xx クライアントエラー
5xx サーバエラー

よく使われるステータスコード

  • 200 OK:リクエスト成功
    リクエストが成功したことを示す
  • 201 Created:リソースの作成成功
    リソースを新たに作成したことを示す。POSTとPUTのレスポンスとして返される。
  • 301 Moved Permanently:リソースの恒久的な移動
    指定したリソースが新しいURIに移動したことを示す。古いURIを保ちつつ新しいURIに移行する際に用いる。
  • 303 See Other:別URIの参照
    リクエストに対する処理結果が別のURIで取得できることを示す
  • 400 Bad Request:リクエストの間違い
    リクエストの構文やパラメータが間違っていたことを示す。ほかに適切なクライアントエラーを示すステータスコードがない場合にも用いる。
  • 401 Unauthorized:アクセス権不正
    適切な認証情報を与えずにリクエストを行ったことを示す
  • 404 Not Found:リソースの不在
    指定したリソースが見つからないことを示す
  • 500 Internal Server Error:サーバ内部エラー
    サーバ側に何らかの異常が生じていて正しいレスポンスが返せないことを示す。ほかに適切なサーバエラーを示すステータスコードがない場合にも用いる。
  • 503 Service Unavailable:サービス停止
    サーバがメンテナンスなどで一時的にアクセスできないことを示す

ステータスコードは正しく使おう。

HTTPヘッダ

MIME(Multipurpose Internet Mail Extensions)メディアタイプ

メッセージでやりとりするリソースの表現の種類を指定するのがMIMEメディアタイプである。HTTPではそのうちのContent-Typeヘッダなどいくつかを利用する。

Content-Typeヘッダ

メッセージのボディの内容がどのような種類なのかをメディアタイプで表す。

<例>

Content-Type: application/xhtml+xml; charset=utf-8

application/xhtml+xmlがメディアタイプ。/の左側をタイプ、右側をサブタイプと呼ぶ。タイプは増やすことはできないがサブタイプは比較的自由に増やすことができる。登録済のタイプとサブタイプの一覧はIANAが管理している。

charsetパラメータ

先ほどの例ではこのXHTML文書をUTF-8エンコードしていることを示している。
charsetパラメータは省略可能だが、タイプがtextの場合は注意が必要であるため、必ずcharsetを付けるほうが望ましい。

言語タグ

charsetパラメータは文字エンコーディング方式を指定するものだが、リソース表現の自然言語を指定するContent-Languageヘッダもある。

<例>

Content-Language: ja-JP

jaが日本語の言語コードJPは地域コード。

コンテントネゴシエーション

クライアントと交渉して決める手法をコンテントネゴシエーションという。

  • Acceptヘッダ
    クライアントが自分の処理できるメディアタイプをサーバに伝える
  • Accept-Charsetヘッダ
    クライアントが自分の処理できる文字エンコーディングをサーバに伝える
  • Accept-Languageヘッダ
    クライアントが自分の処理できる言語タグをサーバに伝える

Content-Lengthメッダ

メッセージがボディを持っている場合、基本的にはContent-Lengthヘッダを利用して、そのサイズを10進数のバイトで示す。

チャンク転送

動的に画像を生成するようなWebサービスの場合、ファイルサイズが決まるまでにレスポンスが返せないのでは応答性能が低下してしまう。このときにTransfer-Encodingヘッダにchunkedを指定すると、最終的なサイズがわからないボディを少しずつ転送できるようになる。

Transfer-Encoding: chunked

認証

主流のHTTP認証方式はBasic認証とDigest認証がある。また、Web APIではWSSE(WS-Security Extension)というHTTP認証の拡張仕様を利用することもある。

Basic認証
ユーザ名とパスワードによる認証方式。
ユーザ名とパスワードはAuthorizationヘッダに入れてリクエストごとに送信する。Authorizationヘッダの内容は認証方式(Basic)に続けてユーザ名とパスワードを:で連結しBase64エンコードした文字列になる。エンコーディングは簡単にデコード可能であるため、Basic認証を利用する場合は、その程度のセキュリティ強度で良いのか、SSLTLSを使ってHTTPS通信するのかを検討する必要がある。

◆Digest認証
Basic認証よりもセキュアで複雑な認証方式。
サーバ上にパスワードのハッシュ値を補完しておけばいいのでパスワードそのものをサーバに預けなくて良い。ただしDigest認証はパスワードを暗号化するだけで、メッセージ自体は平文でネットワーク上を流れるため注意が必要。

キャッシュ

クライアントはサーバから取得したリソースがキャッシュ可能かどうかを調べ、可能な場合はローカルストレージに蓄積する。リソースがキャッシュ可能かどうか、その有効期限がいつまでなのかはPragma、Expires、Cache-Controlヘッダを用いてサーバが指定する。

Pragmaヘッダ

Pragmaヘッダに指定できる値はno-cacheのみ。

pragma: no-cache

Expiresヘッダ

Expiresはキャッシュの有効期限を示すヘッダ。

<例>

Expires: Tue, 1 Sep 2020 17:00:00 GMT

Cache-Controlヘッダ

複雑な指定ができる。

pragma: no-cache

これは

Cache-Control: no-cache

と等しい。

有効期限を指定する場合、現在からの相対時間を設定することができる。

Cache-Control: max-age: 86400

これは86,400秒、すなわち現在から24時間キャッシュが有効であることを示している。

条件付きGET

クライアントがExpiresやCache-Controlヘッダを検証した結果、ローカルキャッシュをそのまま再利用できないと判断した場合でも、条件付きGETを送信すればキャッシュを再利用できる可能性がある。
条件付きGETは、そのリソースがLast-ModifiedヘッダまたはETagヘッダを持っているときに利用できる。

Atom

Atomとは

RSSの仕様が乱立したため、標準フォーマットを策定する目的で作られたXMLフォーマット。RSSは主にブログの新着情報を伝えるフィードの目的で使われていたが、Atomはブログだけでなく検索エンジンや写真管理などさまざまなWeb APIとして利用できる。

Atomの構成要素

f:id:ud_ike:20200902230734p:plain

Atom Publishing Protocol

Atom:データフォーマットの規程(フィード、エントリ)
AtomPub:Atomを利用したリソース編集プロトコルの規程

AtomPubはAtomが規程したリソースの編集、いわゆるCRUD操作を実現するためのRESTスタイルに基づいたプロトコル

AtomPubを使えば、ブラウザ以外のWebクライアントからブログを投稿したり、システム同士を連携したりすることが簡単にできるようになる。

<AtomPubに向いていないWeb API
・Cometを利用するようなリアルタイム性が重要なAPI
・映像のストリーム配信など、HTTP以外のプロトコルを必要とするAPI
・データの階層構造が重要なAPI
・「タイトル」「作者」「更新日時」など、Atomほーマットが用意するメタデータが不要なAPI

JSON

JSON(JavaScript Object Notation)とは

RFC4627が規程するJavaScriptの記法で記述できるデータ記述言語。多くの言語がライブラリを用意しているため、プログラミング言語間でデータを受け渡しできる。

データ型

JSONに組み込みで用意されているデータ型は次の6つ。

JSONには組み込み型としての日時型がないため、日時を表現するときは開発者側で規程を準備しなければならない。最も単純なのはUNIX時間を数値として表現する方法である。

クロスドメイン通信

JSONでリソース表現を提供する副次的効果としてJSONP(JSON with Padding)を利用できる。
Ajaxで用いるXMLHttpRequestというJavaScriptのモジュールは、セキュリティ上の制限からJavaScriptファイルを取得したのと同じサーバとしか通信できない。単一のドメインとしか通信できないことは大きな制約である。

JSONPは、HTMLのscript要素を用いてブラウザのセキュリティ制限を受けないようにし、クロスドメイン通信(ドメインをまたがった通信)を実現する手法である。

リソース設計

リソース設計とは

リソース設計とは、クライアントとサーバ間のインターフェースの設計、つまりWebサービスやWeb APIの外部設計のことである。
リソース設計の指針として唯一存在するのは、「リソース指向アーキテクチャ」の設計アプローチである。

リソース指向アーキテクチャの手法

Webサービスで提供するデータを特定する
②データをリソースに分ける

各リソースに対して次の作業を行う。

③リソースにURIで名前を付ける
④クライアントに提供するリソースの表現を設計する
⑤リンクとフォームを利用してリソース同士を結びつける
⑥イベントの標準的なコースを検討する
⑦エラーについて検討する

WebサービスとWeb APIを分けて考えないことが大切。

他のリソース設計方法

以下の既存の設計手法で得られた成果物をもとにリソースを設計する方法もある。