Skip to content

Commit 143e00c

Browse files
author
Eggya Chiquita
committed
added response, validates and test
1 parent a53d190 commit 143e00c

File tree

5 files changed

+248
-2
lines changed

5 files changed

+248
-2
lines changed

openrtb.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,54 @@ type Request struct {
7272
Ext Extensions
7373
}
7474

75+
// ID and at least one “seatbid” object is required, which contains a bid on at least one impression.
76+
// Other attributes are optional since an exchange may establish default values.
77+
// No-Bids on all impressions should be indicated as a HTTP 204 response.
78+
// For no-bids on specific impressions, the bidder should omit these from the bid response.
79+
type Response struct {
80+
Id *string `json:"id"` // Reflection of the bid request ID for logging purposes
81+
Seatbid []Seatbid `json:"seatbid"` // Array of seatbid objects
82+
Bidid *string `json:"bidid,omitempty"` // Optional response tracking ID for bidders
83+
Cur *string `json:"cur,omitempty"` // Bid currency
84+
Customdata *string `json:"customdata,omitempty"` // Encoded user features
85+
Ext Extensions `json:"ext,omitempty"` // Custom specifications in Json
86+
}
87+
88+
// At least one of Bid is required.
89+
// A bid response can contain multiple “seatbid” objects, each on behalf of a different bidder seat.
90+
// Seatbid object can contain multiple bids each pertaining to a different impression on behalf of a seat.
91+
// Each “bid” object must include the impression ID to which it pertains as well as the bid price.
92+
// Group attribute can be used to specify if a seat is willing to accept any impressions that it can win (default) or if it is
93+
// only interested in winning any if it can win them all (i.e., all or nothing).
94+
type Seatbid struct {
95+
Bid []Bid `json:"id"` // Array of bid objects; each realtes to an imp, if exchange supported can have many bid objects.
96+
Seat *string `json:"seat,omiempty"` // ID of the bidder seat optional string ID of the bidder seat on whose behalf this bid is made.
97+
Group *int `json:"group,omiempty"` // '1' means impression must be won-lost as a group; default is '0'.
98+
Ext Extensions `json:"ext,omiempty"`
99+
}
100+
101+
// ID, Impid and Price are required; all other optional.
102+
// If the bidder wins the impression, the exchange calls notice URL (nurl)
103+
// a) to inform the bidder of the win;
104+
// b) to convey certain information using substitution macros.
105+
// Adomain can be used to check advertiser block list compliance.
106+
// Cid can be used to block ads that were previously identified as inappropriate.
107+
// Substitution macros may allow a bidder to use a static notice URL for all of its bids.
108+
type Bid struct {
109+
Id *string `json:"id"`
110+
Impid *string `json:"impid"` // Required string ID of the impression object to which this bid applies.
111+
Price *float32 `json:"price"` // Bid price in CPM. Suggests using integer math for accounting to avoid rounding errors.
112+
Adid *string `json:"adid,omitempty"` // References the ad to be served if the bid wins.
113+
Nurl *string `json:"nurl,omitempty"` // Win notice URL.
114+
Adm *string `json:"adm,omitempty"` // Actual ad markup. XHTML if a response to a banner object, or VAST XML if a response to a video object.
115+
Adomain []string `json:"adomain,omitempty"` // Advertiser’s primary or top-level domain for advertiser checking; or multiple if imp rotating.
116+
Iurl *string `json:"iurl,omitempty"` // Sample image URL.
117+
Cid *string `json:"cid,omitempty"` // Campaign ID that appears with the Ad markup.
118+
Crid *string `json:"crid,omitempty"` // Creative ID for reporting content issues or defects. This could also be used as a reference to a creative ID that is posted with an exchange.
119+
Attr []int `json:"attr,omitempty"` // Array of creative attributes.
120+
Ext Extensions `json:"ext,omitempty"`
121+
}
122+
75123
// The "imp" object describes the ad position or impression being auctioned. A single bid request
76124
// can include multiple "imp" objects, a use case for which might be an exchange that supports
77125
// selling all ad positions on a given page as a bundle. Each "imp" object has a required ID so that

parser.go renamed to request.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88

99
var (
1010
errValidationReqId = errors.New("openrtb parse: request ID missing")
11-
errValidationImp = errors.New("openrtb parse: no impressions")
11+
errValidationReqImp = errors.New("openrtb parse: no impressions")
1212
errValidationReqSaA = errors.New("openrtb parse: request has site and app")
1313
errValidationImpId = errors.New("openrtb parse: impression ID missing")
1414
errValidationImpBoV = errors.New("openrtb parse: impression has neither a banner nor video")
@@ -57,7 +57,7 @@ func validateReq(req *Request) error {
5757
if req.Id == nil {
5858
return errValidationReqId
5959
} else if len(req.Imp) == 0 {
60-
return errValidationImp
60+
return errValidationReqImp
6161
} else if req.Site != nil && req.App != nil {
6262
return errValidationReqSaA
6363
} else if req.Site != nil {
File renamed without changes.

response.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package openrtb
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
)
7+
8+
var (
9+
errValidationResId = errors.New("openrtb response: missing ID")
10+
errValidationResSeatbid = errors.New("openrtb response: missing seatbids")
11+
errValidationSeatbidBid = errors.New("openrtb response: seatbid is missing bids")
12+
errValidationBidId = errors.New("openrtb response: bid is missing ID")
13+
errValidationBidImpid = errors.New("openrtb response: bid is missing impression ID")
14+
errValidationBidPrice = errors.New("openrtb response: bid is missing price")
15+
)
16+
17+
// Response object to_json
18+
// @return [Json,Error]
19+
func (res *Response) JSON() ([]byte, error) {
20+
return json.Marshal(res)
21+
}
22+
23+
// Validate Response required attributes
24+
// @return [Boolean,Error] true if response,seatbid,bid required attrs present
25+
func (res *Response) Valid() (bool, error) {
26+
27+
if res.Id == nil {
28+
return false, errValidationResId
29+
} else if res.Seatbid == nil || len(res.Seatbid) < 1 {
30+
return false, errValidationResSeatbid
31+
}
32+
33+
for _, sb := range res.Seatbid {
34+
if ok, err := sb.Valid(); !ok {
35+
return ok, err
36+
}
37+
}
38+
39+
return true, nil
40+
}
41+
42+
// Seatbid methods
43+
44+
// Validate Seatbid required attributes
45+
// @return [Boolean,Error]
46+
func (sb *Seatbid) Valid() (bool, error) {
47+
48+
if sb.Bid == nil || len(sb.Bid) < 1 {
49+
return false, errValidationSeatbidBid
50+
}
51+
52+
for _, bid := range sb.Bid {
53+
if ok, err := bid.Valid(); !ok {
54+
return ok, err
55+
}
56+
}
57+
58+
return true, nil
59+
}
60+
61+
// Bid methods
62+
63+
// Validate Bid required attributes
64+
// @return [Boolean,Error]
65+
func (bid *Bid) Valid() (bool, error) {
66+
67+
if bid.Id == nil {
68+
return false, errValidationBidId
69+
} else if bid.Impid == nil {
70+
return false, errValidationBidImpid
71+
} else if bid.Price == nil {
72+
return false, errValidationBidPrice
73+
}
74+
75+
return true, nil
76+
}
77+
78+
// Set the ID
79+
func (bid *Bid) SetID(id string) *Bid {
80+
if bid.Id == nil {
81+
bid.Id = new(string)
82+
}
83+
*bid.Id = id
84+
return bid
85+
}
86+
87+
// Set the ImpID
88+
func (bid *Bid) SetImpID(id string) *Bid {
89+
if bid.Impid == nil {
90+
bid.Impid = new(string)
91+
}
92+
*bid.Impid = id
93+
return bid
94+
}
95+
96+
// Set the Price
97+
func (bid *Bid) SetPrice(p float32) *Bid {
98+
if bid.Price == nil {
99+
bid.Price = new(float32)
100+
}
101+
*bid.Price = p
102+
return bid
103+
}

response_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package openrtb
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestResponse_JSON(t *testing.T) {
9+
res := &Response{}
10+
res.Id = new(string)
11+
*res.Id = "RES_ID"
12+
res.Cur = new(string)
13+
*res.Cur = "USD"
14+
15+
bytes, err := res.JSON()
16+
assert.Nil(t, err)
17+
assert.Equal(t, string(bytes), `{"id":"RES_ID","seatbid":null,"cur":"USD"}`)
18+
}
19+
20+
func TestResponse_Valid(t *testing.T) {
21+
res := &Response{}
22+
23+
ok, err := res.Valid()
24+
assert.Equal(t, ok, false)
25+
if err != nil {
26+
assert.Equal(t, err.Error(), "openrtb response: missing ID")
27+
}
28+
29+
res.Id = new(string)
30+
*res.Id = "RES_ID"
31+
32+
ok, err = res.Valid()
33+
assert.Equal(t, ok, false)
34+
if err != nil {
35+
assert.Equal(t, err.Error(), "openrtb response: missing seatbids")
36+
}
37+
38+
bid := &Bid{}
39+
bid.SetID("BIDID").SetImpID("IMPID").SetPrice(0.0)
40+
41+
sb := &Seatbid{}
42+
sb.Bid = append(sb.Bid, *bid)
43+
44+
res.Seatbid = append(res.Seatbid, *sb)
45+
46+
ok, err = res.Valid()
47+
assert.Equal(t, ok, true)
48+
assert.Nil(t, err)
49+
}
50+
51+
func TestSeatbid_Valid(t *testing.T) {
52+
sb := &Seatbid{}
53+
54+
ok, err := sb.Valid()
55+
assert.Equal(t, ok, false)
56+
if err != nil {
57+
assert.Equal(t, err.Error(), "openrtb response: seatbid is missing bids")
58+
}
59+
60+
bid := &Bid{}
61+
bid.SetID("BIDID").SetImpID("IMPID").SetPrice(0.0)
62+
sb.Bid = append(sb.Bid, *bid)
63+
64+
ok, err = sb.Valid()
65+
assert.Equal(t, ok, true)
66+
assert.Nil(t, err)
67+
}
68+
69+
func TestBid_Valid(t *testing.T) {
70+
bid := &Bid{}
71+
72+
ok, err := bid.Valid()
73+
assert.Equal(t, ok, false)
74+
if err != nil {
75+
assert.Equal(t, err.Error(), "openrtb response: bid is missing ID")
76+
}
77+
78+
bid.SetID("BIDID")
79+
ok, err = bid.Valid()
80+
assert.Equal(t, ok, false)
81+
if err != nil {
82+
assert.Equal(t, err.Error(), "openrtb response: bid is missing impression ID")
83+
}
84+
85+
bid.SetImpID("IMPID")
86+
ok, err = bid.Valid()
87+
assert.Equal(t, ok, false)
88+
if err != nil {
89+
assert.Equal(t, err.Error(), "openrtb response: bid is missing price")
90+
}
91+
92+
bid.SetPrice(0.0)
93+
ok, err = bid.Valid()
94+
assert.Equal(t, ok, true)
95+
}

0 commit comments

Comments
 (0)