はじめに
Goで書いたbotをGAEで運用しようとした際、通信部分(外部APIへのリクエスト)で地味にハマったため簡単にまとめていこうと思います。
実行環境
ローカル:Go v1.10.1
GAE:Go v1.10
Google App Engine(GAE)とは
Google App Engine は、Google のインフラの上でアプリケーションを作り、実行できるようにする PaaS ( Platform as a Service : サービスとしてのプラットフォーム)です。App Engine アプリケーションは、作るのもメンテナンスするのも簡単で、トラフィックやデータストレージのニーズの増減にあわせてスケーリングするのも簡単です。App Engine を使えば、自分でメンテナンスしなければならないサーバーはなくなります。単純にアプリケーションをアップロードすれば、それだけで実行できます。
Googleが提供しているクラウドサーバーです。
外部APIを扱う
通常Getリクエストを行う場合はhttp.get(url)
を行えばよいが、GAEで行う場合はContext
を使うことを配慮しなければなりません。
ローカルで実行する場合
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
response, err := http.Get(url)
if err != nil {
log.Println(err)
}
if response != nil {
defer response.Body.Close()
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
}
fmt.Println(body)
}
GAEの場合
func main() {
http.HandleFunc("/", handler)
appengine.Main()
}
func handler(w http.ResponseWriter, r *http.Request) {
context := appengine.NewContext(r)
httpClient := urlfetch.Client(context)
response, err := httpClient.Get(url)
if err != nil {
log.Println(err)
}
if response != nil {
defer response.Body.Close()
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
}
fmt.Println(body)
}
ハマったポイント
ローカルで実行する場合はhttp.Get(url)
でよかったが、GAEで行う場合はappengine.NewContext(*http.Request)
でcontextを作成し、urlfetch.Client(context)
のようにurlfetch
を利用してリクエストを行わなければならなかった。
まとめ
GAEの場合は通常と異なり、GAEのContextを作成し、urlfetchを用いてリクエストを行うことが必要になります。
func handler(w http.ResponseWriter, r *http.Request) {
context := appengine.NewContext(r)
httpClient := urlfetch.Client(context)
response, err := httpClient.Get(url)
if err != nil {
log.Println(err)
}
if response != nil {
defer response.Body.Close()
}
}