@@ -46,20 +46,20 @@ func initAPIHandlers() {
4646}
4747
4848var apiHandlers = map [string ]APIHandler {
49- "log_error" : apiLogError ,
50- "job_poll" : apiJobPoll ,
51- "job_reset" : apiJobReset ,
52- "job_done" : apiJobDone ,
53- "reporting_poll_bugs" : apiReportingPollBugs ,
54- "reporting_poll_notifs" : apiReportingPollNotifications ,
55- "reporting_poll_closed" : apiReportingPollClosed ,
56- "reporting_update" : apiReportingUpdate ,
57- "new_test_job" : apiNewTestJob ,
58- "needed_assets" : apiNeededAssetsList ,
59- "load_full_bug" : apiLoadFullBug ,
60- "save_discussion" : apiSaveDiscussion ,
61- "create_upload_url" : apiCreateUploadURL ,
62- "send_email" : apiSendEmail ,
49+ "log_error" : typedHandler ( apiLogError ) ,
50+ "job_poll" : typedHandler ( apiJobPoll ) ,
51+ "job_reset" : typedHandler ( apiJobReset ) ,
52+ "job_done" : typedHandler ( apiJobDone ) ,
53+ "reporting_poll_bugs" : typedHandler ( apiReportingPollBugs ) ,
54+ "reporting_poll_notifs" : typedHandler ( apiReportingPollNotifications ) ,
55+ "reporting_poll_closed" : typedHandler ( apiReportingPollClosed ) ,
56+ "reporting_update" : typedHandler ( apiReportingUpdate ) ,
57+ "new_test_job" : typedHandler ( apiNewTestJob ) ,
58+ "needed_assets" : typedHandler ( apiNeededAssetsList ) ,
59+ "load_full_bug" : typedHandler ( apiLoadFullBug ) ,
60+ "save_discussion" : typedHandler ( apiSaveDiscussion ) ,
61+ "create_upload_url" : typedHandler ( apiCreateUploadURL ) ,
62+ "send_email" : typedHandler ( apiSendEmail ) ,
6363 "save_coverage" : gcsPayloadHandler (apiSaveCoverage ),
6464 "upload_build" : nsHandler (apiUploadBuild ),
6565 "builder_poll" : nsHandler (apiBuilderPoll ),
@@ -79,7 +79,6 @@ var apiHandlers = map[string]APIHandler{
7979
8080type JSONHandler func (c context.Context , r * http.Request ) (interface {}, error )
8181type APIHandler func (c context.Context , payload io.Reader ) (interface {}, error )
82- type APINamespaceHandler func (c context.Context , ns string , payload io.Reader ) (interface {}, error )
8382
8483const (
8584 maxReproPerBug = 10
@@ -206,30 +205,34 @@ func gcsPayloadHandler(handler APIHandler) APIHandler {
206205 }
207206}
208207
209- func nsHandler (handler APINamespaceHandler ) APIHandler {
210- return func (c context.Context , payload io. Reader ) (interface {} , error ) {
211- ns := contextNamespace (c )
208+ func nsHandler [ Req any ] (handler func (context. Context , string , * Req ) ( any , error ) ) APIHandler {
209+ return typedHandler ( func (ctx context.Context , req * Req ) (any , error ) {
210+ ns := contextNamespace (ctx )
212211 if ns == "" {
213212 return nil , fmt .Errorf ("must be called within a namespace" )
214213 }
215- return handler (c , ns , payload )
216- }
214+ return handler (ctx , ns , req )
215+ })
217216}
218217
219- func apiLogError (c context.Context , payload io.Reader ) (interface {}, error ) {
220- req := new (dashapi.LogEntry )
221- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
222- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
218+ func typedHandler [Req any ](handler func (context.Context , * Req ) (any , error )) APIHandler {
219+ return func (ctx context.Context , payload io.Reader ) (interface {}, error ) {
220+ req := new (Req )
221+ if payload != nil {
222+ if err := json .NewDecoder (payload ).Decode (req ); err != nil {
223+ return nil , fmt .Errorf ("failed to unmarshal request %T: %w" , req , err )
224+ }
225+ }
226+ return handler (ctx , req )
223227 }
228+ }
229+
230+ func apiLogError (c context.Context , req * dashapi.LogEntry ) (interface {}, error ) {
224231 log .Errorf (c , "%v: %v" , req .Name , req .Text )
225232 return nil , nil
226233}
227234
228- func apiBuilderPoll (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
229- req := new (dashapi.BuilderPollReq )
230- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
231- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
232- }
235+ func apiBuilderPoll (c context.Context , ns string , req * dashapi.BuilderPollReq ) (interface {}, error ) {
233236 bugs , _ , err := loadAllBugs (c , func (query * db.Query ) * db.Query {
234237 return query .Filter ("Namespace=" , ns ).
235238 Filter ("Status<" , BugStatusFixed )
@@ -274,7 +277,7 @@ func reportEmail(c context.Context, ns string) string {
274277 return ""
275278}
276279
277- func apiCommitPoll (c context.Context , ns string , payload io. Reader ) (interface {}, error ) {
280+ func apiCommitPoll (c context.Context , ns string , req * any ) (interface {}, error ) {
278281 resp := & dashapi.CommitPollResp {
279282 ReportEmail : reportEmail (c , ns ),
280283 }
@@ -340,11 +343,7 @@ func pollBackportCommits(c context.Context, ns string, count int) ([]string, err
340343 return backportTitles , nil
341344}
342345
343- func apiUploadCommits (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
344- req := new (dashapi.CommitPollResultReq )
345- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
346- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
347- }
346+ func apiUploadCommits (c context.Context , ns string , req * dashapi.CommitPollResultReq ) (interface {}, error ) {
348347 // This adds fixing commits to bugs.
349348 err := addCommitsToBugs (c , ns , "" , nil , req .Commits )
350349 if err != nil {
@@ -445,46 +444,28 @@ func addCommitInfoToBugImpl(c context.Context, bug *Bug, com dashapi.Commit) (bo
445444 return changed , nil
446445}
447446
448- func apiJobPoll (c context.Context , payload io. Reader ) (interface {}, error ) {
447+ func apiJobPoll (c context.Context , req * dashapi. JobPollReq ) (interface {}, error ) {
449448 if stop , err := emergentlyStopped (c ); err != nil || stop {
450449 // The bot's operation was aborted. Don't accept new crash reports.
451450 return & dashapi.JobPollResp {}, err
452451 }
453- req := new (dashapi.JobPollReq )
454- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
455- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
456- }
457452 if len (req .Managers ) == 0 {
458453 return nil , fmt .Errorf ("no managers" )
459454 }
460455 return pollPendingJobs (c , req .Managers )
461456}
462457
463- // nolint: dupl
464- func apiJobDone (c context.Context , payload io.Reader ) (interface {}, error ) {
465- req := new (dashapi.JobDoneReq )
466- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
467- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
468- }
458+ func apiJobDone (c context.Context , req * dashapi.JobDoneReq ) (interface {}, error ) {
469459 err := doneJob (c , req )
470460 return nil , err
471461}
472462
473- // nolint: dupl
474- func apiJobReset (c context.Context , payload io.Reader ) (interface {}, error ) {
475- req := new (dashapi.JobResetReq )
476- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
477- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
478- }
463+ func apiJobReset (c context.Context , req * dashapi.JobResetReq ) (interface {}, error ) {
479464 err := resetJobs (c , req )
480465 return nil , err
481466}
482467
483- func apiUploadBuild (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
484- req := new (dashapi.Build )
485- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
486- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
487- }
468+ func apiUploadBuild (c context.Context , ns string , req * dashapi.Build ) (interface {}, error ) {
488469 now := timeNow (c )
489470 _ , isNewBuild , err := uploadBuild (c , now , ns , req , BuildNormal )
490471 if err != nil {
@@ -751,11 +732,7 @@ func managerList(c context.Context, ns string) ([]string, error) {
751732 return managers , nil
752733}
753734
754- func apiReportBuildError (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
755- req := new (dashapi.BuildErrorReq )
756- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
757- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
758- }
735+ func apiReportBuildError (c context.Context , ns string , req * dashapi.BuildErrorReq ) (interface {}, error ) {
759736 now := timeNow (c )
760737 build , _ , err := uploadBuild (c , now , ns , & req .Build , BuildFailed )
761738 if err != nil {
@@ -785,15 +762,11 @@ const (
785762 suppressedReportTitle = "suppressed report"
786763)
787764
788- func apiReportCrash (c context.Context , ns string , payload io. Reader ) (interface {}, error ) {
765+ func apiReportCrash (c context.Context , ns string , req * dashapi. Crash ) (interface {}, error ) {
789766 if stop , err := emergentlyStopped (c ); err != nil || stop {
790767 // The bot's operation was aborted. Don't accept new crash reports.
791768 return & dashapi.ReportCrashResp {}, err
792769 }
793- req := new (dashapi.Crash )
794- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
795- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
796- }
797770 build , err := loadBuild (c , ns , req .BuildID )
798771 if err != nil {
799772 return nil , err
@@ -1094,13 +1067,8 @@ func purgeOldCrashes(c context.Context, bug *Bug, bugKey *db.Key) {
10941067 log .Infof (c , "deleted %v crashes for bug %q" , deleted , bug .Title )
10951068}
10961069
1097- func apiReportFailedRepro (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1098- req := new (dashapi.CrashID )
1099- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1100- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1101- }
1070+ func apiReportFailedRepro (c context.Context , ns string , req * dashapi.CrashID ) (interface {}, error ) {
11021071 req .Title = canonicalizeCrashTitle (req .Title , req .Corrupted , req .Suppressed )
1103-
11041072 bug , err := findExistingBugForCrash (c , ns , []string {req .Title })
11051073 if err != nil {
11061074 return nil , err
@@ -1166,11 +1134,7 @@ func saveReproAttempt(c context.Context, bug *Bug, build *Build, log []byte) err
11661134 return nil
11671135}
11681136
1169- func apiNeedRepro (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1170- req := new (dashapi.CrashID )
1171- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1172- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1173- }
1137+ func apiNeedRepro (c context.Context , ns string , req * dashapi.CrashID ) (interface {}, error ) {
11741138 if req .Corrupted {
11751139 resp := & dashapi.NeedReproResp {
11761140 NeedRepro : false ,
@@ -1218,11 +1182,7 @@ func normalizeCrashTitle(title string) string {
12181182 return strings .TrimSpace (limitLength (title , maxTextLen ))
12191183}
12201184
1221- func apiManagerStats (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1222- req := new (dashapi.ManagerStatsReq )
1223- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1224- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1225- }
1185+ func apiManagerStats (c context.Context , ns string , req * dashapi.ManagerStatsReq ) (interface {}, error ) {
12261186 now := timeNow (c )
12271187 err := updateManager (c , ns , req .Name , func (mgr * Manager , stats * ManagerStats ) error {
12281188 mgr .Link = req .Addr
@@ -1243,11 +1203,7 @@ func apiManagerStats(c context.Context, ns string, payload io.Reader) (interface
12431203 return nil , err
12441204}
12451205
1246- func apiUpdateReport (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1247- req := new (dashapi.UpdateReportReq )
1248- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1249- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1250- }
1206+ func apiUpdateReport (c context.Context , ns string , req * dashapi.UpdateReportReq ) (interface {}, error ) {
12511207 bug := new (Bug )
12521208 bugKey := db .NewKey (c , "Bug" , req .BugID , 0 , nil )
12531209 if err := db .Get (c , bugKey , bug ); err != nil {
@@ -1273,7 +1229,7 @@ func apiUpdateReport(c context.Context, ns string, payload io.Reader) (interface
12731229 return nil , runInTransaction (c , tx , nil )
12741230}
12751231
1276- func apiBugList (c context.Context , ns string , payload io. Reader ) (interface {}, error ) {
1232+ func apiBugList (c context.Context , ns string , req * any ) (interface {}, error ) {
12771233 keys , err := db .NewQuery ("Bug" ).
12781234 Filter ("Namespace=" , ns ).
12791235 KeysOnly ().
@@ -1288,11 +1244,7 @@ func apiBugList(c context.Context, ns string, payload io.Reader) (interface{}, e
12881244 return resp , nil
12891245}
12901246
1291- func apiLoadBug (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1292- req := new (dashapi.LoadBugReq )
1293- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1294- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1295- }
1247+ func apiLoadBug (c context.Context , ns string , req * dashapi.LoadBugReq ) (interface {}, error ) {
12961248 bug := new (Bug )
12971249 bugKey := db .NewKey (c , "Bug" , req .ID , 0 , nil )
12981250 if err := db .Get (c , bugKey , bug ); err != nil {
@@ -1304,11 +1256,7 @@ func apiLoadBug(c context.Context, ns string, payload io.Reader) (interface{}, e
13041256 return loadBugReport (c , bug )
13051257}
13061258
1307- func apiLoadFullBug (c context.Context , payload io.Reader ) (interface {}, error ) {
1308- req := new (dashapi.LoadFullBugReq )
1309- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1310- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1311- }
1259+ func apiLoadFullBug (c context.Context , req * dashapi.LoadFullBugReq ) (interface {}, error ) {
13121260 bug , bugKey , err := findBugByReportingID (c , req .BugID )
13131261 if err != nil {
13141262 return nil , fmt .Errorf ("failed to find the bug: %w" , err )
@@ -1334,11 +1282,7 @@ func loadBugReport(c context.Context, bug *Bug) (*dashapi.BugReport, error) {
13341282 return createBugReport (c , bug , crash , crashKey , bugReporting , reporting )
13351283}
13361284
1337- func apiAddBuildAssets (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1338- req := new (dashapi.AddBuildAssetsReq )
1339- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1340- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1341- }
1285+ func apiAddBuildAssets (c context.Context , ns string , req * dashapi.AddBuildAssetsReq ) (interface {}, error ) {
13421286 assets := []Asset {}
13431287 for i , toAdd := range req .Assets {
13441288 asset , err := parseIncomingAsset (c , toAdd , ns )
@@ -1379,7 +1323,7 @@ func parseIncomingAsset(c context.Context, newAsset dashapi.NewAsset, ns string)
13791323 }, nil
13801324}
13811325
1382- func apiNeededAssetsList (c context.Context , payload io. Reader ) (interface {}, error ) {
1326+ func apiNeededAssetsList (c context.Context , req * any ) (interface {}, error ) {
13831327 return queryNeededAssets (c )
13841328}
13851329
@@ -1760,11 +1704,7 @@ func handleRefreshSubsystems(w http.ResponseWriter, r *http.Request) {
17601704 }
17611705}
17621706
1763- func apiSaveDiscussion (c context.Context , payload io.Reader ) (interface {}, error ) {
1764- req := new (dashapi.SaveDiscussionReq )
1765- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1766- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1767- }
1707+ func apiSaveDiscussion (c context.Context , req * dashapi.SaveDiscussionReq ) (interface {}, error ) {
17681708 d := req .Discussion
17691709 newBugIDs := []string {}
17701710 for _ , id := range d .BugIDs {
@@ -1803,11 +1743,7 @@ func recordEmergencyStop(c context.Context) error {
18031743// Share crash logs for non-reproduced bugs with syz-managers.
18041744// In future, this can also take care of repro exchange between instances
18051745// in the place of syz-hub.
1806- func apiLogToReproduce (c context.Context , ns string , payload io.Reader ) (interface {}, error ) {
1807- req := new (dashapi.LogToReproReq )
1808- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1809- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1810- }
1746+ func apiLogToReproduce (c context.Context , ns string , req * dashapi.LogToReproReq ) (interface {}, error ) {
18111747 build , err := loadBuild (c , ns , req .BuildID )
18121748 if err != nil {
18131749 return nil , err
@@ -1927,19 +1863,15 @@ func takeReproTask(c context.Context, ns, manager string) ([]byte, error) {
19271863 return log , err
19281864}
19291865
1930- func apiCreateUploadURL (c context.Context , payload io. Reader ) (interface {}, error ) {
1866+ func apiCreateUploadURL (c context.Context , req * any ) (interface {}, error ) {
19311867 bucket := getConfig (c ).UploadBucket
19321868 if bucket == "" {
19331869 return nil , errors .New ("not configured" )
19341870 }
19351871 return fmt .Sprintf ("%s/%s.upload" , bucket , uuid .New ().String ()), nil
19361872}
19371873
1938- func apiSendEmail (c context.Context , payload io.Reader ) (interface {}, error ) {
1939- req := new (dashapi.SendEmailReq )
1940- if err := json .NewDecoder (payload ).Decode (req ); err != nil {
1941- return nil , fmt .Errorf ("failed to unmarshal request: %w" , err )
1942- }
1874+ func apiSendEmail (c context.Context , req * dashapi.SendEmailReq ) (interface {}, error ) {
19431875 var headers mail.Header
19441876 if req .InReplyTo != "" {
19451877 headers = mail.Header {"In-Reply-To" : []string {req .InReplyTo }}
0 commit comments