main.go (3726B)
1 package main 2 3 import ( 4 "database/sql" 5 "fmt" 6 "html/template" 7 "log" 8 "net/http" 9 "os" 10 "time" 11 12 _ "github.com/ncruces/go-sqlite3/driver" 13 _ "github.com/ncruces/go-sqlite3/embed" 14 15 "github.com/pelletier/go-toml/v2" 16 ) 17 18 type Config struct { 19 GetPath string 20 PostPath string 21 DBFile string 22 TemplateFile string 23 } 24 25 type Message struct { 26 Name string 27 Website string 28 Email string 29 Message string 30 Time time.Time 31 } 32 33 var cfg Config 34 var database *sql.DB 35 var message_template string 36 37 func GetGuestbook(w http.ResponseWriter, r *http.Request) { 38 39 if r.Method != "GET" { 40 http.Error(w, "Unsupported method", http.StatusBadRequest) 41 return 42 } 43 44 // Pull database contents 45 46 rows, err := database.Query("SELECT name,website,email,message,time FROM Messages ORDER BY time DESC;") 47 48 if err != nil { 49 http.Error(w, "Error reading SQL database", http.StatusInternalServerError) 50 log.Print(err) 51 return 52 } 53 54 defer rows.Close() 55 56 messages := []*Message{} 57 58 for rows.Next() { 59 var m Message 60 err := rows.Scan( 61 &m.Name, 62 &m.Website, 63 &m.Email, 64 &m.Message, 65 &m.Time, 66 ) 67 68 if err != nil { 69 http.Error(w, "Error reading SQL database", http.StatusInternalServerError) 70 log.Print(err) 71 return 72 } 73 74 messages = append(messages, &m) 75 } 76 77 rows.Close() 78 79 err = rows.Err() 80 if err != nil { 81 http.Error(w, "Error reading SQL database", http.StatusInternalServerError) 82 log.Print(err) 83 return 84 } 85 86 // Apply guestbook template 87 88 tmpl, err := template.New("guestbook").Parse(message_template) 89 if err != nil { 90 http.Error(w, "Error parsing template", http.StatusInternalServerError) 91 log.Print(err) 92 return 93 } 94 err = tmpl.Execute(w, messages) 95 if err != nil { 96 http.Error(w, "Error executing template", http.StatusInternalServerError) 97 log.Print(err) 98 return 99 } 100 } 101 102 func PostToGuestbook(w http.ResponseWriter, r *http.Request) { 103 104 if r.Method != "POST" { 105 http.Error(w, "Unsupported method", http.StatusBadRequest) 106 return 107 } 108 109 err := r.ParseForm() 110 if err != nil { 111 http.Error(w, "Error parsing form response", http.StatusBadRequest) 112 log.Print(err) 113 return 114 } 115 116 name := r.PostForm.Get("name") 117 email := r.PostForm.Get("email") 118 website := r.PostForm.Get("website") 119 message := r.PostForm.Get("message") 120 121 stmt, err := database.Prepare("INSERT INTO Messages (name, email, website, message) VALUES (?, ?, ?, ?)") 122 if err != nil { 123 http.Error(w, "Error accessing database", http.StatusInternalServerError) 124 log.Print(err) 125 return 126 } 127 defer stmt.Close() 128 129 _, err = stmt.Exec(name, email, website, message) 130 if err != nil { 131 http.Error(w, "Error accessing database", http.StatusInternalServerError) 132 log.Print(err) 133 return 134 } 135 } 136 137 func main() { 138 139 var err error 140 141 config_str, err := os.ReadFile("config.toml") 142 if err != nil { 143 log.Fatal(err) 144 } 145 err = toml.Unmarshal(config_str, &cfg) 146 if err != nil { 147 log.Fatal(err) 148 } 149 150 database, err = sql.Open("sqlite3", cfg.DBFile) 151 152 if err != nil { 153 log.Fatal(err) 154 } 155 156 err = database.Ping() 157 if err != nil { 158 log.Fatal(err) 159 } 160 161 _, table_check := database.Query("SELECT * FROM Messages;") 162 163 if table_check != nil { 164 _, err = database.Exec(` 165 CREATE TABLE Messages ( 166 name VARCHAR(256) NOT NULL, 167 website VARCHAR(256), 168 email VARCHAR(256), 169 message VARCHAR(4096) NOT NULL, 170 time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL 171 ) 172 `) 173 if err != nil { 174 log.Fatal(err) 175 } 176 } 177 178 message_template_bytes, err := os.ReadFile(cfg.TemplateFile) 179 if err != nil { 180 log.Fatal(err) 181 } 182 message_template = string(message_template_bytes) 183 184 http.HandleFunc(cfg.GetPath, GetGuestbook) 185 http.HandleFunc(cfg.PostPath, PostToGuestbook) 186 187 fmt.Println("Starting server at port 48378") 188 if err := http.ListenAndServe(":48378", nil); err != nil { 189 log.Fatal(err) 190 } 191 }