Rename Responder to Handler

This commit is contained in:
Adnan Maolood 2021-02-08 12:50:50 -05:00
parent 29f2b3738d
commit 7910ed433b
3 changed files with 48 additions and 41 deletions

9
fs.go
View File

@ -13,11 +13,12 @@ func init() {
mime.AddExtensionType(".gemini", "text/gemini") mime.AddExtensionType(".gemini", "text/gemini")
} }
// FileServer takes a filesystem and returns a Responder which uses that filesystem. // FileServer returns a handler that serves Gemini requests with the contents
// The returned Responder cleans paths before handling them. // of the file system rooted at root.
// The returned handler cleans paths before handling them.
// //
// TODO: Use io/fs.FS when available. // TODO: Use io/fs.FS when available.
func FileServer(fsys FS) Responder { func FileServer(fsys FS) Handler {
return fsHandler{fsys} return fsHandler{fsys}
} }
@ -25,7 +26,7 @@ type fsHandler struct {
FS FS
} }
func (fsh fsHandler) Respond(w *ResponseWriter, r *Request) { func (fsh fsHandler) ServeGemini(w *ResponseWriter, r *Request) {
p := path.Clean(r.URL.Path) p := path.Clean(r.URL.Path)
f, err := fsh.Open(p) f, err := fsh.Open(p)
if err != nil { if err != nil {

28
mux.go
View File

@ -50,7 +50,7 @@ type ServeMux struct {
} }
type muxEntry struct { type muxEntry struct {
r Responder r Handler
pattern string pattern string
} }
@ -78,7 +78,7 @@ func cleanPath(p string) string {
// Find a handler on a handler map given a path string. // Find a handler on a handler map given a path string.
// Most-specific (longest) pattern wins. // Most-specific (longest) pattern wins.
func (mux *ServeMux) match(path string) Responder { func (mux *ServeMux) match(path string) Handler {
// Check for exact match first. // Check for exact match first.
v, ok := mux.m[path] v, ok := mux.m[path]
if ok { if ok {
@ -130,9 +130,9 @@ func (mux *ServeMux) shouldRedirectRLocked(path string) bool {
return false return false
} }
// Respond dispatches the request to the responder whose // ServeGemini dispatches the request to the handler whose
// pattern most closely matches the request URL. // pattern most closely matches the request URL.
func (mux *ServeMux) Respond(w *ResponseWriter, r *Request) { func (mux *ServeMux) ServeGemini(w *ResponseWriter, r *Request) {
path := cleanPath(r.URL.Path) path := cleanPath(r.URL.Path)
// If the given path is /tree and its handler is not registered, // If the given path is /tree and its handler is not registered,
@ -157,19 +157,19 @@ func (mux *ServeMux) Respond(w *ResponseWriter, r *Request) {
w.Status(StatusNotFound) w.Status(StatusNotFound)
return return
} }
resp.Respond(w, r) resp.ServeGemini(w, r)
} }
// Handle registers the responder for the given pattern. // Handle registers the handler for the given pattern.
// If a responder already exists for pattern, Handle panics. // If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, responder Responder) { func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock() mux.mu.Lock()
defer mux.mu.Unlock() defer mux.mu.Unlock()
if pattern == "" { if pattern == "" {
panic("gemini: invalid pattern") panic("gemini: invalid pattern")
} }
if responder == nil { if handler == nil {
panic("gemini: nil responder") panic("gemini: nil responder")
} }
if _, exist := mux.m[pattern]; exist { if _, exist := mux.m[pattern]; exist {
@ -179,7 +179,7 @@ func (mux *ServeMux) Handle(pattern string, responder Responder) {
if mux.m == nil { if mux.m == nil {
mux.m = make(map[string]muxEntry) mux.m = make(map[string]muxEntry)
} }
e := muxEntry{responder, pattern} e := muxEntry{handler, pattern}
mux.m[pattern] = e mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' { if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e) mux.es = appendSorted(mux.es, e)
@ -201,10 +201,10 @@ func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
return es return es
} }
// HandleFunc registers the responder function for the given pattern. // HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, responder func(*ResponseWriter, *Request)) { func (mux *ServeMux) HandleFunc(pattern string, handler func(*ResponseWriter, *Request)) {
if responder == nil { if handler == nil {
panic("gemini: nil responder") panic("gemini: nil responder")
} }
mux.Handle(pattern, ResponderFunc(responder)) mux.Handle(pattern, HandlerFunc(handler))
} }

View File

@ -37,35 +37,36 @@ type Server struct {
ErrorLog *log.Logger ErrorLog *log.Logger
// registered responders // registered responders
responders map[responderKey]Responder responders map[handlerKey]Handler
hosts map[string]bool hosts map[string]bool
} }
type responderKey struct { type handlerKey struct {
scheme string scheme string
hostname string hostname string
} }
// Handle registers a responder for the given pattern. // Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
// //
// The pattern must be in the form of "hostname" or "scheme://hostname". // The pattern must be in the form of "hostname" or "scheme://hostname".
// If no scheme is specified, a scheme of "gemini://" is implied. // If no scheme is specified, a scheme of "gemini://" is implied.
// Wildcard patterns are supported (e.g. "*.example.com"). // Wildcard patterns are supported (e.g. "*.example.com").
// To handle any hostname, use the wildcard pattern "*". // To handle any hostname, use the wildcard pattern "*".
func (s *Server) Handle(pattern string, responder Responder) { func (s *Server) Handle(pattern string, handler Handler) {
if pattern == "" { if pattern == "" {
panic("gemini: invalid pattern") panic("gemini: invalid pattern")
} }
if responder == nil { if handler == nil {
panic("gemini: nil responder") panic("gemini: nil responder")
} }
if s.responders == nil { if s.responders == nil {
s.responders = map[responderKey]Responder{} s.responders = map[handlerKey]Handler{}
s.hosts = map[string]bool{} s.hosts = map[string]bool{}
} }
split := strings.SplitN(pattern, "://", 2) split := strings.SplitN(pattern, "://", 2)
var key responderKey var key handlerKey
if len(split) == 2 { if len(split) == 2 {
key.scheme = split[0] key.scheme = split[0]
key.hostname = split[1] key.hostname = split[1]
@ -77,13 +78,13 @@ func (s *Server) Handle(pattern string, responder Responder) {
if _, ok := s.responders[key]; ok { if _, ok := s.responders[key]; ok {
panic("gemini: multiple registrations for " + pattern) panic("gemini: multiple registrations for " + pattern)
} }
s.responders[key] = responder s.responders[key] = handler
s.hosts[key.hostname] = true s.hosts[key.hostname] = true
} }
// HandleFunc registers a responder function for the given pattern. // HandleFunc registers the handler function for the given pattern.
func (s *Server) HandleFunc(pattern string, responder func(*ResponseWriter, *Request)) { func (s *Server) HandleFunc(pattern string, handler func(*ResponseWriter, *Request)) {
s.Handle(pattern, ResponderFunc(responder)) s.Handle(pattern, HandlerFunc(handler))
} }
// ListenAndServe listens for requests at the server's configured address. // ListenAndServe listens for requests at the server's configured address.
@ -225,20 +226,20 @@ func (s *Server) respond(conn net.Conn) {
return return
} }
resp.Respond(w, req) resp.ServeGemini(w, req)
} }
func (s *Server) responder(r *Request) Responder { func (s *Server) responder(r *Request) Handler {
if h, ok := s.responders[responderKey{r.URL.Scheme, r.URL.Hostname()}]; ok { if h, ok := s.responders[handlerKey{r.URL.Scheme, r.URL.Hostname()}]; ok {
return h return h
} }
wildcard := strings.SplitN(r.URL.Hostname(), ".", 2) wildcard := strings.SplitN(r.URL.Hostname(), ".", 2)
if len(wildcard) == 2 { if len(wildcard) == 2 {
if h, ok := s.responders[responderKey{r.URL.Scheme, "*." + wildcard[1]}]; ok { if h, ok := s.responders[handlerKey{r.URL.Scheme, "*." + wildcard[1]}]; ok {
return h return h
} }
} }
if h, ok := s.responders[responderKey{r.URL.Scheme, "*"}]; ok { if h, ok := s.responders[handlerKey{r.URL.Scheme, "*"}]; ok {
return h return h
} }
return nil return nil
@ -252,15 +253,20 @@ func (s *Server) logf(format string, args ...interface{}) {
} }
} }
// A Responder responds to a Gemini request. // A Handler responds to a Gemini request.
type Responder interface { //
// Respond accepts a Request and constructs a Response. // ServeGemini should write the response header and data to the ResponseWriter
Respond(*ResponseWriter, *Request) // and then return.
type Handler interface {
ServeGemini(*ResponseWriter, *Request)
} }
// ResponderFunc is a wrapper around a bare function that implements Responder. // The HandlerFunc type is an adapter to allow the use of ordinary functions
type ResponderFunc func(*ResponseWriter, *Request) // as Gemini handlers. If f is a function with the appropriate signature,
// HandlerFunc(f) is a Handler that calls f.
type HandlerFunc func(*ResponseWriter, *Request)
func (f ResponderFunc) Respond(w *ResponseWriter, r *Request) { // ServeGemini calls f(w, r).
func (f HandlerFunc) ServeGemini(w *ResponseWriter, r *Request) {
f(w, r) f(w, r)
} }