webscaffold/Application.go

104 lines
2.1 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"path/filepath"
"time"
"github.com/NYTimes/gziphandler"
"golang.org/x/crypto/acme/autocert"
)
const AppName = `webscaffold`
type WebSession struct {
LastRefreshTime time.Time
}
type Application struct {
c Config
webfile http.Handler
db *sql.DB
sessions map[string]WebSession
}
func (this *Application) Start() error {
log.Printf("Starting %s application...", AppName)
// Connect to DB
err := this.connectToDB()
if err != nil {
return err
}
// Resources
this.webfile = http.FileServer(http.Dir(this.c.WebrootDir))
// Set up HTTP server
if this.c.Autocert == "" {
log.Printf("Starting web server (HTTP on %s)...", this.c.ListenAddress)
return http.ListenAndServe(this.c.ListenAddress, this) // Plain HTTP
} else {
log.Printf("Starting web server (HTTPS as '%s' on :80 + :443)...", this.c.Autocert)
return http.Serve(autocert.NewListener(this.c.Autocert), this) // HTTPS
}
}
func (this *Application) respondWith(object interface{}, nerr netError) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { // curry over extra arity
if nerr != nil {
nerr.Respond(w)
return
}
// Plaintext response
// Buffer the resulting json data, so that we can determine the final size
jb, err := json.Marshal(object)
if err != nil {
systemError{err}.Respond(w)
return
}
w.Header().Set(`Content-Type`, `application/json`)
w.Header().Set(`Content-Length`, fmt.Sprintf("%d", len(jb)))
w.WriteHeader(200)
w.Write(jb)
}
}
func (this *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.Header.Set(`Server`, AppName+`/1.0`)
switch r.Method {
case "GET":
r.Header.Set(`X-Frame-Options`, `Deny`)
if r.URL.Path == `/` {
http.ServeFile(w, r, filepath.Join(this.c.WebrootDir, "index.html")) // n.b. no gzip
} else {
gziphandler.GzipHandler(this.webfile).ServeHTTP(w, r)
}
case "POST":
if r.URL.Path == `/api/v1/login` {
resp, err := this.apiLogin(r)
gziphandler.GzipHandler(this.respondWith(resp, err)).ServeHTTP(w, r)
} else {
http.Error(w, "not found", 404)
}
}
}