This commit is contained in:
2026-03-26 19:12:59 -04:00
commit d741a30495
24 changed files with 5975 additions and 0 deletions

71
internal/server/routes.go Normal file
View File

@@ -0,0 +1,71 @@
package server
import (
"encoding/json"
"log"
"net/http"
"github.com/a-h/templ"
"go-htmx/cmd/web"
)
func (s *Server) RegisterRoutes() http.Handler {
mux := http.NewServeMux()
// Register routes
mux.HandleFunc("/", s.HelloWorldHandler)
mux.HandleFunc("/health", s.healthHandler)
fileServer := http.FileServer(http.FS(web.Files))
mux.Handle("/assets/", fileServer)
mux.Handle("/web", templ.Handler(web.HelloForm()))
mux.HandleFunc("/hello", web.HelloWebHandler)
// Wrap the mux with CORS middleware
return s.corsMiddleware(mux)
}
func (s *Server) corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Set CORS headers
w.Header().Set("Access-Control-Allow-Origin", "*") // Replace "*" with specific origins if needed
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, X-CSRF-Token")
w.Header().Set("Access-Control-Allow-Credentials", "false") // Set to "true" if credentials are required
// Handle preflight OPTIONS requests
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusNoContent)
return
}
// Proceed with the next handler
next.ServeHTTP(w, r)
})
}
func (s *Server) HelloWorldHandler(w http.ResponseWriter, r *http.Request) {
resp := map[string]string{"message": "Hello World"}
jsonResp, err := json.Marshal(resp)
if err != nil {
http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(jsonResp); err != nil {
log.Printf("Failed to write response: %v", err)
}
}
func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
resp, err := json.Marshal(s.db.Health())
if err != nil {
http.Error(w, "Failed to marshal health check response", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(resp); err != nil {
log.Printf("Failed to write response: %v", err)
}
}

View File

@@ -0,0 +1,31 @@
package server
import (
"io"
"net/http"
"net/http/httptest"
"testing"
)
func TestHandler(t *testing.T) {
s := &Server{}
server := httptest.NewServer(http.HandlerFunc(s.HelloWorldHandler))
defer server.Close()
resp, err := http.Get(server.URL)
if err != nil {
t.Fatalf("error making request to server. Err: %v", err)
}
defer resp.Body.Close()
// Assertions
if resp.StatusCode != http.StatusOK {
t.Errorf("expected status OK; got %v", resp.Status)
}
expected := "{\"message\":\"Hello World\"}"
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("error reading response body. Err: %v", err)
}
if expected != string(body) {
t.Errorf("expected response body to be %v; got %v", expected, string(body))
}
}

39
internal/server/server.go Normal file
View File

@@ -0,0 +1,39 @@
package server
import (
"fmt"
"net/http"
"os"
"strconv"
"time"
_ "github.com/joho/godotenv/autoload"
"go-htmx/internal/database"
)
type Server struct {
port int
db database.Service
}
func NewServer() *http.Server {
port, _ := strconv.Atoi(os.Getenv("PORT"))
NewServer := &Server{
port: port,
db: database.New(),
}
// Declare Server config
server := &http.Server{
Addr: fmt.Sprintf(":%d", NewServer.port),
Handler: NewServer.RegisterRoutes(),
IdleTimeout: time.Minute,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
}
return server
}