8 // ServeMux is an DNS request multiplexer. It matches the zone name of
9 // each incoming request against a list of registered patterns add calls
10 // the handler for the pattern that most closely matches the zone name.
12 // ServeMux is DNSSEC aware, meaning that queries for the DS record are
13 // redirected to the parent zone (if that is also registered), otherwise
14 // the child gets the query.
16 // ServeMux is also safe for concurrent access from multiple goroutines.
18 // The zero ServeMux is empty and ready for use.
19 type ServeMux struct {
24 // NewServeMux allocates and returns a new ServeMux.
25 func NewServeMux() *ServeMux {
29 // DefaultServeMux is the default ServeMux used by Serve.
30 var DefaultServeMux = NewServeMux()
32 func (mux *ServeMux) match(q string, t uint16) Handler {
41 // TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575
42 // lands in a go release, replace the following with strings.ToLower.
44 for i := 0; i < len(q); i++ {
46 if !(c >= 'A' && c <= 'Z') {
53 for ; i < len(q); i++ {
55 if c >= 'A' && c <= 'Z' {
66 for off, end := 0, false; !end; off, end = NextLabel(q, off) {
67 if h, ok := mux.z[q[off:]]; ok {
71 // Continue for DS to see if we have a parent too, if so delegate to the parent
76 // Wildcard match, if we have found nothing try the root zone as a last resort.
77 if h, ok := mux.z["."]; ok {
84 // Handle adds a handler to the ServeMux for pattern.
85 func (mux *ServeMux) Handle(pattern string, handler Handler) {
87 panic("dns: invalid pattern " + pattern)
91 mux.z = make(map[string]Handler)
93 mux.z[Fqdn(pattern)] = handler
97 // HandleFunc adds a handler function to the ServeMux for pattern.
98 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
99 mux.Handle(pattern, HandlerFunc(handler))
102 // HandleRemove deregisters the handler specific for pattern from the ServeMux.
103 func (mux *ServeMux) HandleRemove(pattern string) {
105 panic("dns: invalid pattern " + pattern)
108 delete(mux.z, Fqdn(pattern))
112 // ServeDNS dispatches the request to the handler whose pattern most
113 // closely matches the request message.
115 // ServeDNS is DNSSEC aware, meaning that queries for the DS record
116 // are redirected to the parent zone (if that is also registered),
117 // otherwise the child gets the query.
119 // If no handler is found, or there is no question, a standard SERVFAIL
120 // message is returned
121 func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
123 if len(req.Question) >= 1 { // allow more than one question
124 h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
134 // Handle registers the handler with the given pattern
135 // in the DefaultServeMux. The documentation for
136 // ServeMux explains how patterns are matched.
137 func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
139 // HandleRemove deregisters the handle with the given pattern
140 // in the DefaultServeMux.
141 func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
143 // HandleFunc registers the handler function with the given pattern
144 // in the DefaultServeMux.
145 func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
146 DefaultServeMux.HandleFunc(pattern, handler)