159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
func httpLog(r *http.Request) {
|
||
|
n := time.Now()
|
||
|
fmt.Printf("%s (%s) [%s] \"%s %s\" %03d\n",
|
||
|
r.RemoteAddr,
|
||
|
n.Format(time.RFC822Z),
|
||
|
r.Method,
|
||
|
r.URL.Path,
|
||
|
r.Proto,
|
||
|
r.ContentLength,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func makeAuth(d *Store) func(w http.ResponseWriter, r *http.Request) {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
_, err := authUserFromHeader(d, r)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusUnauthorized)
|
||
|
w.Write([]byte(`{"message": "Unauthorized"}`))
|
||
|
return
|
||
|
}
|
||
|
w.Header().Add("Content-type", "application/json")
|
||
|
w.WriteHeader(200)
|
||
|
w.Write([]byte(`{"authorized": "OK"}`))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeProgress(d *Store) func(w http.ResponseWriter, r *http.Request) {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
u, err := authUserFromHeader(d, r)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusUnauthorized)
|
||
|
w.Write([]byte(`{"message": "Unauthorized"}`))
|
||
|
return
|
||
|
}
|
||
|
prog := Progress{}
|
||
|
dec := json.NewDecoder(r.Body)
|
||
|
err = dec.Decode(&prog)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
http.Error(w, "invalid document", http.StatusNotFound)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
prog.User = *u
|
||
|
prog.Save(d)
|
||
|
|
||
|
w.Header().Add("Content-type", "application/json")
|
||
|
w.WriteHeader(200)
|
||
|
w.Write([]byte(fmt.Sprintf(`{"document": "%s", "timestamp": "%d"}`, prog.Document, prog.Timestamp)))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeCreate(reg *bool, d *Store) func(w http.ResponseWriter, r *http.Request) {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
if !*reg {
|
||
|
w.WriteHeader(http.StatusUnauthorized)
|
||
|
w.Write([]byte(`{"message": "Registration disabled"}`))
|
||
|
return
|
||
|
}
|
||
|
u := User{}
|
||
|
|
||
|
dec := json.NewDecoder(r.Body)
|
||
|
err := dec.Decode(&u)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
_, err = d.Get(u.Key())
|
||
|
if err != nil {
|
||
|
d.Set(u.Key(), u.Password)
|
||
|
} else {
|
||
|
log.Println(err)
|
||
|
http.Error(w, "Username is already registered", http.StatusPaymentRequired)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
w.Header().Add("Content-type", "application/json")
|
||
|
w.WriteHeader(201)
|
||
|
w.Write(u.Created())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeDocSync(d *Store) func(w http.ResponseWriter, r *http.Request) {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
|
||
|
// TODO: I have no idea why this PathValue returns "".. dirty hack
|
||
|
// to grab it from the URL anyway :(
|
||
|
doc := r.PathValue("document")
|
||
|
if doc == "" {
|
||
|
parts := strings.Split(r.URL.String(), "/")
|
||
|
doc = parts[len(parts)-1]
|
||
|
if doc == "" {
|
||
|
http.Error(w, "Invalid Request", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
u, err := authUserFromHeader(d, r)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusUnauthorized)
|
||
|
w.Write([]byte(`{"message": "Unauthorized"}`))
|
||
|
return
|
||
|
}
|
||
|
prog := Progress{
|
||
|
Document: doc,
|
||
|
User: *u,
|
||
|
}
|
||
|
|
||
|
err = prog.Get(d)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
b, err := json.Marshal(prog)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
w.Header().Add("Content-type", "application/json")
|
||
|
w.WriteHeader(200)
|
||
|
w.Write(b)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
w.Header().Add("Content-type", "application/json")
|
||
|
w.WriteHeader(200)
|
||
|
w.Write([]byte(`{"state": "OK"}`))
|
||
|
}
|
||
|
|
||
|
func slashHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
httpLog(r)
|
||
|
w.Header().Add("Content-type", "text/plain")
|
||
|
w.WriteHeader(200)
|
||
|
w.Write([]byte(`kogs: koreader sync server`))
|
||
|
}
|