銀色うつ時間

思い出すたび何か胸につっかえてるだけ

HTTPってなんなの 2/2

※第2回目

前半はこちら

http://d.hatena.ne.jp/arerreee/20120821/1345568635

さて、前回はHTTPプロトコルの概要およびHTTPリクエストが果たす機能について説明した。今回はHTTPにおいてリクエストの受け手であり、返してであるHTTPレスポンスの役割についてまとめていく。

HTTPレスポンスの構成

通信の開始は常にクライアント側であり、クライアントが投げるリクエストに対してサーバーは何かしらのリアクションを返す、というHTTPの基本原則は前回のエントリで触れた。HTTPレスポンスとは、受け取ったリクエストに応じてサーバー側からクライアント側に送られる情報である。

HTTPレスポンスは、以下の情報群によって構成されている。

  • レスポンスステータス行
  • メッセージヘッダ
  • データ本体(メッセージボディ)

状態を表すコードが第1行目に登場し、その後詳細な情報を表すヘッダ部が続き、最後にメッセージボディが送られる。この構造はクライアント側から送られるHTTPリクエストと殆ど同一のものであることがわかる。実際に前回HTTPリクエストを確認した2chにアクセスしたときに送られてきたレスポンスを調べてみる。

HTTP/1.1 200 OK
Date: Thu, 30 Aug 2012 13:59:10 GMT
Server: Apache/2.2.15
Last-Modified: Wed, 02 Jun 2004 15:33:37 GMT
Etag: "e8280b-1b63-3dbe269f6b640"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 2174
Connection: close
Content-Type: text/html

これらの情報が私たちのブラウザに送られた後に、メッセージボディ(つまりは2chのhtmlデータや画像)が送られてくるというわけだ。そのデータをブラウザが構築することでこのページが表示されている、というわけ。

http://www2.2ch.net/

レスポンスステータス行

HTTPレスポンスにおいてまず何より大事なのが1行目のステータス行だ。

HTTP/1.1 200 OK

最初の"HTTP/1.1"の部分はWebサーバーがサポートするHTTPのバージョンを表している。次に続く"200"こそがなじみ深いHTTPステータスコードだ。これは要するにアクセスするクライアント側への結果発表みたいなもので、ブラウザからのリクエストをサーバーがどう処理したかを番号で表している。考えてみれば当然で、ホスト側に伝える大量の情報群の中でも、最初に伝えるべきなのは結果なのだ。その辺の書類と同じである。最後の「OK」の部分は、ステータス・コードの補足説明。ここでは無事に要求通りのものをサーバーが持ってきたことを示している。

さて、404や403など、誰でも知っているようなステータスコードもあるだろうが、他にはどのようなものがあるだろうか。先日素晴らしいコンテンツがインターネットで話題になっていたのでそちらを紹介し、ここでは主要なものに留めることにしておく。ぜひ目を通しておきたい。

先輩と覚える HTTP ステータスコード ― Gist - Gist - GitHub

https://gist.github.com/3401612

  • 1xx Informational リクエストはサーバーに届けられ、処理は継続する。
  • 2xx Success リクエストはサーバーに受理される。200:要望通りのモノをもってきた。成功。おっけー。
  • 3xx Redirection リクエストを完了させるために、さらなる処理が必要。
    • 301:恒久的な移動。Locationヘッダに移動先は記述される。「このホームページは引越ししました。10秒後に・・・」
  • 4xx Client Error クライアント側のリクエストに誤りがあった。お前何言ってるかわかんねーよ。
    • 403:Forbidden。リソースにアクセスすることを禁止されている。サーバー側から排他的な処理がなされている場合が多い。アク禁
    • 404:Not Fouund。そんなものなかった。
  • 5xx Server Error サーバー側がリクエストの処理に失敗した。
    • 500:Internal Server Error。サーバー内部にエラーがあった。プログラムの文法ミスなどで処理が止まるなど。
    • 502:Bad Gatewayゲートウェイ・プロキシサーバーが不正なリクエストを受け取り、これを拒否した。
レスポンスヘッダ部分

リクエストのヘッダフィールドと同じく、レスポンスヘッダフィールドも

フィールド名: 内容

という形式で表される。今回サーバーから受け取った情報を順に見ていく。

Date: Thu, 30 Aug 2012 13:59:10 GMT //メッセージの作成日時を示す
Server: Apache/2.2.15 //サーバのベンダー名、バージョン番号を示す
Last-Modified: Wed, 02 Jun 2004 15:33:37 GMT //オブジェクトが最後に変更された日時を示す
Etag: "e8280b-1b63-3dbe269f6b640" //オブジェクトのエンティティタグ値を示す。ネットワークの帯域を節約するための キャッシュの管理で用いられる。
Accept-Ranges: bytes //オブジェクトの一部に対するリクエストをサーバが受け入れ可能か示す
Vary: Accept-Encoding //サーバがレスポンス内容を決定する際にリクエストURI以外に用いたヘッダのリストを示す
Content-Encoding: gzip //オブジェクトのエンコーディングを示す
Content-Length: 2174 // 	オブジェクトのサイズをバイト単位で示す
Connection: close //中間システムが転送すべきでないヘッダのリストを示す
Content-Type: text/html //オブジェクトのタイプを示す

その他のヘッダで重要なものとしては、set-CookieやLocationが挙げられる。

クッキーは、まずサーバがSet-Cookieというヘッダを発行する所から始まる。これをクライアントは受け取り、次回以降のアクセスでsetされたCookieをリクエストヘッダに付加してサーバーに送ることでサーバーは一意のクライアントを判別することができ、ショッピングカートや視聴履歴といったシステムが可能となる。サーバがクライアントにクッキーを送る時のレスポンスヘッダは以下のような形式となる。

Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure

set-Cookieヘッダを利用してsessionIDをクライアントに送ることでユーザーを同定しているのだから、これさえ入手すれば第三者ユーザーになりすますことも当然可能である。好きな女の子のCookie情報をこっそり引っ張ってこれれば、などと考えてしまう人が時折登場するのも性である。ブラウザが持つCookieとはそれほどに尊いものなのだ。

  • Location

これはステータスコード3xx系でよく用いられる。Locationヘッダフィールドは、リクエストの完了や新しいリソースの識別をするため用いられる。受信者をRequest-URI以外の場所にリダイレクトするってこと。3xxレスポンスの場合、Locationはリソースへ自動でリダイレクションさせるためにサーバが望むURIを示すべき。単一の絶対 URI から成る。

Location: http://www.w3.org/pub/WWW/People.html

まとめ

HTTPレスポンスはレスポンス行、ヘッダフィールド、メッセージボディの3つに大別され、レスポンス行では応答のサマリーとして状態を示すステータスコードが記載され、以降のヘッダフィールドにはクライアント側に返すのに必要な形式やサイズといったメタ情報が記されていることが分かった。それらの情報の後にクライアント側が要求するオブジェクト、すなわちhtmlやcssといったコードや画像や音声といったバイナリデータが本体として送信されている。前エントリで学んだリクエストヘッダを受けたサーバーがこのような処理を行うことで、HTTP通信が行われる。主要なステータスコードやヘッダフィールドはちゃんと覚えておきましょう。全2回に分けるほどHTTPで学ぶべき領域は膨大であった。「未だHTTPの5%も理解できていないのでは」とも思うが、今回は一応これで区切りとしておく。

なにか間違いがあったらご指摘ください!

HTTPってなんなの 1/2

※全2回です

HTTPってなんのことだか分かりますか!

ぼくは分かりません!

でもインターネットだいすきです!

このような人は多いと思う(自分含めて)

さっそく学んでいく。

HTTPとはHyperText Transfer Protocol(ハイパーテキスト・トランスファー・プロトコル)の略称である。WebブラウザとWebサーバの間でHTMLなどのコンテンツの送受信に用いられる通信プロトコルのことで、ITIFによりRFC2616で規定されている。ハイパーテキスト転送プロトコルとも呼ばれる。乱暴な言い方をすれば、僕らがブラウザを通じてやってることはだいたいHTTPという規格の上で通信している、ということ。通信プロトコルについてまでまとめると大変なことになるので、また時間のあるときに。とはいえwikipediaに載っている程度の情報はさらっと目を通しておいた方がよい。

通信プロトコル - Wikipedia

http://ja.wikipedia.org/wiki/%E9%80%9A%E4%BF%A1%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB

もうちょい概要

ティム・バーナーズ・リーらが1990年に世界初のWebサーバーとWebブラウザを開発した。サーバーとブラウザ間による通信を行うために彼らが設計した通信プロトコルこそが、HTTPであり、トランスポートプロトコルとしてTCPを使用している。HTTPは名前の通りHTMLやXMLの転送を主な目的としているが、周知の通り音声や映像などのバイナリ形式も転送可能である。リクエスト-レスポンス型のプロトコルであり、クライアント(ブラウザ側)がサーバにリクエストメッセージを送信する。サーバはこれにレスポンスメッセージを返し、基本的にこの時点で初期状態に戻る。つまりこれは、サーバ側がクライアントの状態を保存しないことを意味する(これを解決するCookieについては後述)。他には、ポート番号80をデフォルトで使用すること、TLSによって暗号化されることでセキュリティを保った通信はHTTPSと呼ばれることなどが挙げられる。

HTTPリクエスト

先に述べたように、リクエストを投げるのは常にクライアント側である。逆を返せば、サーバーはリクエストがなければ応答しない。HTTP通信を開始できるのはクライアント側のみなのだ。基本的な考え方は非常に単純で、リクエストは「何を」「どうして」欲しいのかをサーバーに伝える。URLが「何を」、メソッドが「どうして」に当たる。

HTTPリクエストの構成

基礎を確認するのだから静的なウェブサイトが好ましい。試しにhttp://www.2ch.netにアクセスしたときに自分のブラウザから投げたリクエストを確認してみた。firebug(chromeの場合は付属の開発者ツール)なんかですぐに調べられる。

GET / HTTP/1.1
Host: www.2ch.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw
If-Modified-Since: Mon, 09 Jul 2012 16:28:11 GMT
If-None-Match: "159100-10b9-4c468198a9cc0"-gzip
Cache-Control: max-age=0

HTTPリクエストには

  • HTTPリクエスト行
  • HTTPヘッダ
  • データ本体(メッセージボディ)

の3つのパートが存在する。HTTPリクエストの1行目が、リクエスト内容を示すHTTPリクエスト行(リクエストライン)で、ここには「メソッド」「URI」「HTTPのバージョン」の3つの情報が含まれている。記述方法は以下。URIに関しては後述。

[メソッド][空白][URI][空白][HTTP バージョン]
今回のリクエストではこの部分(ドメインは省略されている、というかサーバー側の絶対パスなのでスラッシュのみ。もちろん階層を下がればindex.htmlなどといった文字列が出現する)
GET / HTTP/1.1

今回のようにGETメソッドの場合、HTTPリクエストではデータ本体は送られない。メソッドがPOSTの場合は、HTTPヘッダの後にデータ本体が続く。HTTPヘッダに関してだが、GETメソッドを用いているこのリクエストでは2行目以降はすべてHTTPヘッダである。POSTなど他のメソッドだった場合は次行からメッセージボディが続くことになる。

GET, POSTを初めとするHTTPメソッド

GETやPOSTといったメソッドは私達に馴染み深いが、実は他にもHTTPメソッドは存在する。おさらいも兼ねて以下にまとめる。

  • GET
    • 指定されたURIのリソースをサーバーから取り出すHTTPの最も基本的な動作。
  • POST
    • GETとは反対にクライアントがサーバにデータを送信する。Webフォームや掲示板の投稿などをイメージすると分かりやすい。GETの場合と同じく、サーバはクライアントにデータを返すことができるが、クライアント側から見ればGETは受け取るメソッドであり、POSTは送信するメソッドなので混同しないようにする。

あとはあまり馴染みのないメソッドたちだが、いつか出会うこともあるだろう。

  • PUT
    • 指定したURIにリソースを保存する。URIが指し示すリソースが存在しない場合は、サーバはそのURIにリソースを作成する。画像のアップロードなどが代表的。
  • DELETE
    • 指定したURIのリソースを削除する。
  • OPTION
    • サーバを調査する。例えば、サーバがサポートしているHTTPバージョンなどを知ることができる。
  • HEAD
    • GETと似ているが、サーバはHTTPヘッダのみ返す。クライアントはWebページを取得せずともそのWebページが存在するかどうかを知ることができる。例えばWebページのリンク先が生きているか、データを全て取得することなく検証することができる。
  • TRACE
    • サーバまでのネットワーク経路をチェックする。サーバは受け取ったメッセージのそれ自体をレスポンスのデータにコピーして応答する。WindowsのTracertやUNIXのTracerouteとよく似た動作。
  • CONNECT
    • 暗号化したメッセージをプロキシで転送する際に用いる。
URIとは

先に触れたURIについて。URLと名前も概念もなんだか混同してしまいそうだが、一応別の識別子である。が、ことHTTPにおいては殆ど同義といえる。めんどいから概要はWikipediaから。

Uniform Resource Identifier(ユニフォーム リソース アイデンティファイア、URI)または統一資源識別子(とういつしげんしきべつし)は、一定の書式によってリソース(資源)を指し示す識別子。1998年8月にRFC2396として規定され、2005年1月にRFC3986として改定された。URI はUniform Resource Locator (URL) の考え方を拡張したものである。

URIはhttp/httpsftpなどのスキームで始まり、コロン(:)による区切りのあとにスキームごとに定義された書式によってリソースを示す。また、URIによって示されるリソースはコンピュータが扱うデータに限らず、人や会社、書籍などを示すことも可能である。

(アイデンティファイアとか名前かっこいいな・・・)

要は膨大なウェブの中で、「hogehoge区にお住まいのfoobarさんちのfugafugaさん」みたいに一意の存在を識別するための仕組みであると考えられる。もう少し詳しく見ていこう。

http://www.2ch.net:80/foo?bar#bazというURIについて考える。この文字列は

  • http
  • www.2ch.net
  • 80
  • foo
  • bar
  • baz

に分けられるが、それぞれどんな解釈がされるのだろうか。以下に見ていく。

  • scheme
    • 最初の文字列はデータリソースにアクセスするための手法を識別する。ここでのスキームは当然http。
  • host
    • 次のwww.2ch.netはホスト名、つまりそのリソースを持っているコンピュータ(たいていはサーバー)の名前を指定する。IPアドレスによる指定も可能だが奨励されていない。
  • port
    • ファイル共有ソフトなんかのお陰で開発に携わらない人間にも馴染みが深いポート番号。これを指定する。先に述べたようにデフォルトのHTTPが扱うポート番号はWell known portとして80番が予約されてるが、それ以外の番号を使用することも可能。8000や8080などをテスト用として利用することや、セキュリティの観点から別の番号を用いることもある。ポート番号が明示されていない時は80を使用する。ポートに限らずTCP/IP関連はまた別の機会に。
  • abs-pass
    • absolute pass、すなわち絶対パス。そのコンピューター内でのリソースの場所を指定する。スラッシュ(/) をディレクトリ区分に用いる。
  • query
    • クエリ文字列、よくクエリパラメータとか呼ぶ。絶対パスとの区切りには?を利用する。指定したリソースに情報を流す場合に用いるのだが、GETメソッドを利用する場合にも使われる。
  • fragment
    • 部分識別子。絶対パスとの区切りには、#を用いる。fragmentもURIの中に含まれるが、"http_URL"の中にはfragmentは含まれない。HTTPにおいて、fragmentはリソース内の特定部分を指すものであり、即ちfragmentはリソース取得後にのみ意味を持つ。

がどう使われるか。どの部分がクライアントで解釈されるか、どの部分がサーバーで解釈されるか。

HTTPヘッダ

2ch.netにアクセスしたときのリクエストにも、hostやrefererなどといった文字列があった。これらがHTTPヘッダである。クライアントとサーバーは、HTTPヘッダを使ってデータやソフトウェアの情報をやりとりしている。HTTP/0.9では、データの取得のみを目的としていたので、HTTPヘッダというものは存在しなかったが、wwwが活用され始めるにつれリソースサイズや更新時刻といった「取得するリソースに関連する情報」や、ユーザエージェントの種類やそれを参照するリソースのURIなどの「クライアント側の情報」をやりとりする必要性に迫られ、実際のリソースとは別のメタ情報を扱うものとして、HTTPヘッダが開発されたという経緯がある。ヘッダの書式は、

フィールド名: 内容

という形式で記述される。代表的なリクエストヘッダを列挙する。

  • Accept
    • サーバのレスポンスに含まれるメッセージボディで受け入れることが出来るコンテンツタイプと各コンテンツタイプの相対的な優先度を指定するリクエストヘッダ。
  • Accept-Charset
    • レスポンスで返されるメッセージボディの文字コードを指定するリクエストヘッダ。Acceptと同じく複数指定でき品質係数も設定できる。定義済み文字セットはIANAが管理している。
  • Accept-Encoding
  • Accept-Language
    • レスポンスの言語(人間の言語)に対する優先度を指定する。言語コードはISO-639の2文字の省略コードを用いる。書き方は他のAccept-群と変わらず。
  • Host
    • Hostヘッダはhttp/1.1における唯一の必須ヘッダである。必須の理由として、ネームベースのバーチャルホストが用いられた際の名前解決に必要となることが挙げられる。バーチャルホストでは、たとえば192.168.0.100というIPアドレスを持つ1台のホストサーバがあったとして、これにhost1.2ch.net,host2.2ch.net, host3.2ch.netという3つのドメインを割り当てたとする。これによって、クライアントから見るとまるで3台のホストサーバがあるように見えるので、IPアドレスを“節約”することができるのだ。この時にhttp://host3.2ch.net/hogeへリクエストをするとどうなるだろうか。クライアントがリソースを取得するためには、まずホスト名をIPアドレスに変換する、すなわち名前解決をしてサーバを探し出した後にリクエストをする必要がある。(参考:DNSの仕組みについて http://d.hatena.ne.jp/arerreee/20120814/1344960272)だがこの場合リクエスト先のIPアドレスには3つのホストが同居しているので、このままでは望むリソースを取得することができない。対策として、それぞれにIPアドレスを付与する方法もあるがIPv4の資源を無駄にすることになる。そこで、Hostヘッダを使用し予めホスト名をメタデータに明示しておくことで名前解決を行なっている、というわけだ。
Host: www.2ch.net
  • User-Agent
    • ブラウザの種類やOSの情報。アクセスしているのがブラウザではなく検索エンジンのクローラの場合、Googlebotなどの名前が入る。歴史的経緯からどのブラウザもMozillaを入れていたりする。また、モバイル端末やキャリア、OSの識別もUser-Agentを利用して行う。
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
  • Referer
    • どのページから発生したリクエストなのかを示す。つまり、ページAに記されたリンクをクリックしてページBに行った場合に、ページBへのHTTPリクエストにリファラとしてページAが入ってくる。同様に、ページCを表示する際にページ内で使われている画像をリクエストする際に、画像のHTTPリクエストにリファラーとしてページCが入る。リファラの活用はクロスサイトリクエストフォージェリ(いわゆるCSRF)対策としても一般的であろ、統計的用途にもよく使われる。余談だが、本来の参照元という意味の英単語は"referrer"であるにもかかわらず、HTTPリファラの場合は意図的に"referer"と綴る。これは、HTTPが策定された時にヘッダ名を間違ったスペルで書いてしまい、それが今でも使われているという歴史的経緯のためである。仕様上のヘッダ名は"referer"であるため、特にHTTPヘッダを直接扱うようなソフトウェアプログラムの場合、"referrer"と綴ると意図通りに動作しない場合すらある。ここではgoogleから辿ってきたので次のような内容となる。
Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw
  • Cookie
    • クッキー(Cookie)は実のところRFCによって定義されていいない非標準HTTPヘッダである。元々ユーザエージェント(Webブラウザ)によって保存される「小さな」ファイルを指す。主に「状態管理」のために利用され、ログイン情報やショッピングカートを実現するために利用されている。Cookie、Set-Cookieという専用のHTTPヘッダ。
  • Content-Disposition
    • これも非標準。Content-Dispositionは、本来MIME仕様に従うデータの提示的情(presentational information)を転送するためのヘッダだが、HTTPはメッセージの形式がMIMEに似ているので、HTMLフォームからmultipart dataをアップロードする際にも流用されている。つまりファイルのアップロードに用いられるヘッダ。filename属性を使うと、転送されたデータのファイル名をデータの送信側が示すことができる。

次回に向けて

HTTPについてまとめるとプロトコルやポートなどといったTCP/IPの領域、さらにはリクエストラインのメソッドやリクエストヘッダなどのおびただしい形式などが出現して頭が破裂するかと思った。特にリクエストヘッダにはヘッダごとに更に属性を保持していたりでやっかい。少しずつ覚えて記事にしていこうと思う。やっぱ本1冊程度は読んでおくべきだよなーこの辺、などと。

次回は残りのHTTPレスポンスについて書く。

何か間違いがあったらご指摘ください。

githubのセットアップ

備忘録です。

MacOS or Linuxならこれで大丈夫かと。githubにアカウント作成済み、gitは既に入れてあるものする。確か自分の環境では、Macならhomebrew経由でインストールするか、バイナリで配布されているものを使えばよい。Ubuntuなら「sudo apt-get install git」でおk。

SSH公開鍵をさくっと作る

githubとの通信にはSSHが必要になる。まずは公開鍵と秘密鍵のペアを作っておく。さっさと作ってしまおう。カレントディレクトリは自分のホームディレクトリで。

cd .ssh もし.sshディレクトリが存在しなければ mkdir .ssh <-.sshディレクトリに移動
ssh-keygen -t rsa  -C "githubに登録したアドレス" <-公開鍵作成

ssh-keygenすると「どこに鍵作る?」などと聞いてくるが、.ssh内でよいので空のままEnterで。続けてパスワードが求められるので適当なパスワードを設定しておく。確認でもう一度タイプ。

 --[ RSA 2048]----
|       .=.E      |
|         =       |
|        + .      |
|     o + o       |
|    o O S        |
|   o + = o       |
|    + + o .      |
|     o * .       |
|      o .        |
+-----------------+

こんなんが出たら公開・秘密鍵のペアが作成されているはず。lsでid_rsa(秘密鍵)とid_rsa.pub(公開鍵)が出来ているのを確認する。

githubへ公開鍵の登録をする

githubにアクセスし、AccountSettingsからSSHKeysの項目を開き、新しく鍵を登録する。鍵は先ほど作った公開鍵のid_rsa.pubを使う。

cat id_rsa.pub

これで出力された文字列をコピーして、github側に貼り付ける。名前は適当に入れておく。保存すれば公開鍵の登録は終了。

試しにSSHgithubに接続してみる

以下のコマンドを打つ。

ssh -T git@github.com

接続を許可するかどうか聞いてくるはず。そしたらyesと打ち込んであげればよい。あと恐らくクライアント側からパスワードが要求されると思う。「hogehogeさんこんにちは!とはいえまだ設定終わってないぜ!」みたいなこと言い出したら接続に成功している。ついでにgithubにpushしたときに使われる名前なども登録してしまう。

git config --global user.email "hogehoge"
git config --global user.email "foo@bar.com"

リポジトリ作成とgit push

さて通信もできたところで、ささっとリポジトリ作成からpushするところまでやってしまいましょう。

ブラウザからgithubに行き、ダッシュボードかどこかで新規リポジトリ作成をクリック。TestRepoという名前にでもしておきましょうか。画面通りに進んで名前だけ決めておけばあと別になにもしなくてもよい。

で、github側の登録が済んだら、再び端末。ローカルリポジトリを作りましょう。カレントはどこでもいいので、リポジトリを置きたい場所でブラウザで作ったリポジトリと同名のディレクトリを作成する。

mkdir TestRepo
cd TestRepo
git init TestRepo
touch UNKO
echo TestRepo is my first contact by git. > UNKO 

git initは文字通り初期化、リポジトリの作成コマンドである。gitリポジトリの管理ファイルなどがこのコマンドを打った後作成されているはずである。なんでもいいのでとりあえずファイルを作るためにtouchしている。一応UNKOファイルに文字を入れておく。ファイルが無事できたが、それをローカルリポジトリに登録していないので登録しておく。コミットもここでしておかなければならない。サーバー側のリポジトリ(github側)にpushするときにエラーが出る。

git add UNKO
git commit -m 'unko!!!'

無事ファイルがローカルリポジトリにadd,commitできたら、サーバー側に上げてやる。初めてpushする前に、まずはリモートリポジトリがどこにあるのか設定する一文を書いてやらなきゃならない。

git remote add origin git@github.com:"ゆーざー名"/"リポジトリ名(ここではMyRepo)".git
git push -u origin master

これで怒られずにpush完了のお知らせが来ていることを待つ。githubにアクセスして、期待通りTestRepoにUNKOファイルがあれば無事セットアップ完了。お疲れさまでした。



あとの流れ

ローカルリポジトリとリモートリポジトリが無事繋がったので、あとはやりたい放題。リポジトリ管理に入れたいファイルやディレクトリをTestRepoに入れるなり、また新しくリポジトリを作成したりなど。既存のリポジトリに追加する場合、基本的には以下のコマンドでおk。

git add hoge
git commit -m 'massage'
git push -u origin master

githubからリポジトリをコピーするコマンドをよく忘れるのでこれも追記。

git clone git://github.com/xxxx/xxxx/xxxx.git

DNSの仕組みについて

日頃から私達のネットを支えるDNSについて。IPアドレスに対して対応する適切な名前を返してくれるサーバー、くらいの認識しか持っていなかったのだが、理解を深めるために調べてみました。

そもそもDNSサーバー(ネームサーバー)ってなんだ

Domain Name System(ドメイン ネーム システム、DNS)はインターネットを使った階層的な分散型データベースシステムである。1983年に情報科学研究所 (ISI) のポール・モカペトリスとジョン・ポステルにより開発された。現在では主にインターネット上のホスト名や電子メールに使われるドメイン名と、IPアドレスとの対応づけを管理するために使用されている。 -wikipediaより

これは歴史的経緯から考えるとわかりやすい。TCP/IPのネットワークプロトコル下では、それぞれの ホスト(コンピュータやルータなど)は、IPアドレスによって識別され、通信が行われている。インターネットに接続されるすべてのホスト、すなわちコンピュータは固有のIPアドレスを保有しているのだ。すなはち、どのホストにアクセスする際も最終的にはIPアドレスを知る必要がある。とはいえ、IPアドレスは最大12桁(ipv4では)の十進数だがこれを把握するのは非常に難しいので、IPアドレスを人間でも覚えられるように別の文字列に置き換える機構が生まれた。これがDNSというわけだ。試しにブラウザから以下のIPアドレスを叩いてみよう。

124.83.203.233

ブラウザにはyahoo!japanのトップページが表示されるはずだ(20012/08現在)。このようにIPアドレスに対して対応する文字列(これがURL)を渡す役割をするのがDNSである。ちなみにこの仕組こそが「名前解決」という名前で呼ばれるものだ。余談だが、IPアドレスを調べるためには、hostコマンドを用いる。「host [調べたいドメイン]」と打つだけ。

【追記】

ipv4において最大12桁のアドレスは、8bit * 4 で 32bitとなる。

ドメイン構成について

世の中に存在するIPアドレスは膨大だ。どう考えてもとても1つのコンピューターで処理できる量ではない。そう考えると、DNSサーバー(ネームサーバーとも呼ばれる)も膨大な数が存在するのだろうと想像がつく。では、世界中にあるDNSサーバーはどのようにして役割分担をしているのだろうか。URLはホストとドメインの連結文となっており、ピリオド「.」で区切られていることに着目したい。例えばwww.yahoo.co.jpだと、

jp         ->トップレベルドメイン(国別コード)
|-co.jp       ->第二レベルドメイン(組織種別コード)
|-yahoo.co.jp    ->第三レベルドメイン(組織名)
|-www.yahoo.co.jp  ->第四レベルドメイン
最大255文字

となっていることが分かる。この階層構造において、yahoo.co.jpはco.jpの配下であり、jpの配下という構成で成立している。組織名は、さらに組織内の階層をピリオドで区切って指定できる。例えばwww.dev.yahoo.co.jpなどといった形式である(これをサブドメインという)。

名前解決

それぞれのネームサーバーは担当するドメインの対応表を保有しており、この木構造のノード、つまりはピリオドを辿ることで、最終的なIPアドレスが得られるという仕組みだ。ここで、「木構造の最上位には何が位置しているのか?」という疑問が生じる。我々の期待している通り、最上位には「ルートサーバー」と呼ばれるネームサーバーが全世界に13台分散配置されており、こいつらがDNS界の親玉なわけだ。とまあそんな構造をもったDNSによる名前解決、その処理の流れは以下のように完結にまとまる。

  • まず最寄の(送信元ホストと同じドメインの)ネームサーバーに問い合わせる
    • 目的のアドレスがあれば、ここで解決
  • 最寄のネームサーバーになければ、まずルートサーバーに問い合わせる
  • jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはco.jpドメインを管理するネームサーバーのアドレスを返す
  • co.jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはyahoo.co.jpドメインを管理するネームサーバーのアドレスを返す
  • yahoo.co.jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはwww.yahoo.co.jpドメインを管理するネームサーバーのアドレスを返す
  • www.yahoo.co.jpドメインのネームサーバーに問い合わせる
    • 対応表から124.83.203.233というIPアドレスを割り出し、これをクライアントに返す

hostsとは

DNSと同じように、IPアドレスとホスト名のマッピングを行う原始的な仕組みが、「hosts」ファイルだ。各ホストがローカルファイルとしてマッピング情報を管理している。LinuxMacOSでは「/etc/hosts」に存在するファイルそれに当たる。hostsファイルとは、ローカルでホスト名をIPアドレスに変換する際に参照するファイルだ。このファイルは先に述べた名前解決の流れの中で用いられる。「google.co.jp」というホスト名を、「216.239.33.100」という実際のIPアドレスに変換する時に参照するのだが、ここで重要なポイントは、このhostsファイルの記述はDNSサーバーによる変換より優先されるということだ。/etc/hostsに以下を追加してみる。

216.239.33.100 yahoo.co.jp

hostsファイルはこのように「IPアドレス ホスト名」というように書くのだが、この場合はどうなるだろうか。結果としては、ブラウザからyahooのアドレスを打ち込んだとき、表示されるページはgoogleになる。先に述べた、DNSを参照してyahoo.co.jpのIPである124.83.203.233に辿り着く前にhostsファイルで変換されてしまい、google(216.239.33.100)に飛ばされるわけだ。hostsファイルの設定は大規模な名前解決の手段とはならないものの、特定ページへのアクセスを別の参照先に飛ばしたい場合や、ローカル環境での開発などに有用である。



以上!なにか間違いがあったら指摘ください!

vimのomni補完をためしてみる

IDEに関しては素人童貞程度の経験しかないのですが、補完機能が優秀なのはやっぱりいいなあと思うわけです。そこでvimでもomni補完というものがなかなか優秀だと聞くので試してみました(今まで補完機能すらまともに使ってなかったのかよこのクズという罵声は悦んで受けます)。vimで何か適当な関数を入力しているときに[ctr + x][ctr + o]と打ってみる。するとこんな感じで候補となる関数一覧が表示される。

f:id:arerreee:20120727000829p:image

[ctr + n]で下にカーソル移動、[ctr + p]で上にカーソル移動、決定は[ctr + y]で行える。上方に引数の型や返り値なんかが書いてあるので、「この関数どういう順番で引数がくるんだっけ」という場面でわざわざ調べに行く手間を省けて便利。IDEみたいに自動で補完候補が出るようにはできないの?という方にはこちらのプラグインをどうぞ。プラグインへの追加方法はググってね(といっても$HOME/.vimに突っ込むだけですが)

[AutoComplPop]

http://www.vim.org/scripts/script.php?script_id=1879

このプラグインはinsertモード時の入力を監視してファイル名や変数の補完やomni補完をやってくれる気の利いたものなんだけど、デフォルトだと補完対象となる文字列の長さが2文字という鬼畜な仕様なので、ちょっと変えた方がいい。補完機能が働けば働くほどエディタの動作に軽快さを欠き、逆にストレスが溜まるので。。。このプラグインに関してはこの辺が参考になりました。

http://vim-users.jp/2009/07/hack-44/


まだ様子見ではありますが、必要に応じて補完機能を呼び出す方がぼく好みではありそうなのでAutoComplPopは使わずにvimデフォルトのomni補完を使っていく所存。とはいえデフォルトの[ctr + x][ctr + o]はなかなかに鬼畜なコマンドだと思うので、以下のようにキーバインドを変更。変更はconfig_fileである.vimrcに書いておく。これで[ctr + f]で補完機能を呼び出せる。

imap <C-f> <C-x><C-o>

「<C-Space>じゃないのかよ!」という声も聞こえてきそうですが、Macユーザーの場合は[ctr + Space]はspotlightに割り当てられているのでこのように設定しました。

いつか「私のIDEvimです」と言える日が来るその日までめげない。

jQueryでお手軽アコーディオンパネル

http://ascii.jp/elem/000/000/498/498710/

こちらで「40分で覚える!Query速習講座」なるものがあったので、ささっと実装。jQueryもだけど、javascriptの基礎を勉強していきたい。

<!DOCTYPE html>
<html lang="ja">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
  $("dd:not(:first)").css("display","none"); //2つ目以降のddのcssを非表示にする
  $("dl dt").click(function(){ //clickされたらfunction以下を行う
    if($("+dd",this).css("display")=="none"){
//セレクターで指定した要素のdisplayプロパティがnoneなら、{…}内に書かれた命令を実行する。この場合はクリックされたdl要素の次にくるdd要素を示す。
      $("dd").slideUp("normal");
      $("+dd",this).slideDown("normal");
    }
  });
});
</script>
<style type="text/css">
*{
  margin:0;
  padding:0;
  }
dl{
  width:400px;
  margin:50px auto;
  }
dl dt{
  background:#7CADB6;
  border-bottom:1px solid #FFFFFF;
  cursor:pointer;
  }
dl dd{
  border:1px solid #7CAD86;
  border-top:none;
  height:300px;
  }
</style>
</head>
<body>
<dl>
  <dt>text</dt>
  <dd>
    <p>text................text</p>
  </dd>
  <dt>text2</dt>
  <dd>
    <p>text................text</p>
  </dd>
  <dt>text3</dt>
  <dd>
    <p>text///////////////</p>
  </dd>
</dl>
</body>
</html></span></span></span>

これもASCIIの転載ですが、こんな感じで動きます。

http://editors.ascii.jp/m-kobashigawa/jquery_sample/special/sample5.html

最低限入れておきたいvimrcの設定

とりあえず現状の.vimrcは以下のような設定。これで最低限の開発は不自由なくできると思われる。

#新しい行のインデントを現在の行と同じにする
set autoindent
#vi互換を切る
set nocompatible
#タブの代わりに空白文字を挿入する
set expandtab
#変更中のファイルでも、保存しないで他のファイルを表示
set hidden
#インクリメンタルサーチを行う
set incsearch
#行番号を表示する
set number
#シフト移動幅
"set shiftwidth=4
#対応する括弧を表示する
set showmatch
#検索時に大文字を含んでいたら大/小を区別
set smartcase
#高度な自動インデントを行う
set smartindent
#行頭の余白内で Tab を打ち込むと、'shiftwidth' の数だけインデントする。
set smarttab
#ファイル内の <Tab> が対応する空白の数
"set tabstop=4
#カーソルを行頭、行末で止まらないようにする
set whichwrap=b,s,h,l,<,>,[,]
#検索をファイルの先頭へループしない
set nowrapscan
#256色配色を用いる
set t_Co=256
#カラースキーマを指定する(ここではmolokai)
colorscheme molokai

まだ重要な機能があると思う&補完機能などを設定していないので、またしばらくしたら追加する予定