Compare commits
2 commits
e95f47874a
...
07daead293
Author | SHA1 | Date | |
---|---|---|---|
![]() |
07daead293 | ||
![]() |
0f18a44eb8 |
1 changed files with 197 additions and 197 deletions
394
main.go
394
main.go
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue