You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.0 KiB
Go

package bg
import (
"fmt"
"log"
"net/http"
"sync/atomic"
"github.com/jordanorelli/dws/events"
)
type server struct {
port int
fs http.Handler
out chan events.BackgroundEvent
}
func (s *server) listen() {
addr := fmt.Sprintf("0.0.0.0:%d", s.port)
log.Printf("server listening on addr: %s\n", addr)
h := &eventEmittingHandler{
wrapped: s,
out: s.out,
}
if err := http.ListenAndServe(addr, h); err != nil {
panic(err)
}
}
func (s *server) setRoot(path string) {
log.Printf("server setting root to %s\n", path)
s.fs = http.FileServer(http.Dir(path))
}
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if s.fs == nil {
writeNotInitializedResponse(w)
return
}
s.fs.ServeHTTP(w, r)
}
func writeNotInitializedResponse(w http.ResponseWriter) {
w.WriteHeader(500)
fmt.Fprintln(w, "no root directory selected")
}
// trackginWriter is an http.ResponseWriter that tracks the number of bytes
// sent and the status sent
type trackingWriter struct {
http.ResponseWriter
status int // last http status written
wrote int // total number of bytes written
}
func (t *trackingWriter) WriteHeader(status int) {
t.ResponseWriter.WriteHeader(status)
t.status = status
}
func (t *trackingWriter) Write(b []byte) (int, error) {
n, err := t.ResponseWriter.Write(b)
if t.status == 0 {
t.status = 200
}
t.wrote += n
return n, err
}
// eventEmittingHandler is an http.Handler that emits events on an event
// channel to report on requests and responses.
type eventEmittingHandler struct {
wrapped http.Handler
out chan events.BackgroundEvent
count uint32
}
func (h *eventEmittingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
id := int(h.nextCount())
h.out <- events.BeginRequestEvent{
Seq: id,
Path: r.URL.Path,
}
tw := &trackingWriter{ResponseWriter: w}
h.wrapped.ServeHTTP(tw, r)
h.out <- events.EndRequestEvent{
Seq: id,
Status: tw.status,
Bytes: tw.wrote,
}
}
func (h *eventEmittingHandler) nextCount() uint32 {
return atomic.AddUint32(&h.count, 1)
}