2011年5月29日日曜日

Trying Google App Engine SDK for Go (2)

パニクったらどうなるの

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には(一応)デフォルトのエラーハンドラがいる
  • クライアントに適切なエラーコードを返してるかは定かでない
  • どっちにしろ見た目がしょぼいから自分でエラーハンドルしたほうがいい

0 件のコメント:

コメントを投稿