func (r *RouteFetcher) deleteEndpoints(validRoutes []models.Route) { var diff []models.Route for _, curRoute := range r.endpoints { routeFound := false for _, validRoute := range validRoutes { if routeEquals(curRoute, validRoute) { routeFound = true break } } if !routeFound { diff = append(diff, curRoute) } } for _, aRoute := range diff { r.RouteRegistry.Unregister( route.Uri(aRoute.Route), route.NewEndpoint( aRoute.LogGuid, aRoute.IP, uint16(aRoute.Port), aRoute.LogGuid, "", nil, aRoute.GetTTL(), aRoute.RouteServiceUrl, aRoute.ModificationTag, )) } }
func registerAddr(reg *registry.RouteRegistry, path string, routeServiceUrl string, addr net.Addr, instanceId, instanceIndex, appId string) { host, portStr, err := net.SplitHostPort(addr.String()) Expect(err).NotTo(HaveOccurred()) port, err := strconv.Atoi(portStr) Expect(err).NotTo(HaveOccurred()) reg.Register(route.Uri(path), route.NewEndpoint(appId, host, uint16(port), instanceId, instanceIndex, nil, -1, routeServiceUrl, models.ModificationTag{})) }
func (r *Trie) toMap(segment string, m map[route.Uri]*route.Pool) map[route.Uri]*route.Pool { if r.Pool != nil { m[route.Uri(segment)] = r.Pool } for _, child := range r.ChildNodes { var newseg string if len(segment) == 0 { newseg = segment + child.Segment } else { newseg = segment + "/" + child.Segment } child.toMap(newseg, m) } return m }
func (p *proxy) lookup(request *http.Request) *route.Pool { requestPath := request.URL.EscapedPath() uri := route.Uri(hostWithoutPort(request) + requestPath) appInstanceHeader := request.Header.Get(router_http.CfAppInstance) if appInstanceHeader != "" { appId, appIndex, err := router_http.ValidateCfAppInstance(appInstanceHeader) if err != nil { p.logger.Error("invalid-app-instance-header", err) return nil } else { return p.registry.LookupWithInstance(uri, appId, appIndex) } } return p.registry.Lookup(uri) }
func (r *RouteFetcher) HandleEvent(e routing_api.Event) { eventRoute := e.Route uri := route.Uri(eventRoute.Route) endpoint := route.NewEndpoint( eventRoute.LogGuid, eventRoute.IP, uint16(eventRoute.Port), eventRoute.LogGuid, "", nil, eventRoute.GetTTL(), eventRoute.RouteServiceUrl, eventRoute.ModificationTag) switch e.Action { case "Delete": r.RouteRegistry.Unregister(uri, endpoint) case "Upsert": r.RouteRegistry.Register(uri, endpoint) } }
func (r *RouteFetcher) refreshEndpoints(validRoutes []models.Route) { r.deleteEndpoints(validRoutes) r.endpoints = validRoutes for _, aRoute := range r.endpoints { r.RouteRegistry.Register( route.Uri(aRoute.Route), route.NewEndpoint( aRoute.LogGuid, aRoute.IP, uint16(aRoute.Port), aRoute.LogGuid, "", nil, aRoute.GetTTL(), aRoute.RouteServiceUrl, aRoute.ModificationTag, )) } }
var _ = Describe("AccessLogRecord", func() { Measure("Register", func(b Benchmarker) { logger := lagertest.NewTestLogger("test") c := config.DefaultConfig() r := registry.NewRouteRegistry(logger, c, new(fakes.FakeRouteRegistryReporter)) accesslog, err := access_log.CreateRunningAccessLogger(logger, c) Expect(err).ToNot(HaveOccurred()) proxy.NewProxy(proxy.ProxyArgs{ EndpointTimeout: c.EndpointTimeout, Ip: c.Ip, TraceKey: c.TraceKey, Registry: r, Reporter: varz.NewVarz(r), AccessLogger: accesslog, }) b.Time("RegisterTime", func() { for i := 0; i < 1000; i++ { str := strconv.Itoa(i) r.Register( route.Uri("bench.vcap.me."+str), route.NewEndpoint("", "localhost", uint16(i), "", "", nil, -1, "", models.ModificationTag{}), ) } }) }, 10) })
err = natsClient.Publish("router.register", data) Expect(err).ToNot(HaveOccurred()) Consistently(registry.RegisterCallCount).Should(BeZero()) }) }) }) Context("when a route is unregistered through NATS", func() { BeforeEach(func() { process = ifrit.Invoke(sub) Eventually(process.Ready()).Should(BeClosed()) }) It("does not race against registrations", func() { racingURI := route.Uri("test3.example.com") racingMsg := mbus.RegistryMessage{ Host: "host", App: "app", RouteServiceURL: "https://url.example.com", PrivateInstanceID: "id", PrivateInstanceIndex: "index", Port: 1111, StaleThresholdInSeconds: 120, Uris: []route.Uri{racingURI}, Tags: map[string]string{"key": "value"}, } racingData, err := json.Marshal(racingMsg) Expect(err).NotTo(HaveOccurred())
*response[1].TTL = 1 *response[2].TTL = 1 }) It("updates the route registry", func() { client.RoutesReturns(response, nil) err := fetcher.FetchRoutes() Expect(err).ToNot(HaveOccurred()) Expect(registry.RegisterCallCount()).To(Equal(3)) for i := 0; i < 3; i++ { expectedRoute := response[i] uri, endpoint := registry.RegisterArgsForCall(i) Expect(uri).To(Equal(route.Uri(expectedRoute.Route))) Expect(endpoint).To(Equal( route.NewEndpoint(expectedRoute.LogGuid, expectedRoute.IP, uint16(expectedRoute.Port), expectedRoute.LogGuid, "", nil, *expectedRoute.TTL, expectedRoute.RouteServiceUrl, expectedRoute.ModificationTag, ))) } }) It("uses cache when fetching token from UAA", func() { client.RoutesReturns(response, nil)
Ip: conf.Ip, TraceKey: conf.TraceKey, Registry: r, Reporter: test_helpers.NullVarz{}, Logger: logger, AccessLogger: fakeAccessLogger, SecureCookies: conf.SecureCookies, TLSConfig: tlsConfig, RouteServiceEnabled: conf.RouteServiceEnabled, RouteServiceTimeout: conf.RouteServiceTimeout, Crypto: crypto, CryptoPrev: cryptoPrev, HealthCheckUserAgent: "HTTP-Monitor/1.1", }) r.Register(route.Uri("some-app"), &route.Endpoint{}) }) Context("when backend fails to respond", func() { It("logs the error and associated endpoint", func() { body := []byte("some body") req := test_util.NewRequest("GET", "some-app", "/", bytes.NewReader(body)) resp := httptest.NewRecorder() proxyObj.ServeHTTP(resp, req) Eventually(logger).Should(Say("error")) Eventually(logger).Should(Say("route-endpoint")) }) })
package route_test import ( "code.cloudfoundry.org/gorouter/route" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("URIs", func() { Context("RouteKey", func() { var key route.Uri It("creates a route key based on uri", func() { key = route.Uri("dora.app.com").RouteKey() Expect(key.String()).To(Equal("dora.app.com")) key = route.Uri("dora.app.com/").RouteKey() Expect(key.String()).To(Equal("dora.app.com")) key = route.Uri("dora.app.com/v1").RouteKey() Expect(key.String()).To(Equal("dora.app.com/v1")) }) Context("has a context path", func() { It("creates route key with context path", func() { key = route.Uri("dora.app.com/v1").RouteKey() Expect(key.String()).To(Equal("dora.app.com/v1"))
Expect(logger).ToNot(gbytes.Say(`prune.*"log_level":0.*foo.com/bar`)) }) }) Context("when suspend pruning is triggered (i.e. nats offline)", func() { var totalRoutes int BeforeEach(func() { totalRoutes = 1000 Expect(r.NumUris()).To(Equal(0)) Expect(r.NumEndpoints()).To(Equal(0)) // add endpoints for i := 0; i < totalRoutes; i++ { e := route.NewEndpoint("12345", "192.168.1.1", uint16(1024+i), "id1", "", nil, -1, "", modTag) r.Register(route.Uri(fmt.Sprintf("foo-%d", i)), e) } r.StartPruningCycle() r.SuspendPruning(func() bool { return true }) time.Sleep(configObj.PruneStaleDropletsInterval + configObj.DropletStaleThreshold) }) It("does not remove any routes", func() { Expect(r.NumUris()).To(Equal(totalRoutes)) Expect(r.NumEndpoints()).To(Equal(totalRoutes)) interval := configObj.PruneStaleDropletsInterval + 50*time.Millisecond Eventually(logger, interval).Should(gbytes.Say("prune-suspended")) Expect(r.NumUris()).To(Equal(totalRoutes))
}) for _, e := range endpoints { pool.Remove(e) } } It("responds with a 502 BadGateway", func() { ln := registerHandler(r, "nil-endpoint", func(conn *test_util.HttpConn) { conn.CheckLine("GET / HTTP/1.1") resp := test_util.NewResponse(http.StatusOK) conn.WriteResponse(resp) conn.Close() }) defer ln.Close() removeAllEndpoints(r.Lookup(route.Uri("nil-endpoint"))) conn := dialProxy(proxyServer) req := test_util.NewRequest("GET", "nil-endpoint", "/", nil) conn.WriteRequest(req) b := make([]byte, 0, 0) buf := bytes.NewBuffer(b) log.SetOutput(buf) res, _ := conn.ReadResponse() log.SetOutput(os.Stderr) Expect(buf).NotTo(ContainSubstring("multiple response.WriteHeader calls")) Expect(res.StatusCode).To(Equal(http.StatusBadGateway)) }) It("does not capture routing response", func() {