github.com/macb/etcd@v0.3.1-0.20140227003422-a60481c6b1a0/server/peer_server_handlers.go (about)

     1  package server
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/coreos/etcd/third_party/github.com/coreos/raft"
    10  	"github.com/coreos/etcd/third_party/github.com/gorilla/mux"
    11  
    12  	etcdErr "github.com/coreos/etcd/error"
    13  	uhttp "github.com/coreos/etcd/pkg/http"
    14  	"github.com/coreos/etcd/log"
    15  	"github.com/coreos/etcd/store"
    16  )
    17  
    18  // Get all the current logs
    19  func (ps *PeerServer) GetLogHttpHandler(w http.ResponseWriter, req *http.Request) {
    20  	log.Debugf("[recv] GET %s/log", ps.Config.URL)
    21  	w.Header().Set("Content-Type", "application/json")
    22  	w.WriteHeader(http.StatusOK)
    23  	json.NewEncoder(w).Encode(ps.raftServer.LogEntries())
    24  }
    25  
    26  // Response to vote request
    27  func (ps *PeerServer) VoteHttpHandler(w http.ResponseWriter, req *http.Request) {
    28  	rvreq := &raft.RequestVoteRequest{}
    29  
    30  	if _, err := rvreq.Decode(req.Body); err != nil {
    31  		http.Error(w, "", http.StatusBadRequest)
    32  		log.Warnf("[recv] BADREQUEST %s/vote [%v]", ps.Config.URL, err)
    33  		return
    34  	}
    35  
    36  	log.Debugf("[recv] POST %s/vote [%s]", ps.Config.URL, rvreq.CandidateName)
    37  
    38  	resp := ps.raftServer.RequestVote(rvreq)
    39  
    40  	if resp == nil {
    41  		log.Warn("[vote] Error: nil response")
    42  		http.Error(w, "", http.StatusInternalServerError)
    43  		return
    44  	}
    45  
    46  	if _, err := resp.Encode(w); err != nil {
    47  		log.Warn("[vote] Error: %v", err)
    48  		http.Error(w, "", http.StatusInternalServerError)
    49  		return
    50  	}
    51  }
    52  
    53  // Response to append entries request
    54  func (ps *PeerServer) AppendEntriesHttpHandler(w http.ResponseWriter, req *http.Request) {
    55  	start := time.Now()
    56  	aereq := &raft.AppendEntriesRequest{}
    57  
    58  	if _, err := aereq.Decode(req.Body); err != nil {
    59  		http.Error(w, "", http.StatusBadRequest)
    60  		log.Warnf("[recv] BADREQUEST %s/log/append [%v]", ps.Config.URL, err)
    61  		return
    62  	}
    63  
    64  	log.Debugf("[recv] POST %s/log/append [%d]", ps.Config.URL, len(aereq.Entries))
    65  
    66  	ps.serverStats.RecvAppendReq(aereq.LeaderName, int(req.ContentLength))
    67  
    68  	resp := ps.raftServer.AppendEntries(aereq)
    69  
    70  	if resp == nil {
    71  		log.Warn("[ae] Error: nil response")
    72  		http.Error(w, "", http.StatusInternalServerError)
    73  		return
    74  	}
    75  
    76  	if !resp.Success() {
    77  		log.Debugf("[Append Entry] Step back")
    78  	}
    79  
    80  	if _, err := resp.Encode(w); err != nil {
    81  		log.Warn("[ae] Error: %v", err)
    82  		http.Error(w, "", http.StatusInternalServerError)
    83  		return
    84  	}
    85  
    86  	(*ps.metrics).Timer("timer.appendentries.handle").UpdateSince(start)
    87  }
    88  
    89  // Response to recover from snapshot request
    90  func (ps *PeerServer) SnapshotHttpHandler(w http.ResponseWriter, req *http.Request) {
    91  	ssreq := &raft.SnapshotRequest{}
    92  
    93  	if _, err := ssreq.Decode(req.Body); err != nil {
    94  		http.Error(w, "", http.StatusBadRequest)
    95  		log.Warnf("[recv] BADREQUEST %s/snapshot [%v]", ps.Config.URL, err)
    96  		return
    97  	}
    98  
    99  	log.Debugf("[recv] POST %s/snapshot", ps.Config.URL)
   100  
   101  	resp := ps.raftServer.RequestSnapshot(ssreq)
   102  
   103  	if resp == nil {
   104  		log.Warn("[ss] Error: nil response")
   105  		http.Error(w, "", http.StatusInternalServerError)
   106  		return
   107  	}
   108  
   109  	if _, err := resp.Encode(w); err != nil {
   110  		log.Warn("[ss] Error: %v", err)
   111  		http.Error(w, "", http.StatusInternalServerError)
   112  		return
   113  	}
   114  }
   115  
   116  // Response to recover from snapshot request
   117  func (ps *PeerServer) SnapshotRecoveryHttpHandler(w http.ResponseWriter, req *http.Request) {
   118  	ssrreq := &raft.SnapshotRecoveryRequest{}
   119  
   120  	if _, err := ssrreq.Decode(req.Body); err != nil {
   121  		http.Error(w, "", http.StatusBadRequest)
   122  		log.Warnf("[recv] BADREQUEST %s/snapshotRecovery [%v]", ps.Config.URL, err)
   123  		return
   124  	}
   125  
   126  	log.Debugf("[recv] POST %s/snapshotRecovery", ps.Config.URL)
   127  
   128  	resp := ps.raftServer.SnapshotRecoveryRequest(ssrreq)
   129  
   130  	if resp == nil {
   131  		log.Warn("[ssr] Error: nil response")
   132  		http.Error(w, "", http.StatusInternalServerError)
   133  		return
   134  	}
   135  
   136  	if _, err := resp.Encode(w); err != nil {
   137  		log.Warn("[ssr] Error: %v", err)
   138  		http.Error(w, "", http.StatusInternalServerError)
   139  		return
   140  	}
   141  }
   142  
   143  // Get the port that listening for etcd connecting of the server
   144  func (ps *PeerServer) EtcdURLHttpHandler(w http.ResponseWriter, req *http.Request) {
   145  	log.Debugf("[recv] Get %s/etcdURL/ ", ps.Config.URL)
   146  	w.WriteHeader(http.StatusOK)
   147  	w.Write([]byte(ps.server.URL()))
   148  }
   149  
   150  // Response to the join request
   151  func (ps *PeerServer) JoinHttpHandler(w http.ResponseWriter, req *http.Request) {
   152  	command := &JoinCommand{}
   153  
   154  	err := uhttp.DecodeJsonRequest(req, command)
   155  	if err != nil {
   156  		w.WriteHeader(http.StatusInternalServerError)
   157  		return
   158  	}
   159  
   160  	log.Debugf("Receive Join Request from %s", command.Name)
   161  	err = ps.server.Dispatch(command, w, req)
   162  
   163  	// Return status.
   164  	if err != nil {
   165  		if etcdErr, ok := err.(*etcdErr.Error); ok {
   166  			log.Debug("Return error: ", (*etcdErr).Error())
   167  			etcdErr.Write(w)
   168  		} else {
   169  			http.Error(w, err.Error(), http.StatusInternalServerError)
   170  		}
   171  	}
   172  }
   173  
   174  // Response to remove request
   175  func (ps *PeerServer) RemoveHttpHandler(w http.ResponseWriter, req *http.Request) {
   176  	if req.Method != "DELETE" {
   177  		w.WriteHeader(http.StatusMethodNotAllowed)
   178  		return
   179  	}
   180  
   181  	vars := mux.Vars(req)
   182  	command := &RemoveCommand{
   183  		Name: vars["name"],
   184  	}
   185  
   186  	log.Debugf("[recv] Remove Request [%s]", command.Name)
   187  
   188  	ps.server.Dispatch(command, w, req)
   189  }
   190  
   191  // Response to the name request
   192  func (ps *PeerServer) NameHttpHandler(w http.ResponseWriter, req *http.Request) {
   193  	log.Debugf("[recv] Get %s/name/ ", ps.Config.URL)
   194  	w.WriteHeader(http.StatusOK)
   195  	w.Write([]byte(ps.Config.Name))
   196  }
   197  
   198  // Response to the name request
   199  func (ps *PeerServer) VersionHttpHandler(w http.ResponseWriter, req *http.Request) {
   200  	log.Debugf("[recv] Get %s/version/ ", ps.Config.URL)
   201  	w.WriteHeader(http.StatusOK)
   202  	w.Write([]byte(strconv.Itoa(ps.store.Version())))
   203  }
   204  
   205  // Checks whether a given version is supported.
   206  func (ps *PeerServer) VersionCheckHttpHandler(w http.ResponseWriter, req *http.Request) {
   207  	log.Debugf("[recv] Get %s%s ", ps.Config.URL, req.URL.Path)
   208  	vars := mux.Vars(req)
   209  	version, _ := strconv.Atoi(vars["version"])
   210  	if version >= store.MinVersion() && version <= store.MaxVersion() {
   211  		w.WriteHeader(http.StatusOK)
   212  	} else {
   213  		w.WriteHeader(http.StatusForbidden)
   214  	}
   215  }
   216  
   217  // Upgrades the current store version to the next version.
   218  func (ps *PeerServer) UpgradeHttpHandler(w http.ResponseWriter, req *http.Request) {
   219  	log.Debugf("[recv] Get %s/version", ps.Config.URL)
   220  
   221  	// Check if upgrade is possible for all nodes.
   222  	if err := ps.Upgradable(); err != nil {
   223  		http.Error(w, err.Error(), http.StatusInternalServerError)
   224  		return
   225  	}
   226  
   227  	// Create an upgrade command from the current version.
   228  	c := ps.store.CommandFactory().CreateUpgradeCommand()
   229  	if err := ps.server.Dispatch(c, w, req); err != nil {
   230  		http.Error(w, err.Error(), http.StatusInternalServerError)
   231  		return
   232  	}
   233  
   234  	w.WriteHeader(http.StatusOK)
   235  }