Implement server handler, add startup logic

This commit is contained in:
Maksym Pavlenko
2017-08-13 17:39:30 -07:00
parent dba98c2a3f
commit 563f7deb17
3 changed files with 168 additions and 1 deletions
+46 -1
View File
@@ -8,6 +8,14 @@ import (
"os"
"os/signal"
"syscall"
"github.com/mxpv/podsync/web/pkg/api"
"github.com/mxpv/podsync/web/pkg/builders"
"github.com/mxpv/podsync/web/pkg/config"
"github.com/mxpv/podsync/web/pkg/feeds"
"github.com/mxpv/podsync/web/pkg/id"
"github.com/mxpv/podsync/web/pkg/server"
"github.com/mxpv/podsync/web/pkg/storage"
)
func main() {
@@ -17,8 +25,45 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Create core sevices
cfg, err := config.ReadConfiguration()
if err != nil {
panic(err)
}
hashIds, err := id.NewIdGenerator()
if err != nil {
panic(err)
}
redis, err := storage.NewRedisStorage(cfg.RedisURL)
if err != nil {
panic(err)
}
// Builders
youtube, err := builders.NewYouTubeBuilder(cfg.YouTubeApiKey)
if err != nil {
panic(err)
}
vimeo, err := builders.NewVimeoBuilder(ctx, cfg.VimeoApiKey)
if err != nil {
panic(err)
}
feed := feeds.NewFeedService(
feeds.WithIdGen(hashIds),
feeds.WithStorage(redis),
feeds.WithBuilder(api.Youtube, youtube),
feeds.WithBuilder(api.Vimeo, vimeo),
)
srv := http.Server{
Addr: fmt.Sprintf(":%d", 8080),
Addr: fmt.Sprintf(":%d", 8080),
Handler: server.MakeHandlers(feed),
}
go func() {
+31
View File
@@ -73,3 +73,34 @@ func (s *service) GetMetadata(hashId string) (*api.Feed, error) {
return feed, nil
}
type feedOption func(*service)
func WithStorage(storage storage) feedOption {
return func(service *service) {
service.storage = storage
}
}
func WithIdGen(id id) feedOption {
return func(service *service) {
service.id = id
}
}
func WithBuilder(provider api.Provider, builder builder) feedOption {
return func(service *service) {
service.builders[provider] = builder
}
}
func NewFeedService(opts ...feedOption) *service {
svc := &service{}
svc.builders = make(map[api.Provider]builder)
for _, fn := range opts {
fn(svc)
}
return svc
}
+91
View File
@@ -0,0 +1,91 @@
package server
import (
"context"
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
itunes "github.com/mxpv/podcast"
"github.com/mxpv/podsync/web/pkg/api"
"github.com/pkg/errors"
)
type feed interface {
CreateFeed(ctx context.Context, req *api.CreateFeedRequest) (string, error)
GetFeed(hashId string) (*itunes.Podcast, error)
GetMetadata(hashId string) (*api.Feed, error)
}
func MakeHandlers(feed feed) http.Handler {
r := gin.New()
r.Use(gin.Recovery())
r.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "ok")
})
r.POST("/create", func(c *gin.Context) {
req := &api.CreateFeedRequest{}
if err := c.BindJSON(req); err != nil {
c.JSON(badRequest(err))
return
}
if err := binding.Validator.ValidateStruct(req); err != nil {
c.JSON(badRequest(err))
return
}
hashId, err := feed.CreateFeed(c.Request.Context(), req)
if err != nil {
c.JSON(internalError(err))
return
}
c.JSON(http.StatusOK, gin.H{"id": hashId})
})
r.GET("/:hashId", func(c *gin.Context) {
hashId := c.Param("hashId")
if hashId == "" || len(hashId) > 12 {
c.JSON(badRequest(errors.New("invalid feed id")))
return
}
podcast, err := feed.GetFeed(hashId)
if err != nil {
c.JSON(internalError(err))
return
}
c.Data(http.StatusOK, "application/rss+xml", podcast.Bytes())
})
r.GET("/metadata/:hashId", func(c *gin.Context) {
hashId := c.Param("hashId")
if hashId == "" || len(hashId) > 12 {
c.JSON(badRequest(errors.New("invalid feed id")))
return
}
feed, err := feed.GetMetadata(hashId)
if err != nil {
c.JSON(internalError(err))
return
}
c.JSON(http.StatusOK, feed)
})
return r
}
func badRequest(err error) (int, interface{}) {
return http.StatusBadRequest, gin.H{"error": err.Error()}
}
func internalError(err error) (int, interface{}) {
return http.StatusInternalServerError, gin.H{"error": err.Error()}
}