Пример #1
0
func runHTTPTestCases(t *testing.T, h ctxhttp.Handler, cs []httpTestCase) {
	for i, c := range cs {
		req, err := http.NewRequest("GET", c.path, nil)
		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		serveErr := h.ServeHTTPContext(context.Background(), rr, req)
		if serveErr != nil {
			http.Error(rr, serveErr.Error(), http.StatusInternalServerError)
		}

		if have, want := rr.Code, c.code; have != want {
			t.Errorf("Expected request %d at %s to return %d but got %d",
				i, c.path, want, have)
		}

		for name, want := range c.headers {
			if have := rr.HeaderMap.Get(name); have != want {
				t.Errorf("Expected request %d at %s to have header '%s: %s' but got '%s'",
					i, c.path, name, want, have)
			}
		}
	}
}
Пример #2
0
// Handler is an adapter which allows the usage of an ctxhttp.Handler as a
// request handle.
func (r *Router) Handler(method, path string, handler ctxhttp.Handler) {
	r.Handle(method, path,
		func(ctx context.Context, w http.ResponseWriter, req *http.Request) error {
			return handler.ServeHTTPContext(ctx, w, req)
		},
	)
}
Пример #3
0
// WithParseAndValidate represent a middleware handler. For POST or
// PUT requests, it also parses the request body as a form. The extracted valid
// token will be added to the context. The extracted token will be checked
// against the Blacklist. errHandler is an optional argument. Only the first
// item in the slice will be considered. Default errHandler is:
//
//		http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
//
// ProTip: Instead of passing the token as an HTML Header you can also add the token
// to a form (multipart/form-data) with an input name of access_token. If the
// token cannot be found within the Header the fallback triggers the lookup within the form.
func (s *Service) WithParseAndValidate(errHandler ...ctxhttp.Handler) ctxhttp.Middleware {
	var errH ctxhttp.Handler
	errH = ctxhttp.HandlerFunc(defaultTokenErrorHandler)
	if len(errHandler) == 1 && errHandler[0] != nil {
		errH = errHandler[0]
	}
	return func(h ctxhttp.Handler) ctxhttp.Handler {
		return ctxhttp.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

			token, err := jwt.ParseFromRequest(r, s.keyFunc)

			var inBL bool
			if token != nil {
				inBL = s.Blacklist.Has(token.Raw)
			}
			if token != nil && err == nil && token.Valid && !inBL {
				return h.ServeHTTPContext(NewContext(ctx, token), w, r)
			}
			if PkgLog.IsDebug() {
				PkgLog.Debug("ctxjwt.Service.Authenticate", "err", err, "token", token, "inBlacklist", inBL)
			}
			return errH.ServeHTTPContext(NewContextWithError(ctx, err), w, r)
		})
	}
}
Пример #4
0
// WithRateLimit wraps an ctxhttp.Handler to limit incoming requests.
// Requests that are not limited will be passed to the handler
// unchanged.  Limited requests will be passed to the DeniedHandler.
// X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and
// Retry-After headers will be written to the response based on the
// values in the RateLimitResult.
func (t *HTTPRateLimit) WithRateLimit(rlStore throttled.GCRAStore, h ctxhttp.Handler) ctxhttp.Handler {
	if t.Config == nil {
		t.Config = config.DefaultManager
	}
	if t.DeniedHandler == nil {
		t.DeniedHandler = DefaultDeniedHandler
	}

	if t.RateLimiter == nil {
		if rlStore == nil {
			var err error
			rlStore, err = memstore.New(65536)
			if err != nil {
				panic(err)
			}
		}

		var err error
		t.RateLimiter, err = throttled.NewGCRARateLimiter(rlStore, t.quota())
		if err != nil {
			panic(err)
		}
	}

	return ctxhttp.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

		var k string
		if t.VaryBy != nil {
			k = t.VaryBy.Key(r)
		}

		limited, context, err := t.RateLimiter.RateLimit(k, 1)

		if err != nil {
			return err
		}

		setRateLimitHeaders(w, context)

		if !limited {
			return h.ServeHTTPContext(ctx, w, r)
		}

		return t.DeniedHandler.ServeHTTPContext(ctx, w, r)
	})
}