github.com/kula/etcd@v0.2.1-0.20131226070625-e96234382ac0/server/v2/get_handler.go (about)

     1  package v2
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/url"
     8  	"strconv"
     9  
    10  	etcdErr "github.com/coreos/etcd/error"
    11  	"github.com/coreos/etcd/log"
    12  	"github.com/coreos/etcd/store"
    13  	"github.com/coreos/raft"
    14  	"github.com/gorilla/mux"
    15  )
    16  
    17  func GetHandler(w http.ResponseWriter, req *http.Request, s Server) error {
    18  	var err error
    19  	var event *store.Event
    20  
    21  	vars := mux.Vars(req)
    22  	key := "/" + vars["key"]
    23  
    24  	// Help client to redirect the request to the current leader
    25  	if req.FormValue("consistent") == "true" && s.State() != raft.Leader {
    26  		leader := s.Leader()
    27  		hostname, _ := s.ClientURL(leader)
    28  
    29  		url, err := url.Parse(hostname)
    30  		if err != nil {
    31  			log.Warn("Redirect cannot parse hostName ", hostname)
    32  			return err
    33  		}
    34  		url.RawQuery = req.URL.RawQuery
    35  		url.Path = req.URL.Path
    36  
    37  		log.Debugf("Redirect consistent get to %s", url.String())
    38  		http.Redirect(w, req, url.String(), http.StatusTemporaryRedirect)
    39  		return nil
    40  	}
    41  
    42  	recursive := (req.FormValue("recursive") == "true")
    43  	sorted := (req.FormValue("sorted") == "true")
    44  
    45  	if req.FormValue("wait") == "true" { // watch
    46  		// Create a command to watch from a given index (default 0).
    47  		var sinceIndex uint64 = 0
    48  
    49  		waitIndex := req.FormValue("waitIndex")
    50  		if waitIndex != "" {
    51  			sinceIndex, err = strconv.ParseUint(string(req.FormValue("waitIndex")), 10, 64)
    52  			if err != nil {
    53  				return etcdErr.NewError(etcdErr.EcodeIndexNaN, "Watch From Index", s.Store().Index())
    54  			}
    55  		}
    56  
    57  		// Start the watcher on the store.
    58  		eventChan, err := s.Store().Watch(key, recursive, sinceIndex)
    59  		if err != nil {
    60  			return err
    61  		}
    62  
    63  		cn, _ := w.(http.CloseNotifier)
    64  		closeChan := cn.CloseNotify()
    65  
    66  		select {
    67  		case <-closeChan:
    68  			return nil
    69  		case event = <-eventChan:
    70  		}
    71  
    72  	} else { //get
    73  		// Retrieve the key from the store.
    74  		event, err = s.Store().Get(key, recursive, sorted)
    75  		if err != nil {
    76  			return err
    77  		}
    78  	}
    79  
    80  	w.Header().Set("Content-Type", "application/json")
    81  	w.Header().Add("X-Etcd-Index", fmt.Sprint(s.Store().Index()))
    82  	w.Header().Add("X-Raft-Index", fmt.Sprint(s.CommitIndex()))
    83  	w.Header().Add("X-Raft-Term", fmt.Sprint(s.Term()))
    84  	w.WriteHeader(http.StatusOK)
    85  	b, _ := json.Marshal(event)
    86  
    87  	w.Write(b)
    88  
    89  	return nil
    90  }