perkeep/server/go/webserver/webserver.go

83 lines
1.8 KiB
Go

package webserver
import (
"bufio"
"flag"
"http"
"log"
"net"
"os"
"strconv"
)
var Listen *string = flag.String("listen", "0.0.0.0:2856", "host:port to listen on, or :0 to auto-select")
type Server struct {
mux *http.ServeMux
}
func New() *Server {
return &Server{mux: http.NewServeMux()}
}
func (s *Server) HandleFunc(pattern string, fn func(http.ResponseWriter, *http.Request)) {
s.mux.HandleFunc(pattern, fn)
}
func (s *Server) Handle(pattern string, handler http.Handler) {
s.mux.Handle(pattern, handler)
}
func (s *Server) Serve() {
if os.Getenv("TESTING_PORT_WRITE_FD") == "" { // Don't make noise during unit tests
log.Printf("Starting to listen on http://%v/\n", *Listen)
}
listener, err := net.Listen("tcp", *Listen)
if err != nil {
log.Exitf("Failed to listen on %s: %v", *Listen, err)
}
go runTestHarnessIntegration(listener)
err = http.Serve(listener, s.mux)
if err != nil {
log.Printf("Error in http server: %v\n", err)
os.Exit(1)
}
}
func pipeFromEnvFd(env string) *os.File {
fdStr := os.Getenv(env)
if fdStr == "" {
return nil
}
fd, err := strconv.Atoi(fdStr)
if err != nil {
log.Exitf("Bogus test harness fd '%s': %v", fdStr, err)
}
return os.NewFile(fd, "testingpipe-" + env)
}
// Signals the test harness that we've started listening.
// TODO: write back the port number that we randomly selected?
// For now just writes back a single byte.
func runTestHarnessIntegration(listener net.Listener) {
writePipe := pipeFromEnvFd("TESTING_PORT_WRITE_FD")
readPipe := pipeFromEnvFd("TESTING_CONTROL_READ_FD")
if writePipe != nil {
writePipe.Write([]byte(listener.Addr().String() + "\n"))
}
if readPipe != nil {
bufr := bufio.NewReader(readPipe)
for {
line, err := bufr.ReadString('\n')
if err == os.EOF || line == "EXIT\n" {
os.Exit(0)
}
return
}
}
}