Skip to content

Commit

Permalink
1. Change response processing to copy out of a channel to array
Browse files Browse the repository at this point in the history
2. re-write processing logic
3. wrap error handling & handle response errors from w/in go routines
  • Loading branch information
Kaley committed Sep 27, 2016
1 parent 0ad0bf5 commit e1b2e89
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 34 deletions.
99 changes: 66 additions & 33 deletions rackhd/proxy/controller.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import (
regStore "github.com/RackHD/neighborhood-manager/libreg/registry"
"github.com/RackHD/neighborhood-manager/libreg/registry/consul"
"github.com/RackHD/neighborhood-manager/rackhd/watcher"
"github.com/hashicorp/go-cleanhttp"
)

// Responses is an array of Response structs
type Responses []Response

// Server is the proxy server struct
type Server struct {
Address string
Expand Down Expand Up @@ -53,64 +57,85 @@ func (p *Server) HandleTest(w http.ResponseWriter, r *http.Request) {
// HandleNodes sends, recieves, and processes all the data
func (p *Server) HandleNodes(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
addrMap := p.GetAddresses(w, r)
cr, _ := p.GetResp(r, addrMap)
p.RespCheck(w, cr)
addrMap, err := p.GetAddresses(w, r)
if len(addrMap) == 0 {
w.WriteHeader(200)
w.Write([]byte("[]"))
return
}
if err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("%s", err)))
return
}
ar := p.GetResp(r, addrMap)
p.RespCheck(r, w, ar)
}

// GetResp makes channels for the response and errors from http.Get.
// A go func is spun up for each http.Get and the responses are fed
// into their respective channels.
func (p *Server) GetResp(r *http.Request, addrs map[string]struct{}) (chan *Response, chan error) {
func (p *Server) GetResp(r *http.Request, addrs map[string]struct{}) Responses {
cr := make(chan *Response, len(addrs))
errs := make(chan error, len(addrs))
defer close(cr)
defer close(errs)
for entry := range addrs {
p.wg.Add(1)
go func(entry string) {
go func(entry string, r *http.Request) {
defer p.wg.Done()
r.URL.Host = entry
r.URL.Scheme = "http"
fmt.Printf("url string %s\n", r.URL.String())
respGet, err := http.Get(r.URL.String())
req, err := NewRequest(r, entry)
if err != nil {
errs <- fmt.Errorf("Could not send any HTTP Get requests: %s\n", err)
cr <- NewResposeFromError(err)
return
}
client := cleanhttp.DefaultClient()
respGet, err := client.Do(req)
fmt.Println("request sent")
if err != nil {
cr <- NewResposeFromError(err)
return
}
defer respGet.Body.Close()
responseCopy, err := NewResponse(respGet)
if err != nil {
log.Printf("Error copying response => %s\n", err)
cr <- NewResposeFromError(err)
return
}
cr <- responseCopy
respGet.Body.Close()
}(entry)
}(entry, r)
}
p.wg.Wait()
return cr, errs
close(cr)
var ar Responses
for entry := range cr {
ar = append(ar, *entry)
}
return ar
}

// GetAddresses decides from where to retrieve the addresses
func (p *Server) GetAddresses(w http.ResponseWriter, r *http.Request) map[string]struct{} {
func (p *Server) GetAddresses(w http.ResponseWriter, r *http.Request) (map[string]struct{}, error) {
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return nil, err
}
querySlice := r.URL.Query()
if len(querySlice["ip"]) > 0 {
addrMap := p.GetQueryAddresses(querySlice["ip"])
return addrMap
return addrMap, nil
}
addrMap, err := p.GetStoredAddresses()
if err != nil {
return nil, err
}
addrMap := p.GetStoredAddresses()
return addrMap
return addrMap, nil
}

// GetStoredAddresses calls GetAddresses and returns a map of addresses
func (p *Server) GetStoredAddresses() map[string]struct{} {
func (p *Server) GetStoredAddresses() (map[string]struct{}, error) {
addresses, err := p.Store.GetAddresses()
if err != nil {
log.Printf("Did not get IP List ==> %s\n", err)
}
return addresses
return addresses, err
}

// GetQueryAddresses retrives a url flag and returns a map of address(es)
Expand All @@ -132,16 +157,24 @@ func (p *Server) GetQueryAddresses(querySlice []string) map[string]struct{} {

// RespCheck identifies the type of initialResp.Body and calls the appropriate
// helper function to write to the ResponseWriter.
func (p *Server) RespCheck(w http.ResponseWriter, cr chan *Response) {
initialResp := <-cr
if initialResp.Body[0] != '[' {
w.Write(initialResp.Body)
return
}
w.Write(initialResp.Body[0 : len(initialResp.Body)-2])
for r := range cr {
w.Write([]byte(","))
w.Write(r.Body[1 : len(r.Body)-2])
func (p *Server) RespCheck(r *http.Request, w http.ResponseWriter, ar Responses) {
w.Write([]byte("["))
var cutSize int
for i, r := range ar {
if r.Body == nil {
continue
}
if r.Body[0] == '[' {
cutSize = 1
} else if r.Body[0] == '{' {
cutSize = 0
} else {
continue
}
w.Write(r.Body[cutSize : len(r.Body)-cutSize])
if i != len(ar)-1 {
w.Write([]byte(","))
}
}
w.Write([]byte("]"))
}
25 changes: 25 additions & 0 deletions rackhd/proxy/response.go → rackhd/proxy/helper.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Response struct {
StatusCode int
Body []byte
RequestURL string
Error error
}

// NewResponse copies a http.Response into a proxy Response
Expand All @@ -24,6 +25,30 @@ func NewResponse(resp *http.Response) (*Response, error) {
StatusCode: resp.StatusCode,
Body: body,
RequestURL: resp.Request.URL.String(),
Error: nil,
}
return proxyResponse, err
}

// NewResposeFromError sets errors
func NewResposeFromError(err error) *Response {
proxyRespnse := &Response{
StatusCode: 500,
Error: err,
}
return proxyRespnse
}

// NewRequest copies a http.Request & Header and sets the new host
func NewRequest(r *http.Request, host string) (*http.Request, error) {
req, err := http.NewRequest(r.Method, "http://"+host+r.URL.Path, r.Body)
if err != nil {
return nil, err
}
for k, v := range r.Header {
for _, value := range v {
req.Header.Set(k, value)
}
}
return req, nil
}
2 changes: 1 addition & 1 deletion rackhd/watcher/watcher.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (m *Monitor) GetAddresses() (map[string]struct{}, error) {
addr := fmt.Sprintf("%s:%d", entry.ServiceAddress, entry.ServicePort)
addresses[addr] = struct{}{}
}
return addresses, err
return addresses, nil
}

// GetService fetches catalog entries for the given serviceName
Expand Down

0 comments on commit e1b2e89

Please sign in to comment.