Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: go-chi/chi
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.0.0
Choose a base ref
...
head repository: go-chi/chi
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.1.0
Choose a head ref

Commits on Nov 30, 2016

  1. Copy the full SHA
    17a9775 View commit details

Commits on Jan 7, 2017

  1. Export logger field on DefaultLogFormatter, for ability to change pkg…

    … level default logger format
    Peter Kieltyka committed Jan 7, 2017
    Copy the full SHA
    076deb8 View commit details

Commits on Jan 8, 2017

  1. Update benchmarks

    Peter Kieltyka committed Jan 8, 2017
    Copy the full SHA
    73deb7e View commit details

Commits on Jan 15, 2017

  1. Remove the content-length header from compressed responses

    Laurie Clark-Michalek committed Jan 15, 2017
    Copy the full SHA
    9ce1605 View commit details
  2. Merge pull request #135 from lclarkmichalek/compression-content-length

    Remove the content-length header from compressed responses
    Peter Kieltyka authored Jan 15, 2017
    Copy the full SHA
    1b368fd View commit details

Commits on Jan 16, 2017

  1. Add realip middleware test

    kevingo committed Jan 16, 2017
    Copy the full SHA
    861b94d View commit details
  2. Copy the full SHA
    f3cc7c5 View commit details
  3. Merge pull request #137 from cyx/patch-1

    OPTIMIZE: Change ServerBaseContext
    Peter Kieltyka authored Jan 16, 2017
    Copy the full SHA
    8dd9731 View commit details

Commits on Jan 17, 2017

  1. Merge pull request #136 from kevingo/master

    Add realip middleware test
    Peter Kieltyka authored Jan 17, 2017
    Copy the full SHA
    9d7b95c View commit details

Commits on Jan 18, 2017

  1. Assign method not allowed handler to sub router

    Signed-off-by: Jingwen Peng <pengsrc@icloud.com>
    pengsrc committed Jan 18, 2017
    Copy the full SHA
    45e2c82 View commit details

Commits on Jan 19, 2017

  1. Merge pull request #116 from jiop/master

    Fix missing MethodNotAllowed in Router interface
    Peter Kieltyka authored Jan 19, 2017
    Copy the full SHA
    f55e376 View commit details
  2. Merge pull request #139 from prettyxw/master

    Assign method not allowed handler to sub router
    Peter Kieltyka authored Jan 19, 2017
    Copy the full SHA
    bb4b586 View commit details

Commits on Jan 25, 2017

  1. Copy the full SHA
    7765b09 View commit details

Commits on Feb 13, 2017

  1. Compression middleware should implement http.CloseNotifier.

    If the underlying writer does not implement http.CloseNotifier, we
    return a channel that never receives a value. The semantics here is that
    the client never disconnects before the request is processed, and this
    is as close to the default behavior as we can get.
    chuyeow committed Feb 13, 2017
    Copy the full SHA
    d6e62c5 View commit details

Commits on Feb 14, 2017

  1. Merge pull request #154 from chuyeow/compress-with-close-notifier

    Compression middleware should implement http.CloseNotifier
    Peter Kieltyka authored Feb 14, 2017
    Copy the full SHA
    c85a546 View commit details
  2. Add dummy CloseNotify for backwards compatibility.

    This makes code that uses middleware.CloseNotify compile on 1.8.
    
    Also clarify in the documentation that the middleware
    only does nothing on Go 1.8+.
    nkovacs committed Feb 14, 2017
    Copy the full SHA
    65e3ee1 View commit details
  3. Copy the full SHA
    d573d1c View commit details
  4. Merge pull request #157 from nkovacs/closenotify-1.8

    Add dummy CloseNotify for backwards compatibility.
    Peter Kieltyka authored Feb 14, 2017
    Copy the full SHA
    43fed1c View commit details
  5. Merge pull request #158 from nkovacs/patch-1

    Fix example in middleware.Profiler godoc
    Peter Kieltyka authored Feb 14, 2017
    Copy the full SHA
    b206b03 View commit details
  6. Travis, indent

    Peter Kieltyka committed Feb 14, 2017
    Copy the full SHA
    38b26e7 View commit details

Commits on Feb 16, 2017

  1. Add Install section to README

    Rohan Allison committed Feb 16, 2017
    Copy the full SHA
    7e99e62 View commit details
  2. Merge pull request #160 from rohanthewiz/master

    Add Install section to README
    Peter Kieltyka authored Feb 16, 2017
    Copy the full SHA
    5917107 View commit details

Commits on Feb 19, 2017

  1. update func names for both Slashes middleware in README

    dannyvankooten authored and Peter Kieltyka committed Feb 19, 2017
    Copy the full SHA
    57ee761 View commit details

Commits on Mar 13, 2017

  1. Travis to run on 1.7.x and 1.8.x

    Peter Kieltyka committed Mar 13, 2017
    Copy the full SHA
    34bf22a View commit details

Commits on Mar 14, 2017

  1. Find routes by raw url path, fixes #148

    Peter Kieltyka committed Mar 14, 2017
    Copy the full SHA
    822e7b8 View commit details

Commits on Mar 18, 2017

  1. Support inline middlewares for NotFound and MethodNotAllowed

    Peter Kieltyka committed Mar 18, 2017
    Copy the full SHA
    5b7406a View commit details

Commits on Mar 30, 2017

  1. Rewrite of chi/render pkg, introducing Binder and Renderer interfaces…

    … for handling well-defined request/response payloads
    Peter Kieltyka authored and Peter Kieltyka committed Mar 30, 2017
    Copy the full SHA
    af97407 View commit details
  2. Add suggestion about using github.com/pkg/errors for error renderers

    Peter Kieltyka authored and Peter Kieltyka committed Mar 30, 2017
    Copy the full SHA
    2810210 View commit details
  3. Update versions example to use latest render subpkg

    Peter Kieltyka authored and Peter Kieltyka committed Mar 30, 2017
    Copy the full SHA
    7f80c65 View commit details
  4. Update README, CHANGELOG, other comments

    Peter Kieltyka authored and Peter Kieltyka committed Mar 30, 2017
    Copy the full SHA
    e6033ea View commit details
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
language: go

go:
- 1.7.4
- 1.7.x
- 1.8.x
- tip

install:
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
82 changes: 43 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<img alt="chi" src="https://cdn.rawgit.com/pressly/chi/master/_examples/chi.svg" width="220" />
===
# <img alt="chi" src="https://cdn.rawgit.com/pressly/chi/master/_examples/chi.svg" width="220" />


[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis]

@@ -17,6 +17,8 @@ handlers (stdlib-only), developer productivity, and deconstructing a large syste
parts. The core router `github.com/pressly/chi` is quite small (less than 1000 LOC), but we've also
included some useful/optional subpackages: `middleware`, `render` and `docgen`. We hope you enjoy it too!

## Install

`go get -u github.com/pressly/chi`


@@ -230,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
@@ -295,23 +299,23 @@ chi comes equipped with an optional `middleware` package, providing a suite of s
`net/http` middlewares. Please note, any middleware in the ecosystem that is also compatible
with `net/http` can be used with chi's mux.

--------------------------------------------------------------------------------------------------
| Middleware | Description |
|:-------------|:---------------------------------------------------------------------------------
| RequestID | Injects a request ID into the context of each request. |
| RealIP | Sets a http.Request's RemoteAddr to either X-Forwarded-For or X-Real-IP. |
| Logger | Logs the start and end of each request with the elapsed processing time. |
| Recoverer | Gracefully absorb panics and prints the stack trace. |
| NoCache | Sets response headers to prevent clients from caching. |
| CloseNotify | Signals to the request context when a client has closed their connection. |
| Timeout | Signals to the request context when the timeout deadline is reached. |
| Throttle | Puts a ceiling on the number of concurrent requests. |
| Compress | Gzip compression for clients that accept compressed responses. |
| Profiler | Easily attach net/http/pprof to your routers. |
| Slashes | Strip and redirect slashes on routing paths. |
| WithValue | Short-hand middleware to set a key/value on the request context. |
| Heartbeat | Monitoring endpoint to check the servers pulse. |
--------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
| Middleware | Description |
|:---------------------|:---------------------------------------------------------------------------------
| RequestID | Injects a request ID into the context of each request. |
| RealIP | Sets a http.Request's RemoteAddr to either X-Forwarded-For or X-Real-IP. |
| Logger | Logs the start and end of each request with the elapsed processing time. |
| Recoverer | Gracefully absorb panics and prints the stack trace. |
| NoCache | Sets response headers to prevent clients from caching. |
| Timeout | Signals to the request context when the timeout deadline is reached. |
| Throttle | Puts a ceiling on the number of concurrent requests. |
| Compress | Gzip compression for clients that accept compressed responses. |
| Profiler | Easily attach net/http/pprof to your routers. |
| StripSlashes | Strip slashes on routing paths. |
| RedirectSlashes | Redirect slashes on routing paths. |
| WithValue | Short-hand middleware to set a key/value on the request context. |
| Heartbeat | Monitoring endpoint to check the servers pulse. |
----------------------------------------------------------------------------------------------------------

Other cool net/http middlewares:

@@ -339,31 +343,31 @@ and..

The benchmark suite: https://github.com/pkieltyka/go-http-routing-benchmark

Comparison with other routers (as of Aug 1/16): https://gist.github.com/pkieltyka/76a59d33492dd2732e691ad8c0b274a4
Comparison with other routers (as of Jan 7/17): https://gist.github.com/pkieltyka/d0814d5396c996cb3ff8076399583d1f

```shell
BenchmarkChi_Param 5000000 251 ns/op 240 B/op 1 allocs/op
BenchmarkChi_Param5 5000000 393 ns/op 240 B/op 1 allocs/op
BenchmarkChi_Param20 1000000 1012 ns/op 240 B/op 1 allocs/op
BenchmarkChi_ParamWrite 5000000 301 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GithubStatic 5000000 287 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GithubParam 3000000 442 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GithubAll 20000 90855 ns/op 48723 B/op 203 allocs/op
BenchmarkChi_GPlusStatic 5000000 250 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GPlusParam 5000000 280 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GPlus2Params 5000000 337 ns/op 240 B/op 1 allocs/op
BenchmarkChi_GPlusAll 300000 4128 ns/op 3120 B/op 13 allocs/op
BenchmarkChi_ParseStatic 5000000 250 ns/op 240 B/op 1 allocs/op
BenchmarkChi_ParseParam 5000000 275 ns/op 240 B/op 1 allocs/op
BenchmarkChi_Parse2Params 5000000 305 ns/op 240 B/op 1 allocs/op
BenchmarkChi_ParseAll 200000 7671 ns/op 6240 B/op 26 allocs/op
BenchmarkChi_StaticAll 30000 55497 ns/op 37682 B/op 157 allocs/op
BenchmarkChi_Param 5000000 398 ns/op 304 B/op 2 allocs/op
BenchmarkChi_Param5 3000000 556 ns/op 304 B/op 2 allocs/op
BenchmarkChi_Param20 1000000 1184 ns/op 304 B/op 2 allocs/op
BenchmarkChi_ParamWrite 3000000 443 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GithubStatic 3000000 427 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GithubParam 3000000 565 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GithubAll 10000 122143 ns/op 61716 B/op 406 allocs/op
BenchmarkChi_GPlusStatic 5000000 383 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GPlusParam 3000000 431 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GPlus2Params 3000000 500 ns/op 304 B/op 2 allocs/op
BenchmarkChi_GPlusAll 200000 6410 ns/op 3952 B/op 26 allocs/op
BenchmarkChi_ParseStatic 5000000 384 ns/op 304 B/op 2 allocs/op
BenchmarkChi_ParseParam 3000000 415 ns/op 304 B/op 2 allocs/op
BenchmarkChi_Parse2Params 3000000 450 ns/op 304 B/op 2 allocs/op
BenchmarkChi_ParseAll 100000 12124 ns/op 7904 B/op 52 allocs/op
BenchmarkChi_StaticAll 20000 78501 ns/op 47731 B/op 314 allocs/op
```

NOTE: the allocs in the benchmark above are from the calls to http.Request's
`WithContext(context.Context)` method that clones the http.Request, sets the `Context()`
on the duplicated (alloc'd) request and returns it the new request object. This is just
how setting context on a request in Go 1.7 works.
how setting context on a request in Go 1.7+ works.


## Credits
@@ -390,7 +394,7 @@ and even [graphql](https://github.com/graphql-go/graphql). They're all pretty co
own unique approaches and benefits. Specifically, I'd look at gRPC since it makes client-server
communication feel like a single program on a single computer, no need to hand-write a client library
and the request/response payloads are typed contracts. NATS is pretty amazing too as a super
fast and lightweight pub-sub transport that can speak protobufs, with nice service discovery -
fast and lightweight pub-sub transport that can speak protobufs, with nice service discovery -
an excellent combination with gRPC.


52 changes: 28 additions & 24 deletions _examples/logging/main.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,10 @@
// logger using the amazing Sirupsen/logrus package as the logging
// backend.
//
// Also: check out https://github.com/pressly/lg for an improved context
// logger with support for HTTP request logging, based on the example
// below.
//
package main

import (
@@ -20,9 +24,14 @@ import (

func main() {

// Setup the logger
// Setup the logger backend using Sirupsen/logrus and configure
// it to use a custom JSONFormatter. See the logrus docs for how to
// configure the backend at github.com/Sirupsen/logrus
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{} // optional / configurable, see docs
logger.Formatter = &logrus.JSONFormatter{
// disable, as we set our own
DisableTimestamp: true,
}

// Routes
r := chi.NewRouter()
@@ -46,19 +55,19 @@ func main() {

// StructuredLogger is a simple, but powerful implementation of a custom structured
// logger backed on logrus. I encourage users to copy it, adapt it and make it their
// own. It's well suited to live in its own package, and likely soon I will update
// github.com/goware/lg to use this implementation.
// own. Also take a look at https://github.com/pressly/lg for a dedicated pkg based
// on this work, designed for context-based http routers.

func NewStructuredLogger(logger *logrus.Logger) func(next http.Handler) http.Handler {
return middleware.RequestLogger(&StructuredLogger{logger})
}

type StructuredLogger struct {
logger *logrus.Logger
Logger *logrus.Logger
}

func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
entry := &StructuredLoggerEntry{logger: logrus.NewEntry(l.logger)}
entry := &StructuredLoggerEntry{Logger: logrus.NewEntry(l.Logger)}
logFields := logrus.Fields{}

logFields["ts"] = time.Now().UTC().Format(time.RFC1123)
@@ -80,33 +89,28 @@ func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {

logFields["uri"] = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)

entry.logger = entry.logger.WithFields(logFields)
entry.Logger = entry.Logger.WithFields(logFields)

entry.logger.Infoln("request started")
entry.Logger.Infoln("request started")

return entry
}

type StructuredLoggerEntry struct {
logger logrus.FieldLogger
Logger logrus.FieldLogger
}

func (l *StructuredLoggerEntry) Write(status, bytes int, elapsed time.Duration) {
l.logger = l.logger.WithFields(logrus.Fields{
l.Logger = l.Logger.WithFields(logrus.Fields{
"resp_status": status, "resp_bytes_length": bytes,
"resp_elasped_ms": float64(elapsed.Nanoseconds()) / 1000000.0,
})

if status == middleware.StatusClientClosedRequest {
l.logger.Infoln("[disconnected]")
return
}

l.logger.Infoln("request complete")
l.Logger.Infoln("request complete")
}

func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
l.logger = l.logger.WithFields(logrus.Fields{
l.Logger = l.Logger.WithFields(logrus.Fields{
"stack": string(stack),
"panic": fmt.Sprintf("%+v", v),
})
@@ -121,17 +125,17 @@ func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {

func GetLogEntry(r *http.Request) logrus.FieldLogger {
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
return entry.logger
return entry.Logger
}

func LogEntrySetField(r *http.Request, key string, value interface{}) {
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
entry.logger = entry.logger.WithField(key, value)
middleware.WithLogEntry(r, entry)
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
entry.Logger = entry.Logger.WithField(key, value)
}
}

func LogEntrySetFields(r *http.Request, fields map[string]interface{}) {
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
entry.logger = entry.logger.WithFields(fields)
middleware.WithLogEntry(r, entry)
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
entry.Logger = entry.Logger.WithFields(fields)
}
}
Loading