Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goで作る初めてのHTTPサーバー

 Goで作る初めてのHTTPサーバー

ツールを作ったことがあるレベルの初心者がHTTPサーバーを開発している時に思った疑問と調べた結果をまとめています。

from-unknown

April 17, 2018
Tweet

More Decks by from-unknown

Other Decks in Technology

Transcript

  1. Apacheやnginxを使う場合 • リバースプロキシでGolangに流す ◦ GolangはHTTPサーバーとして実行する ▪ サーバーに直アクセス可能 ◦ 必要なヘッダーはApacheから追加する様に設定する ◦

    間にキャッシュサーバーなどを挟むことも可能 • FastCGIでGolangを呼び出す ◦ GolangはFastCGIで実装し、実行する ▪ サーバーに直アクセス不可 ◦ FastCGI側がアクセスに応じて自動でGolangのプロセスを立ち 上げられる
  2. サーバーのソースはどんな感じで書くの? package main import ( "fmt" "log" "net/http" ) func

    handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ※公式のWikiを作るサンプルからコピー https://golang.org/doc/articles/wiki/
  3. サーバーのソースはどんな感じで書くの? package main import ( "fmt" "log" "net/http" ) func

    handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } URLのパスが”/”の時にfunc handlerを実行する
  4. サーバーのソースはどんな感じで書くの? package main import ( "fmt" "log" "net/http" ) func

    handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ResponseWriterに、文言+URLのパス の値(”/”以下全て)を付けて書き込む これがサーバーからの応答のBody部と なる
  5. サーバーのソースはどんな感じで書くの? package main import ( "fmt" "log" "net/http" ) func

    handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ポート8080でアクセスを受 け付ける 異常時はログを出力して終 了する
  6. APIを書く時はもちろんこれだけでは足りない http.HandleFunc("/api/createuser", func(w http.ResponseWriter, r *http.Request) { if r.Method ==

    "OPTIONS" { headers := w.Header() headers.Add("Access-Control-Allow-Origin", "*") headers.Add("Vary", "Origin") … headers.Add("Access-Control-Allow-Methods", "GET, POST,OPTIONS") w.WriteHeader(http.StatusOK) } else { createUserHandler(w, r) } return })
  7. APIを書く時はもちろんこれだけでは足りない http.HandleFunc("/api/createuser", func(w http.ResponseWriter, r *http.Request) { if r.Method ==

    "OPTIONS" { headers := w.Header() headers.Add("Access-Control-Allow-Origin", "*") headers.Add("Vary", "Origin") … headers.Add("Access-Control-Allow-Methods", "GET, POST,OPTIONS") w.WriteHeader(http.StatusOK) } else { createUserHandler(w, r) } return }) CORSのpreflightで 来る”OPTIONS”も ちゃんと捌きましょう
  8. テンプレートファイルの出力の仕方 例: func renderTemplate(w http.ResponseWriter, p *Page) { t, _

    := template.ParseFiles("template.html") t.Execute(w, p) } テンプレートファイルをパースしてExecuteします。 テンプレ内でloopしたり関数を埋め込んだりも可能です。
  9. Cookieのセットの仕方 ※wはhttp.ResponseWriterです sampleCookie := &http.Cookie{ Name: “sample”, Value: “sample”, }

    http.SetCookie(w, sampleCookie) Cookieには上記以外にもMaxAgeなどの設定が追加可能です。
  10. 本番環境と開発環境の切り替えはどうやるの? • 環境変数で切り替える ◦ Init関数(main関数より先に呼ばれる関数)内で環境変数 を取得し、本番か開発かで値を切り替える • build variantsで切り替える ◦

    ソースの一番上部にbuild variantsを記載しておく ◦ tagを指定することで開発時のみや本番時のみだけビルド に含まれるファイルが作成出来る