@@ -357,6 +357,36 @@ func TestContentType_OAuthTokenAcceptsFormUrlencoded(t *testing.T) {
357357 }
358358}
359359
360+ // TestContentType_OAuthTokenUnsupportedMediaNamesBothTypes verifies the 415
361+ // detail on /api/v1/oauth/token names BOTH accepted media types, not just
362+ // application/json — the endpoint genuinely accepts form-urlencoded as well
363+ // (TRA-883 / Round 2.4 F2). text/plain is the unsupported Content-Type; a
364+ // bare `curl -d` would auto-set form-urlencoded and pass, so the probe sets
365+ // text/plain explicitly.
366+ func TestContentType_OAuthTokenUnsupportedMediaNamesBothTypes (t * testing.T ) {
367+ next := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
368+ t .Fatal ("handler must not be reached on unsupported Content-Type" )
369+ })
370+ req := httptest .NewRequest (http .MethodPost , "/api/v1/oauth/token" ,
371+ strings .NewReader ("grant_type=client_credentials" ))
372+ req .Header .Set ("Content-Type" , "text/plain" )
373+ rr := httptest .NewRecorder ()
374+
375+ ContentType (next ).ServeHTTP (rr , req )
376+
377+ if rr .Code != http .StatusUnsupportedMediaType {
378+ t .Fatalf ("status = %d, want 415" , rr .Code )
379+ }
380+ var resp apierrors.ErrorResponse
381+ if err := json .Unmarshal (rr .Body .Bytes (), & resp ); err != nil {
382+ t .Fatalf ("unmarshal: %v" , err )
383+ }
384+ if ! strings .Contains (resp .Error .Detail , "application/json" ) ||
385+ ! strings .Contains (resp .Error .Detail , "application/x-www-form-urlencoded" ) {
386+ t .Errorf ("detail = %q, must name both application/json and application/x-www-form-urlencoded" , resp .Error .Detail )
387+ }
388+ }
389+
360390func TestAuth_MissingHeader_Respond401 (t * testing.T ) {
361391 h := Auth (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) { t .Fatal ("should not reach handler" ) }))
362392 w := httptest .NewRecorder ()
0 commit comments