github.com/gocaveman/caveman@v0.0.0-20191211162744-0ddf99dbdf6e/webutil/http-server.go (about) 1 package webutil 2 3 import ( 4 "context" 5 "log" 6 "net/http" 7 "os" 8 "path" 9 "sync" 10 ) 11 12 // hm, this becomes circular... blarg... maybe it belongs in handlerregistry... 13 // func init() { 14 // handlerregistry.MustRegister(handlerregistry.SeqSetup, "RequestContextHandler", NewRequestContextHandler()) 15 // } 16 17 // StartHTTPServer is a very simple helper that starts an http.Server. 18 // The WaitGroup.Add(1) and Done are called at the appropriate times 19 // and logging is done. This is just to help make projects' main.go 20 // more concise and easier to read. 21 func StartHTTPServer(s *http.Server, wg *sync.WaitGroup) { 22 wg.Add(1) 23 log.Printf("Listening for HTTP at %q", s.Addr) 24 go func() { 25 defer wg.Done() 26 err := s.ListenAndServe() 27 if err != nil { 28 log.Printf("Error from HTTP server: %v", err) 29 } 30 }() 31 } 32 33 // NewRequestContextHandler returns a handler that sets "http.Request" 34 // in the context. Intended for use in HTML templates for things like 35 // getting URL params. 36 func NewRequestContextHandler() ChainHandler { 37 return ChainHandlerFunc(func(w http.ResponseWriter, r *http.Request) (wnext http.ResponseWriter, rnext *http.Request) { 38 return w, r.WithContext(context.WithValue(r.Context(), "http.Request", r)) 39 }) 40 } 41 42 // NewStaticFileHandler returns a handler similar to the stdlib FileServer. 43 // The primary difference is that instead of returning an error if the file 44 // is not found it will instead not serve anything (so the request will 45 // fall through to the next handler in the chain). It also sets the cache-control 46 // header (only if not already set) to tell the browser to not cache if no 47 // query string or to cache for one week if query string. Provides an easy way 48 // to control which files are cached by the browser with the default to not cache 49 // them. This handler will ignore directories and take no action if one is found. 50 func NewStaticFileHandler(fs http.FileSystem) http.Handler { 51 52 fsh := http.FileServer(fs) 53 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 54 p := path.Clean("/" + r.URL.Path) 55 f, err := fs.Open(p) 56 if err == nil { 57 defer f.Close() 58 st, err := f.Stat() 59 if err != nil { 60 HTTPError(w, r, err, "Error inspecting file.", 500) 61 return 62 } 63 if st.IsDir() { 64 return 65 } 66 67 cc := w.Header().Get("cache-control") 68 if cc == "" { 69 if r.URL.RawQuery == "" { 70 w.Header().Set("cache-control", "no-cache") 71 } else { 72 w.Header().Set("cache-control", "max-age=604800") 73 } 74 } 75 76 fsh.ServeHTTP(w, r) 77 } else { 78 // differentiate here between a file that doesn't exist an something else wrong with the filesystem 79 if !os.IsNotExist(err) { 80 HTTPError(w, r, err, "Error serving file.", 500) 81 return 82 } 83 } 84 }) 85 86 }