diff --git a/nameserver/http.go b/nameserver/http.go index d4a4d4c1..0427e79c 100644 --- a/nameserver/http.go +++ b/nameserver/http.go @@ -1,6 +1,7 @@ package nameserver import ( + "errors" "fmt" "github.com/miekg/dns" . "github.com/zettio/weave/common" @@ -8,9 +9,18 @@ import ( "log" "net" "net/http" - "github.com/gorilla/mux" + "strings" ) +// Parse a URL of the form PUT /name// +func parseUrl(url string) (identifier string, ipaddr string, err error) { + parts := strings.Split(url, "/") + if len(parts) != 4 { + return "", "", errors.New("Unable to parse url: " + url) + } + return parts[2], parts[3], nil +} + func httpErrorAndLog(level *log.Logger, w http.ResponseWriter, msg string, status int, logmsg string, logargs ...interface{}) { http.Error(w, msg, status) @@ -19,76 +29,79 @@ func httpErrorAndLog(level *log.Logger, w http.ResponseWriter, msg string, func ListenHttp(version string, server *DNSServer, domain string, db Zone, port int) { - router := mux.NewRouter() - - router.Methods("GET").Path("/status").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, fmt.Sprintln("weave DNS", version)) - io.WriteString(w, server.Status()) + http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } else { + io.WriteString(w, fmt.Sprintln("weave DNS", version)) + io.WriteString(w, server.Status()) + } }) - router.Methods("PUT").Path("/name/{identifier:.+}/{ip:.+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("/name/", func(w http.ResponseWriter, r *http.Request) { + reqError := func(msg string, logmsg string, logargs ...interface{}) { - httpErrorAndLog(Warning, w, msg, http.StatusBadRequest, logmsg, logargs...) + httpErrorAndLog(Warning, w, msg, http.StatusBadRequest, + logmsg, logargs...) } - vars := mux.Vars(r) - ident := vars["identifier"] - ipStr := vars["ip"] - name := r.FormValue("fqdn") + switch r.Method { + case "PUT": + ident, ipStr, err := parseUrl(r.URL.Path) + name := r.FormValue("fqdn") + if ident == "" || ipStr == "" || name == "" { + reqError("Invalid request", "Invalid request: %s, %s", r.URL, r.Form) + return + } - if name == "" { - reqError("Invalid FQDN", "Invalid FQDN in request: %s, %s", r.URL, r.Form) - return - } + ip := net.ParseIP(ipStr) + if ip == nil { + reqError("Invalid IP", "Invalid IP in request: %s", ipStr) + return + } - ip := net.ParseIP(ipStr) - if ip == nil { - reqError("Invalid IP", "Invalid IP in request: %s", ipStr) - return - } + if dns.IsSubDomain(domain, name) { + Info.Printf("[http] Adding %s -> %s", name, ipStr) + if err = db.AddRecord(ident, name, ip); err != nil { + if _, ok := err.(DuplicateError); !ok { + httpErrorAndLog( + Error, w, "Internal error", http.StatusInternalServerError, + "Unexpected error from DB: %s", err) + return + } // oh, I already know this. whatever. + } + } else { + Info.Printf("[http] Ignoring name %s, not in %s", name, domain) + } - if dns.IsSubDomain(domain, name) { - Info.Printf("[http] Adding %s -> %s", name, ipStr) - if err := db.AddRecord(ident, name, ip); err != nil { - if _, ok := err.(DuplicateError); !ok { + case "DELETE": + ident, ipStr, err := parseUrl(r.URL.Path) + if ident == "" || ipStr == "" { + reqError("Invalid Request", "Invalid request: %s, %s", r.URL, r.Form) + return + } + + ip := net.ParseIP(ipStr) + if ip == nil { + reqError("Invalid IP in request", "Invalid IP in request: %s", ipStr) + return + } + Info.Printf("[http] Deleting %s (%s)", ident, ipStr) + if err = db.DeleteRecord(ident, ip); err != nil { + if _, ok := err.(LookupError); !ok { httpErrorAndLog( Error, w, "Internal error", http.StatusInternalServerError, "Unexpected error from DB: %s", err) return - } // oh, I already know this. whatever. + } } - } else { - Info.Printf("[http] Ignoring name %s, not in %s", name, domain) - } - }) - - router.Methods("DELETE").Path("/name/{identifier:.+}/{ip:.+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - reqError := func(msg string, logmsg string, logargs ...interface{}) { - httpErrorAndLog(Warning, w, msg, http.StatusBadRequest, logmsg, logargs...) - } - - vars := mux.Vars(r) - ident := vars["identifier"] - ipStr := vars["ip"] - - ip := net.ParseIP(ipStr) - if ip == nil { - reqError("Invalid IP in request", "Invalid IP in request: %s", ipStr) + default: + msg := "Unexpected http method: " + r.Method + reqError(msg, msg) return } - Info.Printf("[http] Deleting %s (%s)", ident, ipStr) - if err := db.DeleteRecord(ident, ip); err != nil { - if _, ok := err.(LookupError); !ok { - httpErrorAndLog( - Error, w, "Internal error", http.StatusInternalServerError, - "Unexpected error from DB: %s", err) - return - } - } }) - http.Handle("/", router) - address := fmt.Sprintf(":%d", port) if err := http.ListenAndServe(address, nil); err != nil { Error.Fatal("[http] Unable to create http listener: ", err)