package main import ( "encoding/json" "fmt" "io" "net/http" "os" "path" "path/filepath" "strconv" "strings" "ponyo.epfl.ch/gitlab/alexandre.tuleu/narco" bleve_http "github.com/blevesearch/bleve/http" "github.com/codemodus/chain" "github.com/julienschmidt/httprouter" "golang.org/x/net/context" ) func (a *appData) buildRouter() http.Handler { router := httprouter.New() logger := narco.NewLogger() f, err := os.Create(filepath.Join("tmp", "log", "access.log")) if err != nil { panic(err.Error()) } logger.SetOutput(f) recoverer := narco.NewRecoverer() ctx := narco.WithErrorFormatter(context.Background(), narco.BasicHTMLErrorFormatter) ch := chain.New(logger.Wrap(), recoverer.Wrap()).SetContext(ctx) bleve_http.RegisterIndexName("album", a.index) searchHandler := bleve_http.NewSearchHandler("album") router.POST("/api/search", narco.EndChain(ch, narco.HandlerFunc(func(_ context.Context, w http.ResponseWriter, req *http.Request, _ httprouter.Params) { searchHandler.ServeHTTP(w, req) }))) router.GET("/api/recents", narco.EndChain(ch, narco.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request, _ httprouter.Params) { albums, err := a.db.ByPurchaseDate() if err != nil { narco.Error(ctx, w, err, http.StatusInternalServerError) return } enc := json.NewEncoder(w) err = enc.Encode(albums) if err != nil { narco.Error(ctx, w, err, http.StatusInternalServerError) return } }))) router.GET("/api/albums/:id", narco.EndChain(ch, narco.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request, ps httprouter.Params) { var id uint64 var err error idStr := ps.ByName("id") if len(idStr) > 0 { id, err = strconv.ParseUint(idStr, 10, 64) } if len(idStr) == 0 || err != nil { narco.Error(ctx, w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } albumUnsafe, err := a.db.Get(AlbumID(id)) if err != nil { narco.Error(ctx, w, err, http.StatusInternalServerError) return } album := *albumUnsafe album.CoverURL = fmt.Sprintf("/covers/%d%s", album.ID, AlbumCoverExt(album.CoverURL)) enc := json.NewEncoder(w) if err := enc.Encode(album); err != nil { narco.Error(ctx, w, err, http.StatusInternalServerError) return } }))) router.GET("/covers/:name", narco.EndChain(ch, narco.HandlerFunc( func(ctx context.Context, w http.ResponseWriter, req *http.Request, ps httprouter.Params) { var ID uint64 var err error = fmt.Errorf("Not Found") var requestedExt string name := ps.ByName("name") if len(name) > 0 { requestedExt = path.Ext(name) ID, err = strconv.ParseUint(strings.TrimSuffix(name, requestedExt), 10, 64) } if err != nil { narco.Error(ctx, w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } rc, ext, err := a.cover.GetCover(AlbumID(ID)) if rc != nil { defer closeOrPanic(rc, "Album cover "+name) } if err != nil { if _, ok := err.(ErrorNotRegistered); ok == true { narco.Error(ctx, w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } narco.Error(ctx, w, err, http.StatusInternalServerError) return } if ext != requestedExt { narco.Error(ctx, w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } _, err = io.Copy(w, rc) if err != nil { panic(fmt.Sprintf("internal error: %s", err)) } }))) dirs := []string{"css", "js", "img", "bower_components", "html"} for _, d := range dirs { router.ServeFiles(path.Join("/", d, "/*filepath"), http.Dir(filepath.Join("webapp", d))) } router.GET("/", narco.EndChain(ch, narco.HandlerFunc( func(ctx context.Context, w http.ResponseWriter, req *http.Request, _ httprouter.Params) { f, err := os.Open(filepath.Join("webapp", "index.html")) if err != nil { narco.Error(ctx, w, err, http.StatusInternalServerError) return } defer closeOrPanic(f, filepath.Join("webapp", "index.html")) _, err = io.Copy(w, f) if err != nil { panic(fmt.Sprintf("internal error: %s", err)) } }))) return router }