Split index

This commit is contained in:
Clayton Coleman 2014-07-29 17:35:33 -04:00
parent b70a145161
commit d5e22bfe2a
3 changed files with 86 additions and 40 deletions

View File

@ -115,8 +115,8 @@ func New(storage map[string]RESTStorage, prefix string) *APIServer {
s.mux.HandleFunc(s.prefix+"/", s.ServeREST) s.mux.HandleFunc(s.prefix+"/", s.ServeREST)
healthz.InstallHandler(s.mux) healthz.InstallHandler(s.mux)
s.mux.HandleFunc("/", s.handleIndex)
s.mux.HandleFunc("/version", s.handleVersionReq) s.mux.HandleFunc("/version", s.handleVersionReq)
s.mux.HandleFunc("/", handleIndex)
// Handle both operations and operations/* with the same handler // Handle both operations and operations/* with the same handler
s.mux.HandleFunc(s.operationPrefix(), s.handleOperationRequest) s.mux.HandleFunc(s.operationPrefix(), s.handleOperationRequest)
@ -137,17 +137,6 @@ func (server *APIServer) watchPrefix() string {
return path.Join(server.prefix, "watch") return path.Join(server.prefix, "watch")
} }
func (server *APIServer) handleIndex(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/" && req.URL.Path != "/index.html" {
server.notFound(w, req)
return
}
w.WriteHeader(http.StatusOK)
// TODO: serve this out of a file?
data := "<html><body>Welcome to Kubernetes</body></html>"
fmt.Fprint(w, data)
}
// handleVersionReq writes the server's version information. // handleVersionReq writes the server's version information.
func (server *APIServer) handleVersionReq(w http.ResponseWriter, req *http.Request) { func (server *APIServer) handleVersionReq(w http.ResponseWriter, req *http.Request) {
server.writeRawJSON(http.StatusOK, version.Get(), w) server.writeRawJSON(http.StatusOK, version.Get(), w)
@ -156,7 +145,7 @@ func (server *APIServer) handleVersionReq(w http.ResponseWriter, req *http.Reque
func (server *APIServer) handleMinionReq(w http.ResponseWriter, req *http.Request) { func (server *APIServer) handleMinionReq(w http.ResponseWriter, req *http.Request) {
minionPrefix := "/proxy/minion/" minionPrefix := "/proxy/minion/"
if !strings.HasPrefix(req.URL.Path, minionPrefix) { if !strings.HasPrefix(req.URL.Path, minionPrefix) {
server.notFound(w, req) notFound(w, req)
return return
} }
@ -301,29 +290,24 @@ func (server *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// ServeREST handles requests to all our RESTStorage objects. // ServeREST handles requests to all our RESTStorage objects.
func (server *APIServer) ServeREST(w http.ResponseWriter, req *http.Request) { func (server *APIServer) ServeREST(w http.ResponseWriter, req *http.Request) {
if !strings.HasPrefix(req.URL.Path, server.prefix) { if !strings.HasPrefix(req.URL.Path, server.prefix) {
server.notFound(w, req) notFound(w, req)
return return
} }
requestParts := strings.Split(req.URL.Path[len(server.prefix):], "/")[1:] requestParts := strings.Split(req.URL.Path[len(server.prefix):], "/")[1:]
if len(requestParts) < 1 { if len(requestParts) < 1 {
server.notFound(w, req) notFound(w, req)
return return
} }
storage := server.storage[requestParts[0]] storage := server.storage[requestParts[0]]
if storage == nil { if storage == nil {
httplog.LogOf(w).Addf("'%v' has no storage object", requestParts[0]) httplog.LogOf(w).Addf("'%v' has no storage object", requestParts[0])
server.notFound(w, req) notFound(w, req)
return return
} }
server.handleREST(requestParts, req, w, storage) server.handleREST(requestParts, req, w, storage)
} }
func (server *APIServer) notFound(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Not Found: %#v", req)
}
// write writes an API object in wire format. // write writes an API object in wire format.
func (server *APIServer) write(statusCode int, object interface{}, w http.ResponseWriter) { func (server *APIServer) write(statusCode int, object interface{}, w http.ResponseWriter) {
output, err := api.Encode(object) output, err := api.Encode(object)
@ -430,7 +414,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
case 2: case 2:
item, err := storage.Get(parts[1]) item, err := storage.Get(parts[1])
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -439,11 +423,11 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
server.write(http.StatusOK, item, w) server.write(http.StatusOK, item, w)
default: default:
server.notFound(w, req) notFound(w, req)
} }
case "POST": case "POST":
if len(parts) != 1 { if len(parts) != 1 {
server.notFound(w, req) notFound(w, req)
return return
} }
body, err := server.readBody(req) body, err := server.readBody(req)
@ -453,7 +437,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
obj, err := storage.Extract(body) obj, err := storage.Extract(body)
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -462,7 +446,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
out, err := storage.Create(obj) out, err := storage.Create(obj)
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -472,12 +456,12 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
server.finishReq(out, sync, timeout, w) server.finishReq(out, sync, timeout, w)
case "DELETE": case "DELETE":
if len(parts) != 2 { if len(parts) != 2 {
server.notFound(w, req) notFound(w, req)
return return
} }
out, err := storage.Delete(parts[1]) out, err := storage.Delete(parts[1])
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -487,7 +471,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
server.finishReq(out, sync, timeout, w) server.finishReq(out, sync, timeout, w)
case "PUT": case "PUT":
if len(parts) != 2 { if len(parts) != 2 {
server.notFound(w, req) notFound(w, req)
return return
} }
body, err := server.readBody(req) body, err := server.readBody(req)
@ -497,7 +481,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
obj, err := storage.Extract(body) obj, err := storage.Extract(body)
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -506,7 +490,7 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
out, err := storage.Update(obj) out, err := storage.Update(obj)
if IsNotFound(err) { if IsNotFound(err) {
server.notFound(w, req) notFound(w, req)
return return
} }
if err != nil { if err != nil {
@ -515,24 +499,24 @@ func (server *APIServer) handleREST(parts []string, req *http.Request, w http.Re
} }
server.finishReq(out, sync, timeout, w) server.finishReq(out, sync, timeout, w)
default: default:
server.notFound(w, req) notFound(w, req)
} }
} }
func (server *APIServer) handleOperationRequest(w http.ResponseWriter, req *http.Request) { func (server *APIServer) handleOperationRequest(w http.ResponseWriter, req *http.Request) {
opPrefix := server.operationPrefix() opPrefix := server.operationPrefix()
if !strings.HasPrefix(req.URL.Path, opPrefix) { if !strings.HasPrefix(req.URL.Path, opPrefix) {
server.notFound(w, req) notFound(w, req)
return return
} }
trimmed := strings.TrimLeft(req.URL.Path[len(opPrefix):], "/") trimmed := strings.TrimLeft(req.URL.Path[len(opPrefix):], "/")
parts := strings.Split(trimmed, "/") parts := strings.Split(trimmed, "/")
if len(parts) > 1 { if len(parts) > 1 {
server.notFound(w, req) notFound(w, req)
return return
} }
if req.Method != "GET" { if req.Method != "GET" {
server.notFound(w, req) notFound(w, req)
return return
} }
if len(parts) == 0 { if len(parts) == 0 {
@ -544,7 +528,7 @@ func (server *APIServer) handleOperationRequest(w http.ResponseWriter, req *http
op := server.ops.Get(parts[0]) op := server.ops.Get(parts[0])
if op == nil { if op == nil {
server.notFound(w, req) notFound(w, req)
return return
} }
@ -559,16 +543,16 @@ func (server *APIServer) handleOperationRequest(w http.ResponseWriter, req *http
func (server *APIServer) handleWatch(w http.ResponseWriter, req *http.Request) { func (server *APIServer) handleWatch(w http.ResponseWriter, req *http.Request) {
prefix := server.watchPrefix() prefix := server.watchPrefix()
if !strings.HasPrefix(req.URL.Path, prefix) { if !strings.HasPrefix(req.URL.Path, prefix) {
server.notFound(w, req) notFound(w, req)
return return
} }
parts := strings.Split(req.URL.Path[len(prefix):], "/")[1:] parts := strings.Split(req.URL.Path[len(prefix):], "/")[1:]
if req.Method != "GET" || len(parts) < 1 { if req.Method != "GET" || len(parts) < 1 {
server.notFound(w, req) notFound(w, req)
} }
storage := server.storage[parts[0]] storage := server.storage[parts[0]]
if storage == nil { if storage == nil {
server.notFound(w, req) notFound(w, req)
} }
if watcher, ok := storage.(ResourceWatcher); ok { if watcher, ok := storage.(ResourceWatcher); ok {
var watching watch.Interface var watching watch.Interface
@ -594,5 +578,5 @@ func (server *APIServer) handleWatch(w http.ResponseWriter, req *http.Request) {
return return
} }
server.notFound(w, req) notFound(w, req)
} }

28
pkg/apiserver/errors.go Normal file
View File

@ -0,0 +1,28 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package apiserver
import (
"fmt"
"net/http"
)
// notFound renders a simple not found error
func notFound(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Not Found: %#v", req.RequestURI)
}

34
pkg/apiserver/index.go Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package apiserver
import (
"fmt"
"net/http"
)
// handleIndex is the root index page for Kubernetes
func handleIndex(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/" && req.URL.Path != "/index.html" {
notFound(w, req)
return
}
w.WriteHeader(http.StatusOK)
// TODO: serve this out of a file?
data := "<html><body>Welcome to Kubernetes</body></html>"
fmt.Fprint(w, data)
}