Beispiel #1
0
func TestThrottleClientTimeout(t *testing.T) {
	r := chi.NewRouter()

	r.Use(ThrottleBacklog(10, 50, time.Second*10))

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		time.Sleep(time.Second * 5) // Expensive operation.
		w.Write(testContent)
	})

	server := httptest.NewServer(r)

	client := http.Client{
		Timeout: time.Second * 3, // Maximum waiting time.
	}

	var wg sync.WaitGroup

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			_, err := client.Get(server.URL)
			assert.Error(t, err)
		}(i)
	}

	wg.Wait()

	server.Close()
}
Beispiel #2
0
func main() {

	// Setup the logger
	logger := logrus.New()
	logger.Formatter = &logrus.JSONFormatter{} // optional / configurable, see docs

	// Routes
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	r.Use(NewStructuredLogger(logger))
	r.Use(middleware.Recoverer)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("welcome"))
	})
	r.Get("/wait", func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(1 * time.Second)
		LogEntrySetField(r, "wait", true)
		w.Write([]byte("hi"))
	})
	r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {
		panic("oops")
	})
	http.ListenAndServe(":3333", r)
}
Beispiel #3
0
func main() {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)
	r.Use(render.UsePresenter(v3.Presenter)) // API version 3 (latest) by default.

	// Redirect for Example convenience.
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/v3/articles/1", 302)
	})

	// API version 3.
	r.Route("/v3", func(r chi.Router) {
		r.Mount("/articles", articleRouter())
	})

	// API version 2.
	r.Route("/v2", func(r chi.Router) {
		r.Use(render.UsePresenter(v2.Presenter))
		r.Mount("/articles", articleRouter())
	})

	// API version 1.
	r.Route("/v1", func(r chi.Router) {
		r.Use(randomErrorMiddleware) // Simulate random error, ie. version 1 is buggy.
		r.Use(render.UsePresenter(v1.Presenter))
		r.Mount("/articles", articleRouter())
	})

	http.ListenAndServe(":3333", r)
}
Beispiel #4
0
func TestSimple(t *testing.T) {
	r := chi.NewRouter()

	r.Use(TokenAuth.Verifier, jwtauth.Authenticator)

	r.Get("/", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("welcome"))
	})

	ts := httptest.NewServer(r)
	defer ts.Close()

	// sending unauthorized requests
	if status, resp := testRequest(t, ts, "GET", "/", nil, nil); status != 401 && resp != "Unauthorized\n" {
		t.Fatalf(resp)
	}

	h := http.Header{}
	h.Set("Authorization", "BEARER "+newJwtToken([]byte("wrong"), map[string]interface{}{}))
	if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 && resp != "Unauthorized\n" {
		t.Fatalf(resp)
	}
	h.Set("Authorization", "BEARER asdf")
	if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 && resp != "Unauthorized\n" {
		t.Fatalf(resp)
	}

	// sending authorized requests
	if status, resp := testRequest(t, ts, "GET", "/", newAuthHeader(), nil); status != 200 && resp != "welcome" {
		t.Fatalf(resp)
	}
}
Beispiel #5
0
func accountsRouter() chi.Router {
	r := chi.NewRouter()

	r.Use(sup1)

	r.Get("/", listAccounts)
	r.Post("/", createAccount)
	r.Get("/hi", hiAccounts)

	r.Group(func(r chi.Router) {
		r.Use(sup2)

		r.Get("/hi2", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			v := ctx.Value("sup2").(string)
			w.Write([]byte(fmt.Sprintf("hi2 - '%s'", v)))
		})
	})

	r.Route("/:accountID", func(r chi.Router) {
		r.Use(accountCtx)
		r.Get("/", getAccount)
		r.Put("/", updateAccount)
		r.Get("/*", other)
	})

	return r
}
Beispiel #6
0
func router() http.Handler {
	r := chi.NewRouter()

	// Protected routes
	r.Group(func(r chi.Router) {
		// Seek, verify and validate JWT tokens
		r.Use(TokenAuth.Verifier)

		// Handle valid / invalid tokens. In this example, we use
		// the provided authenticator middleware, but you can write your
		// own very easily, look at the Authenticator method in jwtauth.go
		// and tweak it, its not scary.
		r.Use(jwtauth.Authenticator)

		r.Get("/admin", func(w http.ResponseWriter, r *http.Request) {
			ctx := r.Context()
			token := ctx.Value("jwt").(*jwt.Token)
			claims := token.Claims
			w.Write([]byte(fmt.Sprintf("protected area. hi %v", claims["user_id"])))
		})
	})

	// Public routes
	r.Group(func(r chi.Router) {
		r.Get("/", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("welcome anonymous"))
		})
	})

	return r
}
Beispiel #7
0
// New returns a new blank Engine instance with no middleware attached
func New(opts Options) *Engine {
	namespace := opts.Namespace
	if len(namespace) == 0 {
		namespace = "/"
	}

	engine := &Engine{}
	engine.Router = &Router{
		namespace: namespace,
		engine:    engine,
		mux:       chi.NewRouter(),
	}
	engine.options = opts
	engine.pool.New = func() interface{} {
		ctx := &Context{
			Engine: engine,
			render: render.New(render.Options{
				Layout: "layout",
			}),
		}
		return ctx
	}

	return engine
}
Beispiel #8
0
func TestThrottleMaximum(t *testing.T) {
	r := chi.NewRouter()

	r.Use(ThrottleBacklog(50, 50, time.Second*5))

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		time.Sleep(time.Second * 2) // Expensive operation.
		w.Write(testContent)
	})

	server := httptest.NewServer(r)

	client := http.Client{
		Timeout: time.Second * 60, // Maximum waiting time.
	}

	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			res, err := client.Get(server.URL)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, res.StatusCode)

			buf, err := ioutil.ReadAll(res.Body)
			assert.NoError(t, err)
			assert.Equal(t, testContent, buf)

		}(i)
	}

	// Wait less time than what the server takes to reply.
	time.Sleep(time.Second * 1)

	// At this point the server is still processing, all the following request
	// will be beyond the server capacity.
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			res, err := client.Get(server.URL)
			assert.NoError(t, err)

			buf, err := ioutil.ReadAll(res.Body)
			assert.Equal(t, http.StatusServiceUnavailable, res.StatusCode)
			assert.Equal(t, errCapacityExceeded, strings.TrimSpace(string(buf)))

		}(i)
	}

	wg.Wait()

	server.Close()
}
Beispiel #9
0
//New create all routers under one Handler
func New() http.Handler {
	r := chi.NewRouter()

	r.Mount("/auth", auth.Routes())
	r.Mount("/apps", apps.Routes())

	return r
}
Beispiel #10
0
//Routes returns chi's Router for Auth APIs
func Routes() chi.Router {
	r := chi.NewRouter()

	r.Post("/register", m.BodyParser(registerRequestBuilder, 512), register)
	r.Post("/login", m.BodyParser(loginRequestBuilder, 512), login)
	r.Head("/logout", logout)

	return r
}
Beispiel #11
0
func main() {
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	r.Use(middleware.Logger)
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hello world"))
	})
	http.ListenAndServe(":3333", r)
}
Beispiel #12
0
func articleRouter() http.Handler {
	r := chi.NewRouter()
	r.Get("/", listArticles)
	r.Route("/:articleID", func(r chi.Router) {
		r.Get("/", getArticle)
		// r.Put("/", updateArticle)
		// r.Delete("/", deleteArticle)
	})
	return r
}
Beispiel #13
0
func TestThrottleTriggerGatewayTimeout(t *testing.T) {
	r := chi.NewRouter()

	r.Use(ThrottleBacklog(50, 100, time.Second*5))

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		time.Sleep(time.Second * 10) // Expensive operation.
		w.Write(testContent)
	})

	server := httptest.NewServer(r)

	client := http.Client{
		Timeout: time.Second * 60, // Maximum waiting time.
	}

	var wg sync.WaitGroup

	// These requests will be processed normally until they finish.
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			res, err := client.Get(server.URL)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, res.StatusCode)

		}(i)
	}

	time.Sleep(time.Second * 1)

	// These requests will wait for the first batch to complete but it will take
	// too much time, so they will eventually receive a timeout error.
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			res, err := client.Get(server.URL)
			assert.NoError(t, err)

			buf, err := ioutil.ReadAll(res.Body)
			assert.Equal(t, http.StatusServiceUnavailable, res.StatusCode)
			assert.Equal(t, errTimedOut, strings.TrimSpace(string(buf)))

		}(i)
	}

	wg.Wait()

	server.Close()
}
Beispiel #14
0
func main() {
	r := chi.NewRouter()

	// Limit to 5 requests globally.
	r.Use(throttler.Limit(5))
	r.Get("/*", handler)

	admin := chi.NewRouter()
	// Limit to 2 requests for admin route
	admin.Use(throttler.Limit(2))
	admin.Get("/", handler)

	r.Mount("/admin/", admin)

	fmt.Printf("Try running the following commands (in different terminal):\n\n")
	fmt.Printf("for i in `seq 1 10`; do (curl 127.0.0.1:8000/ &); done\n\n")
	fmt.Printf("for i in `seq 1 10`; do (curl 127.0.0.1:8000/admin/ &); done\n\n")

	http.ListenAndServe(":8000", r)
}
Beispiel #15
0
func initChi() {
	h := chi.NewRouter()
	h.Get("/", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		fmt.Fprintf(w, "Hello, World")
	})
	h.Get("/:name", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		fmt.Fprintf(w, "Hello, %s", chi.URLParams(ctx)["name"])
	})
	registerHandler("chi", h)
}
Beispiel #16
0
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Handle("/vars", expVars)
	r.Handle("/pprof/", pprof.Index)
	r.Handle("/pprof/cmdline", pprof.Cmdline)
	r.Handle("/pprof/profile", pprof.Profile)
	r.Handle("/pprof/symbol", pprof.Symbol)
	r.Handle("/pprof/block", pprof.Handler("block").ServeHTTP)
	r.Handle("/pprof/heap", pprof.Handler("heap").ServeHTTP)
	r.Handle("/pprof/goroutine", pprof.Handler("goroutine").ServeHTTP)
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
	return r
}
Beispiel #17
0
func main() {
	r := chi.NewRouter()

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hi"))
	})

	workDir, _ := os.Getwd()
	filesDir := filepath.Join(workDir, "files")
	r.FileServer("/files", http.Dir(filesDir))

	http.ListenAndServe(":3333", r)
}
Beispiel #18
0
func main() {
	r := chi.NewRouter()

	// use middleware
	r.Use(middleware.Logger)

	// add routing
	r.Get("/", apiIndex)

	r.Route("/todo", func(r chi.Router) {
		r.Get("/", getTodoList)
	})
	http.ListenAndServe(":3333", r)
}
Beispiel #19
0
// A completely separate router for administrator routes
func adminRouter() http.Handler { // or chi.Router {
	r := chi.NewRouter()
	r.Use(AdminOnly)
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("admin: index"))
	})
	r.Get("/accounts", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("admin: list accounts.."))
	})
	r.Get("/users/:userId", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(fmt.Sprintf("admin: view user id %v", chi.URLParams(ctx)["userId"])))
	})
	return r
}
Beispiel #20
0
func main() {
	r := chi.NewRouter()

	r.Use(middleware.Logger)
	r.Use(httpcoala.Route("HEAD", "GET")) // or, Route("*")

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(100 * time.Millisecond) // expensive op
		w.WriteHeader(200)
		w.Write([]byte("hi"))
	})

	http.ListenAndServe(":1111", r)
}
Beispiel #21
0
// NewRouter creates new chakra Mux and appends its route to acl.route, unless
// the passed route is chakra.UseParentRoute.
func NewRouter(route string) *Mux {
	if route == "" {
		panic("new router created without acl route")
	}
	if accessControl == nil {
		panic("you have not defined access control function with SetAC")
	}

	r := &Mux{chi.NewRouter()}
	if route != UseParentRoute {
		r.Mux.Use(Route(route))
	}

	return r
}
Beispiel #22
0
func TestRedirectSlashes(t *testing.T) {
	r := chi.NewRouter()

	// This middleware must be mounted at the top level of the router, not at the end-handler
	// because then it'll be too late and will end up in a 404
	r.Use(RedirectSlashes)

	r.NotFound(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(404)
		w.Write([]byte("nothing here"))
	})

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("root"))
	})

	r.Route("/accounts/:accountID", func(r chi.Router) {
		r.Get("/", func(w http.ResponseWriter, r *http.Request) {
			accountID := chi.URLParam(r, "accountID")
			w.Write([]byte(accountID))
		})
	})

	ts := httptest.NewServer(r)
	defer ts.Close()

	if status, resp := testRequest(t, ts, "GET", "/", nil); resp != "root" && status != 200 {
		t.Fatalf(resp)
	}

	// NOTE: the testRequest client will follow the redirection..
	if status, resp := testRequest(t, ts, "GET", "//", nil); resp != "root" && status != 200 {
		t.Fatalf(resp)
	}

	if status, resp := testRequest(t, ts, "GET", "/accounts/admin", nil); resp != "admin" && status != 200 {
		t.Fatalf(resp)
	}

	// NOTE: the testRequest client will follow the redirection..
	if status, resp := testRequest(t, ts, "GET", "/accounts/admin/", nil); resp != "admin" && status != 200 {
		t.Fatalf(resp)
	}

	if status, resp := testRequest(t, ts, "GET", "/nothing-here", nil); resp != "nothing here" && status != 200 {
		t.Fatalf(resp)
	}
}
Beispiel #23
0
// StartAPI Starts the API listener on port 8081
func StartAPI() {
	r := chi.NewRouter()

	cors := cors.New(cors.Options{
		AllowedOrigins:   []string{"*"},
		AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE"},
		AllowCredentials: true,
	})

	r.Use(cors.Handler)
	r.Use(middleware.Recoverer)
	//r.Use(middleware.Logger)

	r.Route("/api", func(r chi.Router) {
		r.Route("/dashboard", func(r chi.Router) {
			r.Route("/widgets", func(r chi.Router) {
				r.Get("/", getWidgets)
				r.Get("/events", getEvents)
				r.Get("/feed/:feedName", getFeed)
				r.Get("/options", getWidgetOptions)
				r.Get("/names", getWidgetNames)
				r.Get("/name/:widgetName", getWidgetByName)
				r.Put("/name/:widgetName", putWidget)
				r.Delete("/name/:widgetName", deleteWidget)
			})
		})
		r.Route("/assets", func(r chi.Router) {
			r.Route("/:assetType", func(r chi.Router) {
				r.Get("/", getAssets)
			})
		})
		r.Route("/classes", func(r chi.Router) {
			r.Get("/export", exportClasses)
			//r.Get("/import", importClasses) // TODO
			r.Route("/:classType", func(r chi.Router) {
				r.Get("/", getClasses)
				r.Get("/options", getClassOptions)
				r.Get("/names", getClassNames)
				r.Get("/name/:className", getClassByName)
				r.Put("/name/:className", putClass)
				r.Delete("/name/:className", deleteClass)
			})
		})
	})

	http.ListenAndServe(":8081", r)
}
Beispiel #24
0
func main() {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.RealIP)
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("."))
	})

	r.Mount("/users", usersResource{}.Routes())
	r.Mount("/todos", todosResource{}.Routes())

	http.ListenAndServe(":3333", r)
}
Beispiel #25
0
// Routes creates a REST router for the todos resource
func (rs usersResource) Routes() chi.Router {
	r := chi.NewRouter()
	// r.Use() // some middleware..

	r.Get("/", rs.List)    // GET /todos - read a list of todos
	r.Post("/", rs.Create) // POST /todos - create a new todo and persist it
	r.Put("/", rs.Delete)

	r.Route("/:id", func(r chi.Router) {
		// r.Use(rs.TodoCtx) // lets have a todos map, and lets actually load/manipulate
		r.Get("/", rs.Get)       // GET /todos/:id - read a single todo by :id
		r.Put("/", rs.Update)    // PUT /todos/:id - update a single todo by :id
		r.Delete("/", rs.Delete) // DELETE /todos/:id - delete a single todo by :id
	})

	return r
}
Beispiel #26
0
func Router() chi.Router {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.RealIP)
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)

	r.Use(func(h chi.Handler) chi.Handler {
		return chi.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			ctx = context.WithValue(ctx, "example", true)
			h.ServeHTTPC(ctx, w, r)
		})
	})

	r.Get("/", apiIndex)

	return r
}
Beispiel #27
0
func main() {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.RealIP)
	r.Use(middleware.Logger)

	r.Use(func(h chi.Handler) chi.Handler {
		return chi.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			ctx = context.WithValue(ctx, "example", true)
			h.ServeHTTPC(ctx, w, r)
		})
	})

	r.Get("/", apiIndex)

	r.Mount("/accounts", accountsRouter())

	http.ListenAndServe(":3333", r)
}
Beispiel #28
0
func TestThrottleBacklog(t *testing.T) {
	r := chi.NewRouter()

	r.Use(ThrottleBacklog(10, 50, time.Second*10))

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		time.Sleep(time.Second * 1) // Expensive operation.
		w.Write(testContent)
	})

	server := httptest.NewServer(r)

	client := http.Client{
		Timeout: time.Second * 5, // Maximum waiting time.
	}

	var wg sync.WaitGroup

	// The throttler proccesses 10 consecutive requests, each one of those
	// requests lasts 1s. The maximum number of requests this can possible serve
	// before the clients time out (5s) is 40.
	for i := 0; i < 40; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			res, err := client.Get(server.URL)
			assert.NoError(t, err)

			assert.Equal(t, http.StatusOK, res.StatusCode)
			buf, err := ioutil.ReadAll(res.Body)
			assert.NoError(t, err)
			assert.Equal(t, testContent, buf)
		}(i)
	}

	wg.Wait()

	server.Close()
}
Beispiel #29
0
func Routes(qmd *qmd.Qmd) http.Handler {
	handlers.Qmd = qmd

	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.RealIP)
	r.Use(middleware.NoCache)
	r.Use(middleware.Recoverer)
	r.Use(middleware.Logger)
	r.Use(qmd.ClosingResponder)

	r.Get("/", handlers.Index)
	r.Get("/ping", handlers.Ping)

	r.Post("/scripts/:filename", handlers.CreateJob)

	r.Get("/jobs", handlers.Jobs)
	r.Get("/jobs/*", GetLongID, handlers.Job)

	return r
}
Beispiel #30
0
// Profiler is a convenient subrouter used for mounting net/http/pprof. ie.
//
//  func MyService() http.Handler {
//    r := chi.NewRouter()
//    // ..middlewares
//    r.Mount("/debug", profiler.Router())
//    // ..routes
//    return r
//  }
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Use(NoCache)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/pprof/", 301)
	})
	r.HandleFunc("/pprof", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/", 301)
	})

	r.HandleFunc("/pprof/", pprof.Index)
	r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
	r.HandleFunc("/pprof/profile", pprof.Profile)
	r.HandleFunc("/pprof/symbol", pprof.Symbol)
	r.Handle("/pprof/block", pprof.Handler("block"))
	r.Handle("/pprof/heap", pprof.Handler("heap"))
	r.Handle("/pprof/goroutine", pprof.Handler("goroutine"))
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate"))
	r.HandleFunc("/vars", expVars)

	return r
}