Exemple #1
0
func TestSetHeaders(t *testing.T) {
	expectedFromEmptyHeader := http.Header{
		textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{openrtb.VERSION},
		"Content-Type": []string{"application/json; charset=utf-8"},
	}

	tests := []struct {
		input    http.Header
		expected http.Header
	}{
		// Should set from empty header.
		{
			http.Header{},
			expectedFromEmptyHeader,
		},

		// Should replace the old content type.
		{
			http.Header{"Content-Type": []string{"text/plain"}},
			expectedFromEmptyHeader,
		},

		// Should replace the old OpenRTB spec version.
		{
			http.Header{textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{"2.1"}},
			expectedFromEmptyHeader,
		},

		// Should keep existing, non-overlapped headers.
		{
			http.Header{"X-Additional-Header": []string{"for test"}},
			http.Header{
				textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{openrtb.VERSION},
				"Content-Type":        []string{"application/json; charset=utf-8"},
				"X-Additional-Header": []string{"for test"},
			},
		},
	}

	for i, test := range tests {
		t.Logf("Testint %d...", i)
		openrtb.SetHeaders(test.input)
		if !reflect.DeepEqual(test.input, test.expected) {
			t.Errorf("Expected the HTTP headers to be\n%v instead of\n%v.", test.expected, test.input)
		}
	}
}
Exemple #2
0
// Do method sends a high-level bid request and returns a high-level bid response following the
// OpenRTB specification and configurations on client.
//
// There are generally three kinds of errors that may be returned:
// 	- A NoBidError is returned when the HTTP status or bid response implies no-bid;
// 	- A net.Error with Timeout() == true may be returned when the underlying TCP connection or the
// 	  governing context expires;
// 	- Any other error unexpected, e.g. context.Canceled, which will be returned as its raw error
// 	  type; callers can panic or log errors depending on their use case.
//
// When err is nil, resp is always non-nil with non-nil properties. Callers does not need to manage
// underlying HTTP or TCP connection states but just use the resp to perform additional application
// logic.
func (c *Client) Do(req *Request) (resp *Response, err error) {
	if h := req.Http().Header; len(h.Get(openrtb.HEADER_VERSION)) == 0 {
		openrtb.SetHeaders(h)
	}

	r, err := c.doHttp(req.context(), req.Http())
	defer func() {
		if r == nil || r.Body == nil {
			return
		}

		go c.discard(r)
	}()

	if err != nil {
		if err == context.DeadlineExceeded {
			err = &timeoutError{err}
		}

		return nil, err
	} else if err := c.handleNoBid(r); err != nil {
		return nil, err
	}

	// TODO(@garukun): Consider wrapping r.Body with TeeReader to duplicate the content read to
	// another writer say, logger.
	br, err := c.decode(r.Body)
	if err != nil {
		return nil, &nobid{err: err}
	} else if br.IsNoBid() {
		return nil, &nobid{br: br}
	}

	resp = &Response{
		hr: r,
		br: br,
	}

	return resp, nil
}