github.com/jpetazzo/etcd@v0.2.1-0.20140113055439-97f1363afac5/server/peer_server_handlers.go (about)

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