clean up app engine init a bit; show error messages in browser.

Change-Id: Id99a2015b65a0d8aa6618451adfac38f21969222
This commit is contained in:
Brad Fitzpatrick 2011-10-17 07:53:30 -07:00
parent 5a0de07a47
commit b7c75e2011
1 changed files with 31 additions and 20 deletions

View File

@ -21,55 +21,66 @@ import (
"http" "http"
"sync" "sync"
"appengine"
"camli/blobserver" "camli/blobserver"
"camli/serverconfig" "camli/serverconfig"
) )
var mux = http.NewServeMux()
// lazyInit is our root handler for App Engine. We don't have an App Engine // lazyInit is our root handler for App Engine. We don't have an App Engine
// context until the first request and we need that context to figure out // context until the first request and we need that context to figure out
// our serving URL. So we use this to defer setting up our environment until // our serving URL. So we use this to defer setting up our environment until
// the first request. // the first request.
type lazyInit struct { type lazyInit struct {
mux http.Handler mu sync.Mutex
once sync.Once ready bool
mux *http.ServeMux
} }
func (li *lazyInit) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (li *lazyInit) ServeHTTP(w http.ResponseWriter, r *http.Request) {
li.once.Do(func() { li.mu.Lock()
realInit(r) if !li.ready {
}) li.ready = realInit(w, r)
}
li.mux.ServeHTTP(w, r) li.mu.Unlock()
if li.ready {
li.mux.ServeHTTP(w, r)
}
} }
var root = &lazyInit{mux: mux} var root = new(lazyInit)
func init() { func init() {
blobserver.RegisterStorageConstructor("appengine", blobserver.StorageConstructor(newFromConfig))
http.Handle("/", root) http.Handle("/", root)
} }
func exitFailure(pattern string, args ...interface{}) { func realInit(w http.ResponseWriter, r *http.Request) bool {
panic(fmt.Sprintf(pattern, args...)) ctx := appengine.NewContext(r)
}
func realInit(r *http.Request) { errf := func(format string, args ...interface{}) bool {
blobserver.RegisterStorageConstructor("appengine", blobserver.StorageConstructor(newFromConfig)) ctx.Errorf("In init: "+format, args...)
http.Error(w, fmt.Sprintf(format, args...), 500)
return false
}
config, err := serverconfig.Load("./config.json") config, err := serverconfig.Load("./config.json")
if err != nil { if err != nil {
exitFailure("Could not load server config: %v", err) return errf("Could not load server config: %v", err)
} }
// Update the config to use the URL path derived from the first App Engine request. // Update the config to use the URL path derived from the first App Engine request.
// TODO(bslatkin): Support hostnames that aren't x.appspot.com // TODO(bslatkin): Support hostnames that aren't x.appspot.com
// TODO(bslatkin): Support the HTTPS scheme // TODO(bslatkin): Support the HTTPS scheme
config.Obj["baseURL"] = fmt.Sprintf("http://%s/", r.Header.Get("X-Appengine-Default-Version-Hostname")) baseURL := fmt.Sprintf("http://%s/", r.Header.Get("X-Appengine-Default-Version-Hostname"))
ctx.Infof("baseurl = %q", baseURL)
config.Obj["baseURL"] = baseURL
baseURL := "" root.mux = http.NewServeMux()
err = config.InstallHandlers(mux, baseURL) err = config.InstallHandlers(root.mux, baseURL)
if err != nil { if err != nil {
exitFailure("Error parsing config: %v", err) return errf("Error installing handlers: %v", err)
} }
return true
} }