summaryrefslogtreecommitdiff
path: root/gemini/handler.go
blob: 0f48e621bf1353ac5de62ddde07b49804646f646 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package gemini

import "context"

// Handler is a function which can turn a gemini request into a gemini response.
//
// A Handler MUST NOT return a nil response. Errors should be returned in the form
// of error responses (4x, 5x, 6x response status). If the Handler should not be
// responsible for the requested resource it can return a 51 response.
type Handler func(context.Context, *Request) *Response

// Middleware is a handle decorator.
//
// It returns a handler which may call the passed-in handler or not, or may
// transform the request or response in some way.
type Middleware func(Handler) Handler

// FallthroughHandler builds a handler which tries multiple child handlers.
//
// The returned handler will invoke each of the passed child handlers in order,
// stopping when it receives a response with status other than 51.
func FallthroughHandler(handlers ...Handler) Handler {
	return func(ctx context.Context, req *Request) *Response {
		for _, handler := range handlers {
			response := handler(ctx, req)
			if response.Status != StatusNotFound {
				return response
			}
		}

		return NotFound("Resource does not exist.")
	}
}

// Filter wraps a handler with a predicate which determines whether to run the handler.
//
// When the predicate function returns false, the Filter returns the provided failure
// response. The failure argument may be nil, in which case a "51 Resource does not exist."
// response will be used.
func Filter(
	predicate func(context.Context, *Request) bool,
	handler Handler,
	failure *Response,
) Handler {
	if failure == nil {
		failure = NotFound("Resource does not exist.")
	}
	return func(ctx context.Context, req *Request) *Response {
		if !predicate(ctx, req) {
			return failure
		}
		return handler(ctx, req)
	}
}