Skip to content
Snippets Groups Projects
Commit 05f102b5 authored by ale's avatar ale
Browse files

simplify the structure of the http server

parent a7208316
Branches
No related tags found
No related merge requests found
...@@ -111,10 +111,19 @@ func (h *HttpRedirector) serveSource(w http.ResponseWriter, r *http.Request) { ...@@ -111,10 +111,19 @@ func (h *HttpRedirector) serveSource(w http.ResponseWriter, r *http.Request) {
return return
} }
// Hijack the incoming connection. This is just so that we can // Hijack the incoming connection. This is necessary, rather
// reset the timeout on the underlying network connection // than using httputil.ReverseProxy, for two important
// (which we have no use for once the stream has been // reasons:
// established), but then we get to run the two-way proxy... //
// 1) So that we can reset the timeout on the underlying
// network connection (which we have no use for once the
// stream has been established).
//
// 2) Because streaming is still mostly a HTTP/1.0 world, the
// HTTP/1.1 features used by Go's net/http package (mostly the
// chunked encoding, I think) will apparently confuse clients
// and servers alike.
//
conn, _, err := w.(http.Hijacker).Hijack() conn, _, err := w.(http.Hijacker).Hijack()
if err != nil { if err != nil {
log.Printf("source: hijack failed: %v", err) log.Printf("source: hijack failed: %v", err)
...@@ -178,50 +187,52 @@ func (h *HttpRedirector) serveStatusPage(w http.ResponseWriter, r *http.Request) ...@@ -178,50 +187,52 @@ func (h *HttpRedirector) serveStatusPage(w http.ResponseWriter, r *http.Request)
w.Write(buf.Bytes()) w.Write(buf.Bytes())
} }
func (h *HttpRedirector) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "" || r.URL.Path == "/" {
// Serve the status page through a GZIPHandler. Binds
// to h using function closure.
handler := handlers.GZIPHandler(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.serveStatusPage(w, r)
}), nil)
handler.ServeHTTP(w, r)
} else if r.Method == "SOURCE" {
h.serveSource(w, r)
} else {
h.serveRelay(w, r)
}
}
// Run starts the HTTP server on the given addr. Does not return. // Run starts the HTTP server on the given addr. Does not return.
func (h *HttpRedirector) Run(addr, staticDir, templateDir string) { func (h *HttpRedirector) Run(addr, staticDir, templateDir string) {
h.template = template.Must( h.template = template.Must(
template.ParseGlob( template.ParseGlob(
filepath.Join(templateDir, "*.html"))) filepath.Join(templateDir, "*.html")))
// The purpose of the odd usage of GZIPHandler is to bypass it // Create our HTTP handler stack. Passes the /debug/ queries
// on SOURCE and m3u requests. May not be necessary though. // along to the global ServeMux (where moodules such as pprof
// install their handlers).
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc( mux.Handle(
"/static/", "/static/",
handlers.GZIPHandler( http.StripPrefix(
http.StripPrefix( "/static/",
"/static/", http.FileServer(http.Dir(staticDir))))
http.FileServer(http.Dir(staticDir))), mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
nil)) switch {
mux.Handle("/", h) case r.URL.Path == "" || r.URL.Path == "/":
h.serveStatusPage(w, r)
// It would be nice to add a logging handler on top of case strings.HasPrefix(r.URL.Path, "/debug/"):
// everything, but we would become unable to hijack the http.DefaultServeMux.ServeHTTP(w, r)
// connection on SOURCE requests... default:
// h.serveRelay(w, r)
//logopts := handlers.NewLogOptions(nil, handlers.Lshort) }
//logger := handlers.LogHandler(mux, logopts) })
// Add some handlers to support gzip-encoded responses and
// request logging.
wraph := handlers.GZIPHandler(mux, nil)
logopts := handlers.NewLogOptions(nil, handlers.Lshort)
wraph = handlers.LogHandler(wraph, logopts)
// Serve SOURCE requests bypassing the logging and gzip
// handlers: since they wrap the ResponseWriter, we would be
// unable to hijack the underlying connection for proxying.
rooth := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "SOURCE" {
h.serveSource(w, r)
} else {
wraph.ServeHTTP(w, r)
}
})
httpServer := &http.Server{ httpServer := &http.Server{
Addr: addr, Addr: addr,
Handler: mux, Handler: rooth,
ReadTimeout: 10 * time.Second, ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second,
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment