Add support for wildcard hostnames

This commit is contained in:
Adnan Maolood 2020-10-21 13:22:26 -04:00
parent 960ebd9b46
commit 9daf84a121

View File

@ -34,15 +34,18 @@ type Server struct {
} }
type handlerKey struct { type handlerKey struct {
Scheme string scheme string
Host string hostname string
wildcard bool
} }
// Handle registers a handler for the given hostname. // Handle registers a handler for the given pattern.
// A default scheme of gemini:// is assumed. // Patterns must be in the form of scheme://hostname (e.g. gemini://example.com).
func (s *Server) Handle(hostname string, handler Handler) { // If no scheme is specified, a default scheme of gemini:// is assumed.
if hostname == "" { // Wildcard patterns are supported (e.g. *.example.com).
panic("gmi: invalid hostname") func (s *Server) Handle(pattern string, handler Handler) {
if pattern == "" {
panic("gmi: invalid pattern")
} }
if handler == nil { if handler == nil {
panic("gmi: nil handler") panic("gmi: nil handler")
@ -50,20 +53,29 @@ func (s *Server) Handle(hostname string, handler Handler) {
if s.handlers == nil { if s.handlers == nil {
s.handlers = map[handlerKey]Handler{} s.handlers = map[handlerKey]Handler{}
} }
s.HandleScheme("gemini", hostname, handler)
split := strings.SplitN(pattern, "://", 2)
var key handlerKey
if len(split) == 2 {
key.scheme = split[0]
key.hostname = split[1]
} else {
key.scheme = "gemini"
key.hostname = split[0]
}
split = strings.SplitN(key.hostname, ".", 2)
if len(split) == 2 {
if split[0] == "*" {
key.hostname = split[1]
key.wildcard = true
}
}
s.handlers[key] = handler
} }
func (s *Server) HandleFunc(hostname string, handler func(*ResponseWriter, *Request)) { func (s *Server) HandleFunc(pattern string, handler func(*ResponseWriter, *Request)) {
s.Handle(hostname, HandlerFunc(handler)) s.Handle(pattern, HandlerFunc(handler))
}
// HandleScheme registers a handler for the given scheme and hostname.
func (s *Server) HandleScheme(scheme string, hostname string, handler Handler) {
s.handlers[handlerKey{scheme, hostname}] = handler
}
func (s *Server) HandleSchemeFunc(scheme string, hostname string, handler func(*ResponseWriter, *Request)) {
s.HandleScheme(scheme, hostname, HandlerFunc(handler))
} }
type handlerEntry struct { type handlerEntry struct {
@ -233,9 +245,15 @@ func (s *Server) respond(conn net.Conn) {
} }
func (s *Server) handler(r *Request) Handler { func (s *Server) handler(r *Request) Handler {
if h, ok := s.handlers[handlerKey{r.URL.Scheme, r.URL.Hostname()}]; ok { if h, ok := s.handlers[handlerKey{r.URL.Scheme, r.URL.Hostname(), false}]; ok {
return h return h
} }
wildcard := strings.SplitN(r.URL.Hostname(), ".", 2)
if len(wildcard) == 2 {
if h, ok := s.handlers[handlerKey{r.URL.Scheme, wildcard[1], true}]; ok {
return h
}
}
return NotFoundHandler() return NotFoundHandler()
} }