Documentation
¶
Overview ¶
Package gg is the Garcon toolbox.
Index ¶
- Constants
- Variables
- func AppendPrefixes(origins []string, prefixes ...string) []string
- func AppendURLs(urls []*url.URL, prefixes ...*url.URL) []*url.URL
- func B2S(b []byte) string
- func BrotliCompressor(file *os.File, level int) io.WriteCloser
- func Compress(buf []byte, fn, ext string, level int) time.Duration
- func Compressor(file *os.File, ext string, level int) (io.WriteCloser, error)
- 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 Decompress(fn, ext string) []byte
- func Deduplicate[T comparable](duplicates []T) []T
- func EncodeHexOrB64(in string, isHex bool) string
- 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 FastSanitize(str string) string
- func GZipCompressor(file *os.File, level int) (io.WriteCloser, error)
- func KeepSchemeHostOnly(urls []*url.URL) []string
- func Namify(str string) string
- func NewHash() (hash.Hash, error)
- func Obfuscate(str string) (string, error)
- 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 S2Compressor(file *os.File, level int) io.WriteCloser
- 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 SupportedDecoders() []string
- func SupportedEncoders() []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)
- func ZStdCompressor(file *os.File, level int) (io.WriteCloser, error)
- type Chain
- type LogNotifier
- type MattermostNotifier
- type Middleware
- type Notifier
- type RTChain
- type RTMiddleware
- type RoundTripperFunc
- type TelegramNotifier
Constants ¶
const ( BrotliExt = ".br" Bzip2Ext = ".bz2" GZipExt = ".gz" S2Ext = ".s2" // S2 is a Snappy extension ZStdExt = ".zst" )
Variables ¶
var ErrNonPrintable = errors.New("non-printable")
Functions ¶
func AppendPrefixes ¶
func B2S ¶ added in v0.30.1
B2S (Bytes to String) returns a string pointing to a []byte without copying.
func BrotliCompressor ¶ added in v0.33.0
func BrotliCompressor(file *os.File, level int) io.WriteCloser
func Compressor ¶ added in v0.33.0
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 ConvertSize with int64 input. A good alternative is `ByteSize()“ from "github.com/gofiber/fiber".
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 Decompress ¶ added in v0.31.0
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 EncodeHexOrB64 ¶ added in v0.30.1
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 FastSanitize ¶ added in v0.33.0
FastSanitize is an alternative of the Sanitize function using an optimized implementation.
func GZipCompressor ¶ added in v0.33.0
func KeepSchemeHostOnly ¶ added in v0.35.0
func Namify ¶ added in v0.32.0
Namify extracts the wider "[a-zA-Z0-9_]+" string from the end of str. If str is a path or an URL, keep the last basename. Example: keep "myapp" from "https://example.com/path/myapp/" Namify also removes all punctuation characters except "_" and "-".
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 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 S2Compressor ¶ added in v0.33.0
func S2Compressor(file *os.File, level int) io.WriteCloser
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 string into sanitized tokens.
func SplitCleanedLines ¶
SplitCleanedLines splits on linefeed, drops redundant blank lines, replaces the non-printable runes by spaces, trims leading/trailing/redundant spaces,.
func SupportedDecoders ¶ added in v0.31.0
func SupportedDecoders() []string
func SupportedEncoders ¶ added in v0.31.0
func SupportedEncoders() []string
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.
func Value ¶
Value returns the /endpoint/{key} (URL path) else the "key" form (HTTP body) else the "key" query string (URL) else the HTTP header. Value requires chi.URLParam().
func ZStdCompressor ¶ added in v0.33.0
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 LogNotifier ¶ added in v0.31.0
type LogNotifier struct{}
LogNotifier implements a Notifier interface that logs the received notifications. LogNotifier 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 NewLogNotifier ¶ added in v0.31.0
func NewLogNotifier() LogNotifier
NewLogNotifier creates a LogNotifier.
func (LogNotifier) Notify ¶ added in v0.31.0
func (n LogNotifier) 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 MattermostNotifier given a Mattermost server endpoint (see mattermost hooks).
func (MattermostNotifier) Notify ¶
func (n MattermostNotifier) Notify(msg string) error
Notify sends a message to a Mattermost server.
type Middleware ¶
Middleware is a constructor function returning a http.Handler.
type Notifier ¶
Notifier interface for sending messages.
func NewNotifier ¶
NewNotifier selects the Notifier type depending on the parameter 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.
type TelegramNotifier ¶ added in v0.31.0
type TelegramNotifier struct {
// contains filtered or unexported fields
}
TelegramNotifier is a Notifier for a specific Telegram chat room.
func NewTelegramNotifier ¶ added in v0.31.0
func NewTelegramNotifier(endpoint, chatID string) TelegramNotifier
NewTelegramNotifier creates a TelegramNotifier.
func (TelegramNotifier) Notify ¶ added in v0.31.0
func (n TelegramNotifier) Notify(msg string) error
Notify sends a message to the Telegram server.