Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
w.Header().Set("X-Prebid", version.BuildXPrebidHeader(version.Ver))
setBrowsingTopicsHeader(w, r)

req, impExtInfoMap, storedAuctionResponses, storedBidResponses, bidderImpReplaceImp, account, errL := deps.parseRequest(r, &labels, hookExecutor)
req, impExtInfoMap, storedAuctionResponses, storedBidResponses, bidderImpReplaceImp, account, rawRequestBody, errL := deps.parseRequest(r, &labels, hookExecutor)
if errortypes.ContainsFatalError(errL) {
logBadInputRequest(errL, req)
logBadInputRequest(errL, req, rawRequestBody)
if writeError(errL, w, &labels) {
return
}
Expand Down Expand Up @@ -239,7 +239,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
err := deps.setIntegrationType(req, account)
if err != nil {
errL = append(errL, err)
logBadInputRequest(errL, req)
logBadInputRequest(errL, req, rawRequestBody)
writeError(errL, w, &labels)
return
}
Expand Down Expand Up @@ -285,7 +285,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
rejectErr, isRejectErr := hookexecution.CastRejectErr(err)
if err != nil && !isRejectErr {
if errortypes.ReadCode(err) == errortypes.BadInputErrorCode {
logBadInputRequest([]error{err}, req)
logBadInputRequest([]error{err}, req, rawRequestBody)
writeError([]error{err}, w, &labels)
return
}
Expand Down Expand Up @@ -421,7 +421,7 @@ func setBrowsingTopicsHeader(w http.ResponseWriter, r *http.Request) {
// possible, it will return errors with messages that suggest improvements.
//
// If the errors list has at least one element, then no guarantees are made about the returned request.
func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metrics.Labels, hookExecutor hookexecution.HookStageExecutor) (req *openrtb_ext.RequestWrapper, impExtInfoMap map[string]exchange.ImpExtInfo, storedAuctionResponses stored_responses.ImpsWithBidResponses, storedBidResponses stored_responses.ImpBidderStoredResp, bidderImpReplaceImpId stored_responses.BidderImpReplaceImpID, account *config.Account, errs []error) {
func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metrics.Labels, hookExecutor hookexecution.HookStageExecutor) (req *openrtb_ext.RequestWrapper, impExtInfoMap map[string]exchange.ImpExtInfo, storedAuctionResponses stored_responses.ImpsWithBidResponses, storedBidResponses stored_responses.ImpBidderStoredResp, bidderImpReplaceImpId stored_responses.BidderImpReplaceImpID, account *config.Account, rawRequestBody []byte, errs []error) {
errs = nil
var err error
var errL []error
Expand All @@ -448,9 +448,14 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metric
requestJson, err := io.ReadAll(limitedReqReader)
if err != nil {
errs = []error{err}
// Save raw body even if read failed (may be partial)
rawRequestBody = requestJson
return
}
labels.RequestSize = len(requestJson)
// Save a copy of the raw request body for logging purposes
rawRequestBody = make([]byte, len(requestJson))
copy(rawRequestBody, requestJson)

if limitedReqReader.N <= 0 {
// Limited Reader returns 0 if the request was exactly at the max size or over the limit.
Expand Down Expand Up @@ -482,7 +487,7 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metric

impInfo, errs := parseImpInfo(requestJson)
if len(errs) > 0 {
return nil, nil, nil, nil, nil, nil, errs
return nil, nil, nil, nil, nil, nil, rawRequestBody, errs
}

storedBidRequestId, hasStoredBidRequest, storedRequests, storedImps, errs := deps.getStoredRequests(ctx, requestJson, impInfo)
Expand Down Expand Up @@ -528,7 +533,7 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metric
if hasPayloadUpdatesAt(hooks.StageRawAuctionRequest.String(), hookExecutor.GetOutcomes()) {
impInfo, errs = parseImpInfo(requestJson)
if len(errs) > 0 {
return nil, nil, nil, nil, nil, nil, errs
return nil, nil, nil, nil, nil, nil, rawRequestBody, errs
}
storedBidRequestId, hasStoredBidRequest, storedRequests, storedImps, errs = deps.getStoredRequests(ctx, requestJson, impInfo)
if len(errs) > 0 {
Expand Down Expand Up @@ -578,7 +583,7 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request, labels *metric
storedAuctionResponses, storedBidResponses, bidderImpReplaceImpId, errL = stored_responses.ProcessStoredResponses(ctx, req, deps.storedRespFetcher)
if len(errL) > 0 {
errs = append(errs, errL...)
return nil, nil, nil, nil, nil, nil, errs
return nil, nil, nil, nil, nil, nil, rawRequestBody, errs
}

hasStoredAuctionResponses := len(storedAuctionResponses) > 0
Expand Down Expand Up @@ -1933,7 +1938,7 @@ func setDoNotTrackImplicitly(httpReq *http.Request, r *openrtb_ext.RequestWrappe
}

// logBadInputRequest logs the request and errors for badinput cases
func logBadInputRequest(errs []error, req *openrtb_ext.RequestWrapper) {
func logBadInputRequest(errs []error, req *openrtb_ext.RequestWrapper, rawRequestBody []byte) {
// Check if this is a badinput case (not BlockedApp, AccountDisabled, or MalformedAcct)
isBadInput := true
for _, err := range errs {
Expand All @@ -1949,7 +1954,11 @@ func logBadInputRequest(errs []error, req *openrtb_ext.RequestWrapper) {
}

// Log the request and errors for badinput
if req != nil && req.BidRequest != nil {
// Prefer raw request body if available (even if it's not valid JSON)
if len(rawRequestBody) > 0 {
logger.Errorf("/openrtb2/auction BadInput request body: %s, errors: %v", string(rawRequestBody), errs)
} else if req != nil && req.BidRequest != nil {
// Fallback to marshaling the parsed request if raw body is not available
if reqBytes, marshalErr := jsonutil.Marshal(req.BidRequest); marshalErr == nil {
logger.Errorf("/openrtb2/auction BadInput request: %s, errors: %v", string(reqBytes), errs)
} else {
Expand Down
4 changes: 2 additions & 2 deletions endpoints/openrtb2/auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3777,7 +3777,7 @@ func TestParseRequestParseImpInfoError(t *testing.T) {

req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody))

resReq, impExtInfoMap, _, _, _, _, errL := deps.parseRequest(req, &metrics.Labels{}, hookExecutor)
resReq, impExtInfoMap, _, _, _, _, _, errL := deps.parseRequest(req, &metrics.Labels{}, hookExecutor)

assert.Nil(t, resReq, "Result request should be nil due to incorrect imp")
assert.Nil(t, impExtInfoMap, "Impression info map should be nil due to incorrect imp")
Expand Down Expand Up @@ -3871,7 +3871,7 @@ func TestParseGzipedRequest(t *testing.T) {
} else {
req = httptest.NewRequest("POST", "/openrtb2/auction", bytes.NewReader(reqBody))
}
resReq, impExtInfoMap, _, _, _, _, errL := deps.parseRequest(req, &metrics.Labels{}, hookExecutor)
resReq, impExtInfoMap, _, _, _, _, _, errL := deps.parseRequest(req, &metrics.Labels{}, hookExecutor)

if test.expectedErr == "" {
assert.Nil(t, errL, "Error list should be nil", test.desc)
Expand Down