ふとした拍子に忘れてしまうappengineでの静的ファイルをサーブする設定についてのメモです。
内容はほぼ Serving Static Content | App Engine standard environment for Go | Google Cloud に載ってる内容です。
例えば以下のようなディレクトリ構成を考えてstaticディレクトリとassetsの2つのディレクトリに静的ファイル( jsとかcssとかimgといったファイル )を保持してwebサイト上で使いたいケースを考えます。
GOPATH ├── assets │ └── index.html ├── src │ └── app │ ├── app.yaml │ └── main.go └── static └── index.html
まずは適当にサーバーを用意します。
package main import ( "fmt" "log" "net/http" "os" ) // App Handle Object type App struct{} // Index App Root Handler func (a *App) Index(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("hello world")) } func main() { app := &App{} mux := http.NewServeMux() mux.HandleFunc("/", app.Index) port := os.Getenv("PORT") if port == "" { port = "8080" log.Printf("Defaulting to port %s", port) } log.Printf("Listening on port %s", port) if err := http.ListenAndServe(fmt.Sprintf(":%s", port), mux); err != nil { panic(err) } }
次にapp.yamlにサーブしたいファイルのディレクトリを指定します。せっかくなのでgo111でやってみます。
go111ではアプリケーションを作成するときのディレクトリ構成が 1.9以下のそれとは異なっているので例えば1.9の環境で以下のようなディレクトリ構成を考えると
GOPATH ├── assets │ └── index.html ├── app.yaml └── static └── index.html
このケースではにはyamlに定義する handlers の urlディレクティブのstatic_dir(実際サーブしているファイルのpathを指定するproperty)はapp.yamlと同階層にあるので以下のように記載しました。
runtime: go1.9 handlers: - url: /static static_dir: static - url: /assets static_dir: assets - url: /.* script: auto
ちなみに 1.9以下で指定するときは 最後の /.*
より上部にサーブしたいディレクトリのルーティングの設定を書かないと正確にルーティングされません でした。なぜかは謎です。
go111の環境ではディレクトリ構成が異なります。最初に示した通り、go111ではapp.yamlはmainパッケージと同階層にあることが必要です。
そのため、app.yamlと実際にサーブするディレクトリは1.9以下のように同階層にあるわけではありません。(同階層にあるとした場合)
app.yamlから静的ファイルをサーブするディレクトリを指定するケースにおいてはそのディレクトリは相対パスで指定することになりますので以下のようになります。
runtime: go111 handlers: - url: /static static_dir: ../../static secure: always - url: /assets static_dir: ../../assets secure: always - url: /.* script: auto secure: always
※ go1.9の時にあった /.*
より上に静的ファイルをサーブするディレクトリを記載しなくてもgo111のケースではちゃんと動作してくれました。
この状態で実際にgo111の環境でアプリを起動します。
$ dev_appserver.py src/app/app.yaml $ curl -i -X GET http://localhost:8080/static/index.html HTTP/1.1 200 OK Content-length: 41 Content-type: text/html ETag: "LTgyNzU4ODE4Ng==" Expires: Fri, 01 Jan 1990 00:00:00 GMT Cache-Control: public Server: Development/2.0 Date: Mon, 19 Nov 2018 17:42:50 GMT <html> <p>hello static dir</p> </html> $ curl -i -X GET http://localhost:8080/assets/index.html HTTP/1.1 200 OK Content-length: 41 Content-type: text/html ETag: "MTc0MjM0NzkzMg==" Expires: Fri, 01 Jan 1990 00:00:00 GMT Cache-Control: public Server: Development/2.0 Date: Mon, 19 Nov 2018 17:42:48 GMT <html> <p>hello assets dir</p> </html>
正常に静的ファイルがルーティングされてることが確認できました。
追加で app.yamlの各propertyの意味は app.yaml Configuration File | App Engine standard environment for Go 1.11 docs | Google Cloud にあるので目を通してみると良いと思います。
ちなみに今回使ったhandlerには以下のように記載してあります。
Optional. A list of URL patterns and descriptions of how they should be handled. App Engine can handle URLs by executing application code, or by serving static files uploaded with the code, such as images, CSS, or JavaScript.
静的ファイルをサーブする時に使うpropertyと記載ありますね。
handlers propertyの要素については app.yaml Configuration File | App Engine standard environment for Go 1.11 docs | Google Cloud にあるのでこちらも合わせて目を通してみると良いと思います。
app.yamlのhandlers要素の最後に script: auto
と書いてますが、これはドキュメントに以下のような静的ファイルをサーブするケースでの記載に則ったものです。
Optional. Specifies that requests to the specific handler should target your app. The only accepted value for the script element is auto because all traffic is served using the entrypoint command. In order to use static handlers, at least one of your handlers must contain the line script: auto to deploy successfully.
script: auto
を設定してねと記載があるのでこれはおまじないのように必須の項目のようです。localで起動する分には必要ありませんが。
[追記]
1.9以下で指定するときは 最後の
/.*
より上部にサーブしたいディレクトリのルーティングの設定を書かないと正確にルーティングされません でした。なぜかは謎です。
これ、そもそも /.*
に食われてその先(このルーティングより下部に設定したurl) は読み込まれないとFBもらいました。(そんな仕様知らんがな)