| 19 | ) |
| 20 | |
| 21 | func main() { |
| 22 | r := chi.NewRouter() |
| 23 | |
| 24 | r.Use(middleware.RequestID) |
| 25 | r.Use(middleware.Logger) |
| 26 | r.Use(middleware.Recoverer) |
| 27 | |
| 28 | r.Get("/", func(w http.ResponseWriter, r *http.Request) { |
| 29 | w.Write([]byte("root.")) |
| 30 | }) |
| 31 | |
| 32 | r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { |
| 33 | w.Write([]byte("pong")) |
| 34 | }) |
| 35 | |
| 36 | r.Get("/panic", func(w http.ResponseWriter, r *http.Request) { |
| 37 | panic("test") |
| 38 | }) |
| 39 | |
| 40 | // Slow handlers/operations. |
| 41 | r.Group(func(r chi.Router) { |
| 42 | // Stop processing after 2.5 seconds. |
| 43 | r.Use(middleware.Timeout(2500 * time.Millisecond)) |
| 44 | |
| 45 | r.Get("/slow", func(w http.ResponseWriter, r *http.Request) { |
| 46 | rand.Seed(time.Now().Unix()) |
| 47 | |
| 48 | // Processing will take 1-5 seconds. |
| 49 | processTime := time.Duration(rand.Intn(4)+1) * time.Second |
| 50 | |
| 51 | select { |
| 52 | case <-r.Context().Done(): |
| 53 | return |
| 54 | |
| 55 | case <-time.After(processTime): |
| 56 | // The above channel simulates some hard work. |
| 57 | } |
| 58 | |
| 59 | w.Write([]byte(fmt.Sprintf("Processed in %v seconds\n", processTime))) |
| 60 | }) |
| 61 | }) |
| 62 | |
| 63 | // Throttle very expensive handlers/operations. |
| 64 | r.Group(func(r chi.Router) { |
| 65 | // Stop processing after 30 seconds. |
| 66 | r.Use(middleware.Timeout(30 * time.Second)) |
| 67 | |
| 68 | // Only one request will be processed at a time. |
| 69 | r.Use(middleware.Throttle(1)) |
| 70 | |
| 71 | r.Get("/throttled", func(w http.ResponseWriter, r *http.Request) { |
| 72 | select { |
| 73 | case <-r.Context().Done(): |
| 74 | switch r.Context().Err() { |
| 75 | case context.DeadlineExceeded: |
| 76 | w.WriteHeader(504) |
| 77 | w.Write([]byte("Processing too slow\n")) |
| 78 | default: |