Пример #1
0
func Test_rebuildHashes_whenDataIsHashedForAProxy_andStillAProxy_keysAreNotChanged(t *testing.T) {
	RegisterTestingT(t)
	webserver := false

	db := cache.NewInMemoryCache()

	pair := models.RequestResponsePair{
		Request: models.RequestDetails{
			Path:        "/hello",
			Destination: "a-host.com",
		},
		Response: models.ResponseDetails{
			Body: "a body",
		},
	}

	pairBytes, _ := pair.Encode()

	db.Set([]byte(pair.Id()), pairBytes)

	rebuildHashes(db, webserver)

	result, err := db.Get([]byte(pair.Id()))

	Expect(err).To(BeNil())
	Expect(result).To(Equal(pairBytes))
}
Пример #2
0
func TestImportImportRequestResponsePairs_CanImportAMultiplePairs(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	originalPair1 := v1.RequestResponsePairView{
		Response: v1.ResponseDetailsView{
			Status:      200,
			Body:        "hello_world",
			EncodedBody: false,
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}},
		},
		Request: v1.RequestDetailsView{
			Path:        StringToPointer("/"),
			Method:      StringToPointer("GET"),
			Destination: StringToPointer("/"),
			Scheme:      StringToPointer("scheme"),
			Query:       StringToPointer(""),
			Body:        StringToPointer(""),
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}}}}

	originalPair2 := originalPair1
	originalPair2.Request.Path = StringToPointer("/new/path")

	originalPair3 := originalPair1
	originalPair3.Request.Path = StringToPointer("/newer/path")

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{originalPair1, originalPair2, originalPair3})

	pairBytes, err := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	Expect(err).To(BeNil())
	decodedPair1, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair1).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair1)))

	pairBytes, err = cache.Get([]byte("9c03e4af1f30542ff079a712bddad602"))
	Expect(err).To(BeNil())
	decodedPair2, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair2).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair2)))

	pairBytes, err = cache.Get([]byte("fd099332afee48101edb7441b098cd4a"))
	Expect(err).To(BeNil())
	decodedPair3, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair3).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair3)))
}
Пример #3
0
func TestImportRequestResponsePairs_CanImportASinglePair(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	originalPair := v1.RequestResponsePairView{
		Response: v1.ResponseDetailsView{
			Status:      200,
			Body:        "hello_world",
			EncodedBody: false,
			Headers:     map[string][]string{"Content-Type": []string{"text/plain"}}},
		Request: v1.RequestDetailsView{
			Path:        StringToPointer("/"),
			Method:      StringToPointer("GET"),
			Destination: StringToPointer("/"),
			Scheme:      StringToPointer("scheme"),
			Query:       StringToPointer(""),
			Body:        StringToPointer(""),
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}}}}

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{originalPair})
	value, _ := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	decodedPair, _ := models.NewRequestResponsePairFromBytes(value)
	Expect(*decodedPair).To(Equal(models.RequestResponsePair{
		Response: models.ResponseDetails{
			Status:  200,
			Body:    "hello_world",
			Headers: map[string][]string{"Content-Type": []string{"text/plain"}},
		},
		Request: models.RequestDetails{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{
				"Content-Type": []string{"text/plain; charset=utf-8"},
				"Hoverfly":     []string{"testing"},
			},
		},
	}))
}
Пример #4
0
func TestImportImportRequestResponsePairs_CanImportASingleBase64EncodedPair(t *testing.T) {
	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	encodedPair := views.RequestResponsePairView{
		Response: views.ResponseDetailsView{
			Status:      200,
			Body:        base64String("hello_world"),
			EncodedBody: true,
			Headers:     map[string][]string{"Content-Encoding": []string{"gzip"}}},
		Request: views.RequestDetailsView{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{"Hoverfly": []string{"testing"}}}}

	hv.ImportRequestResponsePairViews([]views.RequestResponsePairView{encodedPair})

	value, err := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	Expect(err).To(BeNil())

	decodedPair, err := models.NewRequestResponsePairFromBytes(value)
	Expect(err).To(BeNil())

	Expect(decodedPair).ToNot(Equal(models.RequestResponsePair{
		Response: models.ResponseDetails{
			Status:  200,
			Body:    "hello_world",
			Headers: map[string][]string{"Content-Encoding": []string{"gzip"}}},
		Request: models.RequestDetails{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{"Hoverfly": []string{"testing"}}}}))
}
Пример #5
0
func TestImportImportRequestResponsePairs_CanImportARequestTemplateResponsePair(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	requestTemplate := v1.RequestDetailsView{
		RequestType: StringToPointer("template"),
		Method:      StringToPointer("GET"),
	}

	responseView := v1.ResponseDetailsView{
		Status:      200,
		Body:        "hello_world",
		EncodedBody: false,
		Headers:     map[string][]string{"Hoverfly": []string{"testing"}},
	}

	templatePair := v1.RequestResponsePairView{
		Response: responseView,
		Request:  requestTemplate,
	}

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{templatePair})

	Expect(len(hv.RequestMatcher.TemplateStore)).To(Equal(1))

	request := models.NewRequestDetailsFromRequest(requestTemplate)
	responseFromCache, err := hv.RequestMatcher.TemplateStore.GetResponse(request, false)
	Expect(err).To(BeNil())

	response := models.NewResponseDetailsFromResponse(responseView)

	Expect(*responseFromCache).To(Equal(response))
}
Пример #6
0
func main() {
	log.SetFormatter(&log.JSONFormatter{})
	flag.Var(&importFlags, "import", "import from file or from URL (i.e. '-import my_service.json' or '-import http://mypage.com/service_x.json'")
	flag.Var(&destinationFlags, "dest", "specify which hosts to process (i.e. '-dest fooservice.org -dest barservice.org -dest catservice.org') - other hosts will be ignored will passthrough'")
	flag.Parse()

	if *version {
		fmt.Println(hoverflyVersion)
		os.Exit(0)
	}

	// getting settings
	cfg := hv.InitSettings()

	if *verbose {
		// Only log the warning severity or above.
		log.SetLevel(log.DebugLevel)
	}
	cfg.Verbose = *verbose

	if *dev {
		// making text pretty
		log.SetFormatter(&log.TextFormatter{})
	}

	if *generateCA {
		tlsc, err := hvc.GenerateAndSave(*certName, *certOrg, 365*24*time.Hour)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Fatal("failed to generate certificate.")
		}
		goproxy.GoproxyCa = *tlsc

	} else if *cert != "" && *key != "" {
		tlsc, err := tls.LoadX509KeyPair(*cert, *key)
		if err != nil {
			log.Fatalf("Failed to load certifiate and key pair, got error: %s", err.Error())
		}

		goproxy.GoproxyCa = tlsc

	}

	// overriding environment variables (proxy and admin ports)
	if *proxyPort != "" {
		cfg.ProxyPort = *proxyPort
	}
	if *adminPort != "" {
		cfg.AdminPort = *adminPort
	}

	// development settings
	cfg.Development = *dev

	// overriding default middleware setting
	cfg.Middleware = *middleware

	mode := getInitialMode(cfg)

	// setting mode
	cfg.SetMode(mode)

	// disabling authentication if no-auth for auth disabled env variable
	if *authEnabled {
		cfg.AuthEnabled = true
	}

	// disabling tls verification if flag or env variable is set to 'false' (defaults to true)
	if !cfg.TLSVerification || !*tlsVerification {
		cfg.TLSVerification = false
		log.Info("tls certificate verification is now turned off!")
	}

	if len(destinationFlags) > 0 {
		cfg.Destination = strings.Join(destinationFlags[:], "|")

	} else {
		//  setting destination regexp
		cfg.Destination = *destination
	}

	var requestCache cache.Cache
	var metadataCache cache.Cache
	var tokenCache cache.Cache
	var userCache cache.Cache

	if *databasePath != "" {
		cfg.DatabasePath = *databasePath
	}

	if *database == boltBackend {
		log.Info("Creating bolt db backend...")
		db := cache.GetDB(cfg.DatabasePath)
		defer db.Close()
		requestCache = cache.NewBoltDBCache(db, []byte("requestsBucket"))
		metadataCache = cache.NewBoltDBCache(db, []byte("metadataBucket"))
		tokenCache = cache.NewBoltDBCache(db, []byte(backends.TokenBucketName))
		userCache = cache.NewBoltDBCache(db, []byte(backends.UserBucketName))
	} else if *database == inmemoryBackend {
		log.Info("Creating in memory map backend...")
		log.Warn("Turning off authentication...")
		cfg.AuthEnabled = false

		requestCache = cache.NewInMemoryCache()
		metadataCache = cache.NewInMemoryCache()
		tokenCache = cache.NewInMemoryCache()
		userCache = cache.NewInMemoryCache()
	} else {
		log.Fatalf("unknown database type chosen: %s", *database)
	}

	authBackend := backends.NewCacheBasedAuthBackend(tokenCache, userCache)

	hoverfly := hv.GetNewHoverfly(cfg, requestCache, metadataCache, authBackend)

	// if add new user supplied - adding it to database
	if *addNew {
		err := hoverfly.Authentication.AddUser(*addUser, *addPassword, *isAdmin)
		if err != nil {
			log.WithFields(log.Fields{
				"error":    err.Error(),
				"username": *addUser,
			}).Fatal("failed to add new user")
		} else {
			log.WithFields(log.Fields{
				"username": *addUser,
			}).Info("user added successfuly")
		}
		return
	}
	if cfg.AuthEnabled {
		if os.Getenv(hv.HoverflyAdminUsernameEV) != "" && os.Getenv(hv.HoverflyAdminPasswordEV) != "" {
			hoverfly.Authentication.AddUser(
				os.Getenv(hv.HoverflyAdminUsernameEV),
				os.Getenv(hv.HoverflyAdminPasswordEV),
				true)
		}

		// checking if there are any users
		users, err := hoverfly.Authentication.GetAllUsers()
		if err != nil {
			log.WithFields(log.Fields{
				"error": err,
			}).Fatal("got error while trying to get all users")
		}
		if len(users) < 1 {
			createSuperUser(hoverfly)
		}
	}

	// importing records if environment variable is set
	ev := os.Getenv(hv.HoverflyImportRecordsEV)
	if ev != "" {
		err := hoverfly.Import(ev)
		if err != nil {
			log.WithFields(log.Fields{
				"error":  err.Error(),
				"import": ev,
			}).Fatal("Environment variable for importing was set but failed to import this resource")
		} else {
			err = hoverfly.MetadataCache.Set([]byte("import_from_env_variable"), []byte(ev))
		}
	}

	// importing stuff
	if len(importFlags) > 0 {
		for i, v := range importFlags {
			if v != "" {
				log.WithFields(log.Fields{
					"import": v,
				}).Debug("Importing given resource")
				err := hoverfly.Import(v)
				if err != nil {
					log.WithFields(log.Fields{
						"error":  err.Error(),
						"import": v,
					}).Fatal("Failed to import given resource")
				} else {
					err = hoverfly.MetadataCache.Set([]byte(fmt.Sprintf("import_%d", i+1)), []byte(v))
				}
			}
		}
	}

	// start metrics registry flush
	if *metrics {
		hoverfly.Counter.Init()
	}

	cfg.Webserver = *webserver

	err := hoverfly.StartProxy()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Fatal("failed to start proxy...")
	}

	// starting admin interface, this is blocking
	hoverfly.StartAdminInterface()
}
Пример #7
0
func TestImportImportRequestResponsePairs_CanImportARequestResponsePair_AndRequestTemplateResponsePair(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	requestTemplate := v1.RequestDetailsView{
		RequestType: StringToPointer("template"),
		Method:      StringToPointer("GET"),
	}

	requestView := v1.RequestDetailsView{
		Method:      StringToPointer("GET"),
		Path:        StringToPointer("/"),
		Destination: StringToPointer("test.com"),
		Scheme:      StringToPointer("http"),
	}

	responseView := v1.ResponseDetailsView{
		Status:      200,
		Body:        "hello_world",
		EncodedBody: false,
		Headers:     map[string][]string{"Hoverfly": []string{"testing"}},
	}

	templatePair := v1.RequestResponsePairView{
		Request:  requestTemplate,
		Response: responseView,
	}

	ordinaryPair := v1.RequestResponsePairView{
		Request:  requestView,
		Response: responseView,
	}

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{templatePair, ordinaryPair})

	cacheCount, err := hv.RequestCache.RecordsCount()
	Expect(cacheCount).To(Equal(1))
	Expect(err).To(BeNil())

	Expect(len(hv.RequestMatcher.TemplateStore)).To(Equal(1))

	request := models.NewRequestDetailsFromRequest(requestTemplate)
	response := models.NewResponseDetailsFromResponse(responseView)

	pairBytes, err := hv.RequestCache.Get([]byte("76cf08e38439f083de2658b0971df9bf"))
	Expect(err).To(BeNil())

	savedPair, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())

	Expect(savedPair.Response).To(Equal(response))

	responseFromCache, err := hv.RequestMatcher.TemplateStore.GetResponse(request, false)
	Expect(err).To(BeNil())
	Expect(*responseFromCache).To(Equal(response))

}