func main() { r := chi.NewRouter() r.Use(middleware.RequestID) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("...")) }) r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) }) r.Get("/panic", func(w http.ResponseWriter, r *http.Request) { panic("test") }) // Slow handlers/operations. r.Group(func(r chi.Router) { // Stop processing when client disconnects. r.Use(middleware.CloseNotify) // Stop processing after 2.5 seconds. r.Use(middleware.Timeout(2500 * time.Millisecond)) r.Get("/slow", func(ctx context.Context, w http.ResponseWriter, r *http.Request) { rand.Seed(time.Now().Unix()) // Processing will take 1-5 seconds. processTime := time.Duration(rand.Intn(4)+1) * time.Second select { case <-ctx.Done(): return case <-time.After(processTime): // The above channel simulates some hard work. } w.Write([]byte(fmt.Sprintf("Processed in %v seconds\n", processTime))) }) }) // Throttle very expensive handlers/operations. r.Group(func(r chi.Router) { // Stop processing after 30 seconds. r.Use(middleware.Timeout(30 * time.Second)) // Only one request will be processed at a time. r.Use(middleware.Throttle(1)) r.Get("/throttled", func(ctx context.Context, w http.ResponseWriter, r *http.Request) { select { case <-ctx.Done(): switch ctx.Err() { case context.DeadlineExceeded: w.WriteHeader(504) w.Write([]byte("Processing too slow\n")) default: w.Write([]byte("Canceled\n")) } return case <-time.After(5 * time.Second): // The above channel simulates some hard work. } w.Write([]byte("Processed\n")) }) }) // RESTy routes for "articles" resource r.Route("/articles", func(r chi.Router) { r.Get("/", paginate, listArticles) // GET /articles r.Post("/", createArticle) // POST /articles r.Route("/:articleID", func(r chi.Router) { r.Use(ArticleCtx) r.Get("/", getArticle) // GET /articles/123 r.Put("/", updateArticle) // PUT /articles/123 r.Delete("/", deleteArticle) // DELETE /articles/123 }) }) // Mount the admin sub-router r.Mount("/admin", adminRouter()) http.ListenAndServe(":3333", r) }
func (srv *Server) NewRouter() http.Handler { cf := srv.Config conrd, err := consistentrd.New(cf.Cluster.LocalNode, cf.Cluster.Nodes) if err != nil { panic(err) } r := chi.NewRouter() r.Use(ParentContext(srv.Ctx)) r.Use(middleware.RequestID) r.Use(middleware.RealIP) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.ThrottleBacklog(cf.Limits.MaxRequests, cf.Limits.BacklogSize, cf.Limits.BacklogTimeout)) r.Use(middleware.CloseNotify) r.Use(middleware.Timeout(cf.Limits.RequestTimeout)) r.Use(httpcoala.Route("HEAD", "GET")) r.Use(heartbeat.Route("/ping")) r.Use(heartbeat.Route("/favicon.ico")) if cf.Airbrake.ApiKey != "" { r.Use(AirbrakeRecoverer(cf.Airbrake.ApiKey)) } if srv.Config.Profiler { r.Mount("/debug", middleware.NoCache, Profiler()) } r.Get("/", trackRoute("root"), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write([]byte(".")) }) r.Get("/info", trackRoute("imageInfo"), GetImageInfo) r.Route("/:bucket", func(r chi.Router) { r.Post("/", BucketImageUpload) r.Group(func(r chi.Router) { cors := cors.New(cors.Options{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{"GET", "OPTIONS"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, ExposedHeaders: []string{"Link"}, AllowCredentials: true, MaxAge: 300, // Maximum value not ignored by any of major browsers }) r.Use(cors.Handler) r.Get("/", conrd.RouteWithParams("url"), trackRoute("bucketV1GetItem"), BucketGetIndex) r.Get("/fetch", conrd.RouteWithParams("url"), trackRoute("bucketV1GetItem"), BucketFetchItem) }) // TODO: review r.Get("/add", trackRoute("bucketAddItems"), BucketAddItems) r.Get("/:key", conrd.Route(), BucketGetItem) r.Delete("/:key", conrd.Route(), BucketDeleteItem) }) // DEPRECATED r.Get("/fetch", trackRoute("bucketV0GetItem"), BucketV0FetchItem) // for Pressilla v2 apps r.Get("/:bucket//fetch", conrd.RouteWithParams("url"), trackRoute("bucketV1GetItem"), BucketFetchItem) // -- return r }
func main() { r := chi.NewRouter() r.Use(middleware.RequestID) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("root.")) }) r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) }) r.Get("/panic", func(w http.ResponseWriter, r *http.Request) { panic("test") }) // Slow handlers/operations. r.Group(func(r chi.Router) { // Stop processing when client disconnects. r.Use(middleware.CloseNotify) // Stop processing after 2.5 seconds. r.Use(middleware.Timeout(2500 * time.Millisecond)) r.Get("/slow", func(w http.ResponseWriter, r *http.Request) { rand.Seed(time.Now().Unix()) // Processing will take 1-5 seconds. processTime := time.Duration(rand.Intn(4)+1) * time.Second select { case <-r.Context().Done(): return case <-time.After(processTime): // The above channel simulates some hard work. } w.Write([]byte(fmt.Sprintf("Processed in %v seconds\n", processTime))) }) }) // Throttle very expensive handlers/operations. r.Group(func(r chi.Router) { // Stop processing after 30 seconds. r.Use(middleware.Timeout(30 * time.Second)) // Only one request will be processed at a time. r.Use(middleware.Throttle(1)) r.Get("/throttled", func(w http.ResponseWriter, r *http.Request) { select { case <-r.Context().Done(): switch r.Context().Err() { case context.DeadlineExceeded: w.WriteHeader(504) w.Write([]byte("Processing too slow\n")) default: w.Write([]byte("Canceled\n")) } return case <-time.After(5 * time.Second): // The above channel simulates some hard work. } w.Write([]byte("Processed\n")) }) }) http.ListenAndServe(":3333", r) }