【Go入門】net/httpパッケージを使ったWEBサーバの構築とHTTPリクエストハンドラの実装

シェアする

こんにちは。Go入門ブログの第23回です。

今回から他記事と並行して、Goによる実践的なWEB開発の方法を解説していきたいと思います。
まずは導入として、net/httpパッケージを利用したWEBサーバの構築方法と、HTTPリクエストの基本的な処理について解説します。

net/httpパッケージは、HTTPサーバおよびクライアントの機能を提供し、GoにおけるWEB開発の基盤となる重要な標準パッケージです。

WEBサーバの起動 – http.ListenAndServe

WEBサーバの起動方法は非常にシンプルで、net/httpパッケージに含まれるListenAndServe関数を実行するだけです。

http.ListenAndServe(TCPネットワークアドレス string, handler Handler)

このように、第1引数にリッスンするTCPネットワークアドレスを文字列形式で指定します。
第2引数にはhttp.Handlerというインターフェース型を指定しますが、これについては後述します。

とりあえず第2引数をnilとし、リッスンポート8080でサーバを起動してみましょう。

package main

import (
	"fmt"
	"net/http"
)

func main() {
	// localhost:8080でサーバー処理開始
	http.ListenAndServe(":8080", nil)
}

このコードを実行し、ブラウザでhttp://localhost:8080/にアクセスしてみてください。


まだコンテンツが存在しませんが、きちんと404のHTTPステータスコードが返されることが確認できます。

HTTPリクエストハンドラ

次に、リクエストに対して任意のコンテンツを返す為のハンドラを扱う方法を見ていきましょう。

http.HandleFunc

まず、net/httpパッケージに含まれるHandleFunc関数を使用したハンドラ定義方法を解説します。

http.HandleFuncを使用すると、func(ResponseWriter, *Request)型の関数をハンドラとして定義することができます。
以下のように、第1引数にパスを、第2引数にハンドラとして登録する関数を指定します。

http.HandleFunc(パス string, ハンドラ func(ResponseWriter, *Request))

それではサンプルをみてみましょう。

package main

import (
	"io"

	"net/http"
)

func hogeHandler(w http.ResponseWriter, req *http.Request) {
	// HTMLテキストをhttp.ResponseWriterへ書き込む
	io.WriteString(w, `
    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="UTF-8">
      <title>Go | net/httpパッケージ</title>
    </head>
    <body>
      <h1>Hello, World!</h1>
      <p>net/httpパッケージを利用すると、簡単にWEBサーバ機能を組み込むことができます。</p>
      <p>http.HandleFunc関数により、指定したパスへのリクエストに対するhandler関数を登録できます。</p>
    </body>
    </html>
`)
}

func main() {
	// "/hoge"へのリクエストを関数で処理する
	http.HandleFunc("/hoge", hogeHandler)
	// localhost:8080でサーバー処理開始
	http.ListenAndServe(":8080", nil)
}

この例では、/hogeに対するHTTPアクセスが発生した場合のハンドラとして、関数hogeHandlerを定義しています。
このコードを実行し、ブラウザでhttp://localhost:8080/hogeにアクセスしてみてください。


HTTPリクエストに対し、関数hogeHandlerに記述したHTMLが返されていることが確認できますね。
なお、ioパッケージについては別記事で改めて解説したいと思います。

http.Handle

続いて、同じくnet/httpパッケージに含まれるHandle関数を使用したハンドラ定義方法を解説します。

http.Handleは、関数ServeHTTP(ResponseWriter, *Request)を実装する構造体をハンドラとして定義することができます。
以下のように、第1引数にパスを、第2引数にハンドラとして登録する構造体を指定します。

http.Handle(パス string, ハンドラ strunct)

それではサンプルをみてみましょう。
HandlerFuncを使用した場合と比較できるよう、パスとHTMLの内容以外は同一の記述にしています。

それではサンプルをみてみましょう。

package main

import (
	"fmt"
	"net/http"
)

type fugaHandler string

// String に ServeHTTP 関数を追加
func (s fugaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// HTMLテキストをhttp.ResponseWriterへ書き込み
	fmt.Fprint(w, s)
}

func main() {

	// DuckTyping的に、ServeHTTP関数があれば良い.
	http.Handle("/fuga", fugaHandler(`
    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="UTF-8">
      <title>Go | net/httpパッケージ</title>
    </head>
    <body>
      <h1>Hello, World!</h1>
      <p>net/httpパッケージを利用すると、簡単にWEBサーバ機能を組み込むことができます。</p>
      <p>http.Handle関数により、指定したパスへのリクエストに対するhandler構造体を登録できます。</p>
    </body>
    </html>
  `))

	// 8080ポートで起動
	http.ListenAndServe(":8080", nil)
}

この例では、/fugaに対するHTTPアクセスが発生した場合のハンドラとして、関数ServeHTTPを実装する構造体fugaHandlerを定義しています。
このコードを実行し、ブラウザでhttp://localhost:8080/fugaにアクセスしてみてください。

HTTPリクエストに対し、構造体fugaHandlerに渡したHTMLが返されていることが確認できます。

ただしこのような用途の場合は、構造体をつくらずに関数を直接ハンドラとして定義できる分、http.HandlerFuncの方が使いやすいかもしれません。

静的HTMLファイルを使用する – http.FileServer

HTTPリクエストハンドラの実装方法として、http.HandleFuncを使用する方法と、http.Handleを使用する方法を解説しました。

いずれの方法でも、リクエストに対しレスポンスとなるHTMLをハンドラの中で記述していましたが、外部のHTMLファイルを使用することもできます。
この場合、ハンドラの実装にはhttp.Handleを使用し、パラメータとして渡すハンドラにhttp.FileServer関数を使用します。

http.FileServerは、HTTPリクエストに対し、rootを起点とするファイルシステムの内容を返すハンドラを返します。

実際にコードを記述してみましょう。

まず、Goプログラムと同じディレクトリにhtmlディレクトリを作成し、以下のようなindex.htmlファイルを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Go | net/httpパッケージ</title>
</head>
<body>
  <h1>Hello, World!</h1>
  <p>net/httpパッケージを利用すると、簡単にWEBサーバ機能を組み込むことができます。</p>
  <p>こちらはあらかじめ作成したHTMLファイルを表示する例です。</p>
</body>
</html>

次に、このファイルをレスポンスとして使用するコードを記述します

package main

import (
	"net/http"
)

func main() {
	// ルートへのリクエストを"html"ディレクトリ内のHTMLファイルで処理する
	http.Handle("/", http.FileServer(http.Dir("html")))

	// localhost:8080でサーバー処理開始
	http.ListenAndServe(":8080", nil)
}

このコードを実行し、ブラウザでhttp://localhost:8080/にアクセスしてみてください。

HTTPリクエストに対し、htmlディレクトリ内のindex.htmlの内容が返されていることが確認できます。

終わりに

いかがでしたでしょうか。
Goではnet/httpを使用することで、HTTPサーバ機能を簡単に組み込めることがお解りいただけたかと思います。
次回以降も継続して、WEB開発のノウハウを解説していきますので是非お付き合いください。。

スポンサーリンク
スポンサーリンク
スポンサーリンク

シェアする

フォローする

スポンサーリンク
スポンサーリンク