[ja] apply patch
This commit is contained in:
@@ -59,19 +59,12 @@ Handler:リクエストを処理し、返すデータを生成する処理ロ
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
tempDelay = 0
|
tempDelay = 0
|
||||||
if srv.ReadTimeout != 0 {
|
|
||||||
rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
|
|
||||||
}
|
|
||||||
if srv.WriteTimeout != 0 {
|
|
||||||
rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
|
|
||||||
}
|
|
||||||
c, err := srv.newConn(rw)
|
c, err := srv.newConn(rw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go c.serve()
|
go c.serve()
|
||||||
}
|
}
|
||||||
panic("not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
監視した後どのようにしてクライアントのリクエストを受け取るのでしょうか?上のコードではポートの監視を実行後、`srv.Serve(net.Listener)`関数をコールしています。この関数はクライアントのリクエスト情報を処理しています。この関数では`for{}`が置かれており、まずListenerを通じてリクエストを受け取った後、Connを作成します。最後に単独のgoroutineを開きます。このリクエストのデータを引数としてこのconnに渡します。:`go c.serve()`。これはマルチスレッドを行なっています。ユーザが行うリクエストはすべて真新しいgoroutineの上で行われ、互いに影響しません。
|
監視した後どのようにしてクライアントのリクエストを受け取るのでしょうか?上のコードではポートの監視を実行後、`srv.Serve(net.Listener)`関数をコールしています。この関数はクライアントのリクエスト情報を処理しています。この関数では`for{}`が置かれており、まずListenerを通じてリクエストを受け取った後、Connを作成します。最後に単独のgoroutineを開きます。このリクエストのデータを引数としてこのconnに渡します。:`go c.serve()`。これはマルチスレッドを行なっています。ユーザが行うリクエストはすべて真新しいgoroutineの上で行われ、互いに影響しません。
|
||||||
@@ -92,4 +85,3 @@ Handler:リクエストを処理し、返すデータを生成する処理ロ
|
|||||||
* [目次](<preface.md>)
|
* [目次](<preface.md>)
|
||||||
* 前へ: [GOで簡単なwebサービスを立ち上げる](<03.2.md>)
|
* 前へ: [GOで簡単なwebサービスを立ち上げる](<03.2.md>)
|
||||||
* 次へ: [Goのhttpパッケージ詳細](<03.4.md>)
|
* 次へ: [Goのhttpパッケージ詳細](<03.4.md>)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ Goがクライアントのリクエストを待ち受けるには以下のよう
|
|||||||
type ServeMux struct {
|
type ServeMux struct {
|
||||||
mu sync.RWMutex //ミューテックス、リクエストがマルチスレッド処理に及んだことでミューテックス機構が必要になります。
|
mu sync.RWMutex //ミューテックス、リクエストがマルチスレッド処理に及んだことでミューテックス機構が必要になります。
|
||||||
m map[string]muxEntry // ルーティングルール、一つのstringがひとつのmuxエンティティに対応します。ここではstringは登録されるルーティングを表現しています。
|
m map[string]muxEntry // ルーティングルール、一つのstringがひとつのmuxエンティティに対応します。ここではstringは登録されるルーティングを表現しています。
|
||||||
|
hosts bool // 任意のルールにhost情報が含まれているか
|
||||||
}
|
}
|
||||||
|
|
||||||
以下でmuxEntryを見てみましょう
|
以下でmuxEntryを見てみましょう
|
||||||
@@ -31,6 +32,7 @@ Goがクライアントのリクエストを待ち受けるには以下のよう
|
|||||||
type muxEntry struct {
|
type muxEntry struct {
|
||||||
explicit bool // 精確にマッチするか否か
|
explicit bool // 精確にマッチするか否か
|
||||||
h Handler // このルーティング式はどのhandlerに対応するか
|
h Handler // このルーティング式はどのhandlerに対応するか
|
||||||
|
pattern string //マッチング文字列
|
||||||
}
|
}
|
||||||
|
|
||||||
次にHandlerの定義を見てみましょう。
|
次にHandlerの定義を見てみましょう。
|
||||||
@@ -48,25 +50,47 @@ Handlerはインターフェースですが、前の節の中で`sayhelloName`
|
|||||||
f(w, r)
|
f(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
ルータでは対応するルーティングルールを保存した後、具体的にはどのようにリクエストを振り分けているのでしょうか?
|
ルータでは対応するルーティングルールを保存した後、具体的にはどのようにリクエストを振り分けているのでしょうか?以下のコードをご覧ください。デフォルトのルータは`ServerHTTP`を実装します:
|
||||||
|
|
||||||
ルータはリクエストを受け取った後、`mux.handler(r).ServerHTTP(w, r)`をコールします。
|
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
||||||
|
if r.RequestURI == "*" {
|
||||||
|
w.Header().Set("Connection", "close")
|
||||||
|
w.WriteHeader(StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h, _ := mux.Handler(r)
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
言い換えれば、目的のルーティングのhandlerのServerHTTPインターフェースをコールすると、mux.handler(r)はどのように処理するのでしょうか?
|
上に示す通りルータはリクエストを受け取った後、`*`であれば接続を切断し、そうでなければ`mux.handler(r).ServerHTTP(w, r)`をコールして対応する設定された処理Handlerを返し、`h.ServeHTTP(w, r)`を実行します。
|
||||||
|
|
||||||
func (mux *ServeMux) handler(r *Request) Handler {
|
つまり、目的のルーティングのhandlerのServerHTTPインターフェースへのコールです。ではmux.Handler(r)はどのように処理するのでしょうか?
|
||||||
|
|
||||||
|
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
|
||||||
|
if r.Method != "CONNECT" {
|
||||||
|
if p := cleanPath(r.URL.Path); p != r.URL.Path {
|
||||||
|
_, pattern = mux.handler(r.Host, p)
|
||||||
|
return RedirectHandler(p, StatusMovedPermanently), pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mux.handler(r.Host, r.URL.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
|
||||||
mux.mu.RLock()
|
mux.mu.RLock()
|
||||||
defer mux.mu.RUnlock()
|
defer mux.mu.RUnlock()
|
||||||
|
|
||||||
// Host-specific pattern takes precedence over generic ones
|
// Host-specific pattern takes precedence over generic ones
|
||||||
h := mux.match(r.Host + r.URL.Path)
|
if mux.hosts {
|
||||||
if h == nil {
|
h, pattern = mux.match(host + path)
|
||||||
h = mux.match(r.URL.Path)
|
|
||||||
}
|
}
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = NotFoundHandler()
|
h, pattern = mux.match(path)
|
||||||
}
|
}
|
||||||
return h
|
if h == nil {
|
||||||
|
h, pattern = NotFoundHandler(), ""
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
もともとこれはユーザのリクエストしたURLとルータの中に保存されているmapのマッチングに従って、このhandlerのServHTTPインターフェースをコールすることで目的の関数を実行することができます。
|
もともとこれはユーザのリクエストしたURLとルータの中に保存されているmapのマッチングに従って、このhandlerのServHTTPインターフェースをコールすることで目的の関数を実行することができます。
|
||||||
@@ -155,4 +179,3 @@ httpパッケージへの分析を通して、全体のコードの実行プロ
|
|||||||
* [目次](<preface.md>)
|
* [目次](<preface.md>)
|
||||||
* 前へ: [Goはどのようにしてweb作業を行うか](<03.3.md>)
|
* 前へ: [Goはどのようにしてweb作業を行うか](<03.3.md>)
|
||||||
* 次へ: [概要](<03.5.md>)
|
* 次へ: [概要](<03.5.md>)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user