Documentation
¶
Overview ¶
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides utility functions and helpers for common operations. revive:disable:var-naming
Package util provides various utility functions for common tasks revive:disable:var-naming
Index ¶
- Constants
- func CloseAndLogOnError(ctx context.Context, closer io.Closer, message ...string)
- func ComputeLookupToken(hmacKey []byte, normalized string) []byte
- func ContextWithLogger(ctx context.Context, logger *LogEntry) context.Context
- func ContextWithRequestID(ctx context.Context, requestID string) context.Context
- func DecryptValue(aesKey []byte, payload []byte) ([]byte, error)
- func EncryptValue(aesKey []byte, plaintext []byte) ([]byte, error)
- func GetEnv(key string, fallback ...string) string
- func GetIP(r *http.Request) string
- func GetLocalIP() string
- func GetMacAddress() string
- func GetRequestID(ctx context.Context) string
- func IDString() string
- func IDStringWithTime(t time.Time) string
- func MakeJSONAPI(handler JSONRequestHandler) http.HandlerFunc
- func ParseLevel(levelStr string) (slog.Level, error)
- func Protect(handler http.HandlerFunc) http.HandlerFunc
- func RandomString(n int) string
- func RequestWithLogging(req *http.Request) *http.Request
- func SLog(ctx context.Context) *slog.Logger
- func SetCORSHeaders(w http.ResponseWriter)
- func SetTenancy(ctx context.Context, tenancyInfo TenancyInfo) context.Context
- func SortAndUnique(data sort.Interface) int
- func Unique(data sort.Interface) int
- func UniqueStrings(strings []string) []string
- func WithCORSOptions(handler http.HandlerFunc) http.HandlerFunc
- type JSONRequestHandler
- type JSONResponse
- type LogEntry
- func (e *LogEntry) Debug(msg string, args ...any)
- func (e *LogEntry) Enabled(ctx context.Context, level slog.Level) bool
- func (e *LogEntry) Error(msg string, args ...any)
- func (e *LogEntry) Fatal(msg string, args ...any)
- func (e *LogEntry) Info(msg string, args ...any)
- func (e *LogEntry) Log(ctx context.Context, level slog.Level, msg string, fields ...any)
- func (e *LogEntry) Logf(ctx context.Context, level slog.Level, format string, args ...interface{})
- func (e *LogEntry) Panic(msg string, args ...any)
- func (e *LogEntry) Printf(format string, args ...any)
- func (e *LogEntry) Release()
- func (e *LogEntry) SLog() *slog.Logger
- func (e *LogEntry) Trace(msg string, args ...any)
- func (e *LogEntry) Warn(msg string, args ...any)
- func (e *LogEntry) With(args ...any) *LogEntry
- func (e *LogEntry) WithContext(ctx context.Context) *LogEntry
- func (e *LogEntry) WithError(err error) *LogEntry
- func (e *LogEntry) WithField(key string, value any) *LogEntry
- func (e *LogEntry) WithFields(fields map[string]any) *LogEntry
- type MultiHandler
- type Option
- func WithLogAddSource(addSource bool) Option
- func WithLogHandler(handler slog.Handler) Option
- func WithLogHandlerExclusive() Option
- func WithLogLevel(level slog.Level) Option
- func WithLogNoColor(noColor bool) Option
- func WithLogOutput(output io.Writer) Option
- func WithLogStackTrace() Option
- func WithLogTimeFormat(format string) Option
- type TenancyInfo
Examples ¶
Constants ¶
const ( StatusFound = 302 StatusInternalServerError = 500 DefaultRequestIDLength = 12 Status2xx = 2 )
const ( CallerDepth = 2 FileLineAttr = "caller" )
Variables ¶
This section is empty.
Functions ¶
func CloseAndLogOnError ¶ added in v0.3.2
CloseAndLogOnError Closes io.Closer and logs the error if any with the messages supplied.
func ComputeLookupToken ¶ added in v0.3.9
ComputeLookupToken generates a cryptographically secure lookup token from input data.
The token is computed using HMAC-SHA256 with the provided key, making it suitable for: - Database indexing operations - Cache key generation - Deduplication identifiers
Security properties:
- Deterministic: Same input always produces the same token
- Non-reversible: Cannot derive the original input from the token
- Constant-time comparison: Safe against timing attacks
- Rainbow table resistant: Requires secret HMAC key
The function is tenant-scoped when tenant_id is included in the normalized input, ensuring multi-tenant data isolation.
Parameters:
- hmacKey: Secret key for HMAC (must be kept secure, recommended 32+ bytes)
- normalized: Input data to be tokenized (should be pre-normalized for consistency)
Returns:
- 32-byte HMAC-SHA256 token suitable for indexing and comparison
Example:
key := []byte("32-byte-secret-key-for-hmac")
input := "[email protected]"
token := ComputeLookupToken(key, input)
Example ¶
Example tests.
package main
import (
"fmt"
"github.com/pitabwire/util"
)
func main() {
key := []byte("32-byte-secret-key-for-hmac")
input := "[email protected]"
token := util.ComputeLookupToken(key, input)
// Token is a 32-byte array suitable for indexing
fmt.Printf("%x", token)
}
Output: e0797b7f749ebb70773d3190feef382cc41d3e907485be7f5e3ee766c98463fc
func ContextWithLogger ¶
ContextWithLogger associates a logger with the context.
func ContextWithRequestID ¶ added in v0.2.4
func DecryptValue ¶ added in v0.3.9
DecryptValue decrypts data encrypted with EncryptValue using AES-GCM.
This function verifies the authentication tag to ensure the ciphertext has not been tampered with before decryption. Any modification to the ciphertext or nonce will cause decryption to fail.
Security properties:
- Authenticated decryption: Detects any ciphertext tampering
- Automatic nonce extraction: Nonce is read from the payload prefix
- Constant-time operations: Safe against timing attacks in verification
Parameters:
- aesKey: AES decryption key (must be identical to encryption key)
- payload: Combined nonce + ciphertext from EncryptValue
Returns:
- Decrypted plaintext data
- Error if decryption fails, authentication fails, or inputs are invalid
Common failure scenarios:
- Incorrect key: "cipher: message authentication failed"
- Corrupted payload: "cipher: message authentication failed"
- Invalid payload length: Various cipher errors
- Wrong key size: "crypto/aes: invalid key size"
Example:
plaintext, err := DecryptValue(key, ciphertext)
if err != nil {
// Handle decryption failure
}
func EncryptValue ¶ added in v0.3.9
EncryptValue encrypts plaintext using AES-GCM with authenticated encryption.
AES-GCM (Galois/Counter Mode) provides both confidentiality and authenticity, making it suitable for sensitive data encryption. The function generates a random nonce for each encryption to ensure semantic security.
Security properties:
- Confidentiality: Plaintext is encrypted using AES-256
- Authenticity: GCM authentication tag detects tampering
- Semantic security: Random nonce ensures identical plaintexts produce different ciphertexts
- No padding oracle: GCM doesn't require padding
Parameters:
- aesKey: AES encryption key (must be 16, 24, or 32 bytes for AES-128/192/256)
- plaintext: Data to be encrypted
Returns:
- Combined nonce + ciphertext (nonce size + ciphertext + auth tag)
- Error if key is invalid or encryption fails
The returned payload format is: [nonce][ciphertext][authentication-tag] Use DecryptValue with the same key to decrypt.
Example:
key := make([]byte, 32) // AES-256 key
rand.Read(key)
ciphertext, err := EncryptValue(key, []byte("sensitive data"))
Example (Roundtrip) ¶
package main
import (
"crypto/rand"
"fmt"
"github.com/pitabwire/util"
)
func main() {
key := make([]byte, 32)
_, _ = rand.Read(key)
original := []byte("secret message")
// Encrypt
ciphertext, err := util.EncryptValue(key, original)
if err != nil {
panic(err)
}
// Decrypt
decrypted, err := util.DecryptValue(key, ciphertext)
if err != nil {
panic(err)
}
// Verify round-trip
if string(decrypted) != string(original) {
panic("decryption failed")
}
fmt.Println(string(decrypted))
}
Output: secret message
func GetEnv ¶ added in v0.3.3
GetEnv Obtains the environment key or returns the first fallback value.
func GetIP ¶ added in v0.3.3
GetIP retrieves the client's IP address from an HTTP request. It checks for common proxy headers and falls back to the remote address.
func GetLocalIP ¶ added in v0.3.3
func GetLocalIP() string
GetLocalIP convenience method that obtains the non localhost ip address for machine running app.
func GetMacAddress ¶ added in v0.3.3
func GetMacAddress() string
GetMacAddress convenience method to get some unique address based on the network interfaces the application is running on.
func GetRequestID ¶
GetRequestID returns the request ID associated with this context, or the empty string if one is not associated with this context.
func IDStringWithTime ¶ added in v0.1.3
func MakeJSONAPI ¶
func MakeJSONAPI(handler JSONRequestHandler) http.HandlerFunc
MakeJSONAPI creates an HTTP handler which always responds to incoming requests with JSON responses. Incoming http.Requests will have a logger (with a request ID/method/path logged) attached to the Context. This can be accessed via GetLogger(Context).
func ParseLevel ¶ added in v0.2.0
ParseLevel converts a string to a log.level. It is case-insensitive. Returns an error if the string does not match a known level.
func Protect ¶
func Protect(handler http.HandlerFunc) http.HandlerFunc
Protect panicking HTTP requests from taking down the entire process, and log them using the correct logger, returning a 500 with a JSON response rather than abruptly closing the connection. The http.Request MUST have a ctxValueLogger.
func RandomString ¶
RandomString generates a cryptographically secure random string of length n.
func RequestWithLogging ¶
RequestWithLogging sets up standard logging for http.Requests. http.Requests will have a logger (with a request ID/method/path logged) attached to the Context. This can be accessed via GetLogger(Context).
func SetCORSHeaders ¶
func SetCORSHeaders(w http.ResponseWriter)
SetCORSHeaders sets unrestricted origin Access-Control headers on the response writer.
func SetTenancy ¶ added in v0.3.7
func SetTenancy(ctx context.Context, tenancyInfo TenancyInfo) context.Context
func SortAndUnique ¶
SortAndUnique sorts the data and removes duplicates. O(nlog(n)).
func Unique ¶
Unique removes duplicate items from a sorted list in place. Takes the same interface as sort.Sort Returns the length of the data without duplicates Uses the last occurrence of a duplicate. O(n).
func UniqueStrings ¶
UniqueStrings returns a sorted slice of unique strings. O(nlog(n)).
func WithCORSOptions ¶
func WithCORSOptions(handler http.HandlerFunc) http.HandlerFunc
WithCORSOptions intercepts all OPTIONS requests and responds with CORS headers. The request handler is not invoked when this happens.
Types ¶
type JSONRequestHandler ¶
type JSONRequestHandler interface {
OnIncomingRequest(req *http.Request) JSONResponse
}
JSONRequestHandler represents an interface that must be satisfied in order to respond to incoming HTTP requests with JSON.
func NewJSONRequestHandler ¶
func NewJSONRequestHandler(f func(req *http.Request) JSONResponse) JSONRequestHandler
NewJSONRequestHandler converts the given OnIncomingRequest function into a JSONRequestHandler.
type JSONResponse ¶
type JSONResponse struct {
// HTTP status code.
Code int
// JSON represents the JSON that should be serialised and sent to the client
JSON interface{}
// Headers represent any headers that should be sent to the client
Headers map[string]any
}
JSONResponse represents an HTTP response which contains a JSON body.
func ErrorResponse ¶
func ErrorResponse(err error) JSONResponse
ErrorResponse returns an HTTP 500 JSONResponse with the stringified form of the given error.
func MatrixErrorResponse ¶
func MatrixErrorResponse(httpStatusCode int, errCode, message string) JSONResponse
MatrixErrorResponse is a function that returns error responses in the standard Matrix Error format (errcode / error).
func MessageResponse ¶
func MessageResponse(code int, msg string) JSONResponse
MessageResponse returns a JSONResponse with a 'message' key containing the given text.
func RedirectResponse ¶
func RedirectResponse(location string) JSONResponse
RedirectResponse returns a JSONResponse which 302s the client to the given location.
func (JSONResponse) Is2xx ¶
func (r JSONResponse) Is2xx() bool
Is2xx returns true if the Code is between 200 and 299.
type LogEntry ¶ added in v0.2.0
type LogEntry struct {
// contains filtered or unexported fields
}
LogEntry is a lightweight wrapper with optional stack traces.
func (*LogEntry) Release ¶ added in v0.2.5
func (e *LogEntry) Release()
Release returns the entry to the pool.
func (*LogEntry) WithContext ¶ added in v0.2.0
type MultiHandler ¶ added in v0.3.5
type MultiHandler struct {
// contains filtered or unexported fields
}
MultiHandler fans out records to multiple handlers.
type Option ¶ added in v0.3.0
type Option func(*logOptions)
Option is a function that configures logOptions.
func WithLogAddSource ¶ added in v0.3.0
WithLogAddSource enables or disables source code position in log entries.
func WithLogHandler ¶ added in v0.3.0
WithLogHandler sets a custom slog.Handler implementation.
func WithLogHandlerExclusive ¶ added in v0.3.5
func WithLogHandlerExclusive() Option
WithLogHandlerExclusive sets slog.Handler to be exclusively utilized.
func WithLogLevel ¶ added in v0.3.0
WithLogLevel sets the log level.
func WithLogNoColor ¶ added in v0.3.0
WithLogNoColor enables or disables colored output.
func WithLogOutput ¶ added in v0.3.0
WithLogOutput sets the output writer for logs.
func WithLogStackTrace ¶ added in v0.3.0
func WithLogStackTrace() Option
WithLogStackTrace enables automatic stack trace printing.
func WithLogTimeFormat ¶ added in v0.3.0
WithLogTimeFormat sets the time format for log timestamps.
type TenancyInfo ¶ added in v0.3.7
func GetTenancy ¶ added in v0.3.7
func GetTenancy(ctx context.Context) TenancyInfo