Skip to content

Commit

Permalink
Adding external cancelation context to the gentleman client
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJCross committed Jul 30, 2020
1 parent 34f7cae commit 8b6324c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 4 deletions.
12 changes: 12 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gentleman

import (
gocontext "context"
"net/http"

"gopkg.in/h2non/gentleman.v2/context"
Expand Down Expand Up @@ -185,6 +186,17 @@ func (c *Client) CookieJar() *Client {
return c
}

// UseContext adds a cancelation context to the client to enable the use of early cancelation. This is useful for
// server outgoing calls where we can attach the context from the incoming client. This will allow the downstream
// calls to be canceled early on the case of a tcp close or http2 cancellation.
// e.g. client.Get().URL("someUrl").UseContext( incomingServerRequest.Context() ).Send()
func (c *Client) UseContext(cancelContext gocontext.Context) *Client {
c.UseRequest(func(c *context.Context, handler context.Handler) {
handler.Next(c.SetCancelContext(cancelContext))
})
return c
}

// Use uses a new plugin to the middleware stack.
func (c *Client) Use(p plugin.Plugin) *Client {
c.Middleware.Use(p)
Expand Down
26 changes: 24 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package gentleman

import (
gocontext "context"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/nbio/st"
"github.com/stretchr/testify/assert"

"gopkg.in/h2non/gentleman.v2/context"
)

Expand Down Expand Up @@ -53,7 +56,7 @@ func TestClientRequestMiddleware(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", r.Header.Get("Client"))
w.Header().Set("Agent", r.Header.Get("Agent"))
fmt.Fprintln(w, "Hello, world")
_, _ = fmt.Fprintln(w, "Hello, world")
}))
defer ts.Close()

Expand All @@ -79,7 +82,7 @@ func TestClientRequestMiddleware(t *testing.T) {

func TestClientRequestResponseMiddleware(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world")
_, _ = fmt.Fprintln(w, "Hello, world")
}))
defer ts.Close()

Expand Down Expand Up @@ -114,6 +117,8 @@ func TestClientErrorMiddleware(t *testing.T) {

req := client.Request()
res, err := req.Do()
assert.Error(t, err)
assert.NotNil(t, res)
st.Expect(t, err.Error(), "error: foo error")
st.Expect(t, res.Ok, false)
st.Expect(t, res.StatusCode, 0)
Expand All @@ -132,6 +137,9 @@ func TestClientCustomPhaseMiddleware(t *testing.T) {

req := client.Request()
res, err := req.Do()

assert.Error(t, err)
assert.NotNil(t, res)
st.Expect(t, err.Error(), "error: foo error")
st.Expect(t, res.Ok, false)
st.Expect(t, res.StatusCode, 0)
Expand Down Expand Up @@ -299,3 +307,17 @@ func TestClientVerbMethods(t *testing.T) {
t.Errorf("Invalid request method: %s", req.Context.Request.Method)
}
}

func TestClientWithCanceledContext(t *testing.T) {

ctx, cancel := gocontext.WithCancel(gocontext.Background())
cancel()
_, err := New().
URL("http://localhost:8999").
UseContext(ctx).
Post().
Path("/test").
Send()
assert.EqualError(t, err, "Post \"http://localhost:8999/test\": context canceled")

}
6 changes: 6 additions & 0 deletions context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ func (c *Context) Value(key interface{}) interface{} {
return c.Request.Context().Value(key)
}

func (c *Context) SetCancelContext(ctx context.Context) *Context {
golRequestContext := context.WithValue(ctx, Key, c.Value(Key))
c.Request = c.Request.WithContext(golRequestContext)
return c
}

// emptyContext creates a new empty context.Context
func emptyContext() context.Context {
return context.WithValue(context.Background(), Key, Store{})
Expand Down
6 changes: 4 additions & 2 deletions plugins/proxy/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package proxy

import (
"github.com/nbio/st"
"github.com/stretchr/testify/assert"

"gopkg.in/h2non/gentleman.v2/context"
"net/http"
"testing"
Expand Down Expand Up @@ -37,8 +39,8 @@ func TestProxyParseError(t *testing.T) {

transport := ctx.Client.Transport.(*http.Transport)
_, err := transport.Proxy(ctx.Request)

st.Expect(t, err.Error(), "parse ://: missing protocol scheme")
assert.Error(t, err)
st.Expect(t, err.Error(), "parse \"://\": missing protocol scheme")
}

type handler struct {
Expand Down

0 comments on commit 8b6324c

Please sign in to comment.