// Run skipper. Expects address to listen on and one or more urls to find // the etcd service at. If the flag 'insecure' is true, skipper will accept // invalid TLS certificates from the backends. // If a routesFilePath is given, that file will be used INSTEAD of etcd func Run(address string, etcdUrls []string, storageRoot string, insecure bool, routesFilePath string, customFilters ...skipper.FilterSpec) error { var dataClient skipper.DataClient var err error if len(routesFilePath) > 0 { dataClient, err = settings.MakeFileDataClient(routesFilePath) if err != nil { return err } } else { dataClient, err = etcd.Make(etcdUrls, storageRoot) if err != nil { return err } } // create a filter registry with the available filter specs registered, // and register the custom filters registry := filters.RegisterDefault() registry.Add(customFilters...) // create a settings dispatcher instance // create a settings source // create the proxy instance dispatcher := dispatch.Make() settingsSource := settings.MakeSource(dataClient, registry, dispatcher) proxy := proxy.Make(settingsSource, insecure) // subscribe to new settings settingsChan := make(chan skipper.Settings) dispatcher.Subscribe(settingsChan) // start the http server log.Printf("listening on %v\n", address) return http.ListenAndServe(address, proxy) }
func makeTestSettingsDispatcher(url string, filters []skipper.Filter, shunt bool) skipper.SettingsDispatcher { sd := dispatch.Make() sd.Push() <- mock.MakeSettings(url, filters, shunt) // todo: don't let to get into busy loop c := make(chan skipper.Settings) sd.Subscribe(c) for { if s := <-c; s != nil { return sd } } }
func TestParseAndDispatchRawData(t *testing.T) { url1 := "https://www.zalando.de" data := `hello: Path("/hello") -> "https://www.zalando.de"` dc := mock.MakeDataClient(data) mwr := &mock.FilterRegistry{} d := dispatch.Make() s := MakeSource(dc, mwr, d) c1 := make(chan skipper.Settings) c2 := make(chan skipper.Settings) s.Subscribe(c1) s.Subscribe(c2) r, _ := http.NewRequest("GET", "http://localhost:9090/hello", nil) // let the settings be populated: time.Sleep(3 * time.Millisecond) s1 := <-c1 s2 := <-c2 rt1, _ := s1.Route(r) rt2, _ := s2.Route(r) up1, _ := url.ParseRequestURI(url1) if rt1.Backend().Scheme() != up1.Scheme || rt1.Backend().Host() != up1.Host || rt2.Backend().Scheme() != up1.Scheme || rt2.Backend().Host() != up1.Host { t.Error("wrong url 1") } data = `hello: Path("/hello") -> "https://www.zalan.do"` dc.Feed(data) // let the new settings fan through time.Sleep(3 * time.Millisecond) s1 = <-c1 s2 = <-c2 rt1, _ = s1.Route(r) rt2, _ = s2.Route(r) up2, _ := url.ParseRequestURI("https://www.zalan.do") if rt1.Backend().Scheme() != up2.Scheme || rt1.Backend().Host() != up2.Host || rt2.Backend().Scheme() != up2.Scheme || rt2.Backend().Host() != up2.Host { t.Error("wrong url 2") } }
func TestNotFoundUntilSettingsReceived(t *testing.T) { payload := []byte("Hello World!") s := startTestServer(payload, 0, func(r *http.Request) { t.Error("shouldn't be able to route to here") }) defer s.Close() u, _ := url.ParseRequestURI("http://localhost:9090/hello/") r := &http.Request{ URL: u, Method: "GET", Header: http.Header{"X-Test-Header": []string{"test value"}}} w := httptest.NewRecorder() p := Make(dispatch.Make(), false) p.ServeHTTP(w, r) if w.Code != 404 { t.Error("wrong status", w.Code) } }