func (hl *handlerLoader) setupHandler(prefix string) { h, ok := hl.config[prefix] if !ok { exitFailure("invalid reference to undefined handler %q", prefix) } if h.setupDone { // Already setup by something else reference it and forcing it to be // setup before the bottom loop got to it. return } hl.prefixStack = append(hl.prefixStack, prefix) if h.settingUp { buf := make([]byte, 1024) buf = buf[:runtime.Stack(buf, false)] exitFailure("loop in configuration graph; %q tried to load itself indirectly: %q\nStack:\n%s", prefix, hl.prefixStack, buf) } h.settingUp = true defer func() { // log.Printf("Configured handler %q", prefix) h.setupDone = true hl.prefixStack = hl.prefixStack[:len(hl.prefixStack)-1] r := recover() if r == nil { if hl.handler[prefix] == nil { panic(fmt.Sprintf("setupHandler for %q didn't install a handler", prefix)) } } else { panic(r) } }() hl.curPrefix = prefix if strings.HasPrefix(h.htype, "storage-") { stype := strings.TrimPrefix(h.htype, "storage-") // Assume a storage interface pstorage, err := blobserver.CreateStorage(stype, hl, h.conf) if err != nil { exitFailure("error instantiating storage for prefix %q, type %q: %v", h.prefix, stype, err) } if ix, ok := pstorage.(*index.Index); ok && hl.reindex { log.Printf("Reindexing %s ...", h.prefix) if err := ix.Reindex(); err != nil { exitFailure("Error reindexing %s: %v", h.prefix, err) } } hl.handler[h.prefix] = pstorage if h.internal { hl.installer.Handle(prefix, unauthorizedHandler{}) } else { hl.installer.Handle(prefix+"camli/", makeCamliHandler(prefix, hl.baseURL, pstorage, hl)) } if cl, ok := pstorage.(blobserver.ShutdownStorage); ok { hl.closers = append(hl.closers, cl) } return } var hh http.Handler if h.htype == "app" { ap, err := app.NewHandler(h.conf, hl.baseURL+"/", prefix) if err != nil { exitFailure("error setting up app for prefix %q: %v", h.prefix, err) } hh = ap auth.AddMode(ap.AuthMode()) if ap.ProgramName() == "publisher" { if err := hl.initPublisherRootNode(ap); err != nil { exitFailure("Error looking/setting up root node for publisher on %v: %v", h.prefix, err) } } } else { var err error 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 var wrappedHandler http.Handler if h.internal { wrappedHandler = unauthorizedHandler{} } else { wrappedHandler = &httputil.PrefixHandler{prefix, hh} if handlerTypeWantsAuth(h.htype) { wrappedHandler = auth.Handler{wrappedHandler} } } hl.installer.Handle(prefix, wrappedHandler) }
func (hl *handlerLoader) setupHandler(prefix string) { h, ok := hl.config[prefix] if !ok { exitFailure("invalid reference to undefined handler %q", prefix) } if h.setupDone { // Already setup by something else reference it and forcing it to be // setup before the bottom loop got to it. return } hl.prefixStack = append(hl.prefixStack, prefix) if h.settingUp { buf := make([]byte, 1024) buf = buf[:runtime.Stack(buf, false)] exitFailure("loop in configuration graph; %q tried to load itself indirectly: %q\nStack:\n%s", prefix, hl.prefixStack, buf) } h.settingUp = true defer func() { // log.Printf("Configured handler %q", prefix) h.setupDone = true hl.prefixStack = hl.prefixStack[:len(hl.prefixStack)-1] r := recover() if r == nil { if hl.handler[prefix] == nil { panic(fmt.Sprintf("setupHandler for %q didn't install a handler", prefix)) } } else { panic(r) } }() hl.curPrefix = prefix if strings.HasPrefix(h.htype, "storage-") { stype := strings.TrimPrefix(h.htype, "storage-") // Assume a storage interface pstorage, err := blobserver.CreateStorage(stype, hl, h.conf) if err != nil { exitFailure("error instantiating storage for prefix %q, type %q: %v", h.prefix, stype, err) } if ix, ok := pstorage.(*index.Index); ok && hl.reindex { log.Printf("Reindexing %s ...", h.prefix) if err := ix.Reindex(); err != nil { exitFailure("Error reindexing %s: %v", h.prefix, err) } } hl.handler[h.prefix] = pstorage if h.internal { hl.installer.Handle(prefix, unauthorizedHandler{}) } else { hl.installer.Handle(prefix+"camli/", makeCamliHandler(prefix, hl.baseURL, pstorage, hl)) } if cl, ok := pstorage.(blobserver.ShutdownStorage); ok { hl.closers = append(hl.closers, cl) } return } var hh http.Handler if h.htype == "app" { // h.conf might already contain the server's baseURL, but // camlistored.go derives (if needed) a more useful hl.baseURL, // after h.conf was generated, so we provide it as well to // FromJSONConfig so NewHandler can benefit from it. hc, err := app.FromJSONConfig(h.conf, hl.baseURL) if err != nil { exitFailure("error setting up app config for prefix %q: %v", h.prefix, err) } ap, err := app.NewHandler(hc) if err != nil { exitFailure("error setting up app for prefix %q: %v", h.prefix, err) } hh = ap auth.AddMode(ap.AuthMode()) // TODO(mpl): this check is weak, as the user could very well // use another binary name for the publisher app. We should // introduce/use another identifier. if ap.ProgramName() == "publisher" { if err := hl.initPublisherRootNode(ap); err != nil { exitFailure("Error looking/setting up root node for publisher on %v: %v", h.prefix, err) } } } else { var err error 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 var wrappedHandler http.Handler if h.internal { wrappedHandler = unauthorizedHandler{} } else { wrappedHandler = &httputil.PrefixHandler{Prefix: prefix, Handler: hh} if handlerTypeWantsAuth(h.htype) { wrappedHandler = auth.Handler{Handler: wrappedHandler} } } hl.installer.Handle(prefix, wrappedHandler) }