webcmd/App.go

100 lines
2.0 KiB
Go

package webcmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"regexp"
"sync"
)
var APP_VERSION string = "x.x.x" // Overridden by makefile
type App struct {
cfg AppConfig
rxTaskInfo *regexp.Regexp
tasksMtx sync.RWMutex
tasks map[string]Task
}
func NewApp(configPath string) (*App, error) {
confBytes, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("Couldn't open configuration file '%s': %s", configPath, err.Error())
}
cfg := AppConfig{}
err = json.Unmarshal(confBytes, &cfg)
if err != nil {
return nil, fmt.Errorf("Invalid configuration file: %s", err.Error())
}
return NewAppFromConfig(cfg), nil
}
func NewAppFromConfig(cfg AppConfig) *App {
return &App{
cfg: cfg,
rxTaskInfo: regexp.MustCompile(`^/task/([A-Z0-9]+)$`),
tasks: make(map[string]Task),
}
}
func (this *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", "webcmd/"+APP_VERSION)
if r.Method == "GET" {
if r.URL.Path == "/" {
this.Serve_Homepage(w)
} else if r.URL.Path == "/style.css" {
this.Serve_StyleCSS(w)
} else if r.URL.Path == "/tasks" {
this.Serve_Tasks(w)
} else if matches := this.rxTaskInfo.FindStringSubmatch(r.URL.Path); len(matches) == 2 {
this.Serve_TaskInfo(w, matches[1])
} else {
http.Error(w, "No matching route for request", 404)
}
} else if r.Method == "POST" {
if r.URL.Path == "/x-new-task" {
this.Action_NewTask(w, r)
} else if r.URL.Path == "/x-abandon-task" {
this.Action_AbandonTask(w, r)
} else if r.URL.Path == "/x-clear-completed-tasks" {
this.Action_ClearCompleted(w, r)
} else {
http.Error(w, "No matching route for request", 404)
}
} else {
http.Error(w, "Invalid method", 400)
}
}
func (this *App) Run() {
mux := http.NewServeMux()
mux.Handle("/", this)
log.Printf("Listening on '%s'...", this.cfg.ListenAddress)
err := http.ListenAndServe(this.cfg.ListenAddress, mux)
if err != nil {
log.Fatalf("Network error: %s", err.Error())
}
}