Refactor API http handlers to prepare for versioning.

This commit is contained in:
Victor Marmol 2014-08-01 09:49:48 -07:00
parent e61f0a15dc
commit d2397e5ab7
2 changed files with 57 additions and 23 deletions

View File

@ -22,6 +22,7 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
"path"
"strings" "strings"
"time" "time"
@ -30,27 +31,63 @@ import (
) )
const ( const (
ApiResource = "/api/v1.0/" apiResource = "/api/"
ContainersApi = "containers" containersApi = "containers"
MachineApi = "machine" subcontainersApi = "subcontainers"
machineApi = "machine"
) )
func HandleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) error { var supportedApiVersions map[string]struct{} = map[string]struct{}{
"v1.0": struct{}{},
}
func RegisterHandlers(m manager.Manager) error {
http.HandleFunc(apiResource, func(w http.ResponseWriter, r *http.Request) {
err := handleRequest(m, w, r)
if err != nil {
fmt.Fprintf(w, "%s", err)
}
})
return nil
}
func handleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) error {
start := time.Now() start := time.Now()
u := r.URL request := r.URL.Path
requestElements := strings.Split(r.URL.Path, "/")
// Get API request type. // Verify that we have all the elements we expect:
requestType := u.Path[len(ApiResource):] // <empty>/api/<version>/<request type>[/<args...>]
i := strings.Index(requestType, "/") // [0] [1] [2] [3] [4...]
requestArgs := "" if len(requestElements) < 4 {
if i != -1 { return fmt.Errorf("incomplete API request %q", request)
requestArgs = requestType[i:] }
requestType = requestType[:i]
// Get all the element parts.
emptyElement := requestElements[0]
apiElement := requestElements[1]
version := requestElements[2]
requestType := requestElements[3]
requestArgs := []string{}
if len(requestElements) > 4 {
requestArgs = requestElements[4:]
}
// Check elements.
if len(emptyElement) != 0 {
return fmt.Errorf("unexpected API request format %q", request)
}
if apiElement != "api" {
return fmt.Errorf("invalid API request format %q", request)
}
if _, ok := supportedApiVersions[version]; !ok {
return fmt.Errorf("unsupported API version %q", version)
} }
switch { switch {
case requestType == MachineApi: case requestType == machineApi:
log.Printf("Api - Machine") log.Printf("Api - Machine")
// Get the MachineInfo // Get the MachineInfo
@ -64,9 +101,9 @@ func HandleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) er
fmt.Fprintf(w, "Failed to marshall MachineInfo with error: %s", err) fmt.Fprintf(w, "Failed to marshall MachineInfo with error: %s", err)
} }
w.Write(out) w.Write(out)
case requestType == ContainersApi: case requestType == containersApi:
// The container name is the path after the requestType // The container name is the path after the requestType.
containerName := requestArgs containerName := path.Join("/", strings.Join(requestArgs, "/"))
log.Printf("Api - Container(%s)", containerName) log.Printf("Api - Container(%s)", containerName)

View File

@ -64,13 +64,10 @@ func main() {
} }
}) })
// Handler for the API. // Register API handler.
http.HandleFunc(api.ApiResource, func(w http.ResponseWriter, r *http.Request) { if err := api.RegisterHandlers(containerManager); err != nil {
err := api.HandleRequest(containerManager, w, r) log.Fatalf("failed to register API handlers: %s", err)
if err != nil {
fmt.Fprintf(w, "%s", err)
} }
})
// Redirect / to containers page. // Redirect / to containers page.
http.Handle("/", http.RedirectHandler(pages.ContainersPage, http.StatusTemporaryRedirect)) http.Handle("/", http.RedirectHandler(pages.ContainersPage, http.StatusTemporaryRedirect))