continuserv: serve multiple paths

pull/977/head
Daniel Wagner-Hall 9 years ago
parent b946d39886
commit 1ce3357927

@ -26,7 +26,7 @@ var (
port = flag.Int("port", 8000, "Port on which to serve HTTP") port = flag.Int("port", 8000, "Port on which to serve HTTP")
mu sync.Mutex // Prevent multiple updates in parallel. mu sync.Mutex // Prevent multiple updates in parallel.
toServe atomic.Value // Always contains valid []byte to serve. May be stale unless wg is zero. toServe atomic.Value // Always contains a bytesOrErr. May be stale unless wg is zero.
wgMu sync.Mutex // Prevent multiple calls to wg.Wait() or wg.Add(positive number) in parallel. wgMu sync.Mutex // Prevent multiple calls to wg.Wait() or wg.Add(positive number) in parallel.
wg sync.WaitGroup // Indicates how many updates are pending. wg sync.WaitGroup // Indicates how many updates are pending.
@ -116,14 +116,29 @@ func serve(w http.ResponseWriter, req *http.Request) {
wgMu.Lock() wgMu.Lock()
wg.Wait() wg.Wait()
wgMu.Unlock() wgMu.Unlock()
b := toServe.Load().(bytesOrErr)
if b.err != nil { file := req.URL.Path
if file[0] == '/' {
file = file[1:]
}
if file == "" {
file = "index.html"
}
m := toServe.Load().(bytesOrErr)
if m.err != nil {
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(b.err.Error())) w.Write([]byte(m.err.Error()))
} else { return
}
b, ok := m.bytes[file]
if ok {
w.Header().Set("Content-Type", "text/html") w.Header().Set("Content-Type", "text/html")
w.Write([]byte(b.bytes)) w.Write([]byte(b))
return
} }
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(404)
w.Write([]byte("Not found"))
} }
func populateOnce(dir string) { func populateOnce(dir string) {
@ -139,12 +154,21 @@ func populateOnce(dir string) {
toServe.Store(bytesOrErr{nil, fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())}) toServe.Store(bytesOrErr{nil, fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())})
return return
} }
specBytes, err := ioutil.ReadFile(path.Join(dir, "scripts", "gen", "specification.html")) fis, err := ioutil.ReadDir(path.Join(dir, "scripts", "gen"))
if err != nil {
toServe.Store(bytesOrErr{nil, err})
return
}
files := make(map[string][]byte)
for _, fi := range fis {
bytes, err := ioutil.ReadFile(path.Join(dir, "scripts", "gen", fi.Name()))
if err != nil { if err != nil {
toServe.Store(bytesOrErr{nil, fmt.Errorf("error reading spec: %v", err)}) toServe.Store(bytesOrErr{nil, fmt.Errorf("error reading spec: %v", err)})
return return
} }
toServe.Store(bytesOrErr{specBytes, nil}) files[fi.Name()] = bytes
}
toServe.Store(bytesOrErr{files, nil})
} }
func doPopulate(ch chan struct{}, dir string) { func doPopulate(ch chan struct{}, dir string) {
@ -173,6 +197,6 @@ func exists(path string) bool {
} }
type bytesOrErr struct { type bytesOrErr struct {
bytes []byte bytes map[string][]byte // filename -> contents
err error err error
} }

Loading…
Cancel
Save