Compare commits

...

2 commits

Author SHA1 Message Date
Lucas
07daead293 Replace deprecated rand.Seed with rand.New
Updates random number generation to use the modern approach with
rand.New(rand.NewSource()) instead of the deprecated rand.Seed().

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-14 02:31:35 +02:00
Lucas
0f18a44eb8 Format Go code with gofmt
Standardizes indentation from spaces to Go's canonical tab formatting.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-14 02:31:17 +02:00

394
main.go
View file

@ -1,74 +1,74 @@
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"time"
_ "modernc.org/sqlite"
"database/sql"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"time"
_ "modernc.org/sqlite"
)
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
ID int `json:"id"`
Name string `json:"name"`
}
type UserInfo struct {
Username string `json:"username"`
Name string `json:"name"`
Email string `json:"email"`
Groups string `json:"groups"`
Headers map[string]string `json:"headers"`
Username string `json:"username"`
Name string `json:"name"`
Email string `json:"email"`
Groups string `json:"groups"`
Headers map[string]string `json:"headers"`
}
var db *sql.DB
func initDB() {
var err error
db, err = sql.Open("sqlite", "items.db")
if err != nil {
log.Fatal("Failed to open database:", err)
}
createTable := `
var err error
db, err = sql.Open("sqlite", "items.db")
if err != nil {
log.Fatal("Failed to open database:", err)
}
createTable := `
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);`
_, err = db.Exec(createTable)
if err != nil {
log.Fatal("Failed to create table:", err)
}
_, err = db.Exec(createTable)
if err != nil {
log.Fatal("Failed to create table:", err)
}
}
func main() {
if len(os.Args) > 1 && os.Args[1] == "--watch" {
watchAndRestart()
return
}
// Initialize database
initDB()
defer db.Close()
// Your actual API
rand.Seed(time.Now().UnixNano())
http.HandleFunc("/randomnumber", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%d", rand.Intn(1000))
})
if len(os.Args) > 1 && os.Args[1] == "--watch" {
watchAndRestart()
return
}
// Initialize database
initDB()
defer db.Close()
// Your actual API
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
http.HandleFunc("/randomnumber", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%d", rng.Intn(1000))
})
http.HandleFunc("/slowtest", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(1 * time.Second)
fmt.Fprintf(w, "true")
time.Sleep(1 * time.Second)
fmt.Fprintf(w, "true")
})
http.HandleFunc("/welcome", func(w http.ResponseWriter, r *http.Request) {
@ -89,176 +89,176 @@ func main() {
// Items API endpoints
http.HandleFunc("/items", handleItems)
http.HandleFunc("/items/", handleItemDelete)
// Auth endpoints
http.HandleFunc("/auth/user", handleAuthUser)
log.Println("API running on :3847")
http.ListenAndServe("127.0.0.1:3847", nil)
log.Println("API running on :3847")
http.ListenAndServe("127.0.0.1:3847", nil)
}
func watchAndRestart() {
binaryPath, _ := os.Executable()
var cmd *exec.Cmd
start := func() {
if cmd != nil && cmd.Process != nil {
cmd.Process.Kill()
}
cmd = exec.Command(binaryPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
}
start() // Initial start
lastMod := getModTime(binaryPath)
for {
time.Sleep(1 * time.Second)
if mod := getModTime(binaryPath); mod.After(lastMod) {
log.Println("Binary changed, restarting...")
lastMod = mod
start()
}
}
binaryPath, _ := os.Executable()
var cmd *exec.Cmd
start := func() {
if cmd != nil && cmd.Process != nil {
cmd.Process.Kill()
}
cmd = exec.Command(binaryPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
}
start() // Initial start
lastMod := getModTime(binaryPath)
for {
time.Sleep(1 * time.Second)
if mod := getModTime(binaryPath); mod.After(lastMod) {
log.Println("Binary changed, restarting...")
lastMod = mod
start()
}
}
}
func getModTime(path string) time.Time {
info, _ := os.Stat(path)
return info.ModTime()
info, _ := os.Stat(path)
return info.ModTime()
}
func handleItems(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case "GET":
getItems(w, r)
case "POST":
createItem(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
}
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case "GET":
getItems(w, r)
case "POST":
createItem(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
}
}
func getItems(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query("SELECT id, name FROM items ORDER BY id")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to fetch items"})
return
}
defer rows.Close()
var items []Item
for rows.Next() {
var item Item
err := rows.Scan(&item.ID, &item.Name)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to scan items"})
return
}
items = append(items, item)
}
// Ensure we always return an array, even if empty
if items == nil {
items = []Item{}
}
json.NewEncoder(w).Encode(items)
rows, err := db.Query("SELECT id, name FROM items ORDER BY id")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to fetch items"})
return
}
defer rows.Close()
var items []Item
for rows.Next() {
var item Item
err := rows.Scan(&item.ID, &item.Name)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to scan items"})
return
}
items = append(items, item)
}
// Ensure we always return an array, even if empty
if items == nil {
items = []Item{}
}
json.NewEncoder(w).Encode(items)
}
func createItem(w http.ResponseWriter, r *http.Request) {
var item Item
err := json.NewDecoder(r.Body).Decode(&item)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid JSON"})
return
}
if item.Name == "" {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Name is required"})
return
}
result, err := db.Exec("INSERT INTO items (name) VALUES (?)", item.Name)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to create item"})
return
}
id, _ := result.LastInsertId()
item.ID = int(id)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(item)
var item Item
err := json.NewDecoder(r.Body).Decode(&item)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid JSON"})
return
}
if item.Name == "" {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Name is required"})
return
}
result, err := db.Exec("INSERT INTO items (name) VALUES (?)", item.Name)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to create item"})
return
}
id, _ := result.LastInsertId()
item.ID = int(id)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(item)
}
func handleItemDelete(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != "DELETE" {
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
return
}
// Extract ID from URL path /items/{id}
path := strings.TrimPrefix(r.URL.Path, "/items/")
id, err := strconv.Atoi(path)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid item ID"})
return
}
result, err := db.Exec("DELETE FROM items WHERE id = ?", id)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to delete item"})
return
}
rowsAffected, _ := result.RowsAffected()
if rowsAffected == 0 {
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{"error": "Item not found"})
return
}
json.NewEncoder(w).Encode(map[string]string{"message": "Item deleted successfully"})
w.Header().Set("Content-Type", "application/json")
if r.Method != "DELETE" {
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
return
}
// Extract ID from URL path /items/{id}
path := strings.TrimPrefix(r.URL.Path, "/items/")
id, err := strconv.Atoi(path)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid item ID"})
return
}
result, err := db.Exec("DELETE FROM items WHERE id = ?", id)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "Failed to delete item"})
return
}
rowsAffected, _ := result.RowsAffected()
if rowsAffected == 0 {
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{"error": "Item not found"})
return
}
json.NewEncoder(w).Encode(map[string]string{"message": "Item deleted successfully"})
}
func handleAuthUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
return
}
// Collect all headers for debugging
headers := make(map[string]string)
for name, values := range r.Header {
headers[name] = strings.Join(values, ", ")
}
// Extract common Authelia headers
userInfo := UserInfo{
Username: r.Header.Get("Remote-User"),
Name: r.Header.Get("Remote-Name"),
Email: r.Header.Get("Remote-Email"),
Groups: r.Header.Get("Remote-Groups"),
Headers: headers,
}
json.NewEncoder(w).Encode(userInfo)
w.Header().Set("Content-Type", "application/json")
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
return
}
// Collect all headers for debugging
headers := make(map[string]string)
for name, values := range r.Header {
headers[name] = strings.Join(values, ", ")
}
// Extract common Authelia headers
userInfo := UserInfo{
Username: r.Header.Get("Remote-User"),
Name: r.Header.Get("Remote-Name"),
Email: r.Header.Get("Remote-Email"),
Groups: r.Header.Get("Remote-Groups"),
Headers: headers,
}
json.NewEncoder(w).Encode(userInfo)
}