gg

package
v0.35.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2024 License: MIT Imports: 29 Imported by: 10

Documentation

Overview

Package gg is the Garcon toolbox.

Index

Constants

View Source
const (
	BrotliExt = ".br"
	Bzip2Ext  = ".bz2"
	GZipExt   = ".gz"
	S2Ext     = ".s2" // S2 is a Snappy extension
	ZStdExt   = ".zst"
)

Variables

View Source
var ErrNonPrintable = errors.New("non-printable")

Functions

func AppendPrefixes

func AppendPrefixes(origins []string, prefixes ...string) []string

func AppendURLs

func AppendURLs(urls []*url.URL, prefixes ...*url.URL) []*url.URL

func B2S added in v0.30.1

func B2S(b []byte) string

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 Compress added in v0.31.0

func Compress(buf []byte, fn, ext string, level int) time.Duration

func Compressor added in v0.33.0

func Compressor(file *os.File, ext string, level int) (io.WriteCloser, error)

func ConvertSize

func ConvertSize(sizeInBytes int) string

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

func ConvertSize64(sizeInBytes int64) string

ConvertSize64 is ConvertSize with int64 input. A good alternative is `ByteSize()“ from "github.com/gofiber/fiber".

func DecodeHexOrB64

func DecodeHexOrB64(in string, outLen int) ([]byte, error)

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

func DecodeHexOrB64Bytes(in []byte, outLen int, reuse bool) ([]byte, error)

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

func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, msg any, maxBytes ...int) error

DecodeJSONRequest decodes the JSON from the request body.

func DecodeJSONResponse

func DecodeJSONResponse(r *http.Response, msg any, maxBytes ...int) error

DecodeJSONResponse decodes the JSON from the request body.

func Decompress added in v0.31.0

func Decompress(fn, ext string) []byte

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 EncodeHexOrB64(in string, isHex bool) string

func EncodeHexOrB64Bytes

func EncodeHexOrB64Bytes(bin []byte, isHex bool) []byte

func EnvInt

func EnvInt(envvar string, fallback ...int) int

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

func EnvStr(envvar string, fallback ...string) string

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

func ExtractWords(csv string, dictionary []string) []string

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

func FastSanitize(str string) string

FastSanitize is an alternative of the Sanitize function using an optimized implementation.

func GZipCompressor added in v0.33.0

func GZipCompressor(file *os.File, level int) (io.WriteCloser, error)

func KeepSchemeHostOnly added in v0.35.0

func KeepSchemeHostOnly(urls []*url.URL) []string

func Namify added in v0.32.0

func Namify(str string) string

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

func NewHash() (hash.Hash, error)

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 Obfuscate

func Obfuscate(str string) (string, error)

Obfuscate hashes the input string to prevent logging sensitive information.

func OverwriteBufferContent

func OverwriteBufferContent(b []byte)

OverwriteBufferContent is to erase a secret when it is no longer required.

func ParseURLs

func ParseURLs(origins []string) []*url.URL

func Printable

func Printable(array ...string) int

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

func PrintableRune(r rune) bool

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 RandomBytes(n int) []byte

func ReadRequest

func ReadRequest(w http.ResponseWriter, r *http.Request, maxBytes ...int) ([]byte, error)

func ReadResponse

func ReadResponse(r *http.Response, maxBytes ...int) ([]byte, error)

func S2Compressor added in v0.33.0

func S2Compressor(file *os.File, level int) io.WriteCloser

func SafeHeader

func SafeHeader(r *http.Request, header string) string

SafeHeader stringifies a safe list of HTTP header values.

func Sanitize

func Sanitize(slice ...string) string

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 Split

func Split(values string, separators ...rune) []string

func SplitClean

func SplitClean(values string, separators ...rune) []string

SplitClean splits the string into sanitized tokens.

func SplitCleanedLines

func SplitCleanedLines(str string) []string

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

func UnmarshalJSONResponse[T json.Unmarshaler](r *http.Response, msg T, maxBytes ...int) error

UnmarshalJSONResponse unmarshals the JSON from the request body.

func Value

func Value(r *http.Request, key, header string) (string, error)

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 Values

func Values(r *http.Request, key string) ([]string, error)

Values requires chi.URLParam().

func ZStdCompressor added in v0.33.0

func ZStdCompressor(file *os.File, level int) (io.WriteCloser, error)

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

func (c Chain) Then(handler http.Handler) http.Handler

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.

func (Chain) ThenFunc

func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler

ThenFunc works identically to Then, but takes a HandlerFunc instead of a Handler.

The following two statements are equivalent:

c.Then(http.HandlerFunc(fn))
c.ThenFunc(fn)

ThenFunc provides all the guarantees of Then.

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

type Middleware func(http.Handler) http.Handler

Middleware is a constructor function returning a http.Handler.

type Notifier

type Notifier interface {
	Notify(message string) error
}

Notifier interface for sending messages.

func NewNotifier

func NewNotifier(dataSourceName string) Notifier

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

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

type RoundTripperFunc func(*http.Request) (*http.Response, error)

RoundTripperFunc is to RoundTripper what HandlerFunc is to Handler. It is a higher-order function that enables chaining of RoundTrippers with the middleware pattern.

func (RoundTripperFunc) RoundTrip

func (f RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip calls the function itself.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL