boxes-api/main.go

159 lines
6.3 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gorilla/mux"
"github.com/jinzhu/gorm"
"github.com/rs/cors"
)
var (
db *gorm.DB // Declare db globally
config *Config
)
func main() {
configFile := os.Getenv("BOXES_API_CONFIG")
var err error
config, err = LoadConfig(configFile)
// get the static files directory
staticPath := config.StaticFilesDir
// Add this before setting up the handler
if _, err := os.Stat(staticPath); os.IsNotExist(err) {
log.Fatalf("Static directory does not exist: %s", staticPath)
}
// Get the allowed origins from the ALLOWED_ORIGINS environment variable
// If empty, defaults to http://localhost:3000
allowedOrigins := config.AllowedOrigins
fmt.Println("Allowed origins: ", allowedOrigins)
origins := []string{"http://localhost:3000"} // Default value
if allowedOrigins != "" {
// Split the comma-separated string into a slice of strings
origins = strings.Split(allowedOrigins, ",")
fmt.Println("Listening for connections from: ", origins)
}
// check for errors
if err != nil || config == nil {
log.Fatalf("Failed to load config: %v", err)
}
fmt.Println(config.DatabasePath)
fmt.Println(config.ImageStorageDir)
fmt.Println(config.JWTSecret)
fmt.Println(config.LogFile)
fmt.Println(config.ListeningPort)
// Connect to the database
db, err = ConnectDB(config.DatabasePath)
if err != nil || db == nil {
log.Fatalf("Failed to connect to database: %v", err)
}
defer db.Close()
customHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Don't handle /static/ paths here - let the static file server handle those
if strings.HasPrefix(r.URL.Path, "/static/") {
http.NotFound(w, r)
return
}
// For all other routes, serve index.html
indexPath := filepath.Join(staticPath, "index.html")
http.ServeFile(w, r, indexPath)
})
// Register the catch-all handler for non-static routes
staticRouter.PathPrefix("/").Handler(customHandler)
fmt.Println("Default user 'boxuser' created successfully!")
// Create the router
baseRouter := mux.NewRouter()
router := baseRouter.PathPrefix("/api/v1").Subrouter()
// Define your routes
router.Handle("/login", http.HandlerFunc(LoginHandler)).Methods("POST", "OPTIONS")
router.Handle("/boxes", AuthMiddleware(http.HandlerFunc(GetBoxesHandler))).Methods("GET", "OPTIONS")
router.Handle("/boxes", AuthMiddleware(http.HandlerFunc(CreateBoxHandler))).Methods("POST", "OPTIONS")
router.Handle("/boxes/{id}", AuthMiddleware(http.HandlerFunc(DeleteBoxHandler))).Methods("DELETE", "OPTIONS")
router.Handle("/boxes/{id}", AuthMiddleware(http.HandlerFunc(GetBoxHandler))).Methods("GET", "OPTIONS")
router.Handle("/items", AuthMiddleware(http.HandlerFunc(GetItemsHandler))).Methods("GET", "OPTIONS")
router.Handle("/items", AuthMiddleware(http.HandlerFunc(CreateItemHandler))).Methods("POST", "OPTIONS")
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(GetItemHandler))).Methods("GET", "OPTIONS")
router.Handle("/boxes/{id}/items", AuthMiddleware(http.HandlerFunc(GetItemsInBoxHandler))).Methods("GET", "OPTIONS")
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(UpdateItemHandler))).Methods("PUT", "OPTIONS")
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(DeleteItemHandler))).Methods("DELETE", "OPTIONS")
router.Handle("/items/{id}/image", AuthMiddleware(http.HandlerFunc(GetItemImageHandler))).Methods("GET", "OPTIONS")
fmt.Println("Registering route for search items...")
router.Handle("/search/items", AuthMiddleware(http.HandlerFunc(SearchItemsHandler))).Methods("GET", "OPTIONS")
// Add a new route for uploading an image with AuthMiddleware
router.HandleFunc("/items/{id}/upload", UploadItemImageHandler).
Methods("POST").
Handler(AuthMiddleware(http.HandlerFunc(UploadItemImageHandler)))
managementRouter := router.PathPrefix("/admin").Subrouter()
managementRouter.Use(AuthMiddleware)
managementRouter.Handle("/user", http.HandlerFunc(GetUsersHandler)).Methods("GET", "OPTIONS")
managementRouter.Handle("/user", http.HandlerFunc(CreateUserHandler)).Methods("POST", "OPTIONS")
managementRouter.Handle("/user/{id}", http.HandlerFunc(GetUserHandler)).Methods("GET", "OPTIONS")
managementRouter.Handle("/user/{id}", http.HandlerFunc(DeleteUserHandler)).Methods("DELETE", "OPTIONS")
managementRouter.Handle("/db", http.HandlerFunc(BackupDatabaseHandler)).Methods("GET", "OPTIONS")
managementRouter.Handle("/db", http.HandlerFunc(RestoreDatabaseHandler)).Methods("POST", "OPTIONS")
managementRouter.Handle("/imagearchive", http.HandlerFunc(GetImageArchiveHandler)).Methods("GET", "OPTIONS")
// Define a route for serving static files
fmt.Println("Serving static files from:", staticPath)
//staticHandler := http.FileServer(http.Dir(staticPath))
fmt.Println("Registering route for serving static files, no StripPrefix")
//staticRouter.HandleFunc("/", customHandler).Methods("GET", "OPTIONS")
// perplexity recommends:
//staticRouter.PathPrefix("/").Handler(http.StripPrefix("/", customHandler))
// Replace your existing static route with this
// Create a dedicated file server for static files
fileServer := http.FileServer(http.Dir(staticPath))
// Register the static file handler with explicit path stripping
//staticRouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", staticFS))
baseRouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fileServer))
baseRouter.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Don't handle /static/ paths here
if strings.HasPrefix(r.URL.Path, "/static/") {
http.NotFound(w, r)
return
}
// For all other routes, serve index.html
indexPath := filepath.Join(staticPath, "index.html")
http.ServeFile(w, r, indexPath)
}))
// Apply CORS middleware
c := cors.New(cors.Options{
AllowedOrigins: origins,
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Authorization", "Content-Type"},
ExposedHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "ETag"},
AllowCredentials: true,
})
// Start the server with CORS middleware
fmt.Printf("Server listening on port %d\n", config.ListeningPort)
http.ListenAndServe(fmt.Sprintf(":%d", config.ListeningPort), c.Handler(baseRouter))
}