Documentation ¶
Overview ¶
Package gg is the Garcon toolbox.
Index ¶
- Variables
- func AppendPrefixes(origins []string, prefixes ...string) []string
- func AppendURLs(urls []*url.URL, prefixes ...*url.URL) []*url.URL
- func ConvertSize(sizeInBytes int) string
- func ConvertSize64(sizeInBytes int64) string
- func DecodeHexOrB64(in string, outLen int) ([]byte, error)
- func DecodeHexOrB64Bytes(in []byte, outLen int, reuse bool) ([]byte, error)
- func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, msg any, maxBytes ...int) error
- func DecodeJSONResponse(r *http.Response, msg any, maxBytes ...int) error
- func Deduplicate[T comparable](duplicates []T) []T
- func EncodeHexOrB64Bytes(bin []byte, isHex bool) []byte
- func EnvInt(envvar string, fallback ...int) int
- func EnvStr(envvar string, fallback ...string) string
- func ExtractWords(csv string, dictionary []string) []string
- func NewHash() (hash.Hash, error)
- func Obfuscate(str string) (string, error)
- func OriginsFromURLs(urls []*url.URL) []string
- func OverwriteBufferContent(b []byte)
- func ParseURLs(origins []string) []*url.URL
- func Printable(array ...string) int
- func PrintableRune(r rune) bool
- func RandomBytes(n int) []byte
- func ReadRequest(w http.ResponseWriter, r *http.Request, maxBytes ...int) ([]byte, error)
- func ReadResponse(r *http.Response, maxBytes ...int) ([]byte, error)
- func SafeHeader(r *http.Request, header string) string
- func Sanitize(slice ...string) string
- func Split(values string, separators ...rune) []string
- func SplitClean(values string, separators ...rune) []string
- func SplitCleanedLines(str string) []string
- func UnmarshalJSONRequest[T json.Unmarshaler](w http.ResponseWriter, r *http.Request, msg T, maxBytes ...int) error
- func UnmarshalJSONResponse[T json.Unmarshaler](r *http.Response, msg T, maxBytes ...int) error
- func Value(r *http.Request, key, header string) (string, error)
- func Values(r *http.Request, key string) ([]string, error)
- type Chain
- type FakeNotifier
- type MattermostNotifier
- type Middleware
- type Notifier
- type RTChain
- type RTMiddleware
- type RoundTripperFunc
Constants ¶
This section is empty.
Variables ¶
var ErrNonPrintable = errors.New("non-printable")
Functions ¶
func AppendPrefixes ¶
func ConvertSize ¶
ConvertSize converts a size in bytes into the most appropriate unit among KiB, MiB, GiB, TiB, PiB and EiB. 1 KiB is 1024 bytes as defined by the ISO/IEC 80000-13:2008 standard. See: https://wikiless.org/wiki/ISO%2FIEC_80000#Units_of_the_ISO_and_IEC_80000_series
func ConvertSize64 ¶
ConvertSize64 is similar ConvertSize but takes in input an int64.
func DecodeHexOrB64 ¶
DecodeHexOrB64 tries to decode the input string as hexadecimal or Base64 depending on the given output length. DecodeHexOrB64 supports the unpadded Base64 as defined in RFC 4648 §5 (URL encoding).
func DecodeHexOrB64Bytes ¶
DecodeHexOrB64Bytes tries to decode the input bytes as hexadecimal or Base64 depending on the given output length. DecodeHexOrB64Bytes supports the unpadded Base64 defined in RFC 4648 §5 for URL encoding. The "reuse" parameter allows to reuse the input bytes reducing the memory allocation. Caution: the input bytes are overwritten with reuse=true.
func DecodeJSONRequest ¶
DecodeJSONRequest decodes the JSON from the request body.
func DecodeJSONResponse ¶
DecodeJSONResponse decodes the JSON from the request body.
func Deduplicate ¶
func Deduplicate[T comparable](duplicates []T) []T
Deduplicate makes a slice of elements unique: it returns a slice with only the unique elements in it.
func EncodeHexOrB64Bytes ¶
func EnvInt ¶
EnvInt does the same as EnvStr but expects the value is an integer. EnvInt panics if the envvar value cannot be parsed as an integer.
func EnvStr ¶
EnvStr searches the environment variable (envvar) and returns its value if found, otherwise returns the optional fallback value. In absence of fallback, "" is returned.
func ExtractWords ¶
ExtractWords converts comma-separated values into a slice of unique words found in the dictionary.
The search is case-insensitive and is based on common prefix: the input value "foo" selects the first word in the dictionary that starts with "foo" (as "food" for example).
Moreover the special value "ALL" means all the dictionary words.
No guarantees are made about ordering. However the returned words are not duplicated. Note this operation alters the content of the dictionary: the found words are replaced by the last dictionary words. Clone the input dictionary if it needs to be preserved:
d2 := append([]string{}, dictionary...) words := garcon.ExtractWords(csv, d2)
func NewHash ¶
NewHash is based on HighwayHash, a hashing algorithm enabling high speed (especially on AMD64). See the study on HighwayHash and some other hash functions: https://github.com/fwessels/HashCompare
func OriginsFromURLs ¶
func OverwriteBufferContent ¶
func OverwriteBufferContent(b []byte)
OverwriteBufferContent is to erase a secret when it is no longer required.
func Printable ¶
Printable returns -1 when all the strings are safely printable else returns the position of the rejected character.
The non printable characters are:
- Carriage Return "\r"
- Line Feed "\n"
- other ASCII control codes (except space)
- invalid UTF-8 codes
Printable can be used to preventing log injection.
When multiple strings are passed, the returned position is sum with the string index multiplied by 1000.
func PrintableRune ¶
PrintableRune returns false if rune is a Carriage Return "\r", a Line Feed "\n", another ASCII control code (except space), or an invalid UTF-8 code. PrintableRune can be used to prevent log injection.
func RandomBytes ¶
func ReadRequest ¶
func SafeHeader ¶
SafeHeader stringifies a safe list of HTTP header values.
func Sanitize ¶
Sanitize replaces control codes by the tofu symbol and invalid UTF-8 codes by the replacement character. Sanitize can be used to prevent log injection.
Inspired from: - https://wikiless.org/wiki/Replacement_character#Replacement_character - https://graphicdesign.stackexchange.com/q/108297
func SplitClean ¶
SplitClean splits the values and sanitize them.
func SplitCleanedLines ¶
SplitCleanedLines splits on linefeed, drops redundant blank lines, replaces the non-printable runes by spaces, trims leading/trailing/redundant spaces,.
func UnmarshalJSONRequest ¶
func UnmarshalJSONRequest[T json.Unmarshaler](w http.ResponseWriter, r *http.Request, msg T, maxBytes ...int) error
UnmarshalJSONRequest unmarshals the JSON from the request body.
func UnmarshalJSONResponse ¶
UnmarshalJSONResponse unmarshals the JSON from the request body.
Types ¶
type Chain ¶
type Chain []Middleware
Chain acts as a list of http.Handler middleware. Chain is effectively immutable: once created, it will always hold the same set of middleware in the same order.
func NewChain ¶
func NewChain(chain ...Middleware) Chain
NewChain creates a new chain, memorizing the given list of middleware. NewChain serves no other function, middleware is only constructed upon a call to chain.Then().
func (Chain) Append ¶
func (c Chain) Append(chain ...Middleware) Chain
Append extends a chain, adding the provided middleware as the last ones in the request flow.
chain := garcon.NewChain(m1, m2) chain = chain.Append(m3, m4) // requests in chain go m1 -> m2 -> m3 -> m4
func (Chain) Then ¶
Then chains the middlewares and returns the final http.Handler.
garcon.NewChain(m1, m2, m3).Then(h)
is equivalent to:
m1(m2(m3(h)))
When the request comes in, it will be passed to m1, then m2, then m3 and finally, the given handler (assuming every middleware calls the following one).
A chain can be safely reused by calling Then() several times.
chain := garcon.NewChain(rateLimitHandler, csrfHandler) indexPipe = chain.Then(indexHandler) authPipe = chain.Then(authHandler)
Note: every call to Then() calls all middleware pieces. Thus several instances of the same middleware will be created when a chain is reused in this previous example. For proper middleware, this should cause no problem.
Then() treats nil as http.DefaultServeMux.
type FakeNotifier ¶
type FakeNotifier struct{}
FakeNotifier implements a Notifier interface that logs the received notifications. FakeNotifier can be used as a mocked Notifier or for debugging purpose or as a fallback when a real Notifier cannot be created for whatever reason.
func (FakeNotifier) Notify ¶
func (n FakeNotifier) Notify(msg string) error
Notify prints the messages to the logs.
type MattermostNotifier ¶
type MattermostNotifier struct {
// contains filtered or unexported fields
}
MattermostNotifier for sending messages to a Mattermost server.
func NewMattermostNotifier ¶
func NewMattermostNotifier(endpoint string) MattermostNotifier
NewMattermostNotifier creates a new MattermostNotifier given a Mattermost server endpoint (see mattermost hooks).
func (MattermostNotifier) Notify ¶
func (n MattermostNotifier) Notify(msg string) error
Notify sends a message to the Mattermost server.
type Middleware ¶
Middleware is a constructor function returning a http.Handler.
type Notifier ¶
Notifier interface for sending messages.
func NewNotifier ¶
New selects the Notifier type depending on the endpoint pattern.
type RTChain ¶
type RTChain []RTMiddleware
RTChain acts as a list of http.RoundTripper middlewares. RTChain is effectively immutable: once created, it will always hold the same set of middleware in the same order.
func NewRTChain ¶
func NewRTChain(chain ...RTMiddleware) RTChain
NewRTChain creates a new chain of HTTP round trippers, memorizing the given list of RoundTrip middlewares. NewRTChain serves no other function, middlewares are only called upon a call to Then().
func (RTChain) Append ¶
func (c RTChain) Append(chain ...RTMiddleware) RTChain
Append extends a chain, adding the specified middlewares as the last ones in the request flow.
Append returns a new chain, leaving the original one untouched.
Example #1
stdChain := garcon.NewRTChain(m1, m2) extChain := stdChain.Append(m3, m4) // requests in stdChain go m1 -> m2 // requests in extChain go m1 -> m2 -> m3 -> m4
Example #2
stdChain := garcon.NewRTChain(m1, m2) ext1Chain := garcon.NewRTChain(m3, m4) ext2Chain := stdChain.Append(ext1Chain...) // requests in stdChain go m1 -> m2 // requests in ext1Chain go m3 -> m4 // requests in ext2Chain go m1 -> m2 -> m3 -> m4
Example #3
aHtmlAfterNosurf := garcon.NewRTChain(m2) aHtml := garcon.NewRTChain(m1, func(rt http.RoundTripper) http.RoundTripper { csrf := nosurf.New(rt) csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail)) return csrf }).Append(aHtmlAfterNosurf) // requests to aHtml hitting nosurfs success handler go: m1 -> nosurf -> m2 -> rt // requests to aHtml hitting nosurfs failure handler go: m1 -> nosurf -> m2 -> csrfFail
func (RTChain) Then ¶
func (c RTChain) Then(rt http.RoundTripper) http.RoundTripper
Then chains the middleware and returns the final http.RoundTripper.
garcon.NewRTChain(m1, m2, m3).Then(rt)
is equivalent to:
m1(m2(m3(rt)))
When the request goes out, it will be passed to m1, then m2, then m3 and finally, the given round tripper (assuming every middleware calls the following one).
A chain can be safely reused by calling Then() several times.
stdStack := garcon.NewRTChain(rateLimitHandler, csrfHandler) indexPipe = stdStack.Then(indexHandler) authPipe = stdStack.Then(authHandler)
Note that middlewares are called on every call to Then() and thus several instances of the same middleware will be created when a chain is reused in this way. For proper middleware, this should cause no problems.
Then() treats nil as http.DefaultTransport.
func (RTChain) ThenFunc ¶
func (c RTChain) ThenFunc(fn RoundTripperFunc) http.RoundTripper
ThenFunc works identically to Then, but takes a RoundTripperFunc instead of a RoundTripper.
The following two statements are equivalent:
c.Then(http.RoundTripperFunc(fn)) c.ThenFunc(fn)
ThenFunc provides all the guarantees of Then.
type RTMiddleware ¶
type RTMiddleware func(http.RoundTripper) http.RoundTripper
RTMiddleware for a piece of RoundTrip middleware. Some middleware uses this out of the box, so in most cases you can just use somepackage.New().
type RoundTripperFunc ¶
RoundTripperFunc is to RoundTripper what HandlerFunc is to Handler. It is a higher-order function that enables chaining of RoundTrippers with the middleware pattern.