retlat's blog

GAE/Go 1.12 の静的ファイル配信

ネット上でGoogle App EngineのGo 1.9やPython 2.7 Runtimeの記事を見かけたが, Go 1.12ではどうにも思った通りにhandlerが設定できないのでいろいろ実験した記録

達成したいのは http://sample.appspot.com/ へのアクセスに対し, app.yamlからの相対パスで public/index.html を返すこと
ドキュメントのサンプルに従えば以下のようにしておけばできるはず

handlers:
- url: /$
  static_files: public/index\.html
  upload: public/.*

- url: /(.*)
  script: auto

ここではscript: autoのプログラムは Response From Go と返し, index.htmlは Static File と記載しているものとする
デプロイしてアクセスしてみると Response From Go と表示される
おかしい…

デプロイしたものがおかしいのかGCPのウェブコンソールでApp Engineのバージョンページに行き, 設定を表示してみる

handlers:
- url: /$
  static_files: public/index\.html
  require_matching_file: false
  upload: public/.*
- url: /(.*)
  script: auto
- url: .*
  script: auto

デプロイしたものに require_matching_file: false が書き足されている
urlの正規表現がマッチしたら評価するが, 該当するファイルがなければ他のhandlerに処理を流すという要素なのだろうか…?
ドキュメントにもない要素でよくわからないので環境の方の調査をしてみる
Stackdriver Loggingでログを見てみると, /var/log/google_init.log に Waiting for network connection open. Subject:"nginx" Address:127.0.0.1:8080" と記述がある
app.yamlはNginxの設定ファイルに変換されていそうなので実験してみる

今回は static_files を指定していて url は正規表現パターンマッチになるため, NginxではLocationディレクティブの正規表現パターンマッチと考えられる
static_files はアップロードしたファイルパスの関連付けを行うためrootかaliasどちらかのディレクティブになるが, 正規表現でキャプチャした値を使用できるためaliasが該当する
そして実際の挙動と require_matching_file という名称から try_files でファイル指定と内部リダイレクトをしていると推測される

以上を元に以下のように変換した設定をDocker ComposeでNginxとGolangコンテナを使って実験してみる

http {
    location ~ /$ {
        alias public/index\.html;
        try_files $uri @fallback;
    }
    location ~ /(.*)$ {
        proxy_pass http://golang:8080;
    }
    location @fallback {
        proxy_pass http://golang:8080;
    }
}

App Engineと同じ出力になるため変換をしているという点は的外れではなさそう

意図しない挙動をした部分について踏み込んでみる
try_files には他に適当な変数が見当たらないためとりあえず$uriを設定したが, 実際の値がわからないためログに出してみると / になっている
変数を展開すると以下のようになることから, 該当するファイルが見つけられず @fallback に内部リダイレクトされているものと思われる

try_files / @fallback;

$uriも含めて変換が上記の実験通りであれば意図した通りの動作に設定できない気がするので, 結局 http.FileServer() で解決することにした
Nginxのaliasとtry_filesの部分を設定できるようになれば, App Engineのインスタンスを起動しなくてよくなるのに