-
Notifications
You must be signed in to change notification settings - Fork 37
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
Allow passing context in requests #176
Comments
Hi @jackhopner At this very moment, the only use we make of the context is for middleware handlers options and we're using the default context of the request which is the default background context. It should be easy to add a context parameter to all the layers and then either:
This brings a couple of questions in terms of implementation and API surface : What should happen when the SDK tries to add a context value and the key is already in use (unlikely but possible) ? My opinion is that it should return an error. Thoughts? What should happen when the request gets cancelled ? With the current implementation, the http adapter will attempt to read the body, and get an error, which will be surfaced all the way up to the chained method API and to the consumer. I believe it's the right thing to do, people can then chose to read and handle the error or ignore it. Thoughts? What should be the API surface? I'm reluctant to add yet another method (on top of
AppendixCancellation repropackage main
import (
"context"
"fmt"
"log"
"net/http"
"time"
"io/ioutil"
)
func main() {
ctx, cancel := context.WithCancel(context.TODO())
time.AfterFunc(5*time.Second, func() {
cancel()
})
makeRequest(ctx)
}
func makeRequest (ctx context.Context) {
req, err := http.NewRequestWithContext(ctx, "GET", "https://httpbin.org/range/2048?duration=8&chunk_size=256", nil)
if err != nil {
log.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
if resp != nil {
fmt.Println("got a response" + resp.Status)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("body len %v", len(body))
}
} returns
|
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. |
Thanks @baywet, sorry I missed your reply.
I would suggest prefixing all keys with
If you pass the context when creating the HTTP request, when the context is cancelled the HTTP client will handle it and return an error of "context cancelled" (along with canceling the request). This means the HTTP adapter would never attempt to read the body and the
Yeah fair the names are already quite long, I would suggest the following (both if possible):
Hopefully that answers all your questions, let me know if you want me to take a stab at the implementation. |
Thanks for the additional information so to recap:
so effectively the decision that needs to be made it between Parameter: (similar to what dotnet is doing using optional parameters) client.Me().Messages().PostWithRequestConfigurationAndResponseHandler(body, nil, nil, context) or Property on the request configuration. configuration := import.NewMessagesPostRequestConfiguration()
configuration.Context = context
client.Me().Messages().PostWithRequestConfigurationAndResponseHandler(body, configuration, nil) The short method staying as it is: client.Me().Messages().Post(body) I'll take that back to the PM @maisarissi and the architect @darrelmiller to get their input. Thanks a lot! |
My vote would be for a Context property on the RequestConfiguration |
As Go doesn't support optional parameter nor does it support overload, adding a new parameter would mean that everyone would need to either pass a context or nil, as opposed to .NET which we can use overloads. Let's go with Context property. |
Thank you for providing input on this discussion, scheduled for July for now. |
On the other side Azure SDK is providing clear design guidelines which also covers the context: For Azure SDK the context is required for all API calls which is IMHO a good decision. |
Thanks for the additional pointers here. It'd be coherent to align things with azure, maybe not as a first parameter though. Also, due to staff shortage on our end, this is most likely going to go to August, maybe September at this point. |
If it's going to be passed as a parameter then it really should be the first, this would be in line with how the stdlib and most other golang libraries work. Also may be worth reading the link below as it warns against putting the context in a struct. (There's actually a golang linter which detects this - https://github.com/sivchari/containedctx) |
@maisarissi cc @baywet @darrelmiller Given that this will be a breaking change, i.e the intentions is to change from client.Me().Messages().PostWithRequestConfigurationAndResponseHandler(body, configuration, responseHandler) to client.Me().Messages().PostWithRequestConfigurationAndResponseHandler(context, body, configuration, responseHandler) should we rename the methods from |
We could rename it to post, but we already have a post method that only accepts the body (people complained about having to pass nil for a bunch of arguments). |
I'd personally recommend just having a single Post method, for a couple of reasons:
In regards to the other args such as
Edit: Excuse the poor naming |
Thanks for the input. Introducing yet another type on the executor method probably won't help us size wise. But we could move the response handler argument to a property on the existing request configuration type. |
Hello everyone. After talking to @darrelmiller, we agreed to proceed with the context as the first parameter of the function.
and yes, let's add responseHandler as part of the request configuration. As size has been an issue to build time and go docs generation let's have something similar to what @jackhopner shared by adding RequestConfiguration as optional and only one Post() method: func Post(ctx context.Context, body BodyType ...opts RequestConfiguration) {
var config *ConfigurationType
for _, opt := range opts {
if opt.Configuration != nil {
config = opt.Configuration
}...
}...
} |
@maisarissi examples 2 and 3 of your last answer are identical, can you update your message? |
Just updated the comment above. Let's go with only one Post() method. |
The only issue I have with that is that it leads people to think they can pass multiple request configuration instances. And forces us to check all entries (or we could check only the first one but that'd be ugly). |
FYI - This is the summary of the changes
func Post(ctx context.Context, body BodyType, opts RequestConfiguration) {
var config *ConfigurationType
}
|
Currently the msgraph-sdk-go doesn't allow passing the context when making requests which removes the ability to cancel API requests when the context is canceled.
Example usage could look like:
The text was updated successfully, but these errors were encountered: