Browse Source

chore(server): handle HEAD for key space efficiently

Implement HEAD in server/v1 and server/v2 functions to avoid
time wasting on JSON marhsal.
Yicheng Qin 11 years ago
parent
commit
89d3df242c
3 changed files with 28 additions and 21 deletions
  1. 8 14
      server/server.go
  2. 6 3
      server/v1/get_key_handler.go
  3. 14 4
      server/v2/get_handler.go

+ 8 - 14
server/server.go

@@ -142,20 +142,9 @@ func (s *Server) installDebug(r *mux.Router) {
 	r.HandleFunc("/debug/pprof/{name}", pprof.Index)
 	r.HandleFunc("/debug/pprof/{name}", pprof.Index)
 }
 }
 
 
-type HEADResponseWriter struct {
-	http.ResponseWriter
-}
-
-func (w *HEADResponseWriter) Write([]byte) (int, error) {
-	return 0, nil
-}
-
 // Adds a v1 server handler to the router.
 // Adds a v1 server handler to the router.
 func (s *Server) handleFuncV1(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request, v1.Server) error) *mux.Route {
 func (s *Server) handleFuncV1(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request, v1.Server) error) *mux.Route {
 	return s.handleFunc(r, path, func(w http.ResponseWriter, req *http.Request) error {
 	return s.handleFunc(r, path, func(w http.ResponseWriter, req *http.Request) error {
-		if req.Method == "HEAD" {
-			w = &HEADResponseWriter{w}
-		}
 		return f(w, req, s)
 		return f(w, req, s)
 	})
 	})
 }
 }
@@ -163,13 +152,18 @@ func (s *Server) handleFuncV1(r *mux.Router, path string, f func(http.ResponseWr
 // Adds a v2 server handler to the router.
 // Adds a v2 server handler to the router.
 func (s *Server) handleFuncV2(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request, v2.Server) error) *mux.Route {
 func (s *Server) handleFuncV2(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request, v2.Server) error) *mux.Route {
 	return s.handleFunc(r, path, func(w http.ResponseWriter, req *http.Request) error {
 	return s.handleFunc(r, path, func(w http.ResponseWriter, req *http.Request) error {
-		if req.Method == "HEAD" {
-			w = &HEADResponseWriter{w}
-		}
 		return f(w, req, s)
 		return f(w, req, s)
 	})
 	})
 }
 }
 
 
+type HEADResponseWriter struct {
+	http.ResponseWriter
+}
+
+func (w *HEADResponseWriter) Write([]byte) (int, error) {
+	return 0, nil
+}
+
 // Adds a server handler to the router.
 // Adds a server handler to the router.
 func (s *Server) handleFunc(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request) error) *mux.Route {
 func (s *Server) handleFunc(r *mux.Router, path string, f func(http.ResponseWriter, *http.Request) error) *mux.Route {
 
 

+ 6 - 3
server/v1/get_key_handler.go

@@ -18,11 +18,14 @@ func GetKeyHandler(w http.ResponseWriter, req *http.Request, s Server) error {
 		return err
 		return err
 	}
 	}
 
 
+	w.WriteHeader(http.StatusOK)
+
+	if req.Method == "HEAD" {
+		return nil
+	}
+
 	// Convert event to a response and write to client.
 	// Convert event to a response and write to client.
 	b, _ := json.Marshal(event.Response(s.Store().Index()))
 	b, _ := json.Marshal(event.Response(s.Store().Index()))
-
-	w.WriteHeader(http.StatusOK)
 	w.Write(b)
 	w.Write(b)
-
 	return nil
 	return nil
 }
 }

+ 14 - 4
server/v2/get_handler.go

@@ -41,13 +41,13 @@ func GetHandler(w http.ResponseWriter, req *http.Request, s Server) error {
 	stream := (req.FormValue("stream") == "true")
 	stream := (req.FormValue("stream") == "true")
 
 
 	if req.FormValue("wait") == "true" {
 	if req.FormValue("wait") == "true" {
-		return handleWatch(key, recursive, stream, waitIndex, w, s)
+		return handleWatch(key, recursive, stream, waitIndex, w, req, s)
 	}
 	}
 
 
-	return handleGet(key, recursive, sort, w, s)
+	return handleGet(key, recursive, sort, w, req, s)
 }
 }
 
 
-func handleWatch(key string, recursive, stream bool, waitIndex string, w http.ResponseWriter, s Server) error {
+func handleWatch(key string, recursive, stream bool, waitIndex string, w http.ResponseWriter, req *http.Request, s Server) error {
 	// Create a command to watch from a given index (default 0).
 	// Create a command to watch from a given index (default 0).
 	var sinceIndex uint64 = 0
 	var sinceIndex uint64 = 0
 	var err error
 	var err error
@@ -84,6 +84,9 @@ func handleWatch(key string, recursive, stream bool, waitIndex string, w http.Re
 					// send to the client in time. Then we simply end streaming.
 					// send to the client in time. Then we simply end streaming.
 					return nil
 					return nil
 				}
 				}
+				if req.Method == "HEAD" {
+					continue
+				}
 
 
 				b, _ := json.Marshal(event)
 				b, _ := json.Marshal(event)
 				_, err := w.Write(b)
 				_, err := w.Write(b)
@@ -99,18 +102,25 @@ func handleWatch(key string, recursive, stream bool, waitIndex string, w http.Re
 	case <-closeChan:
 	case <-closeChan:
 		watcher.Remove()
 		watcher.Remove()
 	case event := <-watcher.EventChan:
 	case event := <-watcher.EventChan:
+		if req.Method == "HEAD" {
+			return nil
+		}
 		b, _ := json.Marshal(event)
 		b, _ := json.Marshal(event)
 		w.Write(b)
 		w.Write(b)
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func handleGet(key string, recursive, sort bool, w http.ResponseWriter, s Server) error {
+func handleGet(key string, recursive, sort bool, w http.ResponseWriter, req *http.Request, s Server) error {
 	event, err := s.Store().Get(key, recursive, sort)
 	event, err := s.Store().Get(key, recursive, sort)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
+	if req.Method == "HEAD" {
+		return nil
+	}
+
 	writeHeaders(w, s)
 	writeHeaders(w, s)
 	b, _ := json.Marshal(event)
 	b, _ := json.Marshal(event)
 	w.Write(b)
 	w.Write(b)