...

Source file src/github.com/go-chi/chi/_examples/limits/main.go

Documentation: github.com/go-chi/chi/_examples/limits

     1  //
     2  // Limits
     3  // ======
     4  // This example demonstrates the use of Timeout, and Throttle middlewares.
     5  //
     6  // Timeout:
     7  //   cancel a request if processing takes longer than 2.5 seconds,
     8  //   server will respond with a http.StatusGatewayTimeout.
     9  //
    10  // Throttle:
    11  //   limit the number of in-flight requests along a particular
    12  //   routing path and backlog the others.
    13  //
    14  package main
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"math/rand"
    20  	"net/http"
    21  	"time"
    22  
    23  	"github.com/go-chi/chi"
    24  	"github.com/go-chi/chi/middleware"
    25  )
    26  
    27  func main() {
    28  	r := chi.NewRouter()
    29  
    30  	r.Use(middleware.RequestID)
    31  	r.Use(middleware.Logger)
    32  	r.Use(middleware.Recoverer)
    33  
    34  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
    35  		w.Write([]byte("root."))
    36  	})
    37  
    38  	r.Get("/ping", func(w http.ResponseWriter, r *http.Request) {
    39  		w.Write([]byte("pong"))
    40  	})
    41  
    42  	r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {
    43  		panic("test")
    44  	})
    45  
    46  	// Slow handlers/operations.
    47  	r.Group(func(r chi.Router) {
    48  		// Stop processing after 2.5 seconds.
    49  		r.Use(middleware.Timeout(2500 * time.Millisecond))
    50  
    51  		r.Get("/slow", func(w http.ResponseWriter, r *http.Request) {
    52  			rand.Seed(time.Now().Unix())
    53  
    54  			// Processing will take 1-5 seconds.
    55  			processTime := time.Duration(rand.Intn(4)+1) * time.Second
    56  
    57  			select {
    58  			case <-r.Context().Done():
    59  				return
    60  
    61  			case <-time.After(processTime):
    62  				// The above channel simulates some hard work.
    63  			}
    64  
    65  			w.Write([]byte(fmt.Sprintf("Processed in %v seconds\n", processTime)))
    66  		})
    67  	})
    68  
    69  	// Throttle very expensive handlers/operations.
    70  	r.Group(func(r chi.Router) {
    71  		// Stop processing after 30 seconds.
    72  		r.Use(middleware.Timeout(30 * time.Second))
    73  
    74  		// Only one request will be processed at a time.
    75  		r.Use(middleware.Throttle(1))
    76  
    77  		r.Get("/throttled", func(w http.ResponseWriter, r *http.Request) {
    78  			select {
    79  			case <-r.Context().Done():
    80  				switch r.Context().Err() {
    81  				case context.DeadlineExceeded:
    82  					w.WriteHeader(504)
    83  					w.Write([]byte("Processing too slow\n"))
    84  				default:
    85  					w.Write([]byte("Canceled\n"))
    86  				}
    87  				return
    88  
    89  			case <-time.After(5 * time.Second):
    90  				// The above channel simulates some hard work.
    91  			}
    92  
    93  			w.Write([]byte("Processed\n"))
    94  		})
    95  	})
    96  
    97  	http.ListenAndServe(":3333", r)
    98  }
    99  

View as plain text