Skip to content

fix(qwen): align auth polling interval and refresh lead#1924

Open
shenshuoyaoyouguang wants to merge 3 commits intorouter-for-me:mainfrom
shenshuoyaoyouguang:pr/qwen-auth-refresh
Open

fix(qwen): align auth polling interval and refresh lead#1924
shenshuoyaoyouguang wants to merge 3 commits intorouter-for-me:mainfrom
shenshuoyaoyouguang:pr/qwen-auth-refresh

Conversation

@shenshuoyaoyouguang
Copy link
Contributor

Summary

  • align qwen auth polling timing with refresh lead behavior
  • add coverage in both internal and sdk auth packages

Business value

  • reduces premature expiry and refresh timing drift for qwen auth flows
  • keeps this provider-specific fix easy to review without unrelated changes

Tests

  • go test ./internal/auth/qwen ./sdk/auth

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the Qwen authentication process by synchronizing token polling intervals with refresh lead times, which mitigates issues of premature token expiry and refresh timing discrepancies. It introduces a new internal method for handling HTTP POST requests, enabling better control over the HTTP client used during token polling. Additionally, comprehensive unit tests have been added to validate both the internal authentication logic and the SDK's refresh lead configuration.

Highlights

  • Qwen Authentication Polling: The polling mechanism for Qwen authentication has been updated to align its timing with the refresh lead behavior, preventing premature token expiry.
  • HTTP Client Customization: The PollForToken function now uses an internal postForm method, allowing the QwenAuth struct to utilize a configurable httpClient.
  • Test Coverage: New test files and cases have been added for both the internal and SDK authentication packages to ensure the robustness of the Qwen authentication flow and refresh lead logic.
  • Refresh Lead Adjustment: The RefreshLead method in the SDK's Qwen authenticator was adjusted to correctly return a pointer to the time.Duration value.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • internal/auth/qwen/qwen_auth.go
    • Replaced direct http.PostForm call with a new qa.postForm method to allow for custom HTTP client usage.
    • Introduced postForm method to QwenAuth to encapsulate HTTP POST request logic and use qa.httpClient if available.
  • internal/auth/qwen/qwen_auth_test.go
    • Added a new test file to include unit tests for the qwen authentication package.
    • Implemented TestPollForTokenUsesConfiguredHTTPClient to verify that the PollForToken function correctly utilizes a configured http.Client.
  • sdk/auth/qwen.go
    • Modified the RefreshLead method to return a pointer to a time.Duration variable, ensuring correct handling of the refresh lead value.
  • sdk/auth/qwen_test.go
    • Added a new test file for the qwen SDK authentication package.
    • Included TestQwenRefreshLead to confirm that the RefreshLead method returns the expected 3-hour duration.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request aligns Qwen authentication polling timing and adds test coverage. However, a potential path traversal vulnerability was identified in sdk/auth/qwen.go where user-supplied email input is used to construct a file path without sanitization. While the refactoring of an HTTP POST call into a new helper method is a solid improvement for testability and a fix for the refresh lead time is included, consider adding support for context.Context to the new helper method to allow for request cancellation, which would enhance robustness and align with existing patterns.

Comment on lines +313 to +325
func (qa *QwenAuth) postForm(endpoint string, data url.Values) (*http.Response, error) {
client := qa.httpClient
if client == nil {
client = http.DefaultClient
}
req, err := http.NewRequest(http.MethodPost, endpoint, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
return client.Do(req)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new postForm helper function is a good abstraction. However, it should accept a context.Context to allow for request cancellation and timeouts. The http.NewRequest call should be replaced with http.NewRequestWithContext.

This change would also imply updating the calling function, PollForToken, to accept and pass down a context. This is a best practice for long-running operations like polling, especially since its caller, sdk/auth/qwen.go:Login, already has a context available that is not being utilized for this operation.

Many other network-calling functions in this package, such as RefreshTokens, already use a context. Aligning PollForToken and postForm with this pattern would improve consistency and robustness.

Suggested change
func (qa *QwenAuth) postForm(endpoint string, data url.Values) (*http.Response, error) {
client := qa.httpClient
if client == nil {
client = http.DefaultClient
}
req, err := http.NewRequest(http.MethodPost, endpoint, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
return client.Do(req)
}
func (qa *QwenAuth) postForm(ctx context.Context, endpoint string, data url.Values) (*http.Response, error) {
client := qa.httpClient
if client == nil {
client = http.DefaultClient
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
return client.Do(req)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in c84bdf7. postForm now accepts context.Context, PollForToken passes the caller context through, and the request is built with http.NewRequestWithContext so cancellation/timeouts propagate correctly.

@shenshuoyaoyouguang shenshuoyaoyouguang marked this pull request as ready for review March 7, 2026 09:39
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@shenshuoyaoyouguang
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request primarily refactors the Qwen authentication process to incorporate context.Context into the PollForToken function and its callers, RequestQwenToken and Login, to enable better cancellation and timeout management. Key changes include modifying the PollForToken signature to accept a context, introducing a new postForm helper method to handle HTTP POST requests with context and a configurable HTTP client, and adding new tests for PollForToken's HTTP client usage and the RefreshLead method. Review comments indicate that the PollForToken's polling loop still uses time.Sleep without checking ctx.Done(), which could lead to goroutine leaks, and that the postForm method's fallback to http.DefaultClient lacks a default timeout, potentially causing indefinite hangs.


// PollForToken polls the token endpoint with the device code to obtain an access token.
func (qa *QwenAuth) PollForToken(deviceCode, codeVerifier string) (*QwenTokenData, error) {
func (qa *QwenAuth) PollForToken(ctx context.Context, deviceCode, codeVerifier string) (*QwenTokenData, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The PollForToken function's polling loop does not properly handle context.Context cancellation, specifically with time.Sleep calls (e.g., on lines 244, 267, 276). This is a vulnerability that can lead to goroutine leaks and blocking calls even after the context is canceled. To ensure full cancellability, replace time.Sleep(pollInterval) with a context-aware wait using a select statement that checks ctx.Done() and time.After(pollInterval).

func (qa *QwenAuth) postForm(ctx context.Context, endpoint string, data url.Values) (*http.Response, error) {
client := qa.httpClient
if client == nil {
client = http.DefaultClient
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The postForm method falls back to http.DefaultClient when qa.httpClient is nil. http.DefaultClient has no default timeout, which, combined with the use of context.Background() in some callers (like RequestQwenToken), can lead to indefinite hangs if the remote server or proxy becomes unresponsive.

Suggested change
client = http.DefaultClient
client = &http.Client{Timeout: 60 * time.Second}

@shenshuoyaoyouguang
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces context awareness to the Qwen device authentication flow, which is a good improvement for handling cancellable operations. It also includes a fix for the RefreshLead function and adds relevant test coverage. My review includes one suggestion to complete the context propagation within the polling loop by utilizing the newly introduced waitForNextPoll function.

resp, err := qa.postForm(ctx, QwenOAuthTokenEndpoint, data)
if err != nil {
fmt.Printf("Polling attempt %d/%d failed: %v\n", attempt+1, maxAttempts, err)
time.Sleep(pollInterval)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

You've introduced a waitForNextPoll helper function to make sleeping context-aware, which is a great improvement. However, the time.Sleep calls within PollForToken have not been updated to use it. To make the polling loop fully cancellable, you should replace the time.Sleep(pollInterval) calls with waitForNextPoll(ctx, pollInterval) and handle the potential context cancellation error.

This change should be applied to all instances of time.Sleep(pollInterval) in this function (lines 244, 252, 267, and 276).

			if err := waitForNextPoll(ctx, pollInterval); err != nil {
				return nil, err
			}

@shenshuoyaoyouguang
Copy link
Contributor Author

Review Navigation: This PR has a smaller scope, mainly aligning qwen auth polling with refresh lead. Subsequent commits have added context cancellation and default timeout, current CI has passed, suitable for priority or mid-early order review.

Copy link
Collaborator

@luispater luispater left a comment

Choose a reason for hiding this comment

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

Summary
Thanks for the focused fix and the added tests. I found one blocking correctness issue in the cancellation path.

Key findings

  • Blocking: PollForToken still retries after ctx cancellation. postForm now uses NewRequestWithContext, but any client.Do error is still treated as retryable, so the loop continues sleeping and retrying instead of returning promptly with ctx.Err().
  • Blocking: waitForNextPoll is defined but never used, so cancellation is not honored during the polling backoff either (authorization_pending / slow_down still use time.Sleep).
  • Non-blocking: please add a regression test that cancels the context and verifies PollForToken exits immediately.

Test plan

  • Reviewed the PR diff and current polling call paths
  • Did not run code locally

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