-
Notifications
You must be signed in to change notification settings - Fork 127
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
Fix: Provide empty context without deadline #445
Fix: Provide empty context without deadline #445
Conversation
The request context has set up a deadline of value DefaultRequestTimeout. The function CreateOAuth2TokenSource would store that context in the token source creator. The token source creator would later try to create a new Token(), but fail since the deadline would be reached. The context passed to oauth2 package controls which HTTP client is used. See the oauth2.HTTPClient variable. Therefore fix the situation by passing an empty context to oauth2 package. Fixes cloudfoundry#444
Thanks for digging into this. Holding onto the context like that definitely seems like the problem and this PR seems like it would address it. I think the only I worry I have is this may make any requests to refresh the oauth token non-cancellable since it uses a new background context. While that may be a problem in some scenarios, it seems like less of a problem than the one you encountered for long running programs. The real problem seems to be the caching of the request context for the duration of the process. It's been a while since I've really dug into this oauth code, so it's very possible I'm misunderstanding something. Out of curiosity, do you know if providing a new context for every call through the loop like |
I must admit it's really challenging (to me) to go through go-cfclient, oauth2 and net/http code base. But it's also challenging to understand how others use go-cfclient and contexts in general and what are the expectations.
I guess a different and probably better solution than the current one in the commit/'PR change' is: The token refresher that is being created with
copies all deadlines from the parent (the current request context).
If we just need a context with the old http client, we could probably copy it over to a new context.Background() context and not copy over the previous deadlines.
|
Most go-cfclient consumers probably just use the request timeout in the config. While probably rarely used with this client, using a cancellable context when making a request allows you cancel inflight requests running in a goroutine: ctx, cancel := context.WithCancel(context.Background())
cf, _ := client.New(cfg)
go func() {
orgs, _ := cf.Organizations.ListAll(ctx, nil)
for _, o := range orgs {
fmt.Printf("%s\n", o.Name)
}
}()
time.Sleep(100 * time.Millisecond)
cancel() My main worry was that using a new context for the oauth call might make that uncancellable. |
Thanks for the sample code. I will try to check on Monday whether I can give a better answer with WithCancel in mind. |
I've created a second pull request #447 and the following text is referring to that PR and my latest state :-)
The token source does not get a request context during the Token() call: https://github.com/golang/oauth2/blob/314ee5b92bf23c4973aa8e61eba3ff458e80eef2/transport.go#L45 Regarding your example scenario in First the following code gets called:
This might already break in the case of password grant type within
and cancel that event finally. So I don't see a reason how the current request could not be cancelled. I've tested so far with the base repo with https://github.com/gogolok/go-cfclient-issue-rg0/ and local modifications (to vendor/ + even the net/http code base). So if you need something else confirmed, please let me know. |
The request context has set up a deadline of value DefaultRequestTimeout. The function CreateOAuth2TokenSource would store that context in the token source creator. The token source creator would later try to create a new Token(), but fail since the deadline would be reached.
The context passed to oauth2 package controls which HTTP client is used. See the oauth2.HTTPClient variable.
Therefore fix the situation by passing an empty context to oauth2 package.
Fixes #444