<commit_before>package sparkle

import (
	"net/http"
)

// ActionResults are the results returned from ActionHandlers,
// they are used to abstract away the commonalities around writting
// responses to the client
type ActionResult interface {
	Execute(http.ResponseWriter, *http.Request, *Context) error
}

// ActionHandlers are functions that are called to handle a request in
// sparkle. They recieve a pointer to a sparkle.Context and can return
// an ActionResult and/or an error.
//
// When ActionHandlers return ActionResults (with no error), that ActionResult
// is later executed (in most cases) in order to write output to the client
//
// On errors, the framework executes it's configured error handler.
type ActionHandler func(*Context) (ActionResult, error)

// ActionWrappers are functions used to wrap ActionHandlers in order to perform
// some function prior to or after ActionHandlers.
//
// They are given a pointer to a *sparkle.Context and the ActionHandler it's wrapping.
//
// Because the ActionWrapper is responsible for calling the ActionHandler, it's possible
// for the ActionWrapper to actually prevent the ActionHandler from being run.
// Since the ActionWrapper also returns an ActionResult, it's also possible for an
// ActionWrapper to change or subvert the ActionResult to be used.
type ActionWrapper func(*Context, ActionHandler) (ActionResult, error)

func createActionHttpHandler(h ActionHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		handleRequest(w, r, h)
	}
}

// Action adds an ActionHandler to be executed when incoming urls match the given pattern.
//
// By default, the pattern matching is the same as the DefaultMux used by net/http
func Action(pattern string, handler ActionHandler) {
	http.HandleFunc(pattern, createActionHttpHandler(handler))
}

func applyActionWrapper(handler ActionHandler, wrapper ActionWrapper) ActionHandler {
	return func(c *Context) (ActionResult, error) {
		return wrapper(c, handler)
	}
}

// ApplyActionWrappers applies one or more ActionWrappers to an ActionHandler and returns
// another ActionHandler that will make sure the wrappers are called into.
//
// Providing that all ActionWrappers call their supplied ActionHandler, then calling
//     ApplyActionWrappers(handler, w1, w2, w3)
// can be seen as creating an ActionHandler that will cause w3 to called, then w2, then w1 and finally handler
//
// A simple example of an ActionWrapper might be for logging when a certain Action is called.
//
//     func LogAction(c *Context, next ActionHandler) (ActionResult, error) {
//	       log("Action Starting")
//         res, err := next(c)
//         log("Action Complete")
//         return res, err
//     }
//
// And this action wrapper can be applied like so:
//     func main() {
//	       sparkle.Action("/MyUrlPattern", sparkle.ApplyActionWrappers(MyHandler, LogAction))
//     }
func ApplyActionWrappers(handler ActionHandler, wrappers ...ActionWrapper) ActionHandler {
	result := handler

	for _, wrapper := range wrappers {
		result = applyActionWrapper(handler, wrapper)
	}

	return result
}
<commit_msg>Simplified the API a bit, by merging the ability to specify ActionWrappers when using sparkle.Action.<commit_after>package sparkle

import (
	"net/http"
)

// ActionResults are the results returned from ActionHandlers,
// they are used to abstract away the commonalities around writting
// responses to the client
type ActionResult interface {
	Execute(http.ResponseWriter, *http.Request, *Context) error
}

// ActionHandlers are functions that are called to handle a request in
// sparkle. They recieve a pointer to a sparkle.Context and can return
// an ActionResult and/or an error.
//
// When ActionHandlers return ActionResults (with no error), that ActionResult
// is later executed (in most cases) in order to write output to the client
//
// On errors, the framework executes it's configured error handler.
type ActionHandler func(*Context) (ActionResult, error)

// ActionWrappers are functions used to wrap ActionHandlers in order to perform
// some function prior to or after ActionHandlers.
//
// They are given a pointer to a *sparkle.Context and the ActionHandler it's wrapping.
//
// Because the ActionWrapper is responsible for calling the ActionHandler, it's possible
// for the ActionWrapper to actually prevent the ActionHandler from being run.
// Since the ActionWrapper also returns an ActionResult, it's also possible for an
// ActionWrapper to change or subvert the ActionResult to be used.
type ActionWrapper func(*Context, ActionHandler) (ActionResult, error)

func createActionHttpHandler(h ActionHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		handleRequest(w, r, h)
	}
}

func applyActionWrapper(handler ActionHandler, wrapper ActionWrapper) ActionHandler {
	return func(c *Context) (ActionResult, error) {
		return wrapper(c, handler)
	}
}

func applyActionWrappers(handler ActionHandler, wrappers ...ActionWrapper) ActionHandler {
	result := handler

	for _, wrapper := range wrappers {
		result = applyActionWrapper(handler, wrapper)
	}

	return result
}

// Action adds an ActionHandler to be executed when incoming urls match the given pattern.
//
// By default, the pattern matching is the same as the DefaultMux used by net/http
//
// wrappers allows you to define the Action Wrappers that act as simple wrappers around the
// ActionHandler allowing them to intercept before or after (or even override and subvert)
// the supplied ActionHandler
//
// Providing that all ActionWrappers call their supplied ActionHandler, then calling
//     ApplyActionWrappers(handler, w1, w2, w3)
// can be seen as creating an ActionHandler that will cause w3 to called, then w2, then w1 and finally handler
//
// A simple example of an ActionWrapper might be for logging when a certain Action is called.
//
//     func LogAction(c *Context, next ActionHandler) (ActionResult, error) {
//	       log("Action Starting")
//         res, err := next(c)
//         log("Action Complete")
//         return res, err
//     }
//
// And this action wrapper can be applied like so:
//     func main() {
//	       sparkle.Action("/MyUrlPattern", sparkle.ApplyActionWrappers(MyHandler, LogAction))
//     }
func Action(pattern string, handler ActionHandler, wrappers ...ActionWrapper) {
	http.HandleFunc(
		pattern,
		createActionHttpHandler(
			applyActionWrappers(handler, wrappers...)))
}

{'fraction_non_alphanumeric': 0.08195453842585433, 'fraction_numerical': 0.001855574454925004, 'mean_word_length': 3.9715603382013835, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '37823', 'n_tokens_mistral': 1698, 'n_tokens_neox': 1680, 'n_words': 744}