NoteServer/main.go
2023-08-17 22:36:17 +02:00

141 lines
3.0 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"io"
"log"
"net/http"
_ "github.com/mattn/go-sqlite3"
)
var db *sql.DB
type Note struct {
Id int64 `json:"id"`
Content string `json:"content"`
}
func httpError(err error, statusCode int, message string, w http.ResponseWriter) bool {
if err != nil {
w.WriteHeader(statusCode)
io.WriteString(w, message)
return true
}
return false
}
func getNotes(w http.ResponseWriter, req *http.Request) {
res, err := db.Query(`SELECT Id, Content FROM Notes`)
if httpError(err, http.StatusInternalServerError, "Failed to load notes", w) {
return
}
defer res.Close()
var notes []Note = []Note{}
for res.Next() {
if httpError(res.Err(), http.StatusInternalServerError, "Failed to load notes", w) {
return
}
var note Note
res.Scan(&note.Id, &note.Content)
notes = append(notes, note)
}
json, err := json.Marshal(notes)
if httpError(err, http.StatusInternalServerError, "Failed to create JSON", w) {
return
}
w.Write(json)
}
func postNotes(w http.ResponseWriter, req *http.Request) {
data, err := io.ReadAll(req.Body)
if httpError(err, http.StatusBadRequest, "Failed to read data", w) {
return
}
var note Note
err = json.Unmarshal(data, &note)
if httpError(err, http.StatusBadRequest, "Invalid request", w) {
return
}
if len(note.Content) == 0 {
w.WriteHeader(http.StatusBadRequest)
io.WriteString(w, "Missing note content")
return
}
stmt, err := db.Prepare(`INSERT INTO Notes(Content) VALUES(?) RETURNING Id`)
if httpError(err, http.StatusInternalServerError, "Failed to store note", w) {
return
}
defer stmt.Close()
res := stmt.QueryRow(note.Content)
err = res.Scan(&note.Id)
if httpError(err, http.StatusInternalServerError, "Failed to store note", w) {
return
}
json, err := json.Marshal(note)
if httpError(err, http.StatusInternalServerError, "Failed to create JSON", w) {
return
}
w.WriteHeader(http.StatusCreated)
w.Write(json)
}
func putNote(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPut {
w.WriteHeader(http.StatusBadRequest)
io.WriteString(w, "Invalid method")
return
}
}
func handleNotes(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
getNotes(w, req)
case http.MethodPost:
postNotes(w, req)
default:
w.WriteHeader(http.StatusBadRequest)
io.WriteString(w, "Invalid method")
}
}
func main() {
log.Println("Starting NoteServer")
log.Println("Loading database")
var err error
db, err = sql.Open("sqlite3", "./notes.sqlite")
if err != nil {
log.Fatalln("Failed to load db:", err)
}
log.Println("Creating missing tables")
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS Notes(Id INTEGER PRIMARY KEY AUTOINCREMENT, Content TEXT)`)
if err != nil {
log.Fatalln("Failed to create table:", err)
}
log.Println("Listening")
http.HandleFunc("/api/notes", handleNotes)
http.HandleFunc("/api/note/", putNote)
http.ListenAndServe(":8080", nil) // TODO: configure host, port, TLS
}