| 144 | } |
| 145 | |
| 146 | func (p *Proxy) Start() error { |
| 147 | // Setup listener first, so we can fail early if the port is in use. |
| 148 | listener, err := net.Listen("tcp", fmt.Sprintf(":%d", p.cfg.ServerServicePort)) |
| 149 | if err != nil { |
| 150 | return err |
| 151 | } |
| 152 | |
| 153 | router := mux.NewRouter() |
| 154 | |
| 155 | // Health check endpoint. |
| 156 | router.Path("/").Methods("GET").Handler(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { |
| 157 | w.WriteHeader(http.StatusOK) |
| 158 | })) |
| 159 | |
| 160 | // register routes |
| 161 | for _, route := range p.routes { |
| 162 | var comparator ResponsesComparator |
| 163 | if p.cfg.CompareResponses { |
| 164 | comparator = route.ResponseComparator |
| 165 | } |
| 166 | router.Path(route.Path).Methods(route.Methods...).Handler(NewProxyEndpoint(p.backends, route.RouteName, p.metrics, p.logger, comparator)) |
| 167 | } |
| 168 | |
| 169 | if p.cfg.PassThroughNonRegisteredRoutes { |
| 170 | for _, backend := range p.backends { |
| 171 | if backend.preferred { |
| 172 | router.PathPrefix("/").Handler(httputil.NewSingleHostReverseProxy(backend.endpoint)) |
| 173 | break |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | p.srvListener = listener |
| 179 | p.srv = &http.Server{ |
| 180 | ReadTimeout: 1 * time.Minute, |
| 181 | WriteTimeout: 2 * time.Minute, |
| 182 | Handler: router, |
| 183 | } |
| 184 | |
| 185 | // Run in a dedicated goroutine. |
| 186 | p.done.Go(func() { |
| 187 | |
| 188 | if err := p.srv.Serve(p.srvListener); err != nil { |
| 189 | level.Error(p.logger).Log("msg", "Proxy server failed", "err", err) |
| 190 | } |
| 191 | }) |
| 192 | |
| 193 | level.Info(p.logger).Log("msg", "The proxy is up and running.") |
| 194 | return nil |
| 195 | } |
| 196 | |
| 197 | func (p *Proxy) Stop() error { |
| 198 | if p.srv == nil { |