예제 #1
0
func TestRequestBodySentToMiddleware(t *testing.T) {
	RegisterTestingT(t)

	// sends a request with fizz=buzz body, server responds with {'message': 'here'}
	// then, since it's modify mode - middleware is applied again, this time
	// middleware takes original request body and replaces response body with it.
	server, dbClient := testTools(200, `{'message': 'here'}`)
	defer server.Close()

	requestBody := []byte("fizz=buzz")

	body := ioutil.NopCloser(bytes.NewBuffer(requestBody))

	req, err := http.NewRequest("POST", "http://capture_body.com", body)
	Expect(err).To(BeNil())

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	Expect(err).To(BeNil())

	dbClient.Cfg.Middleware.FullCommand = "./examples/middleware/reflect_body/reflect_body.py"

	resp, err := dbClient.modifyRequestResponse(req, requestDetails)

	// body from the request should be in response body, instead of server's response
	responseBody, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	Expect(err).To(BeNil())
	Expect(string(responseBody)).To(Equal(string(requestBody)))

}
예제 #2
0
func TestGetResponseCorruptedRequestResponsePair(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(200, `{'message': 'here'}`)
	defer server.Close()

	requestBody := []byte("fizz=buzz")

	body := ioutil.NopCloser(bytes.NewBuffer(requestBody))

	req, err := http.NewRequest("POST", "http://capture_body.com", body)
	Expect(err).To(BeNil())

	_, err = dbClient.captureRequest(req)
	Expect(err).To(BeNil())

	fp := matching.GetRequestFingerprint(req, requestBody, false)

	dbClient.RequestCache.Set([]byte(fp), []byte("you shall not decode me!"))

	// repeating process
	bodyNew := ioutil.NopCloser(bytes.NewBuffer(requestBody))

	reqNew, err := http.NewRequest("POST", "http://capture_body.com", bodyNew)
	Expect(err).To(BeNil())

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(reqNew)
	Expect(err).To(BeNil())

	response, err := dbClient.getResponse(reqNew, requestDetails)
	Expect(err).ToNot(BeNil())

	Expect(response).To(BeNil())
}
예제 #3
0
func TestMatchOnRequestBody(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(200, `{'message': 'here'}`)
	defer server.Close()

	// preparing and saving requests/responses with unique bodies
	for i := 0; i < 5; i++ {
		requestBody := []byte(fmt.Sprintf("fizz=buzz, number=%d", i))
		body := ioutil.NopCloser(bytes.NewBuffer(requestBody))

		request, err := http.NewRequest("POST", "http://capture_body.com", body)
		Expect(err).To(BeNil())

		resp := models.ResponseDetails{
			Status: 200,
			Body:   fmt.Sprintf("body here, number=%d", i),
		}
		pair := models.RequestResponsePair{Response: resp}

		// creating response
		c := NewConstructor(request, pair)
		response := c.ReconstructResponse()

		dbClient.save(request, requestBody, response, []byte(resp.Body))
	}

	// now getting responses
	for i := 0; i < 5; i++ {
		requestBody := []byte(fmt.Sprintf("fizz=buzz, number=%d", i))
		body := ioutil.NopCloser(bytes.NewBuffer(requestBody))

		request, err := http.NewRequest("POST", "http://capture_body.com", body)
		Expect(err).To(BeNil())

		requestDetails, err := models.NewRequestDetailsFromHttpRequest(request)
		Expect(err).To(BeNil())

		response, err := dbClient.getResponse(request, requestDetails)
		Expect(err).To(BeNil())

		responseBody, err := ioutil.ReadAll(response.Body)
		response.Body.Close()

		Expect(err).To(BeNil())
		Expect(string(responseBody)).To(Equal(fmt.Sprintf("body here, number=%d", i)))

	}

}
예제 #4
0
func TestModifyRequestNoMiddleware(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(201, `{'message': 'here'}`)
	defer server.Close()

	dbClient.Cfg.Middleware.FullCommand = ""

	req, err := http.NewRequest("GET", "http://very-interesting-website.com/q=123", nil)
	Expect(err).To(BeNil())

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	Expect(err).To(BeNil())

	_, err = dbClient.modifyRequestResponse(req, requestDetails)
	Expect(err).ToNot(BeNil())
}
예제 #5
0
func TestGetNotRecordedRequest(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(200, `{'message': 'here'}`)
	defer server.Close()

	request, err := http.NewRequest("POST", "http://capture_body.com", nil)
	Expect(err).To(BeNil())

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(request)
	Expect(err).To(BeNil())

	response, err := dbClient.getResponse(request, requestDetails)
	Expect(err).ToNot(BeNil())

	Expect(response).To(BeNil())
}
예제 #6
0
func TestModifyRequest(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(201, `{'message': 'here'}`)
	defer server.Close()

	dbClient.Cfg.Middleware.FullCommand = "./examples/middleware/modify_request/modify_request.py"

	req, err := http.NewRequest("GET", "http://very-interesting-website.com/q=123", nil)
	Expect(err).To(BeNil())

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	Expect(err).To(BeNil())

	response, err := dbClient.modifyRequestResponse(req, requestDetails)
	Expect(err).To(BeNil())

	// response should be changed to 202
	Expect(response.StatusCode).To(Equal(http.StatusAccepted))

}
예제 #7
0
// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (hf *Hoverfly) doRequest(request *http.Request) (*http.Request, *http.Response, error) {

	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	if hf.Cfg.Middleware.FullCommand != "" {
		// middleware is provided, modifying request
		var requestResponsePair models.RequestResponsePair

		rd, err := models.NewRequestDetailsFromHttpRequest(request)
		if err != nil {
			return nil, nil, err
		}
		requestResponsePair.Request = rd

		c := NewConstructor(request, requestResponsePair)

		err = c.ApplyMiddleware(&hf.Cfg.Middleware)

		if err != nil {
			log.WithFields(log.Fields{
				"mode":   hf.Cfg.Mode,
				"error":  err.Error(),
				"host":   request.Host,
				"method": request.Method,
				"path":   request.URL.Path,
			}).Error("could not forward request, middleware failed to modify request.")
			return nil, nil, err
		}

		request, err = c.ReconstructRequest()

		if err != nil {
			return nil, nil, err
		}
	}

	requestBody, _ := ioutil.ReadAll(request.Body)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))

	resp, err := hf.HTTP.Do(request)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))

	if err != nil {
		log.WithFields(log.Fields{
			"mode":   hf.Cfg.Mode,
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("could not forward request, failed to do an HTTP request.")
		return nil, nil, err
	}

	log.WithFields(log.Fields{
		"mode":   hf.Cfg.Mode,
		"host":   request.Host,
		"method": request.Method,
		"path":   request.URL.Path,
	}).Debug("response from external service got successfuly!")

	resp.Header.Set("hoverfly", "Was-Here")

	return request, resp, nil

}
예제 #8
0
// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (hf *Hoverfly) processRequest(req *http.Request) *http.Response {
	var response *http.Response

	mode := hf.Cfg.GetMode()

	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	if err != nil {
		return hoverflyError(req, err, "Could not interpret HTTP request", http.StatusServiceUnavailable)
	}

	if mode == CaptureMode {
		var err error
		response, err = hf.captureRequest(req)

		if err != nil {
			return hoverflyError(req, err, "Could not capture request", http.StatusServiceUnavailable)
		}
		log.WithFields(log.Fields{
			"mode":        mode,
			"middleware":  hf.Cfg.Middleware,
			"path":        req.URL.Path,
			"rawQuery":    req.URL.RawQuery,
			"method":      req.Method,
			"destination": req.Host,
		}).Info("request and response captured")

		return response

	} else if mode == SynthesizeMode {
		var err error
		response, err = SynthesizeResponse(req, requestDetails, &hf.Cfg.Middleware)

		if err != nil {
			return hoverflyError(req, err, "Could not create synthetic response!", http.StatusServiceUnavailable)
		}

		log.WithFields(log.Fields{
			"mode":        mode,
			"middleware":  hf.Cfg.Middleware,
			"path":        req.URL.Path,
			"rawQuery":    req.URL.RawQuery,
			"method":      req.Method,
			"destination": req.Host,
		}).Info("synthetic response created successfuly")

	} else if mode == ModifyMode {
		var err error
		response, err = hf.modifyRequestResponse(req, requestDetails)

		if err != nil {
			log.WithFields(log.Fields{
				"error":      err.Error(),
				"middleware": hf.Cfg.Middleware,
			}).Error("Got error when performing request modification")
			return hoverflyError(req, err, fmt.Sprintf("Middleware (%s) failed or something else happened!", hf.Cfg.Middleware), http.StatusServiceUnavailable)
		}

	} else {
		var err *matching.MatchingError
		response, err = hf.getResponse(req, requestDetails)
		if err != nil {
			return hoverflyError(req, err, err.Error(), err.StatusCode)
		}
	}

	respDelay := hf.ResponseDelays.GetDelay(requestDetails)
	if respDelay != nil {
		respDelay.Execute()
	}

	return response
}