Initial project structure commit.
Static directory for public folders and business logic for the app within internal, split into domain specific folders to keep clear seperation of concerns.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package web
|
||||
|
||||
import "net/http"
|
||||
|
||||
type HomeData struct {
|
||||
Title string
|
||||
}
|
||||
|
||||
func (s *Server) handleHome() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data := HomeData{Title: "NFeeder"}
|
||||
view(w, r, "home", data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package web
|
||||
@@ -0,0 +1,28 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
func (s *Server) setupRoutes() *chi.Mux {
|
||||
router := chi.NewRouter()
|
||||
|
||||
router.Use(middleware.Logger)
|
||||
router.Use(middleware.Recoverer)
|
||||
|
||||
// Setup basic file server nothing fancy
|
||||
router.Handle("/static/*", http.StripPrefix("/static", http.FileServer(http.Dir("static"))))
|
||||
|
||||
// Public routes
|
||||
router.Group(func(r chi.Router) {
|
||||
r.Get("/", s.handleHome())
|
||||
})
|
||||
|
||||
//s.router.Get("/", s.handleIndex())
|
||||
//s.router.Post("/users", s.handleCreateUser())
|
||||
|
||||
return router
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"nfeeder/internal/db"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
httpServer *http.Server
|
||||
store *db.Store
|
||||
}
|
||||
|
||||
func NewServer(store *db.Store) *Server {
|
||||
s := &Server {
|
||||
store: store,
|
||||
}
|
||||
|
||||
s.httpServer = &http.Server {
|
||||
Handler: s.setupRoutes(),
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) Start(addr string) error {
|
||||
s.httpServer.Addr = addr
|
||||
return s.httpServer.ListenAndServe()
|
||||
}
|
||||
|
||||
func (s *Server) Shutdown(ctx context.Context) error {
|
||||
return s.httpServer.Shutdown(ctx)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Renders a full page by combining the base template with a page template
|
||||
// Parsed together so the page can define blocks needed for base template
|
||||
func render(w http.ResponseWriter, _ *http.Request, page string, data any) {
|
||||
files := []string{
|
||||
filepath.Join("internal", "templates", "layouts", "base.html"),
|
||||
filepath.Join("internal", "templates", "pages", page+".html"),
|
||||
}
|
||||
|
||||
tmpl, err := template.ParseFiles(files...)
|
||||
if err != nil {
|
||||
http.Error(w, "template error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
||||
if err := tmpl.ExecuteTemplate(w, "base", data); err != nil {
|
||||
http.Error(w, "render error: "+err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func view(w http.ResponseWriter, r *http.Request, page string, data any) {
|
||||
render(w, r, page, data)
|
||||
}
|
||||
Reference in New Issue
Block a user