https://www.amazon.co.jp/Webを支える技術-HTTP、URI、HTML、そしてREST-WEB-PRESS-plus/dp/4774142042
この本の要約を自分用に書きました。おかしな点等があれば、コメントお願いいたします。
WEBとは何か
ブラウザを通じてインターネットの向こう側にあるwebサーバーとやりとりしながら、私たちはyoutubeとかを見る。 webの用途は3つに分かれる。 ①webサイト ②ユーザーインタフェースとしてのWEB:テレビ、プリンタとかの設定をパソコン使ってやった方が便利なことがある。またHTMLによるヘルプの記述もそう。windowsにはhtmlヘルプ(意味のわかりにくい単語にハイパーリンクが設定されており、クリックすると解説が書かれたページにジャンプする。)という機構があり、HTMLをベースにソフトウェアやハードウェアのヘルプを作成できる。 ③プログラム用APIとしてのWEB:ユーザーインタフェースだけでなく、APIというプログラム用のインターフェースとしても利用されている。WEBを支える技術
HTTP,URI,HTMLがWEBを支える基本的な技術。URIを使えば世界中のあらゆる情報を指し示せる。HTMLはそれらの情報を表現する文書フォーマット。そしてHTTPというプロトコル(コンピューター同士の通信をする際の手順や規格のこと)を使ってそれらの情報を取得したり発注したりする。 この3つの技術によって支えられたWEBは情報システムとして見ると、ハイパーメディアシステムと、分散システムの二つの側面を持っているハイパーメディア
ハイパーメディアとはテキストや画像、音声など様々なメディアをハイパーリンクで結びつけて構成したシステム。はいぱメディア以前(書籍や映画は線形的に先頭から順に読む)のに対し、ハイパーメディアは非線形的にユーザが自分でリンクを選択して情報を取得する。 ハイパーリンクorリンクとはハイパーメディアにおいて情報同士を結びつける機構のこと。htmlで記述されたWEbページには他のWEBページや埋め込まれた画像へのリンクが含まれる。分散システム
一つの中央コンピュータが全てを処理する形式を集中システムという。これに対して複数のコンピュータを組み合わせて処理を分散させる形式を分散システムと呼ぶ。WEBは世界中に配置されたサーバに世界中のブラウザ(WEBサイトを閲覧するために使うソフトのこと)がアクセスする分散システム。WEBの歴史
WEBが持つ歴史的背景をハイパーメディアシステムと分散システムの二つの側面から解説していきます。WEb以前のインターネット
初期のインターネットにはWEBがなかった。 インターネットの起源は1969年に構築されたARPANETまで遡る。これは研究機関を繋ぐためのネットワーク。 WEB以前のインターネット環境は、リアルタイムに相手とやり取りするTCP/IPではなく、バケツリレー方式のUUCPによる転送も存在したので、情報の到達までに遅延があった。WEB以前のハイパーメディア
ハイパーメディアの起源はARPANETの誕生からさらに遡った1945年のMemexという情報検索システムに関する論文に影響を受けたネルソンが生み出した。ネルソンはハイパーメディアとハイパーテキストという言葉を考案した。ハイパーテキストは文字情報中心の文章を相互にリンクさせた概念であるのに対し、ハイパーメディアはその考えを拡張し、音声や画像なども相互にリンクさせた概念。 その後のWEB以前に成功を収めたハイパーメディアとしては、Hyper Cardがある。これにはネットワークを通じてリンクをやり取りする機能はないものの、「カード」と呼ばれる文章を単位に相互にリンクを貼り、スクリプト言語によるプログラムを実行することができた。Web以前のハイパーメディアの問題点
これまでに最も普及したハイパーメディアの実装はWEB。しかし旧来のハイパーメディア推進者の目からするとWEBは不完全なハイパーメディアのように映る。その理由はWebが単方向リンクしかサポートしていない。リンクが切れる可能性がある。バージョン管理やトランスクルージョン(ある文章中に他の文章断片への参照を埋め込みあたかも一つの文章のように見せる技術。)の機能がないなどがあげられる。しかし必要最低限のリンク機能だけを備えたいたのがWEBの成功要因である。旧来のハイパーメディアは複雑すぎた。WEB以前の分散システム
昔は集中システムが主流だった。コンピュータが小型で高性能になると複数のコンピュータを組み合わせて処理を分散させ、全体としての性能を向上させる手法が登場する。RPC
分散システムを実現するためには各サーバが提供する機能を他のサーバやクライアントから呼び出せる必要がある。RPCを用いるとリモートのサーバで実行しているプログラムをクライアント側から呼び出せる。 各社とも自社の分散システム技術を標準にしようと躍起になっていた。 RPCは関数を呼び出す仕組み。ただ現代的なプログラミング言語はほとんど全てがオブジェクト指向機能を備えている。そこで単なる関数呼び出しではなく、オブジェクト自体をリモート側に設置する分散オブジェクトと呼ばれる技術が考案された。ただ汎用的なオブジェクト機能を実装しようとしたため、仕様が非常に複雑になったのと、各社がバラバラで開発したため、互換性がないという問題があった。Web以前の分散システムの問題点
RPCシステムに共通で存在する問題は ①性能劣化の問題:ネットワーク越しの関数呼び出しは、同一プロセス内で関数を呼び出すのに比べると何倍もの時間がかかる。一般に関数の粒度が小さいので目的を達成するために何回も関数を呼び出さないとならず、時間がかかる。 ②データ型変換の問題:プログラミング言語ごとにサポートするデータ型が異なるため、複数の言語が混在する環境ではデータ型の変換で問題が起きる。 ③インターフェースバージョンアップ時の互換性の問題:機能追加に伴ってサーバーのインターフェースを更新した場合、古いクライアントに対して下位互換性を保てない。 ④負荷分散の問題:一般にRPCベースのシステムはサーバ上にアプリケーション状態を保存する。そのためサーバ間でアプリケーション状態を共有しなければならず、多数のサーバーで負荷を分散することが難しい。 このようにWEB以前の分散システムは数を限定した均一なクライアントが前提だった。これでは世界規模で動作するシステムにはならない。Webの誕生
1990年に最初のWebが生まれる。Webの普及を一気に推し進めたのがMosaicというブラウザ。これによって文字情報だけでなく、画像も扱えるようになった。ハイパーメディアとしてのWeb
Webはインターネットを利用したハイパーメディアとして設計された。Web以前のハイパーメディアとの1番の違いはここ。インターネットを利用しているので不特定多数の情報をリンクさせあうことができる。その反面情報の集中的な管理は難しくなり、リンク切れが起きやすい。 Webが実現しているリンクはシンプルな単方向のリンクだけであることも特徴。元々のリンクの概念では外部からリンクを指定するといった拡張リンクの考え方も存在した。分散システムとしてのWeb
RPCは閉じたネットワーク環境で、あらかじめ想定した数と種類のクライアントを相手にサービスを提供するシステムとしては優れている。Webはクラインアントとサーバ間のインターフェースをHTTPというシンプルなプロトコルで固定したことで不特定多数を相手できるようになった。Webの標準化
Webを構成するHTTP,URI,HTMLの標準化が求められた。Web以前のインターネット標準は全てIETFのRFCとして定められてきたが、Webが急速に普及したため、仕様策定が追いつかず、各社がバラバラの仕様で実装を行ってしまった。 この問題を解決するため、各社が集まってW3Cをという団体を創設。HTMLとCSSの仕様がバラバラだったのを長い年月をかけて解消していったが、現在も問題は残っている(cf 「ブラウザ対応」という言葉)RESTの誕生
Webアーキテクチャの決定に関わる重要な人物がロイフィールディング。彼はRESTというアーキテクチャスタイルを名付けた。さまざまなハイパーメディアフォーマットの誕生
初期のWebではHTMLが唯一のハイパーメディアフォーマット。しかしWebの普及に伴ってHTMLでは対応できない様々な要望が生まれ、microformats,Atomとかが誕生した。 HtmlやAtomはXMLをベースにした構造化文書のためのマークアップ言語のため、データを記述するためには表記が冗長すぎる。そこで単純化のためにjsonが生まれた。WebAPIをめぐる議論
初期のWEBは人が文書を読むためのシステム。しかしWEBの用途が多様化するとプログラムから自動処理を行いたいという要求が出る。SOAPとWS-*
WEB上でも分散オブジェクトを実現しようとする動きが出た。その中でHTTPをアプリケーションプロトコルではなく、トランスポートプロトコルとして扱い、HTTPの上で独自のメッセージを転送するSOAPというプロトコルが生まれた。しかしこのSOAPに関連した周辺仕様(WS)がまた乱立してしまい、標準化戦争が起きた。SOAP対REST
SOAPとRESTのどちらがアーキテクチャとして優れているから議論。アマゾンがSORPとREST形式でそれぞれWEB APIを提供したところRESTの方が圧倒的に多く使われた。RESTを否定する人はAmazonのようにセキュリティが必要ない簡単なWEBAPIではURIをGETするだけのシンプルなRESTの方が良い。しかし基幹システムなどでトランザクションや信頼性が必要なときはRESTでは不十分だと主張。SOAPとWS-*の敗因
敗因は2つ。 SOAPはRPC/分散オブジェクトが持っていた技術的な問題点をそのまま継承してしまったという技術的な理由。 またSOAPの中でも標準化戦争の中で解釈に違いが生じ、相互運用性にかけてしまったという政治的な理由。REST WEBのアーキテクチャスタイル
RESTはWebのアーキテクチャスタイル。MVC(model-view-controller)もアーキテクチャスタイルの一種。RESTは特にネットワークシステムのアーキテクチャスタイル。 WebのアーキテクチャスタイルはRESTでもあり、クライアント/システムでもある。クライアント/サーバアーキテクチャスタイルにいくつか制約を加えるとRESTというアーキテクチャスタイルになる。 実装→アーキテクチャ→アーキテクチャスタイルの順に抽象度が上がっていく(p27)リソース
RESTにおける重要な概念の一つにリソースがある。リソースとはWEB上に存在する名前を持ったあらゆるもの(東京の天気予報、ブックマークetc)。リソースの名前がURIである。URIがなかった昔はいちいちファイルの取得方法を自然言語で書く必要があった。(p29) 一つのリソースが複数のURIを持つことが可能(ex todyと10/01 p29)。 サーバとクライアントでやりとりするデータのことをリソースの表現という。一つのリソースは複数の表現をもてる(html、pdfなど)スタイルを組み合わせてレストを構成する
RESTは複数のアーキテクチャスタイルを組み合わせて構築した複合アーキテクチャスタイル。 クライアント/サーバに他のアーキテクチャスタイルを追加して制約を課していくことでRESTを構成する。クライアント/サーバ
クライアント・サーバの利点は単一のコンピュター上で全てを処理するのではなく、クライアントとサーバに分離して処理ができること。これによりクライアントをPCだけでなくゲーム機とかにもできる。 またユーザーインターフェースはクライアントが担当するため、サーバはデータストレージの機能だけを提供すればよく、複数のサーバを組み合わせ(冗長化)ることで、可用性(故障が起きても復帰が早い)をあげられる。ステートレスサーバ
クライアント・サーバに最初に追加するアーキテクチャスタイルがステートレスサーバ。ステートレスとは、クライアントのアプリケーション状態をサーバで管理しないこと。これだと、サーバ側の実装を簡単にできるというメリットがある。 現実にはステートフルなwebサービスがある(Cookieを使ったセッション管理など)。ステートレスだと、クライアントはリクエストごとに全ての情報を送る必要があるが、これだとログイン状態を保持してページを遷移することができないから、Coikieが使われる。 Cookieはステートレスサーバの利点を捨てることになることを理解した上で使用すること。キャッシュ
次のアーキテクチャスタイルはキャッシュ。キャッシュとはリソースの鮮度に基づいて、一度取得したデータをクライアント側で使い回すこと。キャッシュの利点はサーバとクライアント間の通信を減らすことでネットワーク帯域の利用や処理時間を縮小できること。ただ古いキャッシュを使用してしまい、情報の信用性が下がる危険もある。統一インターフェース
次のアーキテクチャスタイルは統一インタフェース。統一インタフェースとはURIで示したリソースに対する操作を統一した限定的なインタフェースで行うこと。例えばHTTP1.1ではGETやPOSTなど8個のメソッドだけが定義されており、通常はこれ以上メソッドは増えない。一般的なプログラミング言語の感覚からすると厳しい制約だが、このおかげでアーキテクチャがシンプルになる。またインタフェースを統一することで、クライアント・サーバの実装の独立性が向上。階層化システム
統一インタフェースの利点の一つにシステム全体を階層化しやすいことがあげられる。webサービスではサーバとクライアントの間にプロキシを設置してアクセス制限したりするが、クライアントからするとサーバもプロキシも同じインタフェースで接続できるので、接続先がサーバからプロキシに変わったことを意識する必要がない。基幹系のレガシーシステムでHTTPのインターフェスを実装してないシステムでも、レガシーシステムの前にWEBサーバを挟めばブラウザなどのクライアントと接続できるようになる。 このようにシステムをいくつかの階層(サーバ/プロキシ/クライアント)に分離するアーキテクチャスタイルを階層化システムという。コードオンデマンド
コードオンデマンドとは、プログラムコードをサーバからダウンロードし、クライアント側でそれを実行するアーキテクチャスタイル。javascriptやflashなどがこれに該当する。この利点はクライアントを後から拡張できること。クライアントプログラムに予め用意した機能以外も使うことができる。 欠点はネットワーク通信におけるプロトコルの可視性が低下すること。HTTPというアプリケーションプロトコルに従って通信している時は通信の意味やアクセスするリソースが明白だが、クライアント側でコードをダウンロードして実行すると、可視性は低下する。RESTまとめ
RESTは以下の6つを組み合わせたアーキテクチャスタイル。 クライアント/サーバ キャッシュ ステートレス コードオンデマンド 統一インタフェース 階層化システム REST以外にもP2Pといったアーキテクチャスタイルがあり、サーバを介さずに通信したい時とかはRESTよりもこっちの方が良かったりする。RESTの2つの側面
RESTとハイパーメディア
web上のリソース同士が持つリンクをたどる作業をいくつか経ることで、ソーシャルブックマークという一つのアプリケーションが誕生するような特徴を、RESTでは「アプリケーションエンジンとしてのハイパーメディア」と呼ぶ。アプリケーション状態とは「ブックマーク一覧を表示している」「新しいブックマークを追加しようとしている」といった具体的な状態。アプリケーション状態はハイパーメディアのリンクを辿ることによって遷移するため、ハイパーメディアがアプリケーション状態エンジンと呼ばれる。 リソースをリンクで接続することで一つのアプリケーションを構成するという考え方はRESTの基幹をなす思想。この考えを「接続性」と呼ぶ。RESTと分散システム
RESTに基づいたWEBサービスはリンクを辿ることでアプリケーションを実現する。リソースはそれ自体で意味を持つ一塊のデータであり、RPCのような分散オブジェクトが呼び出す関数のようなデータよりも粒度が大きい。 またRPCや分散オブジェクトではバージョンアップするたびに、メソッドが増えたり因数や戻り値が変わったりしてAPIの互換性が失われる。一方RESTに基づいたWEBでは統一インタフェースによってこの問題が起こらない。URI
URIを構成するパーツは以下の通り。 URIスキーム:http ホスト名:blog.example.jp パス:/entries/1 ホスト名はドメイン名またはIPアドレス 以下のような複雑なIPアドレスもある。 URIスキーム:http ユーザ情報:yohei:pass ホスト名:blog.example.jp ポート番号:8000 パス:/serch クエリパラメータ:q=test&debug=true URIフラグメント:#n10 ユーザ情報はリソースにアクセスするためのユーザ名とパスワードから成り立つ。ホスト情報はホスト名とポート番号から成り立ち、ポート番号はこのホストにアクセスするときのプロトコルで用いるTCPのポート番号を示す。ポート番号を省略した場合は各プロトコルのデフォルト値が用いられる。 クエリパラメータはクライアントから動的にURLを生成するときに用いる。 URIフラグメントはURIが指し示すリソース内部のさらに細かい部分を特定するときに使用。この例がhtml文書の場合はid属性がn10であることを示す。相対URIと絶対URI
ルート(1番上のディレクトリ)から記述したパスを絶対パスという。相対パスは現在のディレクトリから書く。外部サイトには相対URIを書くことができない。相対URIを使えばドメインを変えても問題が起きないというメリットがある。 相対URIの起点となるURIを指定するのがベースURIである。URIと文字
URIで使える文字は決まっている。日本語を使いたい時は%エンコーディングを使う。%エンコーディングは文字エンコーディング(UTF8など)によって同じ文字でも異なる。URIの実装で気をつけること
クライアントで相対URIを解決するのは大変なので、なるべく絶対URIを使った方がクライアントに親切。 URIに日本語とかを入れるときは%エンコーディングの文字コーディングとしてUTF8が望ましい。 URLとURLを総称する名前がURI。URLはサーバが障害で変更になったりするとアクセスできないが、これを解決するためにドメイン名と独立してリソースに恒久的なIDを振った結果がURN。ただURNはそんなに普及してない。理由はURLが十分永続的なのと、URNはURIとしてリソースを取得できないから。URIの設計
クールなURIは変わらない。URIを変わりにくくするには
・プログラミング言語に依存した拡張子やパスを含めない:ある言語に依存した文字列をURLに含めるとその言語を変更した途端そのURLは使えなくなる。 ・メソッド名やセッションIDを含めない:メソッド名を変更した途端にURIが変更になってしまう。セッションIDをCookieではなくURIに埋め込んではいけない。なぜならセッションIDはログインするたびに変わるから。 ・URIはリソースを表現する名詞にする:URIとHTTPメソッドの関係は動詞と名詞の関係にある。URIは全体として名詞になる必要がある。最近はRubyとかでは実装に依存したURIはデフォルトでは作られないようになっている。URIのユーザビリティ
シンプルなURIは覚えるのも簡単。間違いにくいURIを変更したいとき
リダイレクトを使うURI設計のテクニック
拡張子で表現を指定する。プログラミン言語を指定するのはまずいが、自然言語や(htmlかjson)とかを指定する分には良い。 httpにはコンテントネゴシエーションという機能があり、日本語版のOSを使っている人には日本語、英語版のOSを使っている人には英語を返せる。(Acceptヘッダを使用。他にもacceptヘッダで文字エンコーディングやメディアタイプを指定できる)コンテントネゴシエーションがある場合は日本のOSから英語のリソースを取ってくるにはブラウザの設定を変更しないといけないが、拡張子で言語を明示すればその問題は消える。 階層構造で表すことができず、複数パラメータの組み合わせで表現するようなリソース(マップなど)はマトリクスURIで示す。マトリクスURIでは/ではなく;や,で区切る(p62)Http
インターネットのネットワークプロトコルは階層的。 ネットワークインターフェース層:物理的なケーブルやネットワークアダプタ。(ex イーサネット) インターネット層:ネットワークでデータを実際にやりとりする部分(IP)。IPではデータの基本単位をパケットと呼ぶ。IPではデータを送り出すことだけを保証。送り出したデータが送り先に届くかは保証しない。 トランスポート層:データの転送を保証する(TCP)。TCPは接続先の相手に対してコネクションを貼り、データの到達を保証。TCPで接続して転送したデータがどのアプリケーションに渡るかを決定するのがポート番号。https://www.infraexpert.com/study/tcpip.html アプリケーション層:具体的なアプリケーション(メールやHTTP)を実現する層。TCPでプログラムを作るときはソケットと呼ばれるライブラリを使うのが一般的。ソケットはネットワークでのデータのやりとりを抽象化したAPIで、HTTPサーバやブラウザはソケットを用いて実装。HTTPのバージョン
HTTP0.9が最初のHTTP。WEBが発明されたときに使われていたプロトコルのこと。ヘッダはなく、メソッドもGETしかない。 HTTP1.0はIETFで最初に標準化が行われたバージョンのこと。GET以外のメソッドの追加、ヘッダの導入などが行われる。 HTTP1.1でHTTPが完成する。チャンク転送、ACCEPTヘッダ、複雑なキャッシュコントロールなどが導入。リクエストとレスポンス
サーバでの処理に時間がかかる場合でもクライアントはレスポンスが帰るまで待機。 リクエストとレスポンスの例。 クライアントはまずDNSを使ってドメイン名を名前解決(「ドメインネーム」を「IPアドレス」に変換する)し、その結果得られるIPアドレスを使ってTCP80番ポートに接続して、リクエストを送信。 サーバーはこのリクエストを読み取ってレスポンスを返す。 サーバから帰ってきたレスポンスを解析した結果、再度リクエストが必要になる場合もある。画像やスタイルシートへのリンクがいくつも含まれている時とかは、正しくHTMLをレンダリング(データ記述言語やデータ構造で記述された抽象的で高次の情報から、コンピュータのプログラムを用いて画像・映像・音声などを生成すること)するためには50回以上リクエストを発行しないといけない。 クライアントからリクエストを受けたサーバはまずリクエストメッセージを解析し、クライアントがトップページの取得を要求していると知ったとすると、トップページのHTMLをレンダリングするアプリケーションに処理を委譲し、結果のHTMLを取得。その後適切なヘッダを付加してレスポンスを返す。HTTPメッセージ
リクエストメッセージ
リクエストメッセージの1行目は、リクエストラインと呼ばれる(p77を参照すること) リクエストURIに絶対URIを用いた場合はリクエストラインの次にHostヘッダを書く必要がない。 リクエストメッセージの2行目以降はヘッダが続く。ヘッダの後にはボディがくることもある(リソースを更新したりする場合)。レスポンスメッセージ
レスポンスメッセージの1行目はステータスライン。プロトコルバージョン(HTTP/1.1),ステータスコード(200),テキストフレーズ(OK)からなる。ステータスコードはリクエストの結果(200,404・・)を示す。 レスポンスメッセージの2行目はヘッダ。Content-Typeヘッダなどがある。 ボディが含まれることもある。ヘッダとボディの間には空行があり。HTTPメッセージの構成要素
1行目はスタートライン(リクエストラインorステータスライン) スタートラインの次はヘッダ。ヘッダの終了は空行で示す。ヘッダは省略可能。 ヘッダの次はボディ。ボディも省略可能ステートレス
アプリケーション状態はセッション状態ともいう。システムにログインしてからログアウトするまでの一連の操作をまとめてセッションという。 ステートフルの代表的なプロトコルがftp。 ステートフルの欠点は①クライアントが増えるとサーバがクライアントのアプリケーション状態を覚えるのが大変②クライアントが増えるとサーバを増やす必要があるが、クライアントがどのサーバに接続するか特定できないので、サーバ間でアプリケーション状態を同期する必要があり、この際のオーバーヘッド(間接的なコスト)が問題になる。 ステートレスのメリットはサーバ側の仕組みが単純なこと。デメリットはクライアントから送信する情報が多くなることと、認証などのサーバに負荷がかかる動作を繰り返すこと(認証でデータベースにアクセスするとかは思い処理と言える)。また通信エラーの時の対処も問題になる。なぜならサーバーはアプリケーション状態を覚えてないので、通信障害時にリクエストが処理されたか分からないから。(p86)httpメソッド
CRUDとはcrete,read,update,deleteの略。HTTPメソッドはget,post,put,delete,head,options,trace,connectの8つ。POST
POSTでは子リソースの新規作成ができる。また新規作成ではなくデータの追加も可能。POSTの挙動が作成か追加は実装に依存するので、WEB APIの仕様書とかを確認すること。 POSTでは他のメソッドで対応できない処理の実行も可能。(p93)https://www.iruca21.com/entry/2017/03/16/152616PUT
PUTの機能はリソースの内容の更新とリソースの作成です。PUTはURIを指し示すリソースを直接を指定するが、POSTは子リソースのURIをサーバを勝手に作成するという違いがある。https://hajimehoshi.hatenadiary.org/entry/20090710/1247161012 リソース作成における、PUTとPOSTの使い分けに正解は存在しないが、設計の指針として以下の事実がある。POSTでリソースを作成する場合、クライアントはリソースのURIを決められないが、PUTの場合は逆。 twitterのように呟きのURIをサーバが自動で決定するような場合はPOST。Wikiのようにクライアントが決めたタイトルがURIになる場合はPUT。この場合はURIの上書きを避けるためにクライアントが事前にURIをチェックする必要があるかもしれない。HEAD
HEADはリソースのヘッダだけを取得する。つまりボディが含まれない。ネットワークの帯域を節約しながらリソースの大きさや更新日時を取得するのに使う。OPTIONS
OPTIONSはそのリソースがサポートしてるメソッドの一覧を返す。 OPTIONSを実装する場合は、多くのウェブフレームワークでは自分で実装する必要がある。POSTでPUT/DELETEを代用する方法
HTMLのフォームで使用できるのはGETとPOSTだけ。ただ_methodパラメータを用いるとHTMLフォームでもPUTとか使える。http://portaltan.hatenablog.com/entry/2015/07/22/122031 _methodパラメータはフォームを使ってリクエストを送らない場合(POSTの内容がXMLなど)時は使えない。その場合はX-HTTP-Method-Overrideヘッダを使用する条件付きリクエスト
HTTPメソッドと更新日時などのヘッダを組み合わせることで、メソッドを実行するかどうかをリソースの更新日時を条件にサーバが選択できるようになる。これを条件付きリクエストという。べき等性と安全性
べき等は操作を何回やっても結果が同じことを表す(GET,HEAD,PUT,DELETE) 安全性は操作対象のリソースを変化させないこと(GET,HEAD) POSTはべき等でも安全でもないから、二重注文とかが起こる。 GETメソッドを使ってdeleteを行う(p105)とかをするのは駄目。 POSTがなんでもできるからといって、GET,PUT,DELETEとかの機能をPOSTで行おうとしたら駄目。 PUTで現在のリソースとの差分(+50とか)を送信するとべき等でなくなってしまうから注意。 DELETEがべき等でなくなるのはlatestとか使って表されたURIを削除するとき。これを防ぐために、時間や状況で指し示すリソースが変化するリソースは更新や削除ができないようにするステータスコード
1xx:処理中 2xx:成功 3xx:リダイレクト 4xx:クライアントエラー。クライアントのリクエストに問題がある 5xx:サーバーエラー。サーバー側に問題があるので、その問題が解決すれば、同一リクエストで正常な結果が得られる可能性がある。 未知のステータスコードが来た場合も、100の位が守られてればクライアントは最低限の処理ができる。よく使われるステータスコード
200ok:リクエスト成功 201created:リソースの作成成功 301MovedParmanently:リソースの恒久的な移動。リソースが新しいURIに移動したことを示す。新しいURIはレスポンスのlocationヘッダに絶対URIとして入る。 303SeeOther:別のURIの参照。リクエストに対する処理結果が別のURIで見れることを示す。(POSTでログイン情報を送った後に、ユーザーページのURIを返す時など。) 400BadRequest:リクエストの間違い。リクエストしたパスワードが単純すぎる時など。 401Unauthorize:アクセス権不正。WWW-Authenticateヘッダでクライアントに対して認証方式を伝える。 404notfound:リソースの不在 500InternalServerError:サーバ内部エラー。 503ServiceUnavailable:サービス停止。サーバがメンテナンス中の時とか。 クライアントがアクセプトヘッダでhtml形式とかxml形式とかを指定している場合は、それに応じてエラーメッセージを動的に変更できる。ステータスコードの誤用
p123参照。GETしたいファイルが見つからないというエラーを200OKで返したりしているものがある。HTTPヘッダ
リソースへのアクセス権を設定する認証や、クライアントとサーバの通信回数を減らすキャッシュの機能とかはヘッダで実現。 HTTPの使用は電子メールのメッセージ使用のヘッダ形式を参考に作られているので、ヘッダの詳細を知るには電子メールの仕様を知らなければならない。 電子メールのヘッダには7bit ASCIIコード以外の文字を入れないという制約があり、HTTPヘッダもそれを引き継いでいる。以下代表的なヘッダ。p123以降参照。 日時:DateやExpiresが相当する。日時は全てGMT(グリニッジ天文台)で記述。 MIMEメディアタイプ:リソースの表現の種類を指定。content-typeはapplication/xhtml+xmlみたいにメディアタイプを指定するやつ。/の左がタイプ(text,imageなど)で右がサブタイプ。 charsetパラメータは文字のエンコーディングを指定。省略可能だが、タイプがtextの時は色々と不具合が起こりやすいから注意。textタイプの時は必ずcharsetを指定し、かつtext/xmlという形式は使わずapplication/xmlとかを使うと問題は起こらない。 言語タグ:content-languageヘッダは自然言語を指定。ja-JPなどといった書き方で左がISO639が定義する言語コードで右がISO3166が定義する地域コード。コンテントネゴシエーション
クライアントが自身が処理できるメディアタイプの順位をサーバに伝える。 Accept:処理できるメディアタイプを伝える。サーバがそのメディアタイプに対応してない時は406NotAcceptableが帰る。 Accept-Charset:処理できる文字エンコーディングを伝える。 Accept-Language:処理できる言語を伝える。Content-length:ボディの長さを指定。静的なファイルなどあらかじめサイズの分かってるリソースを転送する場合に使うと良い。
チャンク転送:動的に画像を生成するようなWebサービスの場合、ファイルサイズが決まるまでレスポンスを返せないのでは応答速度が悪くなる。この時はTransfer Encodingヘッダにchunkを指定して、最終的なサイズが分からないボディを少しずつ転送できるようになる。
認証
HTTP認証方式にはBasic認証とDigest認証がある。WWW-Authenticateヘッダによりクライアントはサーバが提供する認証方式を理解できる。 Basic認証はユーザー名とパスワードによる認証方式。Authorizationヘッダの内容はユーザ名とパスワードをBase64エンコードしたものになる。Base64円コーディングは簡単にデコード可能だから、SSL、TLSを使ってHTTPS通信し、通信路上で暗号化したほうが良い。 Digest認証はBasic認証よりも安全。流れとしては、まず認証情報なしでリクエストを送ると認証が失敗し401 Unauthorizeが帰ってくる。この時のwww-Authenticateヘッダにはまずnonceというリクエストごとに変わる文字列が入っている。qopという値も入っていて、この値がauthかauth-intかによってダイジェストの作成方法が変わる。https://ken3ypa.hatenablog.com/entry/2019/01/10/212124 https://ja.wikipedia.org/wiki/Digest認証 Digest認証ではBasic認証と違いパスワードを盗まれ危険がない。Digest認証ではサーバ上にパスワードのハッシュ値を補完しておけば良いのでパスワードそのものをサーバに預けずに済むので安全。https://blog.goo.ne.jp/xmldtp/e/b6a697735a597e8e41af460ae2f2875a Digest認証の場合もパスワード以外は平文でネットワークを流れるので、メッセージを暗号化したい場合はHttpsを使う。 Basic認証の場合は同じURI空間にあればクライアントは一度認証すれば2回目以降は自動でユーザとパスワードを送れる。Digest認証の場合はサーバからのnonceが毎回必要なので、リクエストの度に401レスポンスを得ることになり面倒。Digest認証がサポートされてないサーバーもある。OpenIDとOAuth
OpenIDを使うとYahooのアカウントで自分が開発したサイトにもアクセスできるようになったりする。 OAuthはwebサービス間でデータをやり取りできるようにするための仕様。あるサービスに保存してある写真を他のサービスでも使えるようにすることを認めるもの。WSSE認証
HTTP1.1の標準外の認証方式。AtomPubなどのWeb APIの認証に使われる。BASIC認証もDIGEST認証も使えない場合に、パスワードを盗まれずに送信するための方法。この認証方式は生のパスワードをネットワークに流さずにすむうえDigest認証ほどめんどくさくない。一方サーバ側で生のパスワードを保存しておく必要がある。キャッシュ
クライアントはローカルストーレージにキャッシュを蓄積する。クライアントが蓄積したキャッシュはそのキャッシュが有効な間、クライアントが再度そのリソースにアクセスしようとしたときに再利用する。リソースがキャッシュ可能かその有効期限がいつまでかは、ヘッダを用いてサーバが指定。キャッシュのためのヘッダにはいくつかある。使い方の方針としては, キャッシュをさせない場合はPragmaとCashe-Controlのno-casheを同時に指定。キャッシュの有効期限が絶対的に決まっている時はExpieresを指定。有効期限を相対的(今から〜時間)に決める時はCasheーcontrollのmax-ageを使用。 ローカルキャッシュが期限切れで使えないとクライアントが判断した場合でも、リソースがLast-ModifiedヘッダかETagヘッダを持っている場合は、条件付きGETを使用してサーバのリソースがクライアントのローカルキャッシュから変更されているかを調べて、キャッシュを再利用できるか判断できる。 ETagヘッダの方がおすすめp148。持続的接続
HTTP1.0ではクライアントがTCPコネクションを確立してリクエストを送信し、サーバーがそれにレスポンスを返すたびにTCPのコネクションを切断していた。TCPのコネクション確立はコストがかかる処理なので、画像とかにたくさんリンクしているページを表示させようとするともっさりした動作になった。これを避けるためにkeep-aliveヘッダでサーバとクライアントが常に接続状態であるようにした。この持続的接続状態ではクライアントはサーバのレスポンスを待たずにリクエストを送信できる。これをパイプライン化という。HTML
構造化文書のためのマークアップ言語としてはSGMLがあった。HTMLはSGMLを元に作られた。SGMLでは複雑で処理プログラムが作りにくかったので、仕様をシンプルにしたXMLが開発された。HTMLをSGMLベースからXMLベースに変えた仕様がXHTML。メディアタイプ
HTMLのメディアタイプにはtext/htmlとapplication/xhtml+xmlの2種類がある。前者はSGML形式のHTML、後者はxmlベースのXHTMLを示す。 htmlは木構造になっていて親要素・子要素の関係にある。 内容を持たないから要素があるなど。これは
と省略できる。 要素は属性を持つことができる。属性名=”属性値”という書き方。 「<」とかは特殊文字だから<と表記する。 名前空間:複数のHTMLフォーマットを使うときに名前の衝突を防ぐために使うのが名前空間。属性の名前空間や要素の名前空間とかがある。https://www.cybertech.co.jp/xml/contents/xmlxmldb/serial/_xmlbeginner10.php#title4 名前空間がついた属性をグローバル属性という。ついてないのをローカル属性という。