- Add modernc.org/sqlite (pure Go, no CGO) - Create models package with Post struct - Implement SQLite connection and schema auto-creation - Add CRUD methods to database package - Create post handlers with JSON API - Register API routes: GET/POST/PUT/DELETE /api/v1/posts - Set default DBURL to file:./data.db with WAL mode
138 lines
4.0 KiB
Go
138 lines
4.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"git.eeqj.de/sneak/gohttpserver/internal/models"
|
|
"github.com/go-chi/chi"
|
|
)
|
|
|
|
func (s *Handlers) HandleListPosts() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
posts, err := s.params.Database.ListPosts(r.Context())
|
|
if err != nil {
|
|
s.log.Error("failed to list posts", "error", err)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if posts == nil {
|
|
posts = []*models.Post{}
|
|
}
|
|
|
|
s.respondJSON(w, r, posts, http.StatusOK)
|
|
}
|
|
}
|
|
|
|
func (s *Handlers) HandleGetPost() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseInt(idStr, 10, 64)
|
|
if err != nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "invalid id"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
post, err := s.params.Database.GetPost(r.Context(), id)
|
|
if err != nil {
|
|
s.log.Error("failed to get post", "error", err, "id", id)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if post == nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "not found"}, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
s.respondJSON(w, r, post, http.StatusOK)
|
|
}
|
|
}
|
|
|
|
func (s *Handlers) HandleCreatePost() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
var req models.CreatePostRequest
|
|
if err := s.decodeJSON(w, r, &req); err != nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "invalid request body"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Title == "" || req.Body == "" || req.Author == "" {
|
|
s.respondJSON(w, r, map[string]string{"error": "title, body, and author are required"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
post, err := s.params.Database.CreatePost(r.Context(), &req)
|
|
if err != nil {
|
|
s.log.Error("failed to create post", "error", err)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
s.respondJSON(w, r, post, http.StatusCreated)
|
|
}
|
|
}
|
|
|
|
func (s *Handlers) HandleUpdatePost() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseInt(idStr, 10, 64)
|
|
if err != nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "invalid id"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req models.UpdatePostRequest
|
|
if err := s.decodeJSON(w, r, &req); err != nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "invalid request body"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
post, err := s.params.Database.UpdatePost(r.Context(), id, &req)
|
|
if err != nil {
|
|
s.log.Error("failed to update post", "error", err, "id", id)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if post == nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "not found"}, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
s.respondJSON(w, r, post, http.StatusOK)
|
|
}
|
|
}
|
|
|
|
func (s *Handlers) HandleDeletePost() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseInt(idStr, 10, 64)
|
|
if err != nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "invalid id"}, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
post, err := s.params.Database.GetPost(r.Context(), id)
|
|
if err != nil {
|
|
s.log.Error("failed to get post for delete", "error", err, "id", id)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if post == nil {
|
|
s.respondJSON(w, r, map[string]string{"error": "not found"}, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
if err := s.params.Database.DeletePost(r.Context(), id); err != nil {
|
|
s.log.Error("failed to delete post", "error", err, "id", id)
|
|
s.respondJSON(w, r, map[string]string{"error": "internal server error"}, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
s.respondJSON(w, r, nil, http.StatusNoContent)
|
|
}
|
|
}
|