Coder Social home page Coder Social logo

httpsink's Introduction

HTTPSink

Capture all requests that come into the server and be able to get those requests later for examination. Useful for faking API endpoints.

Using configuration or environment variables, you can set the foreign API endpoint in your code to use "localhost:8888" (or any port). Now, in tests, you can use httpsink to stand up an HTTP sink that will either just swallow up your requests or you can choose for it to yield a desired response.

Features

  • Set port or just use a random available port.
  • Inspect the requests that come into the sink via the sink /get?request_number=:request_number endpoint where request_number is the zero-indexed request to come into the sink.
  • Set the desired response from the sink.
  • Set a capacity for the total number of requests that the sink will allow before it rejects them.
  • Clear stored requests
  • Specify if you want to get the body of the request only
  • Run multiple sinks at the same time.

Example:

func TestSomeCode(t *testing.T) {
	// set up the sink (optionally set the port with the NewHTTPSinkOnAdder("localhost:8888"))
	hSync, _ := NewHTTPSink()
	defer hSync.Close()

	// set the behavior of the foreign API endpoint
	expectedBody := []byte(`{"key":"value"}`)
	hSync.SetResponse(&SimpleResponseWriter{StatusCode: http.StatusTeapot, Body: expectedBody})

	// Set the number of requests that you want to capture.
	// If unset (ie, 0), the sync will never store results and always give back your default response.
	// If set, the server will only accept at max that many requests before returning errors.
	// Capacity must be set for httpsink to store the result for later retrieval.
	hSync.Capacity = 5

	// make call to your code that in-turn makes a call to the foreign API endpoint
	err := sendAPIRequest()
	if err != nil{
	  t.Errorf("error sending api request - %s", err)
	}

	// optionaly verify that the foreign API got the right request if you like
	// hSync.Capacity will have to have been set for this to work.
	getURL := fmt.Sprintf("http://%s/get?request_number=0", hSync.Addr)
	getResp, _ := http.Get(getURL)
	defer getResp.Body.Close()

    // cannot marshal into http.Request due to Body being a ReadCloser()
    // hSync.RequestMask allows us to get access to the Body
	capturedRequest := hSync.RequestMask{}

	// ignoring the error because http.Request.Body does not play well with json.Decode
	// it works for this example, but you could also make a custom struct or use simplejson
	// if using a custom struct, just embedd *http.Request and mask with a Body interface{} property
	_ = json.NewDecoder(getResp.Body).Decode(&capturedRequest)

	if !strings.Contains(capturedRequest.URL.RawQuery, "some_key=some_value") {
		t.Errorf("captured request in sync did not capture proper query - %s", capturedRequest.URL.RawQuery)
	}

	// if you need to clear the stored requests to make room for the next call/test,
	// use the following endpoint. It will return a 204
	clearURL := fmt.Sprintf("http://%s/clear", hSync.Addr)
	http.Get(clearURL)

	// to get the actual request body, set the following hSync config and call get normally
	hSync.BodyOnly = true
	bodyResp, _ := http.Get(getURL)
	defer bodyResp.Body.Close()
}

The response that come back from captured responses at http://$hSync.Addr/get?request_number=x will look like the following, and can be marshalled into httpsink.RequestMask{}:

{"Method":"POST","URL":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/some/url","RawPath":"","RawQuery":"some_key=some_value\u0026some_other_key=some_other_value","Fragment":""},"Proto":"HTTP/1.1","ProtoMajor":1,"ProtoMinor":1,"Header":{"Accept-Encoding":["gzip"],"Content-Length":["16"],"Content-Type":["application/x-www-form-urlencoded"],"User-Agent":["Go-http-client/1.1"]},"ContentLength":16,"TransferEncoding":null,"Close":false,"Host":"127.0.0.1:55987","Form":null,"PostForm":null,"MultipartForm":null,"Trailer":null,"RemoteAddr":"127.0.0.1:55988","RequestURI":"/some/url?some_key=some_value\u0026some_other_key=some_other_value","TLS":null,"Body":"id=123\u0026key=Value","Cancel":null}

httpsink's People

Contributors

trotha01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.