前回までのあらすじ
simplestar-tech.hatenablog.com
Amazon にクレジットカードを登録してボタンをいくつか押すと、世界に向けて golang のサーバーが TLS の秘匿通信で公開され
ログ拡張でアプリの動作の内容がわかるところまで、初心者でも Web サーバーが運用できるところまで資料がまとまりました。
今回やること
サーバー内で 16x16x16x16x16x16のint配列を用意
ベーシック認証で user 名と password が一致しているかチェック
POSTリクエストのみを受け付けて、action が 1 のときのみ value で上書き
それ以外では index で指定した value を取得する
実装は次の通り
package main import ( "encoding/json" "io/ioutil" "log" "net/http" "os" ) func readClientIP(r *http.Request) string { IPAddress := r.Header.Get("X-Real-Ip") if IPAddress == "" { IPAddress = r.Header.Get("X-Forwarded-For") } if IPAddress == "" { IPAddress = r.RemoteAddr } return IPAddress } func main() { cubedata := [16 * 16 * 16 * 16 * 16 * 16]int{} port := os.Getenv("PORT") if port == "" { port = "5000" } f, _ := os.Create("/var/app/current/golang-server.log") defer f.Close() log.SetOutput(f) const indexPage = "public/index.html" http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "Not Found.", http.StatusNotFound) return } user, pass, ok := r.BasicAuth() if ok == false || user != basicAuthUser || pass != basicAuthPassword { http.Error(w, "Not Found.", http.StatusNotFound) return } requestJson := new(RequestJson) if buf, err := ioutil.ReadAll(r.Body); err == nil { if err := json.Unmarshal(buf, requestJson); err != nil { http.Error(w, "Bad Request.", http.StatusBadRequest) return } log.Printf("Received message: %s from %s\n", string(buf), readClientIP(r)) } if 0 > requestJson.Index || len(cubedata) <= requestJson.Index { http.Error(w, "Bad Request.", http.StatusBadRequest) return } if 1 == requestJson.Action { cubedata[requestJson.Index] = requestJson.Value } responseJson := ResponseJson{http.StatusOK, cubedata[requestJson.Index]} res, err := json.Marshal(responseJson) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Write(res) }) http.HandleFunc("/scheduled", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { log.Printf("Received task %s scheduled at %s\n", r.Header.Get("X-Aws-Sqsd-Taskname"), r.Header.Get("X-Aws-Sqsd-Scheduled-At")) } }) http.HandleFunc("/hc", func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Not Found.", http.StatusNotFound) } }) log.Printf("Listening on port %s\n\n", port) http.ListenAndServe(":"+port, nil) } type RequestJson struct { Action int `json:"action"` Index int `json:"index"` Value int `json:"value"` } type ResponseJson struct { Status int `json:"status"` Result int `json:"result"` } const ( basicAuthUser = "user" basicAuthPassword = "password" )
気を付けるべきはBasic 認証の user 名とパスワードは別途違うものにします
ヘルスチェック用のパスを ALB で /hc に切り替える必要あり
まとめ
本番に上記をデプロイして https アドレスに POST して、認証が通りバイナリキャッシュサーバとして機能していました。
16,777,216 キューブ情報を扱ってメモリはわずか67.2 [MB] あればいい、やりました!