You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+81Lines changed: 81 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
28
28
*[Registered URLs](#registered-urls)
29
29
*[Walking Routes](#walking-routes)
30
30
*[Graceful Shutdown](#graceful-shutdown)
31
+
*[Middleware](#middleware)
31
32
*[Full Example](#full-example)
32
33
33
34
---
@@ -447,6 +448,86 @@ func main() {
447
448
}
448
449
```
449
450
451
+
### Middleware
452
+
453
+
Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters.
454
+
Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking.
455
+
456
+
Mux middlewares are defined using the de facto standard type:
457
+
458
+
```go
459
+
typeMiddlewareFuncfunc(http.Handler) http.Handler
460
+
```
461
+
462
+
Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers.
463
+
464
+
A very basic middleware which logs the URI of the request being handled could be written as:
465
+
466
+
```go
467
+
funcsimpleMw(nexthttp.Handler) http.Handler {
468
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
469
+
// Do stuff here
470
+
log.Println(r.RequestURI)
471
+
// Call the next handler, which can be another middleware in the chain, or the final handler.
472
+
next.ServeHTTP(w, r)
473
+
})
474
+
}
475
+
```
476
+
477
+
Middlewares can be added to a router using `Router.AddMiddlewareFunc()`:
478
+
479
+
```go
480
+
r:= mux.NewRouter()
481
+
r.HandleFunc("/", handler)
482
+
r.AddMiddleware(simpleMw)
483
+
```
484
+
485
+
A more complex authentication middleware, which maps session token to users, could be written as:
486
+
487
+
```go
488
+
// Define our struct
489
+
type authenticationMiddleware struct {
490
+
tokenUsers map[string]string
491
+
}
492
+
493
+
// Initialize it somewhere
494
+
func(amw *authenticationMiddleware) Populate() {
495
+
amw.tokenUsers["00000000"] = "user0"
496
+
amw.tokenUsers["aaaaaaaa"] = "userA"
497
+
amw.tokenUsers["05f717e5"] = "randomUser"
498
+
amw.tokenUsers["deadbeef"] = "user0"
499
+
}
500
+
501
+
// Middleware function, which will be called for each request
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
504
+
token:= r.Header.Get("X-Session-Token")
505
+
506
+
ifuser, found:= amw.tokenUsers[token]; found {
507
+
// We found the token in our map
508
+
log.Printf("Authenticated user %s\n", user)
509
+
// Pass down the request to the next middleware (or final handler)
510
+
next.ServeHTTP(w, r)
511
+
} else {
512
+
// Write an error and stop the handler chain
513
+
http.Error(w, "Forbidden", 403)
514
+
}
515
+
})
516
+
}
517
+
```
518
+
519
+
```go
520
+
r:= mux.NewRouter()
521
+
r.HandleFunc("/", handler)
522
+
523
+
amw:= authenticationMiddleware{}
524
+
amw.Populate()
525
+
526
+
r.AddMiddlewareFunc(amw.Middleware)
527
+
```
528
+
529
+
Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares *should* write to `ResponseWriter` if they *are* going to terminate the request, and they *should not* write to `ResponseWriter` if they *are not* going to terminate it.
530
+
450
531
## Full Example
451
532
452
533
Here's a complete, runnable example of a small `mux` based server:
Since **vX.Y.Z**, mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed if a
243
+
match is found (including subrouters). Middlewares are defined using the de facto standard type:
244
+
245
+
type MiddlewareFunc func(http.Handler) http.Handler
246
+
247
+
Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created).
248
+
249
+
A very basic middleware which logs the URI of the request being handled could be written as:
250
+
251
+
func simpleMw(next http.Handler) http.Handler {
252
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
253
+
// Do stuff here
254
+
log.Println(r.RequestURI)
255
+
// Call the next handler, which can be another middleware in the chain, or the final handler.
256
+
next.ServeHTTP(w, r)
257
+
})
258
+
}
259
+
260
+
Middlewares can be added to a router using `Router.Use()`:
261
+
262
+
r := mux.NewRouter()
263
+
r.HandleFunc("/", handler)
264
+
r.AddMiddleware(simpleMw)
265
+
266
+
A more complex authentication middleware, which maps session token to users, could be written as:
267
+
268
+
// Define our struct
269
+
type authenticationMiddleware struct {
270
+
tokenUsers map[string]string
271
+
}
272
+
273
+
// Initialize it somewhere
274
+
func (amw *authenticationMiddleware) Populate() {
275
+
amw.tokenUsers["00000000"] = "user0"
276
+
amw.tokenUsers["aaaaaaaa"] = "userA"
277
+
amw.tokenUsers["05f717e5"] = "randomUser"
278
+
amw.tokenUsers["deadbeef"] = "user0"
279
+
}
280
+
281
+
// Middleware function, which will be called for each request
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
284
+
token := r.Header.Get("X-Session-Token")
285
+
286
+
if user, found := amw.tokenUsers[token]; found {
287
+
// We found the token in our map
288
+
log.Printf("Authenticated user %s\n", user)
289
+
next.ServeHTTP(w, r)
290
+
} else {
291
+
http.Error(w, "Forbidden", 403)
292
+
}
293
+
})
294
+
}
295
+
296
+
r := mux.NewRouter()
297
+
r.HandleFunc("/", handler)
298
+
299
+
amw := authenticationMiddleware{}
300
+
amw.Populate()
301
+
302
+
r.Use(amw.Middleware)
303
+
304
+
Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.
// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
21
+
func (r*Router) Use(mwfMiddlewareFunc) {
22
+
r.middlewares=append(r.middlewares, mwf)
23
+
}
24
+
25
+
// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
0 commit comments