diff --git a/CHANGELOG.md b/CHANGELOG.md
index 754cd2f2..2afb4e05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## v2.1.0 (2017-03-30)
+
+- Minor improvements and update to the chi core library
+- Introduced a brand new `chi/render` sub-package to complete the story of building
+APIs to offer a pattern for managing well-defined request / response payloads. Please
+check out the updated `_examples/rest` example for how it works.
+- Added `MethodNotAllowed(h http.HandlerFunc)` to chi.Router interface
+
+
## v2.0.0 (2017-01-06)
- After many months of v2 being in an RC state with many companies and users running it in
diff --git a/README.md b/README.md
index 19cb9b6a..eba288d7 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
-===
+#
+
[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis]
@@ -232,7 +232,9 @@ type Routes interface {
```
Each routing method accepts a URL `pattern` and chain of `handlers`. The URL pattern
-supports named params (ie. `/users/:userID`) and wildcards (ie. `/admin/*`).
+supports named params (ie. `/users/:userID`) and wildcards (ie. `/admin/*`). URL parameters
+can be fetched at runtime by calling `chi.URLParam(r, "userID")` for named parameters
+and `chi.URLParam(r, "*")` for a wildcard parameter.
### Middleware handlers
diff --git a/_examples/rest/main.go b/_examples/rest/main.go
index 3259d4bc..fd0ca20a 100644
--- a/_examples/rest/main.go
+++ b/_examples/rest/main.go
@@ -56,16 +56,6 @@ import (
var routes = flag.Bool("routes", false, "Generate router documentation")
-// TODO: make a new example as _examples/metrics
-// func TrackRoute(next http.Handler) http.Handler {
-// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-// next.ServeHTTP(w, r)
-// rctx := chi.RouteContext(r.Context())
-// routePattern := strings.Join(rctx.RoutePatterns, "")
-// fmt.Println("route:", routePattern)
-// })
-// }
-
func main() {
flag.Parse()
@@ -75,7 +65,6 @@ func main() {
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(render.SetContentType(render.ContentTypeJSON))
- // r.Use(TrackMetric)
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("root."))
diff --git a/render/README.md b/render/README.md
index ba611ca3..59f3d6db 100644
--- a/render/README.md
+++ b/render/README.md
@@ -1,3 +1,20 @@
-## chi/render is experimental package
+# chi/render
-Please, note that the render pkg API might change.
+The `render` sub-package helps manage HTTP request / response payloads.
+
+Every a well-designed, robust and maintainable Web Service / REST API also needs
+well-*defined* request and response payloads.
+
+Typically in a REST API application, you will have your data models (objects/structs)
+that hold lower-level runtime application state, and at times you need to assemble,
+decorate, hide or transform the representation before responding to a client, and
+also the client will likely provide the same structure as input from its requests.
+
+This is where `render` comes in - offering a few simple helpers and interfaces to
+provide a simple pattern for managing payload encoding and decoding.
+
+We've also combined it with some helpers for responding to content types and parsing
+request bodies. Please have a look at the [rest](https://github.com/pressly/chi/blob/master/_examples/rest/main.go)
+example which uses the latest chi/render sub-pkg.
+
+All feedback is welcome, thank you!
diff --git a/render/content_type.go b/render/content_type.go
index 4e9b6623..69ba9e48 100644
--- a/render/content_type.go
+++ b/render/content_type.go
@@ -10,7 +10,7 @@ var (
ContentTypeCtxKey = &contextKey{"ContentType"}
)
-// A ContentType is an enumeration of common HTTP content types.
+// ContentType is an enumeration of common HTTP content types.
type ContentType int
// ContentTypes handled by this package.
diff --git a/render/render.go b/render/render.go
index 045b06b2..98c8c7b1 100644
--- a/render/render.go
+++ b/render/render.go
@@ -5,14 +5,18 @@ import (
"reflect"
)
+// Renderer interface for managing response payloads.
type Renderer interface {
Render(w http.ResponseWriter, r *http.Request) error
}
+// Binder interface for managing request payloads.
type Binder interface {
Bind(r *http.Request) error
}
+// Bind decodes a request body and executes the Binder method of the
+// payload structure.
func Bind(r *http.Request, v Binder) error {
if err := Decode(r, v); err != nil {
return err
@@ -20,6 +24,7 @@ func Bind(r *http.Request, v Binder) error {
return binder(r, v)
}
+// Render renders a single payload and respond to the client request.
func Render(w http.ResponseWriter, r *http.Request, v Renderer) error {
if err := renderer(w, r, v); err != nil {
return err
@@ -28,6 +33,7 @@ func Render(w http.ResponseWriter, r *http.Request, v Renderer) error {
return nil
}
+// RenderList renders a slice of payloads and responds to the client request.
func RenderList(w http.ResponseWriter, r *http.Request, l []Renderer) error {
for _, v := range l {
if err := renderer(w, r, v); err != nil {