Beispiel #1
0
// Vulcan implements Getter interface that is used by controllers to issue concurrent get requests with failover
func (p *ReverseProxy) Get(w http.ResponseWriter, hosts []string, query client.MultiDict, auth *netutils.BasicAuth) error {
	req, err := http.NewRequest("GET", "http://localhost", nil)
	if err != nil {
		return err
	}
	if query != nil {
		parameters := url.Values{}
		for key, values := range query {
			for i, _ := range values {
				parameters.Add(key, values[i])
			}
		}
		req.URL.RawQuery = parameters.Encode()
	}

	if auth != nil {
		req.SetBasicAuth(auth.Username, auth.Password)
	}

	upstreams, err := command.NewUpstreamsFromUrls(hosts)
	if err != nil {
		return err
	}
	req.Body = &Buffer{&bytes.Reader{}}

	cmd := &command.Forward{
		Failover:  &command.Failover{Active: true},
		Upstreams: upstreams,
	}
	endpoints := command.EndpointsFromUpstreams(cmd.Upstreams)
	_, err = p.proxyRequest(w, req, cmd, endpoints)
	return err
}
Beispiel #2
0
// Main request handler, accepts requests, round trips it to the upstream
// proxies back the response.
func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	p.metrics.Requests.Mark(1)
	glog.Infof("Serving Request %s %s", req.Method, req.RequestURI)

	// Ask controller for instructions
	cmdI, err := p.controller.GetInstructions(req)
	if err != nil {
		glog.Errorf("Error getting instructions: %s", err)
		p.replyError(err, w, req)
		return
	}

	switch cmd := cmdI.(type) {
	case *command.Reply:
		// reply command provides the exact response
		// for the client. Proxy responds and hangs up.
		glog.Infof("Got Reply command: %v", cmd)
		p.metrics.CmdReply.Mark(1)
		p.replyCommand(cmd, w, req)
		return
	case *command.Forward:
		// Forward command contains list of upstreams
		// instructions for the failover and request modification
		glog.Infof("Got Forward command %v", cmd)
		p.metrics.CmdForward.Mark(1)
		// Get upstreams ready to process the request
		retrySeconds, err := p.rateLimit(cmd)
		if err != nil {
			p.replyError(err, w, req)
			return
		}
		if retrySeconds != 0 {
			p.replyError(&command.RetryError{Seconds: retrySeconds}, w, req)
			return
		}
		endpoints := command.EndpointsFromUpstreams(cmd.Upstreams)
		requestBytes, err := p.proxyRequest(w, req, cmd, endpoints)
		if err != nil {
			glog.Error("Failed to proxy to all upstreams:", err)
			p.replyError(&command.AllUpstreamsDownError{}, w, req)
			return
		}
		p.updateRates(requestBytes, cmd)
		return
	}
	p.replyError(fmt.Errorf("Internal logic error"), w, req)
}