diff --git a/lib/go/camli/blobserver/registry.go b/lib/go/camli/blobserver/registry.go index fce2b6dc2..5b6b9a42b 100644 --- a/lib/go/camli/blobserver/registry.go +++ b/lib/go/camli/blobserver/registry.go @@ -27,6 +27,8 @@ import ( type Loader interface { GetStorage(prefix string) (Storage, os.Error) + GetHandler(prefix string) (http.Handler, os.Error) + GetHandlerType(prefix string) string // or "" } type StorageConstructor func(Loader, jsonconfig.Obj) (Storage, os.Error) diff --git a/server/go/camlistored/camlistored.go b/server/go/camlistored/camlistored.go index b0cd842b0..1ab0994e3 100644 --- a/server/go/camlistored/camlistored.go +++ b/server/go/camlistored/camlistored.go @@ -270,6 +270,19 @@ func (hl *handlerLoader) GetStorage(prefix string) (blobserver.Storage, os.Error return nil, fmt.Errorf("bogus storage handler referenced as %q", prefix) } +func (hl *handlerLoader) GetHandler(prefix string) (http.Handler, os.Error) { + hl.setupHandler(prefix) + if h, ok := hl.handler[prefix].(http.Handler); ok { + return h, nil + } + return nil, fmt.Errorf("bogus http handler referenced as %q", prefix) +} + +func (hl *handlerLoader) GetHandlerType(prefix string) string { + hl.setupHandler(prefix) + return hl.configType(prefix) +} + func (hl *handlerLoader) setupHandler(prefix string) { h, ok := hl.config[prefix] if !ok { @@ -290,28 +303,21 @@ func (hl *handlerLoader) setupHandler(prefix string) { panic(fmt.Sprintf("setupHandler for %q didn't install a handler", prefix)) } }() - installHandler := func(creator func(*handlerLoader, jsonconfig.Obj) (h http.Handler, err os.Error)) { - hh, err := creator(hl, h.conf) - if err != nil { - exitFailure("error instantiating handler for prefix %s: %v", - prefix, err) - } - hl.handler[prefix] = hh - hl.ws.Handle(prefix, &httputil.PrefixHandler{prefix, hh}) - } checkConfig := func() { if err := h.conf.Validate(); err != nil { exitFailure("configuration error in \"handlerArgs\" for prefix %s: %v", prefix, err) } } switch h.htype { - case "root": - installHandler((*handlerLoader).createRootHandler) - case "ui": - installHandler((*handlerLoader).createUIHandler) - case "jsonsign": - installHandler((*handlerLoader).createJSONSignHandler) - case "search": + case "ui", "root", "jsonsign": + hh, err := blobserver.CreateHandler(h.htype, hl, h.conf) + if err != nil { + exitFailure("error instantiating handler for prefix %q, type %q: %v", + h.prefix, h.htype, err) + } + hl.handler[prefix] = hh + hl.ws.Handle(prefix, &httputil.PrefixHandler{prefix, hh}) + case "search": // TODO: use blobserver registry indexPrefix := h.conf.RequiredString("index") // TODO: add optional help tips here? ownerBlobStr := h.conf.RequiredString("owner") checkConfig() @@ -327,7 +333,7 @@ func (hl *handlerLoader) setupHandler(prefix string) { searchh := auth.RequireAuth(search.CreateHandler(indexer, ownerBlobRef)) hl.handler[h.prefix] = searchh hl.ws.HandleFunc(prefix+"camli/", searchh) - case "sync": + case "sync": // TODO: use blobserver registry from := h.conf.RequiredString("from") to := h.conf.RequiredString("to") checkConfig() diff --git a/server/go/camlistored/root.go b/server/go/camlistored/root.go index 0dd0fa801..48c865944 100644 --- a/server/go/camlistored/root.go +++ b/server/go/camlistored/root.go @@ -21,6 +21,7 @@ import ( "http" "os" + "camli/blobserver" "camli/jsonconfig" ) @@ -34,7 +35,11 @@ type RootHandler struct { OfferSetup bool } -func (hl *handlerLoader) createRootHandler(conf jsonconfig.Obj) (h http.Handler, err os.Error) { +func init() { + blobserver.RegisterHandlerConstructor("root", newRootFromConfig) +} + +func newRootFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { root := &RootHandler{} root.Stealth = conf.OptionalBool("stealth", false) if err = conf.Validate(); err != nil { diff --git a/server/go/camlistored/sig.go b/server/go/camlistored/sig.go index 994986d6b..50ce5c106 100644 --- a/server/go/camlistored/sig.go +++ b/server/go/camlistored/sig.go @@ -29,6 +29,7 @@ import ( "strings" "camli/blobref" + "camli/blobserver" "camli/blobserver/handlers" "camli/httputil" "camli/jsonconfig" @@ -63,7 +64,11 @@ func (h *JSONSignHandler) secretRingPath() string { return filepath.Join(os.Getenv("HOME"), ".gnupg", "secring.gog") } -func (hl *handlerLoader) createJSONSignHandler(conf jsonconfig.Obj) (http.Handler, os.Error) { +func init() { + blobserver.RegisterHandlerConstructor("jsonsign", newJsonSignFromConfig) +} + +func newJsonSignFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, os.Error) { h := &JSONSignHandler{ keyId: strings.ToUpper(conf.RequiredString("keyId")), secretRing: conf.OptionalString("secretRing", ""), diff --git a/server/go/camlistored/ui.go b/server/go/camlistored/ui.go index 159c71a9a..7125e2038 100644 --- a/server/go/camlistored/ui.go +++ b/server/go/camlistored/ui.go @@ -53,7 +53,11 @@ func defaultFilesDir() string { return filepath.Join(dir, "ui") } -func (hl *handlerLoader) createUIHandler(conf jsonconfig.Obj) (h http.Handler, err os.Error) { +func init() { + blobserver.RegisterHandlerConstructor("ui", newUiFromConfig) +} + +func newUiFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { ui := &UIHandler{} ui.BlobRoot = conf.OptionalString("blobRoot", "") ui.SearchRoot = conf.OptionalString("searchRoot", "") @@ -68,7 +72,7 @@ func (hl *handlerLoader) createUIHandler(conf jsonconfig.Obj) (h http.Handler, e if v == "" { return } - ct := hl.configType(v) + ct := ld.GetHandlerType(v) if ct == "" { err = fmt.Errorf("UI handler's %q references non-existant %q", key, v) } else if ct != htype { @@ -83,14 +87,9 @@ func (hl *handlerLoader) createUIHandler(conf jsonconfig.Obj) (h http.Handler, e } if ui.BlobRoot != "" { - bh := hl.getOrSetup(ui.BlobRoot) - if bh == nil { - return nil, fmt.Errorf("UI handler's blobRoot references non-existant %q", ui.BlobRoot) - } - _, ok := bh.(blobserver.Storage) - if !ok { - return nil, fmt.Errorf("UI handler's blobRoot references %q of type %T; expected a storage target", - ui.BlobRoot, bh) + _, err := ld.GetStorage(ui.BlobRoot) + if err != nil { + return nil, fmt.Errorf("UI handler's blobRoot of %q error: %v", ui.BlobRoot, err) } }