Template
1
0
Fork 0
This commit is contained in:
Atridad Lahiji 2024-01-26 14:39:58 -07:00
parent d84eaeb9ca
commit 983c11a162
No known key found for this signature in database
10 changed files with 95 additions and 116 deletions

View file

@ -3,11 +3,9 @@ package api
import ( import (
"net/http" "net/http"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
) )
func Ping(w http.ResponseWriter, req bunrouter.Request) error { func Ping(c echo.Context) error {
w.WriteHeader(http.StatusOK) return c.String(http.StatusOK, "Pong!")
w.Write([]byte("Pong!"))
return nil
} }

View file

@ -3,28 +3,26 @@ package api
import ( import (
"fmt" "fmt"
"log" "log"
"net/http"
"time" "time"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
"goth.stack/lib" "goth.stack/lib"
) )
func SSE(w http.ResponseWriter, req bunrouter.Request) error { func SSE(c echo.Context) error {
queryParams := req.URL.Query() channel := c.QueryParam("channel")
channel := queryParams.Get("channel")
if channel == "" { if channel == "" {
channel = "default" channel = "default"
} }
// Use the request context, which is cancelled when the client disconnects // Use the request context, which is cancelled when the client disconnects
ctx := req.Context() ctx := c.Request().Context()
pubsub, _ := lib.Subscribe(lib.RedisClient, channel) pubsub, _ := lib.Subscribe(lib.RedisClient, channel)
w.Header().Set("Content-Type", "text/event-stream") c.Response().Header().Set(echo.HeaderContentType, "text/event-stream")
w.Header().Set("Connection", "keep-alive") c.Response().Header().Set(echo.HeaderConnection, "keep-alive")
w.Header().Set("Cache-Control", "no-cache") c.Response().Header().Set(echo.HeaderCacheControl, "no-cache")
// Create a ticker that fires every 15 seconds // Create a ticker that fires every 15 seconds
ticker := time.NewTicker(30 * time.Second) ticker := time.NewTicker(30 * time.Second)
@ -37,10 +35,10 @@ func SSE(w http.ResponseWriter, req bunrouter.Request) error {
return nil return nil
case <-ticker.C: case <-ticker.C:
// Every 30 seconds, send a comment to keep the connection alive // Every 30 seconds, send a comment to keep the connection alive
if _, err := w.Write([]byte(": keep-alive\n\n")); err != nil { if _, err := c.Response().Write([]byte(": keep-alive\n\n")); err != nil {
return err return err
} }
w.(http.Flusher).Flush() c.Response().Flush()
default: default:
// Handle incoming messages as before // Handle incoming messages as before
msg, err := pubsub.ReceiveMessage(ctx) msg, err := pubsub.ReceiveMessage(ctx)
@ -50,11 +48,11 @@ func SSE(w http.ResponseWriter, req bunrouter.Request) error {
} }
data := fmt.Sprintf("data: %s\n\n", msg.Payload) data := fmt.Sprintf("data: %s\n\n", msg.Payload)
if _, err := w.Write([]byte(data)); err != nil { if _, err := c.Response().Write([]byte(data)); err != nil {
return err return err
} }
w.(http.Flusher).Flush() c.Response().Flush()
} }
} }
} }

View file

@ -1,32 +1,25 @@
package api package api
import ( import (
"encoding/json"
"net/http" "net/http"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
"goth.stack/lib" "goth.stack/lib"
) )
func SSEDemoSend(w http.ResponseWriter, req bunrouter.Request) error { func SSEDemoSend(c echo.Context) error {
// Get query parameters channel := c.QueryParam("channel")
queryParams := req.URL.Query()
// Get channel from query parameters
channel := queryParams.Get("channel")
if channel == "" { if channel == "" {
channel = "default" channel = "default"
} }
// Get message from query parameters, form value, or request body // Get message from query parameters, form value, or request body
message := queryParams.Get("message") message := c.QueryParam("message")
if message == "" { if message == "" {
message = req.PostFormValue("message") message = c.FormValue("message")
if message == "" { if message == "" {
var body map[string]string var body map[string]string
err := json.NewDecoder(req.Body).Decode(&body) if err := c.Bind(&body); err != nil {
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return err return err
} }
message = body["message"] message = body["message"]
@ -34,18 +27,11 @@ func SSEDemoSend(w http.ResponseWriter, req bunrouter.Request) error {
} }
if message == "" { if message == "" {
errMsg := map[string]string{"error": "message parameter is required"} return c.JSON(http.StatusBadRequest, map[string]string{"error": "message parameter is required"})
errMsgBytes, _ := json.Marshal(errMsg)
http.Error(w, string(errMsgBytes), http.StatusBadRequest)
return nil
} }
// Send message // Send message
lib.SendSSE("default", message) lib.SendSSE("default", message)
statusMsg := map[string]string{"status": "message sent"} return c.JSON(http.StatusOK, map[string]string{"status": "message sent"})
statusMsgBytes, _ := json.Marshal(statusMsg)
w.Write(statusMsgBytes)
return nil
} }

18
go.mod
View file

@ -13,28 +13,28 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/fatih/color v1.16.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
require ( require (
github.com/alecthomas/assert/v2 v2.4.1 github.com/alecthomas/assert/v2 v2.4.1
github.com/atridadl/bmw v1.0.0
github.com/go-redis/redismock/v9 v9.2.0 github.com/go-redis/redismock/v9 v9.2.0
github.com/google/uuid v1.6.0 // indirect
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v4 v4.11.4
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/redis/go-redis/v9 v9.4.0 github.com/redis/go-redis/v9 v9.4.0
github.com/resendlabs/resend-go v1.7.0 github.com/resendlabs/resend-go v1.7.0
github.com/unrolled/secure v1.14.0 // indirect
github.com/uptrace/bunrouter v1.0.21
github.com/uptrace/bunrouter/extra/reqlog v1.0.21
github.com/yuin/goldmark v1.6.0 github.com/yuin/goldmark v1.6.0
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
golang.org/x/net v0.20.0 // indirect golang.org/x/net v0.20.0 // indirect

32
go.sum
View file

@ -6,8 +6,6 @@ github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurG
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8= github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/atridadl/bmw v1.0.0 h1:f0M3D+B5T7kqzswJgHKTBlVw1CgF78xqlfwD6VRub9o=
github.com/atridadl/bmw v1.0.0/go.mod h1:LHXSDXKjmOvPXgDv32CDeu1nTmT+luIF+YR9xmqPvEw=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@ -23,22 +21,22 @@ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=
github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@ -60,21 +58,17 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/unrolled/secure v1.14.0 h1:u9vJTU/pR4Bny0ntLUMxdfLtmIRGvQf2sEFuA0TG9AE= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/unrolled/secure v1.14.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/uptrace/bunrouter v1.0.21 h1:HXarvX+N834sXyHpl+I/TuE11m19kLW/qG5u3YpHUag= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/uptrace/bunrouter v1.0.21/go.mod h1:TwT7Bc0ztF2Z2q/ZzMuSVkcb/Ig/d3MQeP2cxn3e1hI= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/uptrace/bunrouter/extra/reqlog v1.0.21 h1:k9ebZATe9NOBUrPcMYJAQ2OMb62ERRN7qfwNwoa6Kxs=
github.com/uptrace/bunrouter/extra/reqlog v1.0.21/go.mod h1:j+pXrYzYe3OxTzFb4f/f2JL+CVoGVi1QJJiU0YKSUlw=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -83,6 +77,8 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=

57
main.go
View file

@ -2,47 +2,52 @@ package main
import ( import (
"log" "log"
"net/http"
"github.com/joho/godotenv"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"goth.stack/api" "goth.stack/api"
"goth.stack/pages" "goth.stack/pages"
"github.com/atridadl/bmw"
"github.com/joho/godotenv"
"github.com/uptrace/bunrouter"
"github.com/uptrace/bunrouter/extra/reqlog"
) )
func main() { func main() {
godotenv.Load(".env") // Load environment variables
err := godotenv.Load(".env")
if err != nil {
log.Fatal("Error loading .env file")
}
// Initialize router // Initialize Echo router
router := bunrouter.New( e := echo.New()
bunrouter.Use(reqlog.NewMiddleware(), bmw.RequestID, bmw.SecureHeaders),
) // Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Pre(middleware.RemoveTrailingSlash())
e.Use(middleware.Logger())
e.Use(middleware.RequestID())
e.Use(middleware.Secure())
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
Level: 5,
}))
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(50)))
// Static server // Static server
fs := http.FileServer(http.Dir("public")) e.Static("/public", "public")
router.GET("/public/*filepath", func(w http.ResponseWriter, req bunrouter.Request) error {
http.StripPrefix("/public", fs).ServeHTTP(w, req.Request)
return nil
})
// Page routes // Page routes
rateLimiter := bmw.NewRateLimiter(50) e.GET("/", pages.Home)
pageGroup := router.NewGroup("", bunrouter.Use(rateLimiter.RateLimit)) e.GET("/blog", pages.Blog)
pageGroup.GET("/", pages.Home) e.GET("/post/:post", pages.Post)
pageGroup.GET("/blog", pages.Blog) e.GET("/sse", pages.SSEDemo)
pageGroup.GET("/post/:post", pages.Post)
pageGroup.GET("/sse", pages.SSEDemo)
// API Routes: // API Routes:
apiGroup := router.NewGroup("/api") apiGroup := e.Group("/api")
apiGroup.GET("/ping", api.Ping) apiGroup.GET("/ping", api.Ping)
apiGroup.GET("/sse", api.SSE) apiGroup.GET("/sse", api.SSE)
apiGroup.POST("/sendsse", api.SSEDemoSend) apiGroup.POST("/sendsse", api.SSEDemoSend)
log.Fatal(http.ListenAndServe(":3000", router)) // Start server
e.Logger.Fatal(e.Start(":3000"))
} }

View file

@ -8,7 +8,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
"goth.stack/lib" "goth.stack/lib"
) )
@ -16,19 +16,19 @@ type BlogProps struct {
Posts []lib.CardLink Posts []lib.CardLink
} }
func Blog(w http.ResponseWriter, req bunrouter.Request) error { func Blog(c echo.Context) error {
var posts []lib.CardLink var posts []lib.CardLink
files, err := os.ReadDir("./content/") files, err := os.ReadDir("./content/")
if err != nil { if err != nil {
http.Error(w, "There was an issue finding posts!", http.StatusInternalServerError) http.Error(c.Response().Writer, "There was an issue finding posts!", http.StatusInternalServerError)
return nil return nil
} }
for _, file := range files { for _, file := range files {
frontMatter, err := lib.ExtractFrontMatter(file, "./content/") frontMatter, err := lib.ExtractFrontMatter(file, "./content/")
if err != nil { if err != nil {
http.Error(w, "There was an issue rendering the posts!", http.StatusInternalServerError) http.Error(c.Response().Writer, "There was an issue rendering the posts!", http.StatusInternalServerError)
return nil return nil
} }
@ -62,5 +62,5 @@ func Blog(w http.ResponseWriter, req bunrouter.Request) error {
partials := []string{"header", "navitems", "cardlinks"} partials := []string{"header", "navitems", "cardlinks"}
// Render the template // Render the template
return lib.RenderTemplate(w, "base", partials, props) return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
} }

View file

@ -2,9 +2,8 @@ package pages
import ( import (
"html/template" "html/template"
"net/http"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
"goth.stack/lib" "goth.stack/lib"
) )
@ -16,7 +15,7 @@ type HomeProps struct {
SupportLink string SupportLink string
} }
func Home(w http.ResponseWriter, req bunrouter.Request) error { func Home(c echo.Context) error {
socials := []lib.IconLink{ socials := []lib.IconLink{
{ {
Name: "Email", Name: "Email",
@ -135,6 +134,5 @@ func Home(w http.ResponseWriter, req bunrouter.Request) error {
partials := []string{"header", "navitems"} partials := []string{"header", "navitems"}
// Render the template // Render the template
w.WriteHeader(http.StatusOK) return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
return lib.RenderTemplate(w, "base", partials, props)
} }

View file

@ -7,7 +7,7 @@ import (
"os" "os"
chromahtml "github.com/alecthomas/chroma/v2/formatters/html" chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
"github.com/uptrace/bunrouter" "github.com/labstack/echo/v4"
"github.com/yuin/goldmark" "github.com/yuin/goldmark"
highlighting "github.com/yuin/goldmark-highlighting/v2" highlighting "github.com/yuin/goldmark-highlighting/v2"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -21,26 +21,26 @@ type PostProps struct {
Tags []string Tags []string
} }
func Post(w http.ResponseWriter, req bunrouter.Request) error { func Post(c echo.Context) error {
postName := req.Param("post") postName := c.Param("post")
filePath := "content/" + postName + ".md" filePath := "content/" + postName + ".md"
md, err := os.ReadFile(filePath) md, err := os.ReadFile(filePath)
if err != nil { if err != nil {
http.Error(w, "This post does not exist!", http.StatusNotFound) http.Error(c.Response().Writer, "This post does not exist!", http.StatusNotFound)
return nil return nil
} }
frontmatterBytes, content, err := lib.SplitFrontmatter(md) frontmatterBytes, content, err := lib.SplitFrontmatter(md)
if err != nil { if err != nil {
http.Error(w, "There was an issue rendering this post!", http.StatusInternalServerError) http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
return nil return nil
} }
var frontmatter lib.FrontMatter var frontmatter lib.FrontMatter
if err := yaml.Unmarshal(frontmatterBytes, &frontmatter); err != nil { if err := yaml.Unmarshal(frontmatterBytes, &frontmatter); err != nil {
http.Error(w, "There was an issue rendering this post!", http.StatusInternalServerError) http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
return nil return nil
} }
@ -57,7 +57,7 @@ func Post(w http.ResponseWriter, req bunrouter.Request) error {
) )
if err := markdown.Convert(content, &buf); err != nil { if err := markdown.Convert(content, &buf); err != nil {
http.Error(w, "There was an issue rendering this post!", http.StatusInternalServerError) http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
return nil return nil
} }
@ -72,5 +72,5 @@ func Post(w http.ResponseWriter, req bunrouter.Request) error {
partials := []string{"header", "navitems"} partials := []string{"header", "navitems"}
// Render the template // Render the template
return lib.RenderTemplate(w, "post", partials, props) return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
} }

View file

@ -1,16 +1,14 @@
package pages package pages
import ( import (
"net/http" "github.com/labstack/echo/v4"
"github.com/uptrace/bunrouter"
"goth.stack/lib" "goth.stack/lib"
) )
func SSEDemo(w http.ResponseWriter, req bunrouter.Request) error { func SSEDemo(c echo.Context) error {
// Specify the partials used by this page // Specify the partials used by this page
partials := []string{"header", "navitems"} partials := []string{"header", "navitems"}
// Render the template // Render the template
return lib.RenderTemplate(w, "base", partials, nil) return lib.RenderTemplate(c.Response().Writer, "base", partials, nil)
} }