Skip to content

Commit

Permalink
feat(#4): support base interface for helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
h2non committed Feb 24, 2016
1 parent 38c5d03 commit 6d5ee83
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 46 deletions.
46 changes: 23 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ Plugin-driven, middleware-oriented library to easily create rich, versatile and

<img src="http://s10.postimg.org/5e31ox1ft/gentleman.png" align="center" height="320" />

## Installation

```bash
go get -u gopkg.in/h2non/gentleman.v0
```

Note: I strongly recommend you to use `gopkg.in` when depending on third-party packages to prevent unexpected breaks of the interface contract in upcoming major versions of the package.

## Goals

- Plugin driven.
Expand All @@ -23,9 +15,17 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
- Control-flow capable middleware layer to manage full HTTP live cycle.
- Built-in multiplexer with easy composition features.
- Easy to configure and use.
- Convenient helpers and abstractions over HTTP primitives in Go.
- Convenient helpers and abstractions over Go's HTTP primitives.
- Dependency free.

## Installation

```bash
go get -u gopkg.in/h2non/gentleman.v0
```

Note: I strongly recommend you to use `gopkg.in` when depending on third-party packages to prevent unexpected breaks of the interface contract in upcoming major versions of the package.

## Plugins

<table>
Expand All @@ -43,7 +43,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /</a></td>
<td>Easily declare URL, base URL and path values in HTTP requests</td>
</tr>
Expand All @@ -54,7 +54,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Declare authorization headers in your requests</td>
</tr>
Expand All @@ -65,7 +65,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Easily define bodies based on JSON, XML, strings, buffers or streams</td>
</tr>
Expand All @@ -76,7 +76,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Define body MIME type by alias</td>
</tr>
Expand All @@ -87,7 +87,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Declare and store HTTP cookies easily</td>
</tr>
Expand All @@ -98,7 +98,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-beta-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-beta-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Helpers to define enable/disable HTTP compression</td>
</tr>
Expand All @@ -109,7 +109,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Manage HTTP headers easily</td>
</tr>
Expand All @@ -120,7 +120,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Create multipart forms easily. Supports files and text fields</td>
</tr>
Expand All @@ -131,7 +131,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Configure HTTP proxy servers</td>
</tr>
Expand All @@ -142,7 +142,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Easily manage query params</td>
</tr>
Expand All @@ -153,7 +153,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Easily configure a custom redirect policy</td>
</tr>
Expand All @@ -164,7 +164,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Easily configure the HTTP timeouts (request, dial, TLS...)</td>
</tr>
Expand All @@ -175,7 +175,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Define a custom HTTP transport easily</td>
</tr>
Expand All @@ -186,7 +186,7 @@ Note: I strongly recommend you to use `gopkg.in` when depending on third-party p
<img src="https://godoc.org/github.com/h2non/gentleman?status.svg" />
</a>
</td>
<td><img src="https://img.shields.io/badge/api-stable-green.svg?style=flat" /></td>
<td><img src="https://img.shields.io/badge/status-stable-green.svg?style=flat" /></td>
<td><a href="https://travis-ci.org/h2non/gentleman"><img src="https://travis-ci.org/h2non/gentleman.png" /></a></td>
<td>Configure the TLS options used by the HTTP transport</td>
</tr>
Expand Down
40 changes: 29 additions & 11 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"gopkg.in/h2non/gentleman.v0/context"
"gopkg.in/h2non/gentleman.v0/middleware"
"gopkg.in/h2non/gentleman.v0/plugin"
"gopkg.in/h2non/gentleman.v0/plugins/headers"
"gopkg.in/h2non/gentleman.v0/plugins/url"
)

// NewContext is a convenient alias to context.New factory.
Expand Down Expand Up @@ -86,28 +88,44 @@ func (c *Client) Head() *Request {
return req
}

// Method defines a the default HTTP method used by outgoing client requests.
func (c *Client) Method(name string) *Client {
c.Middleware.UseRequest(func(ctx *context.Context, h context.Handler) {
ctx.Request.Method = name
h.Next(ctx)
})
return c
}

// URL defines the URL for client requests.
// Useful to define at client level the base URL and path.
// Useful to define at client level the base URL and base path used by child requests.
func (c *Client) URL(uri string) *Client {
c.Use(url.URL(uri))
return c
}

// BasePath defines the URL base path for client requests.
func (c *Client) BasePath(base string) *Client {
// BaseURL defines the URL schema and host for client requests.
// Useful to define at client level the base URL used by client child requests.
func (c *Client) BaseURL(uri string) *Client {
c.Use(url.URL(uri))
return c
}

// Set defines a new HTTP header field by key and value in the outgoing client requests.
func (c *Client) Set(key, value string) *Client {
// Path defines the URL base path for client requests.
func (c *Client) Path(path string) *Client {
c.Use(url.Path(path))
return c
}

// Method defines a the default HTTP method used by outgoing client requests.
func (c *Client) Method(name string) *Client {
c.Middleware.UseRequest(func(ctx *context.Context, h context.Handler) {
ctx.Request.Method = name
h.Next(ctx)
})
// Param replaces a path param based on the given param name and value.
func (c *Client) Param(name, value string) *Client {
c.Use(url.Param(name, value))
return c
}

// Set sets a new HTTP header field by key and value in the outgoing client requests.
func (c *Client) Set(key, value string) *Client {
c.Use(headers.Set(key, value))
return c
}

Expand Down
2 changes: 1 addition & 1 deletion plugins/auth/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# gentleman/auth [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/auth) [![API](https://img.shields.io/badge/api-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/auth) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)
# gentleman/auth [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/auth) [![API](https://img.shields.io/badge/status-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/auth) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)

gentleman's plugin to easily define HTTP authorization headers based on multiple schemas.

Expand Down
2 changes: 1 addition & 1 deletion plugins/body/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# gentleman/body [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/body?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/body) [![API](https://img.shields.io/badge/api-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)
# gentleman/body [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/body?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/body) [![API](https://img.shields.io/badge/status-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)

gentleman's plugin to easy define HTTP bodies. Supports JSON, XML, strings or streams with interface polymorphism.

Expand Down
2 changes: 1 addition & 1 deletion plugins/bodytype/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# gentleman/bodytype [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype) [![API](https://img.shields.io/badge/api-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)
# gentleman/bodytype [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype) [![API](https://img.shields.io/badge/status-stable-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/bodytype) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)

gentleman's plugin to easy define HTTP bodies. Supports JSON, XML, strings or streams with interface polymorphism.

Expand Down
4 changes: 2 additions & 2 deletions plugins/bodytype/bodytype.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ var Types = map[string]string{
"form-data": "application/x-www-form-urlencoded",
}

// Type defines an authorization basic header in the outgoing request
func Type(name string) p.Plugin {
// Set defines an authorization basic header in the outgoing request
func Set(name string) p.Plugin {
return p.NewRequestPlugin(func(ctx *c.Context, h c.Handler) {
defineType(name, ctx.Request)
h.Next(ctx)
Expand Down
2 changes: 1 addition & 1 deletion plugins/bodytype/bodytype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestBodyTypeDefineUnsupported(t *testing.T) {
func TestBodyType(t *testing.T) {
ctx := context.New()
fn := newHandler()
Type("json").Request(ctx, fn.fn)
Set("json").Request(ctx, fn.fn)
st.Expect(t, fn.called, true)
st.Expect(t, ctx.Request.Header.Get("Content-Type"), "application/json")
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/compression/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# gentleman/compression [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/compression?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/compression) [![API](https://img.shields.io/badge/api-beta-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/compression) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)
# gentleman/compression [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GoDoc](https://godoc.org/github.com/h2non/gentleman/plugins/compression?status.svg)](https://godoc.org/github.com/h2non/gentleman/plugins/compression) [![API](https://img.shields.io/badge/status-beta-green.svg?style=flat)](https://godoc.org/github.com/h2non/gentleman/plugins/compression) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman)

gentleman's plugin to disable and customize data compression in HTTP requests/responses.

Expand Down
83 changes: 78 additions & 5 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"gopkg.in/h2non/gentleman.v0/middleware"
"gopkg.in/h2non/gentleman.v0/mux"
"gopkg.in/h2non/gentleman.v0/plugin"
"gopkg.in/h2non/gentleman.v0/plugins/body"
"gopkg.in/h2non/gentleman.v0/plugins/bodytype"
"gopkg.in/h2non/gentleman.v0/plugins/multipart"
"gopkg.in/h2non/gentleman.v0/plugins/url"
"gopkg.in/h2non/gentleman.v0/utils"
"io"
Expand Down Expand Up @@ -126,8 +129,26 @@ func (r *Request) URL(uri string) *Request {
}

// Path defines the request URL path to be used in the HTTP request.
func (r *Request) Path(uri string) *Request {
r.Use(url.URL(uri))
func (r *Request) Path(path string) *Request {
r.Use(url.Path(path))
return r
}

// AddPath defines the request URL path to be used in the HTTP request.
func (r *Request) AddPath(path string) *Request {
r.Use(url.AddPath(path))
return r
}

// Param replaces a path param based on the given param name and value.
func (r *Request) Param(name, value string) *Request {
r.Use(url.Param(name, value))
return r
}

// Params replaces path params based on the given params key-value map.
func (r *Request) Params(params map[string]string) *Request {
r.Use(url.Params(params))
return r
}

Expand All @@ -137,12 +158,64 @@ func (r *Request) Set(name, value string) *Request {
return r
}

// Body defines the HTTP request body data based on a io.Reader stream.
func (r *Request) Body(body io.Reader) *Request {
// Type defines the Content-Type header field based on the given type name alias or value.
// You can use the following content type aliases: json, xml, form, html, text and urlencoded.
func (r *Request) Type(name string) *Request {
r.Use(bodytype.Set(name))
return r
}

// Body defines the request body based on a io.Reader stream.
func (r *Request) Body(reader io.Reader) *Request {
r.Use(body.Reader(reader))
return r
}

// BodyString defines the request body based on the given string.
// If using this method, you should define the proper Content-Type header
// representing the real content MIME type.
func (r *Request) BodyString(data string) *Request {
r.Use(body.String(data))
return r
}

// JSON serializes and defines as request body based on the given input.
// The proper Content-Type header will be transparently added for you.
func (r *Request) JSON(data interface{}) *Request {
r.Use(body.JSON(data))
return r
}

// XML serializes and defines the request body based on the given input.
// The proper Content-Type header will be transparently added for you.
func (r *Request) XML(data interface{}) *Request {
r.Use(body.XML(data))
return r
}

// Form serializes and defines the request body as multipart/form-data
// based on the given form data.
func (r *Request) Form(data multipart.FormData) *Request {
r.Use(multipart.Data(data))
return r
}

// File serializes and defines the request body as multipart/form-data
// containing one file field.
func (r *Request) File(name string, reader io.Reader) *Request {
r.Use(multipart.File(name, reader))
return r
}

// Files serializes and defines the request body as multipart/form-data
// containing the given file fields.
func (r *Request) Files(files []multipart.FormFile) *Request {
r.Use(multipart.Files(files))
return r
}

// Send is an alias to Do(), which executes the current request.
// Send is an alias to Do(), which executes the current request
// and returns the response.
func (r *Request) Send() (*Response, error) {
return r.Do()
}
Expand Down

0 comments on commit 6d5ee83

Please sign in to comment.