func (p *Pool) Handle(logRecord *logger.HAProxyLogRecord) { pTime := time.Now() if p.Dummy { logger.Printf("[pool %s] Dummy", p.Name) logRecord.Error(logger.BadGatewayMsg, http.StatusBadGateway) logRecord.Terminate("Pool: " + logger.BadGatewayMsg) return } p.Metrics.ConnectionStart() defer p.Metrics.ConnectionDone() server := p.Next() if server == nil { // reachable when all servers in pool report StatusMaintenance logger.Printf("[pool %s] no server", p.Name) logRecord.Error(logger.ServiceUnavailableMsg, http.StatusServiceUnavailable) logRecord.Terminate("Pool: " + logger.ServiceUnavailableMsg) return } logRecord.PoolUpdateRecord(p.Name, p.Metrics.GetActiveConnections(), p.Metrics.GetTotalConnections(), pTime) server.Handle(logRecord, p.Config.RequestTimeout) }
func (s *Server) Handle(logRecord *logger.HAProxyLogRecord, tout time.Duration) { sTime := time.Now() s.Metrics.RequestStart() defer s.Metrics.RequestDone() // X-Forwarded-For; we are a proxy. ip := strings.Split(logRecord.Request.RemoteAddr, ":")[0] logRecord.Request.Header.Add("X-Forwarded-For", ip) logRecord.ServerUpdateRecord(s.Address, s.Metrics.RequestsServiced, s.Metrics.Cost(), sTime) resErrCh := make(chan ResponseError) tstart := time.Now() go s.RoundTrip(logRecord.Request, resErrCh) tend := time.Now() logRecord.UpdateTr(tstart, tend) select { case resErr := <-resErrCh: if resErr.Error == nil { defer resErr.Response.Body.Close() logRecord.CopyHeaders(resErr.Response.Header) logRecord.WriteHeader(resErr.Response.StatusCode) err := logRecord.Copy(resErr.Response.Body) if err != nil { logger.Errorf("[server %s] failed attempting to copy response body: %s\n", s.Address, err) } else { logRecord.Log() } } else { logger.Errorf("[server %s] failed attempting the roundtrip: %s\n", s.Address, resErr.Error) logRecord.Error(logger.BadGatewayMsg, http.StatusBadGateway) logRecord.Terminate("Server: " + logger.BadGatewayMsg) } case <-time.After(tout): s.Transport.CancelRequest(logRecord.Request) logger.Printf("[server %s] round trip timed out!", s.Address) logRecord.Error(logger.GatewayTimeoutMsg, http.StatusGatewayTimeout) logRecord.Terminate("Server: " + logger.GatewayTimeoutMsg) } }