Replace hand parsing and validation of URLs with Gorilla mux

This commit is contained in:
Adam Harrison committed 2015-03-18 10:10:13 +00:00
1 parent d5eb76f32e
commit bd7b232663
2 files changed
+66 -70

No files matched your search

+54 -67
View File
@@ -1,7 +1,6 @@
package nameserver
import (
"errors"
"fmt"
"github.com/miekg/dns"
. "github.com/zettio/weave/common"
@@ -9,18 +8,9 @@ import (
"log"
"net"
"net/http"
"strings"
"github.com/gorilla/mux"
)
// Parse a URL of the form PUT /name/<identifier>/<ip-address>
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)
@@ -29,78 +19,75 @@ func httpErrorAndLog(level *log.Logger, w http.ResponseWriter, msg string,
func ListenHttp(domain string, db Zone, port int) {
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, "ok")
}
muxRouter := mux.NewRouter()
muxRouter.Methods("GET").Path("/status").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "ok")
})
http.HandleFunc("/name/", func(w http.ResponseWriter, r *http.Request) {
muxRouter.Methods("PUT").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...)
httpErrorAndLog(Warning, w, msg, http.StatusBadRequest, logmsg, logargs...)
}
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
}
vars := mux.Vars(r)
ident := vars["identifier"]
ipStr := vars["ip"]
name := r.FormValue("fqdn")
ip := net.ParseIP(ipStr)
if ip == nil {
reqError("Invalid IP", "Invalid IP in request: %s", ipStr)
return
}
if name == "" {
reqError("Invalid FQDN", "Invalid FQDN in request: %s, %s", r.URL, r.Form)
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)
}
ip := net.ParseIP(ipStr)
if ip == nil {
reqError("Invalid IP", "Invalid IP in request: %s", ipStr)
return
}
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 {
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.
}
default:
msg := "Unexpected http method: " + r.Method
reqError(msg, msg)
return
} else {
Info.Printf("[http] Ignoring name %s, not in %s", name, domain)
}
})
muxRouter.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)
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("/", muxRouter)
address := fmt.Sprintf(":%d", port)
if err := http.ListenAndServe(address, nil); err != nil {
Error.Fatal("[http] Unable to create http listener: ", err)
+12 -3
View File
@@ -16,6 +16,7 @@ import (
"os/signal"
"runtime"
"syscall"
"github.com/gorilla/mux"
)
var version = "(unreleased version)"
@@ -152,16 +153,21 @@ func handleHttp(router *weave.Router) {
if router.UsingPassword() {
encryption = "on"
}
http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
muxRouter := mux.NewRouter()
muxRouter.Methods("GET").Path("/status").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, fmt.Sprintln("weave router", version))
io.WriteString(w, fmt.Sprintln("Encryption", encryption))
io.WriteString(w, router.Status())
})
http.HandleFunc("/status-json", func(w http.ResponseWriter, r *http.Request) {
muxRouter.Methods("GET").Path("/status-json").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json, _ := router.GenerateStatusJSON(version, encryption)
w.Write(json)
})
http.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) {
muxRouter.Methods("POST").Path("/connect").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
peer := r.FormValue("peer")
if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil {
router.ConnectionMaker.InitiateConnection(addr.String())
@@ -169,6 +175,9 @@ func handleHttp(router *weave.Router) {
http.Error(w, fmt.Sprint("invalid peer address: ", err), http.StatusBadRequest)
}
})
http.Handle("/", muxRouter)
address := fmt.Sprintf(":%d", weave.HttpPort)
err := http.ListenAndServe(address, nil)
if err != nil {