Skip to content

Instantly share code, notes, and snippets.

@scottcagno
Created August 8, 2022 19:17
Show Gist options
  • Select an option

  • Save scottcagno/35eb7ecce838b333dba2a2268f649ccb to your computer and use it in GitHub Desktop.

Select an option

Save scottcagno/35eb7ecce838b333dba2a2268f649ccb to your computer and use it in GitHub Desktop.
This is just a simple sample scratch multiplexer. It's fully working but has NO bells or anything.
package main
import (
"fmt"
"net/http"
)
func homeHandler() http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// implement handler logic here...
fmt.Fprintf(w, "Hello, world... this is my home page!!")
}
return http.HandlerFunc(fn)
}
func main() {
mux := NewMuxer()
mux.Register(http.MethodGet, "/home", homeHandler())
fmt.Println(mux)
http.ListenAndServe(":9000", mux)
}
type handler struct {
meth string
path string
http.Handler
}
type Muxer struct {
routes map[string][]handler
}
func NewMuxer() *Muxer {
return &Muxer{
routes: make(map[string][]handler),
}
}
func (m *Muxer) Register(meth, path string, hdlr http.Handler) {
// create and append a new handler to the handler slice on
// the correct method, and we ensure it's set it in the
// routes map.
m.routes[meth] = append(m.routes[meth], handler{
meth: meth,
path: path,
Handler: hdlr,
})
}
// ServeHTTP is what makes this work as a "multiplexer" because it
// is implementing the http.Handler interface. Every other handler
// calls ServeHTTP method of the handler below it at the end, so all
// webservers recognize and call ServeHTTP, even third party ones.
func (m *Muxer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// it should be noted that this is basically a bare-bones
// multiplexer example, and we could have all sorts of other
// things in here like a logger that prints stuff out and
// intelligent error templates that automatically get served
// up, instead of just simple http return values, etc.
// see if we have a route that matches the requested method
hs, found := m.routes[r.Method]
if !found {
// no method is registered that match, so we properly error
// out and return out of the function
code := http.StatusMethodNotAllowed
http.Error(w, http.StatusText(code), code)
return
}
// otherwise, we have found one or more handlers that match the
// requested method. now we have to check to see if any of them
// have a path that matches the requested path.
for _, h := range hs {
if h.path == r.URL.Path {
// we have a match (this is the part that can be wildly
// complicated depending on what you want to match, etc.)
// So we call the handler's ServeHTTP method and return.
h.ServeHTTP(w, r)
return
}
}
// if we get here, we have a method match, but no path matches,
// so we should return a not found error
code := http.StatusNotFound
http.Error(w, http.StatusText(code), code)
return
}
func (m *Muxer) String() string {
ss := fmt.Sprintf("routes:\n")
for method := range m.routes {
ss += fmt.Sprintf("\tmethod: %q\n", method)
for _, h := range m.routes[method] {
ss += fmt.Sprintf("\t\t%#v\n", h)
}
}
return ss
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment