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) } } }
// 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 }