feat: added first api route

This commit is contained in:
2026-02-18 08:32:27 -05:00
parent e1f0a638b9
commit 150f95ee0b
6 changed files with 149 additions and 18 deletions

View File

@@ -4,17 +4,19 @@ import (
"blog/internal/cache"
"blog/internal/config"
"blog/internal/database"
"blog/internal/echo/routes"
"blog/internal/services"
"context"
"os"
"fmt"
"github.com/charmbracelet/log"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
func main() {
// Server config
server_config := config.NewServerConfig()
server_config.LoadConfig()
server_config.LoadConfig()
// Database Config
db_config := config.NewDatabaseConfig()
@@ -23,7 +25,7 @@ func main() {
// Connect to database
db, err := database.Connect(db_config.GetDSN())
if err != nil {
log.Fatal("Failed to connect to database: ", err)
log.Error("Failed to connect to database: ", err)
}
defer db.Close()
@@ -34,20 +36,16 @@ func main() {
// Create Strapi service
strapi_service := services.NewStrapiService(server_config.StrapiEndpoint+"/graphql", server_config.StrapiToken, strapi_cache)
// Strapi logger
strapi_logger := log.NewWithOptions(os.Stderr, log.Options{
ReportTimestamp: true,
Prefix: "STRAPI",
})
// Setup echo server
e := echo.New()
e.Use(middleware.RequestLogger())
// Test strapi get
posts, err := strapi_service.GetFeaturedPosts(context.Background(), 10, 1)
if err != nil {
strapi_logger.Error(err)
os.Exit(0)
// Setup routes
routes.SetupRoutes(e, strapi_service)
// Start server
host := fmt.Sprintf("%s:%d", server_config.Host, server_config.Port)
if err := e.Start(host); err != nil {
log.Fatal("Failed to start server", "error", err)
}
post := posts[0]
strapi_logger.Info(post)
}

2
go.mod
View File

@@ -33,6 +33,7 @@ require (
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/labstack/echo/v5 v5.0.4 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.20 // indirect
@@ -45,4 +46,5 @@ require (
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/time v0.14.0 // indirect
)

4
go.sum
View File

@@ -80,6 +80,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc=
github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
@@ -139,6 +141,8 @@ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -0,0 +1,58 @@
package handlers
import (
"blog/internal/services"
"net/http"
"github.com/labstack/echo/v5"
)
// GetAllPosts returns a list of all posts
func GetAllPosts(c *echo.Context, s *services.StrapiService, pageSize, page int) error {
posts, err := s.GetAllPosts(c.Request().Context(), pageSize, page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, posts)
}
// GetFeaturedPosts returns a list of featured posts
func GetFeaturedPosts(c *echo.Context, s *services.StrapiService, pageSize, page int) error {
posts, err := s.GetFeaturedPosts(c.Request().Context(), pageSize, page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, posts)
}
// GetPost returns a specific post
func GetPost(c *echo.Context, s *services.StrapiService, slug string) error {
post, err := s.GetPost(c.Request().Context(), slug)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, post)
}
// GetPostSummaries returns post summaries
func GetPostSummaries(c *echo.Context, s *services.StrapiService, pageSize, page int) error {
posts, err := s.GetPostSummaries(c.Request().Context(), pageSize, page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, posts)
}
// GetPostsByTag returns a list of posts by tag
func GetPostsByTag(c *echo.Context, s *services.StrapiService, tag string, pageSize, page int) error {
posts, err := s.GetPostsByTag(c.Request().Context(), tag, pageSize, page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusOK, posts)
}

View File

@@ -0,0 +1,33 @@
package middleware
import (
"time"
"github.com/charmbracelet/log"
"github.com/labstack/echo/v5"
)
func ServerHandler(next echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
start := time.Now()
// Process the request
err := next(c)
if err != nil {
c.Logger().Error(err.Error())
}
stop := time.Now()
req := c.Request()
// Log using charmbracelet
log.Info("Request handled",
"method", req.Method,
"path", req.URL.Path,
"latency", stop.Sub(start),
"ip", c.RealIP(),
)
return nil
}
}

View File

@@ -0,0 +1,36 @@
package routes
import (
"blog/internal/echo/handlers"
"blog/internal/echo/middleware"
"blog/internal/services"
"strconv"
"github.com/labstack/echo/v5"
)
// Helper method to get int param or default value
func getIntParam(c *echo.Context, name string, defaultValue int) int {
value, err := strconv.Atoi(c.ParamOr(name, strconv.Itoa(defaultValue)))
if err != nil {
return defaultValue
}
return value
}
func SetupRoutes(e *echo.Echo, s *services.StrapiService) {
// Global middleware
e.Use(middleware.ServerHandler)
// Post routes
posts := e.Group("/posts") // Routing group
// GET /posts/all
posts.GET("/all", func(c *echo.Context) error {
pageSize := getIntParam(c, "pageSize", 10)
page := getIntParam(c, "page", 1)
return handlers.GetAllPosts(c, s, pageSize, page)
})
}