package main import ( "context" // "encoding/json" "fmt" //"io" "log" "net/http" "os" "os/signal" //"strings" "sync" "time" "github.com/gorilla/mux" "github.com/joho/godotenv" "github.com/neo4j/neo4j-go-driver/v5/neo4j" ) func send_error(w http.ResponseWriter, json []byte) { w.WriteHeader(http.StatusBadRequest) w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, string(json)) } func send_response(w http.ResponseWriter, json []byte) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, string(json)) } func serve() { // TODO: Authenticate user credentials to verify they are allowed to even access var wg sync.WaitGroup driver_ctx := context.Background() driver, err := neo4j.NewDriverWithContext(os.Getenv("NEO4J_BOLT"), neo4j.BasicAuth("neo4j", os.Getenv("NEO4J_PASSWORD"), "")) if err != nil { panic(err) } defer driver.Close(driver_ctx) err = driver.VerifyConnectivity(driver_ctx) if err != nil { log.Println("Error connecting to neo4j.") panic(err) } fmt.Println("neo4j connection established.") rsrc_endpoints := []string{ "/auth", "/users", "/users", "/users/{user_id}", "/users/{user_id}", "/users/{user_id}", "/users/{user_id}/posts", "/users/{user_id}/spaces", "/spaces", "/spaces", "/spaces/{space_id}", //"/spaces/{space_id}", "/spaces/{space_id}", "/spaces/{space_id}", "/spaces/{space_id}/users", "/spaces/{space_id}/posts", "/posts", "/posts", "/posts/{post_id}", "/posts/{post_id}", "/posts/{post_id}", } methods := []string{ http.MethodPost, http.MethodPost, http.MethodGet, http.MethodGet, http.MethodPatch, http.MethodDelete, http.MethodGet, http.MethodGet, http.MethodPost, http.MethodGet, http.MethodGet, //http.MethodPost, http.MethodPatch, http.MethodDelete, http.MethodGet, http.MethodGet, http.MethodPost, http.MethodGet, http.MethodGet, http.MethodPatch, http.MethodDelete, } functions := []func(http.ResponseWriter, *http.Request){ auth_user(driver, driver_ctx), create_new_user(driver, driver_ctx), retrieve_all_users(driver, driver_ctx), retrieve_user(driver, driver_ctx), update_user(driver, driver_ctx), delete_user(driver, driver_ctx), retrieve_users_posts(driver, driver_ctx), retrieve_users_spaces(driver, driver_ctx), create_new_space(driver, driver_ctx), retrieve_all_spaces(driver, driver_ctx), retrieve_space(driver, driver_ctx), //auth_user_in_space(driver, driver_ctx), update_space(driver, driver_ctx), delete_space(driver, driver_ctx), retrieve_spaces_users(driver, driver_ctx), retrieve_spaces_posts(driver, driver_ctx), create_new_post(driver, driver_ctx), retrieve_all_posts(driver, driver_ctx), retrieve_post(driver, driver_ctx), update_post(driver, driver_ctx), delete_post(driver, driver_ctx), } r := mux.NewRouter() ServeApi(r, "api", rsrc_endpoints, methods, functions, "7477") log.Println("API routes configured with prefix", "/api") addr := "0.0.0.0:7476" srv := &http.Server{ Addr: addr, WriteTimeout: time.Second * 15, ReadTimeout: time.Second * 15, IdleTimeout: time.Second * 60, Handler: r, } // Run our server in a goroutine so that it doesn't block. wg.Add(1) go func() { defer wg.Done() if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Println(err) } }() log.Println("Router is running on port 7476") c := make(chan os.Signal, 1) // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+Shift+C) signal.Notify(c, os.Interrupt) // Block until we receive our signal. <-c // Create a deadline to wait for. ctx, cancel := context.WithTimeout(context.Background(), time.Duration(30)) defer cancel() // Doesn't block if no connections, but will otherwise wait // until the timeout deadline. srv.Shutdown(ctx) // Optionally, you could run srv.Shutdown in a goroutine and block on // <-ctx.Done() if your application should wait for other services // to finalize based on context cancellation. log.Println("shutting down") wg.Wait() os.Exit(0) } func main() { err := godotenv.Load("../.env") if err != nil { log.Println("Error loading .env.") return } serve() }