Skip to content

fix: release discovery lock before HTTP fetch; route scope errors through error handler#16

Open
appleboy wants to merge 2 commits intomainfrom
fix/discovery-lock-and-middleware-error-handler
Open

fix: release discovery lock before HTTP fetch; route scope errors through error handler#16
appleboy wants to merge 2 commits intomainfrom
fix/discovery-lock-and-middleware-error-handler

Conversation

@appleboy
Copy link
Copy Markdown
Member

Summary

  • discovery: refresh() held the write mutex across the entire function including the HTTP network call, blocking all concurrent Fetch() callers for the duration of the request. Added a singleflight.Group (already a transitive dep) to coalesce concurrent cache misses into a single fetch; the lock is now held only for the cache check and update — matching the pattern already used in clientcreds.

  • middleware: BearerAuth was calling writeInsufficientScope directly for scope failures, silently bypassing any custom ErrorHandler. Scope errors are now routed through cfg.errorHandler as an *oauth.Error{Code: "insufficient_scope"}. Updated defaultErrorHandler to map insufficient_scope → 403 Forbidden with the correct WWW-Authenticate: Bearer error="insufficient_scope" header.

Test plan

  • make test — all packages pass
  • make lint — 0 issues
  • Existing TestFetch_Concurrent covers the concurrent discovery path
  • Existing TestBearerAuth_RequiredScopes covers the scope-failure path; verify custom error handler now receives scope errors

🤖 Generated with Claude Code

…rrors through error handler

- discovery: held write mutex for the entire refresh(), including the HTTP
  network call, blocking all concurrent Fetch() readers. Restructured to
  use singleflight (already a dependency) to coalesce concurrent cache
  misses into a single fetch; the lock is now held only for the cache
  check and update, matching the pattern in clientcreds.

- middleware: BearerAuth scope failures called writeInsufficientScope
  directly, bypassing any custom ErrorHandler. Now routes scope errors
  through cfg.errorHandler as an *oauth.Error{Code: "insufficient_scope"}.
  Updated defaultErrorHandler to map insufficient_scope → 403 Forbidden
  with the correct WWW-Authenticate header.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 17, 2026 10:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves concurrency and error-routing behavior in the SDK by (1) reducing discovery-cache contention during HTTP fetches and (2) ensuring OAuth scope failures flow through the configured middleware error handler.

Changes:

  • Add singleflight.Group to discovery refresh to coalesce concurrent cache misses and avoid holding locks during network I/O.
  • Route BearerAuth required-scope failures through cfg.errorHandler as oauth.Error{Code: "insufficient_scope"}.
  • Update defaultErrorHandler to map insufficient_scope to 403 Forbidden with an appropriate WWW-Authenticate header.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
middleware/middleware.go Adds insufficient_scope handling to the default error handler and routes scope failures through the configured ErrorHandler.
discovery/discovery.go Adds singleflight and narrows lock scope so concurrent discovery cache misses collapse into a single HTTP request.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +209 to +214
return cloneMetadata(&meta), nil
})
if err != nil {
return nil, err
}
return v.(*Metadata), nil
Comment on lines +189 to 193
cfg.errorHandler(w, r, &oauth.Error{
Code: "insufficient_scope",
Description: "Token does not have required scope: " + scope,
})
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants