Files
agent-evals/backend/internal/server/server.go
Evan Reichard c9003a208a fix: resolve JSON.parse error in frontend API calls
- Add error handling for JSON encoding in all backend handlers
- Add CORS support to backend server
- Add proxy configuration for frontend development server
- Improve error handling in frontend API calls
- Build frontend to create static files for backend serving
- Add comprehensive error messages and user feedback

Fixes issue where frontend received malformed JSON responses from backend API.
2026-02-05 20:14:12 -05:00

101 lines
2.4 KiB
Go

package server
import (
"context"
"fmt"
"net/http"
"os"
"markdown-editor/internal/handlers"
"markdown-editor/internal/logger"
"markdown-editor/internal/storage"
"github.com/gorilla/mux"
"github.com/rs/cors"
"github.com/sirupsen/logrus"
)
type Server struct {
logger *logrus.Logger
storage storage.Storage
handlers *handlers.Handlers
router *mux.Router
server *http.Server
dataDir string
port int
host string
}
func StartServer(dataDir string, port int, host string) error {
log := logger.NewLogger()
log.Info("Starting markdown editor server")
// Initialize storage
storage, err := storage.NewFileStorage(dataDir)
if err != nil {
log.Errorf("Failed to initialize storage: %v", err)
return err
}
// Initialize handlers
handlers := handlers.NewHandlers(log, storage)
// Create server
s := &Server{
logger: log,
storage: storage,
handlers: handlers,
dataDir: dataDir,
port: port,
host: host,
}
// Setup routes
s.setupRoutes()
// Start server
s.logger.Infof("Server starting on %s:%d", host, port)
return s.serve()
}
func (s *Server) setupRoutes() {
s.router = mux.NewRouter()
// API routes
apiRouter := s.router.PathPrefix("/api").Subrouter()
apiRouter.Handle("/files", s.handlers.ListFiles()).Methods("GET")
apiRouter.Handle("/files", s.handlers.CreateFile()).Methods("POST")
apiRouter.Handle("/files/{filename}", s.handlers.GetFile()).Methods("GET")
apiRouter.Handle("/files/{filename}", s.handlers.UpdateFile()).Methods("PUT")
apiRouter.Handle("/files/{filename}", s.handlers.DeleteFile()).Methods("DELETE")
// Static file serving
frontendDir := "frontend/build"
if frontendDirEnv := os.Getenv("FRONTEND_BUILD_DIR"); frontendDirEnv != "" {
frontendDir = frontendDirEnv
}
s.router.PathPrefix("/").Handler(http.FileServer(http.Dir(frontendDir)))
// Enable CORS
cors := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000", "http://localhost:8080"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
})
s.router.Use(cors.Handler)
}
func (s *Server) serve() error {
s.server = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.host, s.port),
Handler: s.router,
}
return s.server.ListenAndServe()
}
func (s *Server) Shutdown(ctx context.Context) error {
s.logger.Info("Shutting down server...")
return s.server.Shutdown(ctx)
}