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 }