パニクったらどうなるの
moustachioのサンプルを見ると、ハンドル関数uploadを登録するときにerrorHandlerという関数(関数を返す関数)でラップした上で登録している。これはもしuploadのなかでpanicが起きたときに適切なエラーハンドルをするための措置みたい。
errorHandlerの用法
func init() {
http.HandleFunc("/", errorHandler(upload))
...
}
...
// errorHandler wraps the argument handler with an error-catcher that
// returns a 500 HTTP error if the request fails (calls check with err non-nil).
func errorHandler(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err, ok := recover().(os.Error); ok {
w.WriteHeader(http.StatusInternalServerError)
errorTemplate.Execute(w, err)
}
}()
fn(w, r)
}
}
わざわざこういうエラーハンドラが存在する必要が良くわからなかったので、このエラーハンドルを通さず意図的にpanicを起こしたらどうなるかを見てみた。
サンプル
package hello
import (
"fmt"
"http"
)
func init() {
http.HandleFunc("/", root)
}
func root(w http.ResponseWriter, r *http.Request) {
// test panic here to see what happens
panic("Testing panic")
ch := make(chan string, 1)
go func(){
ch <- "aaaaa!!"
}()
fmt.Fprint(w, "At Root! ", <- ch)
}
実行結果
どうやらデフォルトのエラーハンドラが動いて、ブラウザ上はInternal Server Errorが発生したことが伝わるみたい。ただ、クライアントに対して適切なエラーコードが送られたかどうかは定かでない。
スクリーンショット
dev_appserverのログ
$ dev_appserver.py myapp/ Warning: You are using a Python runtime (2.7) that is more recent than the production runtime environment (2.5). Your application may use features that are not available in the production environment and may not work correctly when deployed to production. INFO 2011-05-29 02:42:43,751 appengine_rpc.py:159] Server: appengine.google.com INFO 2011-05-29 02:42:43,754 appcfg.py:440] Checking for updates to the SDK. INFO 2011-05-29 02:42:44,311 appcfg.py:457] The SDK is up to date. WARNING 2011-05-29 02:42:44,311 datastore_file_stub.py:657] Could not read datastore data from /tmp/dev_appserver.datastore INFO 2011-05-29 02:42:44,313 rdbms_sqlite.py:58] Connecting to SQLite database '' with file '/tmp/dev_appserver.rdbms' INFO 2011-05-29 02:42:44,366 dev_appserver_multiprocess.py:637] Running application xclamm on port 8080: http://localhost:8080 INFO 2011-05-29 02:42:52,748 __init__.py:284] building _go_app INFO 2011-05-29 02:42:53,503 __init__.py:276] running _go_app panic: Testing panic runtime.panic+0xa4 /tmp/appengine/google_appengine/goroot/src/pkg/runtime/proc.c:1060 runtime.panic(0x811c8e4, 0x9762b550) hello.root+0x4e hello/panic.go:14 hello.root(0x976a54a0, 0x9762cf60) http.HandlerFunc·ServeHTTP+0x35 /tmp/appengine/google_appengine/goroot/src/pkg/http/server.go:533 http.HandlerFunc·ServeHTTP(0x805b7f0, 0x976a54a0, 0x9762cf60, 0x976bc000, 0x805b7f0, ...) http.*ServeMux·ServeHTTP+0x194 /tmp/appengine/google_appengine/goroot/src/pkg/http/server.go:728 http.*ServeMux·ServeHTTP(0x9762b2f0, 0x976a54a0, 0x9762cf60, 0x976bc000, 0x9762cf60, ...) http.*conn·serve+0x202 /tmp/appengine/google_appengine/goroot/src/pkg/http/server.go:499 http.*conn·serve(0x9762ce40, 0x0) runtime.goexit /tmp/appengine/google_appengine/goroot/src/pkg/runtime/proc.c:178 runtime.goexit() ----- goroutine created by ----- http.*Server·Serve+0x1cf /tmp/appengine/google_appengine/goroot/src/pkg/http/server.go:820 (後略)
まとめ
一応デフォルトのエラーハンドラは存在するみたい。でもやっぱり自分でハンドルしたほうがいいね。
- Go版のGoogle App Engineには(一応)デフォルトのエラーハンドラがいる
- クライアントに適切なエラーコードを返してるかは定かでない
- どっちにしろ見た目がしょぼいから自分でエラーハンドルしたほうがいい