httpapi.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "io/ioutil"
  17. "log"
  18. "net/http"
  19. "strconv"
  20. )
  21. // Handler for a http based key-value store backed by raft
  22. type httpKVAPI struct {
  23. store *kvstore
  24. }
  25. func (h *httpKVAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  26. key := r.RequestURI
  27. switch {
  28. case r.Method == "PUT":
  29. v, err := ioutil.ReadAll(r.Body)
  30. if err != nil {
  31. log.Printf("Failed to read on PUT (%v)\n", err)
  32. http.Error(w, "Failed on PUT", http.StatusBadRequest)
  33. return
  34. }
  35. h.store.Propose(key, string(v))
  36. // Optimistic-- no waiting for ack from raft. Value is not yet
  37. // committed so a subsequent GET on the key may return old value
  38. w.WriteHeader(http.StatusNoContent)
  39. case r.Method == "GET":
  40. if v, ok := h.store.Lookup(key); ok {
  41. w.Write([]byte(v))
  42. } else {
  43. http.Error(w, "Failed to GET", http.StatusNotFound)
  44. }
  45. default:
  46. w.Header().Set("Allow", "PUT")
  47. w.Header().Add("Allow", "GET")
  48. http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  49. }
  50. }
  51. // serveHttpKVAPI starts a key-value server with a GET/PUT API and listens.
  52. func serveHttpKVAPI(port int, proposeC chan<- string, commitC <-chan *string, errorC <-chan error) {
  53. srv := http.Server{
  54. Addr: ":" + strconv.Itoa(port),
  55. Handler: &httpKVAPI{newKVStore(proposeC, commitC, errorC)},
  56. }
  57. if err := srv.ListenAndServe(); err != nil {
  58. log.Fatal(err)
  59. }
  60. }