From 1506a57231ade980dede2f41f874a22427446051 Mon Sep 17 00:00:00 2001 From: Kasper Juul Hermansen Date: Tue, 21 Dec 2021 00:17:09 +0100 Subject: [PATCH] Add base --- .idea/.gitignore | 8 +++ .idea/downloader.iml | 9 ++++ .idea/modules.xml | 8 +++ api/cmd/api/main.go | 9 ++++ api/go.mod | 8 +++ api/go.sum | 4 ++ .../app/api/common/responses/responses.go | 29 +++++++++++ api/internal/app/api/download/download.go | 42 ++++++++++++++++ api/internal/app/router/router.go | 49 +++++++++++++++++++ api/internal/core/entities/Download.go | 8 +++ .../download_request/download_request.go | 13 +++++ 11 files changed, 187 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/downloader.iml create mode 100644 .idea/modules.xml create mode 100644 api/cmd/api/main.go create mode 100644 api/go.mod create mode 100644 api/go.sum create mode 100644 api/internal/app/api/common/responses/responses.go create mode 100644 api/internal/app/api/download/download.go create mode 100644 api/internal/app/router/router.go create mode 100644 api/internal/core/entities/Download.go create mode 100644 api/internal/core/ports/download_request/download_request.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/downloader.iml b/.idea/downloader.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/downloader.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..05c3fde --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/api/cmd/api/main.go b/api/cmd/api/main.go new file mode 100644 index 0000000..acf460c --- /dev/null +++ b/api/cmd/api/main.go @@ -0,0 +1,9 @@ +package main + +import router "downloader/internal/app/router" + +func main() { + router. + NewRouter(). + Run() +} diff --git a/api/go.mod b/api/go.mod new file mode 100644 index 0000000..fe0a60a --- /dev/null +++ b/api/go.mod @@ -0,0 +1,8 @@ +module downloader + +go 1.17 + +require ( + github.com/go-chi/chi v1.5.4 // indirect + github.com/go-chi/render v1.0.1 // indirect +) diff --git a/api/go.sum b/api/go.sum new file mode 100644 index 0000000..544024a --- /dev/null +++ b/api/go.sum @@ -0,0 +1,4 @@ +github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= +github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= +github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= +github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= diff --git a/api/internal/app/api/common/responses/responses.go b/api/internal/app/api/common/responses/responses.go new file mode 100644 index 0000000..0a082b1 --- /dev/null +++ b/api/internal/app/api/common/responses/responses.go @@ -0,0 +1,29 @@ +package responses + +import ( + "github.com/go-chi/render" + "net/http" +) + +type ErrResponse struct { + Err error `json:"-"` // low-level runtime error + HTTPStatusCode int `json:"-"` // http response status code + + StatusText string `json:"status"` // user-level status message + AppCode int64 `json:"code,omitempty"` // application-specific error code + ErrorText string `json:"error,omitempty"` // application-level error message, for debugging +} + +func (e ErrResponse) Render(w http.ResponseWriter, r *http.Request) error { + render.Status(r, e.HTTPStatusCode) + return nil +} + +func ErrInvalidRequest(err error) render.Renderer { + return &ErrResponse{ + Err: err, + HTTPStatusCode: 400, + StatusText: "Invalid request.", + ErrorText: err.Error(), + } +} diff --git a/api/internal/app/api/download/download.go b/api/internal/app/api/download/download.go new file mode 100644 index 0000000..5b3a4f0 --- /dev/null +++ b/api/internal/app/api/download/download.go @@ -0,0 +1,42 @@ +package download + +import ( + "downloader/internal/app/api/common/responses" + "errors" + "github.com/go-chi/chi" + "github.com/go-chi/render" + "net/http" +) + +type api struct{} + +func New() *api { + return &api{} +} + +func (api *api) SetupDownloadApi(router *chi.Mux) { + router.Route("/downloads", func(r chi.Router) { + r.Post("/", api.requestDownload) + }) +} + +type requestDownloadRequest struct { + Provider string `json:"provider"` + Link string `json:"link"` +} + +func (dr *requestDownloadRequest) Bind(r *http.Request) error { + if dr.Link == "" || dr.Provider == "" { + return errors.New("missing required download request field") + } + + return nil +} + +func (api *api) requestDownload(w http.ResponseWriter, r *http.Request) { + data := &requestDownloadRequest{} + if err := render.Bind(r, data); err != nil { + _ = render.Render(w, r, responses.ErrInvalidRequest(err)) + return + } +} diff --git a/api/internal/app/router/router.go b/api/internal/app/router/router.go new file mode 100644 index 0000000..84c3115 --- /dev/null +++ b/api/internal/app/router/router.go @@ -0,0 +1,49 @@ +package router + +import ( + "downloader/internal/app/api/download" + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "net/http" + "time" +) + +type router struct { + internalRouter *chi.Mux +} + +func NewRouter() *router { + router := &router{internalRouter: chi.NewRouter()} + + router. + setupMiddleware(). + setupRoutes() + + return router +} + +func (router *router) Run() { + http.ListenAndServe(":3333", router.internalRouter) +} + +func (router *router) RegisterApi() *chi.Mux { + return router.internalRouter +} + +func (router *router) setupMiddleware() *router { + router.internalRouter.Use(middleware.Logger) + router.internalRouter.Use(middleware.RequestID) + router.internalRouter.Use(middleware.RealIP) + router.internalRouter.Use(middleware.Recoverer) + router.internalRouter.Use(middleware.Timeout(time.Second * 60)) + + return router +} + +func (router *router) setupRoutes() *router { + downloadApi := download.New() + + downloadApi.SetupDownloadApi(router.internalRouter) + + return router +} diff --git a/api/internal/core/entities/Download.go b/api/internal/core/entities/Download.go new file mode 100644 index 0000000..103437c --- /dev/null +++ b/api/internal/core/entities/Download.go @@ -0,0 +1,8 @@ +package entities + +type Download struct { + ID string `json:"id"` + Status string `json:"status"` + Link string `json:"link"` + Data string `json:"data"` +} diff --git a/api/internal/core/ports/download_request/download_request.go b/api/internal/core/ports/download_request/download_request.go new file mode 100644 index 0000000..cba72de --- /dev/null +++ b/api/internal/core/ports/download_request/download_request.go @@ -0,0 +1,13 @@ +package download_request + +import "downloader/internal/core/entities" + +type Service interface { + Schedule(provider string, link string) (entities.Download, error) + Get(id string) (entities.Download, error) +} + +type Repository interface { + Create(download entities.Download) (entities.Download, error) + GetById(id string) (entities.Download, error) +}