見出し画像

4連休でgoのウェブ関係を学ぼう(Web基礎編)

前回Goのローカル環境構築について書いてきました。

参考サイトはいかになります。

今回も参考サイトに倣ってWebの基礎を復習しようと思います。高校の情報の授業を習った人なら授業の内容を少し詳しくした程度ですが、故に疎かにしがちなところでもあるのでここでもう一度復習をしましょう。

ちなみにGoの基礎文法には触れません。参考サイトには丁寧に書いてあるのでGoの文法について興味がある方は、参考サイトを参照してください。

HTTP通信の流れ

まずはブラウザとWebサーバがどのようなやりとりをしてWebページなどの情報を取得しているか、その流れを確認します。ここでブラウザなどユーザー側をクライアントと呼ぶことにします。

1. IPアドレスの取得

ブラウザでよく目にするURLは機械が理解出来るものではありません。機械はIPアドレスと呼ばれるものでインターネット上のどのサーバーに接続するべきかを判断します。ではURLからどのようにしてIPアドレスを取得しているかというとDNSサーバです。
DNSサーバにはURLとIPアドレスの対応表のようなものがあり、送られてきたURLと対応するIPアドレスを返します。返ってきたIPアドレスはURLに対応するWebサーバの住所になります。

スクリーンショット 2020-09-21 9.31.26

TCPコネクションの確立

IPアドレスにより通信を行うWebサーバを把握したらWebサーバと接続の確立を行います。クライアントとWebサーバはお互いに通信を行っても良いか許可をもらうための要求のメッセージとそれを許可するメッセージを送る必要があります。

スクリーンショット 2020-09-21 9.36.08

お互いの要求が許可されたらTCPコネクションが確立されたことになります。

Webサーバから情報の取得

通信が確立されたのでクライアントは必要な情報をリクエストします。リクエストを受けたサーバは内容に応じた情報(例えばWebページのHTMLファイルなど)をレスポンスとして返します。

スクリーンショット 2020-09-21 9.48.39

TCPコネクションの切断

必要な通信が終了したら接続を切ります。Webページに限らずWeb上のいろいろな通信が上のような形で行われています。これはPC・スマホなどデバイスによらずHTTPによる通信を行う場合はこの流れになります。

HTTP

HTTPはWebサーバに、クライアントとインターネットを通してデータのやりとりをさせるプロトコルです。プロトコルとは、先ほどあげた通信の手順など、通信を行う上でのルールのことです。HTTPはTCPというプロトコル上で成り立っているプロトコルです。コンピュータにはポートと呼ばれるデータの送受信口があり、0~65535番まであります。例えばnginxやnode.jsのexpressなどでポートを指定して開放するとローカルホストのポート番号からアクセスすることが出来ます。インターネットでの通信は基本的に80番が使用されます。

HTTPはリクエストとレスポンスのプロトコルです。クライアントが主体となりリクエストを送り、Webサーバはあくまで受け身で送られてきたリクエストに対してレスポンスを行うのみです。つまりクライアントのリクエストだけが通信を行うトリガーであり、Webサーバ側からクライアントを呼び出すことはないということです。

HTTPはステートレスなプロトコルです。つまりこれまでにどのような通信を行ったのかという状態を持つことはありません。HTTP自体は状態を持ちませんがCookieという機能を導入することで状態を管理することが出来ます。

URL

URLはUniform Resource Locaterの略で情報の場所をさす識別子になります。URLの構造は以下のようになっています(参考サイト参照)

scheme://host[:port#]/path/.../[?query-string][#anchor]
scheme         低レイヤーで使用されるプロトコルを指定します。(例えば:http, https, ftp)
host           HTTPサーバのIPアドレスまたはドメイン
port#          HTTPサーバのデフォルトのポート番号は80です。この場合ポート番号は省略することができます。もし別のポートを使用する場合は指定しなければなりません。例えば http://www.cnblogs.com:8080/
path           リソースまでのパス
query-string   httpサーバへ送るデータ
anchor         アンカー

馴染みのないところでポートの指定やアンカーの指定が出来ます。私はここで初めて知りました。

HTTPでのやりとりの内容

リクエストやレスポンスはパケットで送ります。ここからはGo言語で実際にサーバを立ててリクエストやレスポンスの内容を確認してみましょう。Goの標準パッケージnet/httpを利用すると簡単にサーバを立てることが出来ます。

ワークディレクトリに抵当なディレクトリを作成、その中にmain.goを作成し以下のコードを書いてください。

package main
import (
	"fmt"
	"log"
	"net/http"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm() // オプションを解析
	fmt.Println("----Http.Request----")
	fmt.Println("----line----")
	fmt.Println(r.Method, r.RequestURI, r.Proto)
	fmt.Println("----header----")
	fmt.Println(r.Header)
	fmt.Println("----body----")
	fmt.Println(r.Body)
	fmt.Println("----end----")
	// wに入れられた文字列がクライアントに表示される。
	fmt.Fprintf(w, "hello go server!")
}
func main() {
	http.HandleFunc("/", sayhelloName)
	err := http.ListenAndServe(":9090", nil)
	fmt.Println("Listen in 9090.")
	if err != nil {
		log.Fatal("Listen and server:", err)
	}
}

これだけでlocalhost:9090にアクセスすると”hello go server!”と表示されます。go buildでバイナリデータをビルドし、実行します。localhost:9090にアクセスするとコマンドラインにリクエストが表示されます。

リクエスト

----Http.Request----
----line----
GET /favicon.ico HTTP/1.1
----header----
map[Accept:[image/avif,image/webp,image/apng,image/*,*/*;q=0.8] 
Accept-Encoding:[gzip, deflate, br] Accept-Language:[ja,en-US;q=0.9,en;q=0.8] 
Connection:[keep-alive] Cookie:[_ga=GA1.1.1789600893.1591436885; 
csrftoken=Z66Vzq1xBX1gVzj7sA9S5uHR6wqaqjhhvCbPaxP8yn8UMlrw8s7U6vFPsvzab9es] 
Referer:[http://localhost:9090/] Sec-Fetch-Dest:[image] Sec-Fetch-Mode:[no-cors] 
Sec-Fetch-Site:[same-origin] User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36]]
----body----
{}

リクエストはリクエストライン、ヘッダー、ボディに別れています。

レスポンス

$ curl -D - http://localhost:9090
HTTP/1.1 200 OK
Date: Mon, 21 Sep 2020 01:55:13 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8
hello go server!


このようにリクエスト・レスポンスには日頃私たちが目にしている情報以外にもいろいろ情報が含まれています。

この記事が気に入ったらサポートをしてみませんか?