예제 #1
0
// Handle takes the next handler as an argument and wraps it in this middleware.
func (m *Middle) Handle(next httpware.Handler) httpware.Handler {
	return httpware.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		q := r.URL.Query()
		s := q.Get(m.startQuery)
		l := q.Get(m.limitQuery)
		page := Page{}
		var err error
		if s == "" {
			page.Start = 0
		} else {
			page.Start, err = strconv.Atoi(s)
			if err != nil {
				return httpware.NewErr("invalid query parameter", http.StatusBadRequest).WithField(m.startQuery, "must be an integer")
			}
			if page.Start < 0 {
				return httpware.NewErr("invalid query parameter", http.StatusBadRequest).WithField(m.startQuery, "must not be negative")
			}
		}
		if l == "" {
			page.Limit = m.limitDefault
		} else {
			page.Limit, err = strconv.Atoi(l)
			if err != nil {
				return httpware.NewErr("invalid query parameter", http.StatusBadRequest).WithField(m.limitQuery, "must not be an integer")
			}
			if page.Limit <= 0 {
				return httpware.NewErr("invalid query parameter", http.StatusBadRequest).WithField(m.limitQuery, "must not be greater than zero")
			}
		}

		return next.ServeHTTPCtx(context.WithValue(ctx, httpware.PageKey, page), w, r)
	})
}
예제 #2
0
func TestLog(t *testing.T) {
	var buffer bytes.Buffer
	conf := Defaults
	conf.Logger.Out = &buffer
	m := httpware.Compose(
		httpware.DefaultErrHandler,
		New(conf),
	)
	s := httptest.NewServer(m.ThenFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		if r.URL.Path == "/400" {
			return httpware.NewErr("didnt like your request", http.StatusBadRequest)
		}
		if r.URL.Path == "/500" {
			return httpware.NewErr("ahhhh it blew up", http.StatusInternalServerError)
		}
		if r.URL.Path == "/panic" {
			panic("PANIC!")
		}
		return nil
	}))

	cases := []struct {
		Path     string
		Expected string
	}{
		{
			Path:     "/",
			Expected: "success",
		},
		{
			Path:     "/400",
			Expected: "didnt like your request",
		},
		{
			Path:     "/500",
			Expected: "ahhhh it blew up",
		},
		{
			Path:     "/panic",
			Expected: "PANIC!",
		},
	}
	for _, c := range cases {
		resp, err := http.Get(s.URL + c.Path)
		if err != nil {
			t.Fatal("failed to make request:", err)
		}
		resp.Body.Close()
		got := buffer.String()
		if !strings.Contains(got, c.Expected) {
			t.Fatalf("expected log output to contain: '%s', got: \n%s", c.Expected, got)
		}
	}
}
예제 #3
0
// handle is meant to demonstrate a POST or PUT endpoint.
func handle(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
	u := &User{}
	rqt := contentware.ResponseTypeFromCtx(ctx)
	// Decode from JSON or XML based on the 'Content-Type' header.
	if err := rqt.Decode(r.Body, u); err != nil {
		return httpware.NewErr("could not parse body: "+err.Error(), http.StatusBadRequest)
	}

	if err := u.validate(); err != nil {
		return httpware.NewErr("invalid entity", http.StatusBadRequest).WithField("invalid", err.Error())
	}

	// Store user to db here.

	rst := contentware.ResponseTypeFromCtx(ctx)
	// Write the user back in the response as JSON or XML based on the
	// 'Accept' header.
	rst.Encode(w, u)
	return nil
}
예제 #4
0
파일: limit.go 프로젝트: nstogner/httpware
// Handle takes the next handler as an argument and wraps it in this middleware.
func (m *Middle) Handle(next httpware.Handler) httpware.Handler {
	return httpware.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		remote := strings.Split(r.RemoteAddr, ":")
		if len(remote) != 2 {
			return next.ServeHTTPCtx(ctx, w, r)
		}

		if m.increment(remote[0]) {
			defer m.decrement(remote[0])
			return next.ServeHTTPCtx(ctx, w, r)
		}

		// Send a 429 response (Too Many Requests).
		m.retryHeader(w)
		return httpware.NewErr("exceeded request rate limit", 429)
	})
}
예제 #5
0
파일: token.go 프로젝트: nstogner/httpware
// Handle takes the next handler as an argument and wraps it in this middleware.
func (m *Middle) Handle(next httpware.Handler) httpware.Handler {
	return httpware.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		token, err := request.ParseFromRequest(
			r,
			request.AuthorizationHeaderExtractor,
			func(token *jwt.Token) (interface{}, error) {
				return m.conf.Secret, nil
			},
		)

		if err == nil && token.Valid {
			newCtx := context.WithValue(ctx, httpware.TokenKey, token)
			return next.ServeHTTPCtx(newCtx, w, r)
		}

		// No soup for you.
		return httpware.NewErr("invalid token", http.StatusUnauthorized)
	})
}