Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetUID Error Handling Refactor #3050

Merged
merged 3 commits into from
Sep 18, 2023
Merged
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
62 changes: 26 additions & 36 deletions endpoints/setuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use

cookie := usersync.ReadCookie(r, decoder, &cfg.HostCookie)
if !cookie.AllowSyncs() {
w.WriteHeader(http.StatusUnauthorized)
metricsEngine.RecordSetUid(metrics.SetUidOptOut)
so.Status = http.StatusUnauthorized
handleBadStatus(w, http.StatusUnauthorized, metrics.SetUidOptOut, nil, metricsEngine, &so)
return
}
usersync.SyncHostCookie(r, cookie, &cfg.HostCookie)
Expand All @@ -61,22 +59,14 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use

syncer, bidderName, err := getSyncer(query, syncersByBidder)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
metricsEngine.RecordSetUid(metrics.SetUidSyncerUnknown)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
handleBadStatus(w, http.StatusBadRequest, metrics.SetUidSyncerUnknown, err, metricsEngine, &so)
return
}
so.Bidder = syncer.Key()

responseFormat, err := getResponseFormat(query, syncer)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
handleBadStatus(w, http.StatusBadRequest, metrics.SetUidBadRequest, err, metricsEngine, &so)
return
}

Expand All @@ -86,21 +76,19 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
}
account, fetchErrs := accountService.GetAccount(context.Background(), cfg, accountsFetcher, accountID, metricsEngine)
if len(fetchErrs) > 0 {
w.WriteHeader(http.StatusBadRequest)
var metricValue metrics.SetUidStatus
err := combineErrors(fetchErrs)
w.Write([]byte(err.Error()))
switch err {
case errCookieSyncAccountBlocked:
metricsEngine.RecordSetUid(metrics.SetUidAccountBlocked)
metricValue = metrics.SetUidAccountBlocked
case errCookieSyncAccountConfigMalformed:
metricsEngine.RecordSetUid(metrics.SetUidAccountConfigMalformed)
metricValue = metrics.SetUidAccountConfigMalformed
case errCookieSyncAccountInvalid:
metricsEngine.RecordSetUid(metrics.SetUidAccountInvalid)
metricValue = metrics.SetUidAccountInvalid
default:
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
metricValue = metrics.SetUidBadRequest
}
so.Errors = []error{err}
so.Status = http.StatusBadRequest
handleBadStatus(w, http.StatusBadRequest, metricValue, err, metricsEngine, &so)
return
}

Expand All @@ -122,11 +110,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
if err != nil {
// Only exit if non-warning
if !errortypes.IsWarning(err) {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
handleBadStatus(w, http.StatusBadRequest, metrics.SetUidBadRequest, err, metricsEngine, &so)
return
}
w.Write([]byte("Warning: " + err.Error()))
Expand All @@ -135,16 +119,14 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
tcf2Cfg := tcf2CfgBuilder(cfg.GDPR.TCF2, account.GDPR)

if shouldReturn, status, body := preventSyncsGDPR(gdprRequestInfo, gdprPermsBuilder, tcf2Cfg); shouldReturn {
w.WriteHeader(status)
w.Write([]byte(body))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we remove this line? In order for the refactored version to be completely equivalent, shouldn't we keep it?

121         if shouldReturn, status, body := preventSyncsGDPR(gdprRequestInfo, gdprPermsBuilder, tcf2Cfg); shouldReturn {
    +           w.Write([]byte(body))
122             var metricValue metrics.SetUidStatus
123             switch status {
124             case http.StatusBadRequest:
125                 metricValue = metrics.SetUidBadRequest
126             case http.StatusUnavailableForLegalReasons:
127                 metricValue = metrics.SetUidGDPRHostCookieBlocked
128             }
129             handleBadStatus(w, status, metricValue, errors.New(body), metricsEngine, &so)
130             return
131         }
endpoints/setuid.go

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So after looking into it more, this body value that preventSyncsGDPR is essentially a custom error message. So I don't think there's much of a difference between w.Write([]byte(body)) and w.Write([]byte(errors.New(body)) which is how it's written in handleBadStatus.

So I'd advocate for keeping the code how it is, and keeping it a bit cleaner. However, it is a very small difference, so I'm not totally against changing it either. What do you think?

var metricValue metrics.SetUidStatus
switch status {
case http.StatusBadRequest:
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
metricValue = metrics.SetUidBadRequest
case http.StatusUnavailableForLegalReasons:
metricsEngine.RecordSetUid(metrics.SetUidGDPRHostCookieBlocked)
metricValue = metrics.SetUidGDPRHostCookieBlocked
}
so.Errors = []error{errors.New(body)}
so.Status = status
handleBadStatus(w, status, metricValue, errors.New(body), metricsEngine, &so)
return
}

Expand All @@ -167,10 +149,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
// Write Cookie
encodedCookie, err := cookie.PrepareCookieForWrite(&cfg.HostCookie, encoder)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
metricsEngine.RecordSetUid(metrics.SetUidBadRequest)
so.Errors = []error{err}
so.Status = http.StatusBadRequest
handleBadStatus(w, http.StatusBadRequest, metrics.SetUidBadRequest, err, metricsEngine, &so)
return
}
usersync.WriteCookie(w, encodedCookie, &cfg.HostCookie, setSiteCookie)
Expand Down Expand Up @@ -410,3 +389,14 @@ func preventSyncsGDPR(gdprRequestInfo gdpr.RequestInfo, permsBuilder gdpr.Permis

return true, http.StatusUnavailableForLegalReasons, "The gdpr_consent string prevents cookies from being saved"
}

func handleBadStatus(w http.ResponseWriter, status int, metricValue metrics.SetUidStatus, err error, me metrics.MetricsEngine, so *analytics.SetUIDObject) {
w.WriteHeader(status)
me.RecordSetUid(metricValue)
so.Status = status

if err != nil {
so.Errors = []error{err}
w.Write([]byte(err.Error()))
}
}
Loading