Documentation
¶
Overview ¶
Package dim menyediakan utilitas upload file dengan fitur keamanan komprehensif. Mendukung pemrosesan sequential dan concurrent dengan validasi, sanitisasi, dan deteksi content-type.
Index ¶
- Constants
- Variables
- func BadRequest(w http.ResponseWriter, message string, errors map[string]string) error
- func BuiltinConstraintValidators() map[string]ConstraintValidator
- func CleanIPAddress(address string) string
- func Conflict(w http.ResponseWriter, message string, errors map[string]string) error
- func ContainsDigit(s string) bool
- func ContainsLowercase(s string) bool
- func ContainsRune(s string, predicate func(rune) bool) bool
- func ContainsSpecial(s string) bool
- func ContainsUppercase(s string) bool
- func CreatePasswordResetTokensTable(pool *pgxpool.Pool) error
- func CreateRateLimitsTable(pool *pgxpool.Pool) error
- func CreateRefreshTokensTable(pool *pgxpool.Pool) error
- func CreateTokenBlocklistTable(pool *pgxpool.Pool) error
- func Created(w http.ResponseWriter, data interface{}) error
- func DetectContentType(filename string) string
- func DropPasswordResetTokensTable(pool *pgxpool.Pool) error
- func DropRateLimitsTable(pool *pgxpool.Pool) error
- func DropRefreshTokensTable(pool *pgxpool.Pool) error
- func DropTokenBlocklistTable(pool *pgxpool.Pool) error
- func Forbidden(w http.ResponseWriter, message string) error
- func GenerateCSRFToken(length int) (string, error)
- func GenerateSecureToken(length int) (string, error)
- func GenerateTokenHash(token string) string
- func GetAuthToken(r *http.Request) (string, bool)
- func GetCSRFToken(r *http.Request, headerName string) string
- func GetClaims(r *http.Request) map[string]interface{}
- func GetClientIP(r *http.Request) string
- func GetCookie(r *http.Request, name string) string
- func GetEnv(key string) string
- func GetEnvOrDefault(key, defaultValue string) string
- func GetHeaderValue(r *http.Request, key string) string
- func GetParam(r *http.Request, key string) string
- func GetQueryParam(r *http.Request, key string) string
- func GetQueryParams(r *http.Request, keys ...string) map[string]string
- func GetRequestID(r *http.Request) string
- func HashPassword(password string) (string, error)
- func InternalServerError(w http.ResponseWriter, message string) error
- func IsAppError(err error) bool
- func IsHexChar(char byte) bool
- func IsSafeHttpMethod(method string) bool
- func IsSafeRead(query string) bool
- func IsValidDateFormat(date string) bool
- func IsValidUuid(s string) bool
- func Json(w http.ResponseWriter, status int, data interface{}) error
- func JsonAppError(w http.ResponseWriter, appErr *AppError) error
- func JsonError(w http.ResponseWriter, status int, message string, errors map[string]string) error
- func JsonPagination(w http.ResponseWriter, status int, data interface{}, meta PaginationMeta) error
- func LoadEnvFile(filename string) error
- func LoadEnvFileFromPath(dir string) error
- func MiddlewareToHandler(m MiddlewareFunc, next http.Handler) http.Handler
- func NoContent(w http.ResponseWriter) error
- func NotFound(w http.ResponseWriter, message string) error
- func OK(w http.ResponseWriter, data interface{}) error
- func ParseEnvBool(s string) bool
- func ParseEnvDuration(value string) (time.Duration, error)
- func ParseEnvInt(value string) (int, error)
- func PathMatches(path string, patterns []string) bool
- func Register(m Migration)
- func RegisterMIMEType(ext, mimeType string)
- func RollbackMigration(db *PostgresDatabase, migration Migration) error
- func RunMigrations(db *PostgresDatabase, migrations []Migration) error
- func ServeFile(w http.ResponseWriter, filename, filePath string, statusCode int) error
- func ServeFileInline(w http.ResponseWriter, filename, filePath string, statusCode int) error
- func SetCSRFToken(w http.ResponseWriter, token string, config CSRFConfig)
- func SetContentType(w http.ResponseWriter, contentType string)
- func SetCookie(w http.ResponseWriter, cookie *http.Cookie)
- func SetHeader(w http.ResponseWriter, key, value string)
- func SetHeaders(w http.ResponseWriter, headers map[string]string)
- func SetRequestID(r *http.Request, requestID string) *http.Request
- func SetStatus(w http.ResponseWriter, status int)
- func SetUser(r *http.Request, user Authenticatable) *http.Request
- func SimpleGlobMatch(path, pattern string) bool
- func StartServer(ctx context.Context, config ServerConfig, handler http.Handler) error
- func StripComments(query string) string
- func ToCamelCase(s string) string
- func TooManyRequests(w http.ResponseWriter, retryAfterSeconds int) error
- func Unauthorized(w http.ResponseWriter, message string) error
- func UploadFiles(ctx context.Context, disk storage.Storage, files []*multipart.FileHeader, ...) ([]string, error)
- func ValidatePasswordStrength(password string) error
- func VerifyPassword(hashedPassword, password string) error
- func VerifyTokenHash(hash, token string) error
- type AmountRange
- type AppError
- type AuthService
- func (s *AuthService) Login(ctx context.Context, email, password string) (string, string, error)
- func (s *AuthService) Logout(ctx context.Context, refreshTokenStr string) error
- func (s *AuthService) RefreshToken(ctx context.Context, refreshTokenStr string) (string, string, error)
- func (s *AuthService) RequestPasswordReset(ctx context.Context, email string) (string, error)
- func (s *AuthService) ResetPassword(ctx context.Context, resetTokenStr, newPassword string) error
- func (s *AuthService) WithClaimsProvider(provider ClaimsProvider) *AuthService
- type AuthUserStore
- type Authenticatable
- type CORSConfig
- type CSRFConfig
- type ClaimsProvider
- type Command
- type CommandContext
- type Config
- type Console
- type ConstraintValidator
- type Database
- type DatabaseConfig
- type DateRange
- type EmailConfig
- type ErrorResponse
- type FilterParser
- func (fp *FilterParser) Errors() map[string]string
- func (fp *FilterParser) HasErrors() bool
- func (fp *FilterParser) Parse(target interface{}) *FilterParser
- func (fp *FilterParser) RegisterConstraintValidator(validator ConstraintValidator) *FilterParser
- func (fp *FilterParser) WithMaxValues(max int) *FilterParser
- func (fp *FilterParser) WithTimezone(tz *time.Location) *FilterParser
- type FlaggedCommand
- type HandlerFunc
- type HelpCommand
- type InConstraintValidator
- type InMemoryBlocklist
- type InMemoryRateLimitStore
- type IntRange
- type JWTConfig
- type JWTManager
- func (m *JWTManager) GenerateAccessToken(userID string, email string, sessionID string, ...) (string, error)
- func (m *JWTManager) GenerateRefreshToken(userID, sessionID string) (string, error)
- func (m *JWTManager) GetTokenExpiry(tokenString string) (time.Time, error)
- func (m *JWTManager) IsTokenExpired(tokenString string) (bool, error)
- func (m *JWTManager) VerifyRefreshToken(tokenString string) (string, string, error)
- func (m *JWTManager) VerifyToken(tokenString string) (jwt.MapClaims, error)
- type JsonNull
- type Logger
- type LoginRequest
- type MakeMigrationCommand
- type MiddlewareFunc
- func AllowBearerToken() MiddlewareFunc
- func CORS(config CORSConfig) MiddlewareFunc
- func CSRFMiddleware(config CSRFConfig) MiddlewareFunc
- func ChainMiddleware(middleware ...MiddlewareFunc) MiddlewareFunc
- func Compose(middleware ...MiddlewareFunc) MiddlewareFunc
- func ExpectBearerToken() MiddlewareFunc
- func HandlerToMiddleware(h http.Handler) MiddlewareFunc
- func LoggerMiddleware(logger *Logger) MiddlewareFunc
- func OptionalAuth(jwtManager *JWTManager) MiddlewareFunc
- func RateLimit(config RateLimitConfig, store ...RateLimitStore) MiddlewareFunc
- func Recovery(logger *Logger) MiddlewareFunc
- func RequireAuth(jwtManager *JWTManager, blocklist TokenBlocklist) MiddlewareFunc
- type MigrateCommand
- type MigrateListCommand
- type MigrateRollbackCommand
- type Migration
- type MigrationHistory
- type MockTokenStore
- func (s *MockTokenStore) FindPasswordResetToken(ctx context.Context, tokenHash string) (*PasswordResetToken, error)
- func (s *MockTokenStore) FindRefreshToken(ctx context.Context, tokenHash string) (*RefreshToken, error)
- func (s *MockTokenStore) MarkPasswordResetUsed(ctx context.Context, tokenHash string) error
- func (s *MockTokenStore) RevokeAllUserTokens(ctx context.Context, userID string) error
- func (s *MockTokenStore) RevokeRefreshToken(ctx context.Context, tokenHash string) error
- func (s *MockTokenStore) SavePasswordResetToken(ctx context.Context, token *PasswordResetToken) error
- func (s *MockTokenStore) SaveRefreshToken(ctx context.Context, token *RefreshToken) error
- type Observable
- type Pagination
- type PaginationMeta
- type PaginationParser
- type PaginationResponse
- type PasswordResetToken
- type PasswordValidator
- func (pv *PasswordValidator) RequireDigit(required bool) *PasswordValidator
- func (pv *PasswordValidator) RequireLowercase(required bool) *PasswordValidator
- func (pv *PasswordValidator) RequireSpecial(required bool) *PasswordValidator
- func (pv *PasswordValidator) RequireUppercase(required bool) *PasswordValidator
- func (pv *PasswordValidator) SetMinLength(length int) *PasswordValidator
- func (pv *PasswordValidator) Validate(password string) error
- type PostgresBlocklist
- func (p *PostgresBlocklist) Cleanup(ctx context.Context) error
- func (p *PostgresBlocklist) InitSchema(ctx context.Context) error
- func (p *PostgresBlocklist) Invalidate(ctx context.Context, identifier string, expiresIn time.Duration) error
- func (p *PostgresBlocklist) IsRevoked(ctx context.Context, identifier string) (bool, error)
- type PostgresDatabase
- func (db *PostgresDatabase) AddHook(hook QueryHook)
- func (db *PostgresDatabase) Begin(ctx context.Context) (pgx.Tx, error)
- func (db *PostgresDatabase) Close() error
- func (db *PostgresDatabase) Exec(ctx context.Context, query string, args ...interface{}) error
- func (db *PostgresDatabase) Query(ctx context.Context, query string, args ...interface{}) (Rows, error)
- func (db *PostgresDatabase) QueryRow(ctx context.Context, query string, args ...interface{}) Row
- func (db *PostgresDatabase) WithTx(ctx context.Context, fn TransactionFunc) error
- type PostgresRateLimitStore
- type PostgresTokenStore
- func (s *PostgresTokenStore) FindPasswordResetToken(ctx context.Context, tokenHash string) (*PasswordResetToken, error)
- func (s *PostgresTokenStore) FindRefreshToken(ctx context.Context, tokenHash string) (*RefreshToken, error)
- func (s *PostgresTokenStore) MarkPasswordResetUsed(ctx context.Context, tokenHash string) error
- func (s *PostgresTokenStore) RevokeAllUserTokens(ctx context.Context, userID string) error
- func (s *PostgresTokenStore) RevokeRefreshToken(ctx context.Context, tokenHash string) error
- func (s *PostgresTokenStore) SavePasswordResetToken(ctx context.Context, token *PasswordResetToken) error
- func (s *PostgresTokenStore) SaveRefreshToken(ctx context.Context, token *RefreshToken) error
- type QueryHook
- type Range
- type RateLimitConfig
- type RateLimitStore
- type RateLimiter
- type RefreshToken
- type RouteInfo
- type RouteListCommand
- type Router
- func (r *Router) Build()
- func (r *Router) Delete(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Get(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) GetRoutes() []RouteInfo
- func (r *Router) Group(prefix string, middleware ...MiddlewareFunc) *RouterGroup
- func (r *Router) Head(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Options(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Patch(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Post(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Put(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (r *Router) Register(method, path string, handler HandlerFunc, middleware []MiddlewareFunc)
- func (r *Router) SPA(root fs.FS, index string, middleware ...MiddlewareFunc)
- func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
- func (r *Router) Static(prefix string, root fs.FS, middleware ...MiddlewareFunc)
- func (r *Router) Use(middleware ...MiddlewareFunc)
- type RouterGroup
- func (rg *RouterGroup) Delete(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Get(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Group(prefix string, middleware ...MiddlewareFunc) *RouterGroup
- func (rg *RouterGroup) Head(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Options(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Patch(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Post(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Put(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
- func (rg *RouterGroup) Use(middleware ...MiddlewareFunc)
- type Row
- type Rows
- type ServeCommand
- type ServerConfig
- type SortField
- type SortParser
- type TimestampRange
- type TokenBlocklist
- type TokenResponse
- type TokenStore
- type TokenUser
- type TransactionFunc
- type UUID
- type UploadConfig
- type UploadOption
- func WithAllowedExts(exts ...string) UploadOption
- func WithConcurrent(enabled bool) UploadOption
- func WithLogger(logger *slog.Logger) UploadOption
- func WithMaxFileSize(size uint64) UploadOption
- func WithMaxFiles(max uint8) UploadOption
- func WithMaxWorkers(max int) UploadOption
- func WithPath(path string) UploadOption
- type UploadResult
- type Validator
- func (v *Validator) AddError(field, message string) *Validator
- func (v *Validator) Custom(field string, fn func(string) bool, value string, message string) *Validator
- func (v *Validator) Email(field, value string) *Validator
- func (v *Validator) ErrorCount() int
- func (v *Validator) ErrorMap() map[string]string
- func (v *Validator) Errors() []string
- func (v *Validator) GetError(field string) string
- func (v *Validator) HasError(field string) bool
- func (v *Validator) In(field, value string, allowed ...string) *Validator
- func (v *Validator) IsValid() bool
- func (v *Validator) Length(field, value string, length int) *Validator
- func (v *Validator) Matches(field, value, otherField, otherValue string) *Validator
- func (v *Validator) MaxLength(field, value string, max int) *Validator
- func (v *Validator) MinLength(field, value string, min int) *Validator
- func (v *Validator) NumRange(field string, value, min, max int) *Validator
- func (v *Validator) OptionalEmail(field string, value JsonNull[string]) *Validator
- func (v *Validator) OptionalIn(field string, value JsonNull[string], allowed ...string) *Validator
- func (v *Validator) OptionalLength(field string, value JsonNull[string], length int) *Validator
- func (v *Validator) OptionalMatches(field string, value JsonNull[string], pattern string) *Validator
- func (v *Validator) OptionalMaxLength(field string, value JsonNull[string], max int) *Validator
- func (v *Validator) OptionalMinLength(field string, value JsonNull[string], min int) *Validator
- func (v *Validator) Pattern(field, value string, pattern string) *Validator
- func (v *Validator) Required(field, value string) *Validator
Constants ¶
const ( // MinPasswordLength is the minimum required password length MinPasswordLength = 8 // BcryptCost is the bcrypt cost factor BcryptCost = 12 )
Variables ¶
var ( ErrBadRequest = NewAppError("Permintaan tidak valid", 400) ErrValidation = NewAppError("Validasi gagal", 400) ErrForbidden = NewAppError("Dilarang", 403) ErrNotFound = NewAppError("Tidak ditemukan", 404) ErrConflict = NewAppError("Konflik", 409) ErrInternalServerError = NewAppError("Kesalahan server internal", 500) )
Common error instances
Functions ¶
func BadRequest ¶
BadRequest menulis 400 Bad Request error response. Berguna untuk validation errors atau malformed requests.
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message
- errors: optional map dari field names ke error messages untuk validation errors
Returns:
- error: error jika encoding JSON gagal
Example:
BadRequest(w, "Validasi gagal", map[string]string{
"email": "Email tidak valid",
})
func BuiltinConstraintValidators ¶
func BuiltinConstraintValidators() map[string]ConstraintValidator
BuiltinConstraintValidators returns a map of built-in constraint validators. These validators handle common constraints like "in" for enums. Can be extended by adding custom validators to FilterParser.
func CleanIPAddress ¶
CleanIPAddress menghapus port number dari IP address string. Menangani IPv6 format dengan bracket notation dan IPv4:port format. Returns IP tanpa port atau original string jika tidak ada port.
Parameters:
- address: IP address string dengan atau tanpa port (contoh: "192.168.1.1:8080" atau "[::1]:8080")
Returns:
- string: clean IP address tanpa port
Example:
CleanIPAddress("192.168.1.1:8080") // returns "192.168.1.1"
CleanIPAddress("[::1]:8080") // returns "::1"
CleanIPAddress("192.168.1.1") // returns "192.168.1.1"
func Conflict ¶
Conflict menulis 409 Conflict error response. Berguna untuk requests yang conflict dengan state saat ini (contoh: duplicate email).
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message
- errors: optional map dari field names ke error messages
Returns:
- error: error jika encoding JSON gagal
Example:
Conflict(w, "Email sudah terdaftar", map[string]string{
"email": "Email ini sudah digunakan oleh pengguna lain",
})
func ContainsDigit ¶
ContainsDigit mengecek apakah string contains digits (0-9). Berguna untuk password validation dan number checking.
Parameters:
- s: string yang akan dicek
Returns:
- bool: true jika ada digits, false sebaliknya
Example:
ContainsDigit("Hello123") // returns true
ContainsDigit("Hello") // returns false
func ContainsLowercase ¶
ContainsLowercase mengecek apakah string contains lowercase letters (a-z). Berguna untuk password validation dan character set checking.
Parameters:
- s: string yang akan dicek
Returns:
- bool: true jika ada lowercase letters, false sebaliknya
Example:
ContainsLowercase("Hello") // returns true
ContainsLowercase("HELLO") // returns false
func ContainsRune ¶
ContainsRune mengecek apakah string contains any rune yang match predicate function. Generic helper untuk custom character checking dengan flexible predicates.
Parameters:
- s: string yang akan dicek
- predicate: function yang return true untuk matching runes
Returns:
- bool: true jika ada rune yang match, false sebaliknya
Example:
ContainsRune("Hello123", unicode.IsDigit) // returns true
ContainsRune("Hello", unicode.IsDigit) // returns false
func ContainsSpecial ¶
ContainsSpecial mengecek apakah string contains special characters. Supported special characters: !@#$%^&*()-_=+[]{}|;:',.<>?/\~` Berguna untuk password strength validation.
Parameters:
- s: string yang akan dicek
Returns:
- bool: true jika ada special characters, false sebaliknya
Example:
ContainsSpecial("Hello!123") // returns true
ContainsSpecial("Hello123") // returns false
func ContainsUppercase ¶
ContainsUppercase mengecek apakah string contains uppercase letters (A-Z). Berguna untuk password validation dan character set checking.
Parameters:
- s: string yang akan dicek
Returns:
- bool: true jika ada uppercase letters, false sebaliknya
Example:
ContainsUppercase("Hello") // returns true
ContainsUppercase("hello") // returns false
func CreatePasswordResetTokensTable ¶
CreatePasswordResetTokensTable membuat password_reset_tokens table.
func CreateRateLimitsTable ¶
CreateRateLimitsTable membuat tabel UNLOGGED untuk rate limiting.
func CreateRefreshTokensTable ¶
CreateRefreshTokensTable membuat refresh_tokens table.
func CreateTokenBlocklistTable ¶
CreateTokenBlocklistTable membuat tabel UNLOGGED untuk token blocklist.
func Created ¶
func Created(w http.ResponseWriter, data interface{}) error
Created menulis 201 Created response dengan data. Berguna untuk successful POST requests yang membuat resource baru.
Parameters:
- w: http.ResponseWriter untuk menulis response
- data: resource baru yang dibuat
Returns:
- error: error jika encoding JSON gagal
Example:
user := User{ID: 1, Name: "John"}
Created(w, user) // 201 Created
func DetectContentType ¶
DetectContentType mendeteksi MIME content type file berdasarkan extension-nya.
Fungsi melakukan case-insensitive extension matching terhadap map komprehensif dari MIME types yang diketahui. Mengembalikan MIME type string yang sesuai untuk extension file, atau "application/octet-stream" jika extension tidak diketahui.
Kategori file yang didukung:
- Images: JPEG, PNG, GIF, WebP, SVG, ICO, TIFF, BMP
- Documents: PDF, Word (DOC/DOCX), Excel (XLS/XLSX), PowerPoint (PPT/PPTX), ODF formats
- Text & Code: TXT, CSV, HTML, CSS, JavaScript, JSON, XML, YAML, Markdown, TypeScript, etc.
- Archives: ZIP, RAR, 7Z, TAR, GZIP, BZIP2, etc.
- Video: MP4, AVI, MOV, WMV, WebM, MPEG, MKV, FLV
- Audio: MP3, WAV, OGG, FLAC, M4A, AAC
- Web Fonts: WOFF, WOFF2, TTF, OTF, EOT
- Others: EPUB, TORRENT, etc.
Parameter:
filename - Nama file (dapat include path, extension di-extract otomatis)
Return:
MIME type string dalam format "type/subtype" (misal: "image/jpeg", "text/plain"). Mengembalikan "application/octet-stream" sebagai fallback untuk extension yang tidak diketahui.
Contoh:
DetectContentType("photo.jpg") // Mengembalikan "image/jpeg"
DetectContentType("document.pdf") // Mengembalikan "application/pdf"
DetectContentType("script.js") // Mengembalikan "application/javascript"
DetectContentType("unknown.xyz") // Mengembalikan "application/octet-stream"
DetectContentType("/path/to/file.png") // Mengembalikan "image/png" (path di-handle otomatis)
func DropPasswordResetTokensTable ¶
DropPasswordResetTokensTable menghapus password_reset_tokens table.
func DropRateLimitsTable ¶
DropRateLimitsTable menghapus tabel rate limits.
func DropRefreshTokensTable ¶
DropRefreshTokensTable menghapus refresh_tokens table.
func DropTokenBlocklistTable ¶
DropTokenBlocklistTable menghapus tabel token blocklist.
func Forbidden ¶
func Forbidden(w http.ResponseWriter, message string) error
Forbidden menulis 403 Forbidden error response. Berguna untuk authenticated requests yang tidak punya permission untuk access resource.
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message
Returns:
- error: error jika encoding JSON gagal
Example:
Forbidden(w, "Anda tidak memiliki permission untuk access resource ini")
func GenerateCSRFToken ¶
GenerateCSRFToken menghasilkan token CSRF baru dengan secure random bytes. Token di-encode sebagai hex string dengan specified length. Token ini harus disimpan di cookie dan dikirim di request header atau form untuk verification.
Parameters:
- length: jumlah random bytes untuk generate (contoh: 32)
Returns:
- string: hex-encoded CSRF token
- error: error jika random byte generation gagal
Example:
token, err := GenerateCSRFToken(32)
if err != nil {
return err
}
SetCSRFToken(w, token, csrfConfig)
func GenerateSecureToken ¶
GenerateSecureToken menghasilkan token random yang cryptographically secure. Token di-generate menggunakan crypto/rand dan di-encode sebagai hex string. Berguna untuk session tokens, API keys, CSRF tokens, password reset tokens, dll.
Parameters:
- length: jumlah bytes random untuk generate (contoh: 32)
Returns:
- string: hex-encoded token string
- error: error jika random generation gagal
Example:
token, err := GenerateSecureToken(32)
if err != nil {
return err
}
// token adalah hex string dengan panjang 64 (32 bytes * 2)
func GenerateTokenHash ¶
GenerateTokenHash membuat hash dari token untuk disimpan di database. Menggunakan bcrypt hashing untuk keamanan, bukan actual token.
Parameters:
- token: token string yang akan di-hash
Returns:
- string: hashed token yang bisa disimpan di database
Example:
tokenHash := GenerateTokenHash(refreshToken) // store tokenHash in database instead of actual token
func GetAuthToken ¶
GetAuthToken mengekstrak JWT token dari Authorization header. Mengharapkan format: "Bearer <token>" Returns token dan boolean indicating apakah token ditemukan dan valid format.
Parameters:
- r: *http.Request request yang di-check Authorization headernya
Returns:
- string: JWT token string (tanpa "Bearer" prefix)
- bool: true jika token valid format, false jika tidak ada atau invalid format
Example:
token, ok := GetAuthToken(req)
if !ok {
return JsonError(w, 401, "Token tidak ditemukan", nil)
}
userID, err := jwtManager.VerifyAccessToken(token)
func GetCSRFToken ¶
GetCSRFToken mengekstrak CSRF token dari request dengan mencek multiple sources. Cek dilakukan dalam urutan: header (X-CSRF-Token), form data (_csrf field). Returns empty string jika token tidak ditemukan di manapun. Header check diprioritaskan untuk API requests, form data untuk traditional forms.
Parameters:
- r: *http.Request yang akan di-check token-nya
- headerName: nama header untuk cek CSRF token (contoh: X-CSRF-Token)
Returns:
- string: CSRF token jika ditemukan, empty string jika tidak ada
Example:
token := GetCSRFToken(req, "X-CSRF-Token")
if token == "" {
return JsonError(w, 400, "Token CSRF diperlukan", nil)
}
func GetClaims ¶
GetClaims mengambil custom claims dari request context jika user terotentikasi. Memeriksa apakah user mengimplementasikan method GetClaims() map[string]interface{}.
Parameters:
- r: *http.Request request yang akan diperiksa
Returns:
- map[string]interface{}: map claims, atau nil jika tidak ada atau user tidak punya claims
func GetClientIP ¶
GetClientIP mengekstrak client IP address dari HTTP request. Mengecek X-Forwarded-For, X-Real-IP, X-Forwarded headers (untuk proxy scenarios). Falls back ke RemoteAddr jika headers tidak ada. Menangani IPv4 dan IPv6 formats dengan port numbers.
Parameters:
- r: *http.Request yang berisi client information
Returns:
- string: client IP address string (IPv4 atau IPv6 format tanpa port)
Example:
clientIP := GetClientIP(req) // returns "192.168.1.1" atau "::1"
func GetCookie ¶
GetCookie mengambil nilai cookie dari HTTP request berdasarkan nama. Returns empty string jika cookie tidak ditemukan.
Parameters:
- r: *http.Request yang berisi cookies
- name: nama cookie yang akan diambil
Returns:
- string: cookie value, empty string jika tidak ditemukan
Example:
sessionID := GetCookie(req, "session_id") // returns cookie value atau ""
func GetEnv ¶
GetEnv mengambil environment variable berdasarkan key. Returns empty string jika variable tidak ada.
Parameters:
- key: nama environment variable yang akan diambil
Returns:
- string: value dari environment variable, empty string jika tidak ada
Example:
port := GetEnv("PORT") // jika PORT=8080, returns "8080"
func GetEnvOrDefault ¶
GetEnvOrDefault mengambil environment variable atau return default value jika tidak ada. Useful untuk provide fallback values untuk configuration.
Parameters:
- key: nama environment variable
- defaultValue: default value jika variable tidak ada atau empty
Returns:
- string: value dari environment variable atau defaultValue
Example:
port := GetEnvOrDefault("PORT", "8080") // returns "8080" jika PORT tidak set
dbHost := GetEnvOrDefault("DB_HOST", "localhost")
func GetHeaderValue ¶
GetHeaderValue mengambil header value dari HTTP request. Header names case-insensitive (Go automatically handles this). Returns empty string jika header tidak ditemukan.
Parameters:
- r: *http.Request request yang di-check headernya
- key: nama header yang akan diambil
Returns:
- string: header value, empty string jika tidak ditemukan
Example:
contentType := GetHeaderValue(req, "Content-Type")
func GetParam ¶
GetParam mengambil single path parameter dari request. Menggunakan stdlib r.PathValue() untuk pattern {id}. Returns empty string jika parameter tidak ditemukan.
Parameters:
- r: *http.Request request yang di-check parameternya
- key: nama parameter yang akan diambil
Returns:
- string: parameter value, empty string jika tidak ditemukan
Example:
// Route: GET /users/{id}
userID := GetParam(req, "id")
func GetQueryParam ¶
GetQueryParam mengambil single query parameter dari request URL. Query parameters adalah bagian dari URL setelah "?" (contoh: ?name=value). Returns empty string jika parameter tidak ditemukan.
Parameters:
- r: *http.Request request yang di-check query parameternya
- key: nama query parameter yang akan diambil
Returns:
- string: query parameter value, empty string jika tidak ditemukan
Example:
page := GetQueryParam(req, "page") // dari URL: /users?page=2
func GetQueryParams ¶
GetQueryParams mengambil multiple query parameters dari request URL. Berguna untuk mengambil beberapa query parameters sekaligus. Returns map dengan empty string values untuk parameters yang tidak ditemukan.
Parameters:
- r: *http.Request request yang di-check query parameternya
- keys: variadic list dari query parameter names yang akan diambil
Returns:
- map[string]string: map dari parameter names ke values
Example:
params := GetQueryParams(req, "page", "limit", "sort") page := params["page"]
func GetRequestID ¶
GetRequestID mengambil request ID dari context. Returns empty string jika request ID tidak ditemukan. Gunakan value ini untuk logging dan request tracing.
Parameters:
- r: *http.Request request yang di-check contextnya
Returns:
- string: request ID, empty string jika tidak ada
Example:
requestID := GetRequestID(req)
logger.Info("Processing request", "request_id", requestID)
func HashPassword ¶
HashPassword melakukan hash password menggunakan bcrypt algorithm. Menggunakan BcryptCost constant untuk set hashing difficulty level.
Parameters:
- password: plaintext password yang akan di-hash
Returns:
- string: hashed password yang bisa disimpan di database
- error: error jika hashing gagal
Example:
hashedPassword, err := HashPassword("myPassword123!")
if err != nil {
return err
}
func InternalServerError ¶
func InternalServerError(w http.ResponseWriter, message string) error
InternalServerError menulis 500 Internal Server Error response. Berguna untuk unexpected server errors. Jangan expose detailed error information ke client untuk security.
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message yang aman untuk dikirim ke client
Returns:
- error: error jika encoding JSON gagal
Example:
InternalServerError(w, "Terjadi kesalahan pada server")
func IsAppError ¶
IsAppError mengecek apakah error adalah AppError instance. Berguna untuk type checking sebelum mengakses AppError-specific fields. Gunakan sebelum AsAppError untuk type assertion yang aman.
Parameters:
- err: error yang akan di-check tipenya
Returns:
- bool: true jika error adalah AppError, false jika tipe lain
Example:
if IsAppError(err) {
appErr, _ := AsAppError(err)
JsonAppError(w, appErr)
}
func IsHexChar ¶
IsHexChar mengecek apakah byte adalah valid hex digit (0-9, a-f, A-F). Berguna untuk validasi hex string seperti hash, color codes, dll.
Parameters:
- char: byte character yang akan dicek
Returns:
- bool: true jika char adalah hex digit, false sebaliknya
Example:
IsHexChar('A') // returns true
IsHexChar('5') // returns true
IsHexChar('G') // returns false
func IsSafeHttpMethod ¶
IsSafeHttpMethod mengecek apakah HTTP method adalah safe (tidak mengubah state). Safe methods: GET, HEAD, OPTIONS (tidak memiliki side effects). Berguna untuk CSRF protection, caching, dan conditional logic.
Parameters:
- method: HTTP method string (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
Returns:
- bool: true jika method adalah safe, false sebaliknya
Example:
IsSafeHttpMethod("GET") // returns true
IsSafeHttpMethod("POST") // returns false
IsSafeHttpMethod("OPTIONS") // returns true
func IsSafeRead ¶
IsSafeRead determines if a query is safe to route to a read replica. It uses a whitelist approach: only explicitly safe SELECT and CTE queries are allowed. Everything else (INSERT, UPDATE, Locking Reads, etc.) returns false.
func IsValidDateFormat ¶
IsValidDateFormat memvalidasi apakah string adalah valid YYYY-MM-DD format. Strict validation: harus exactly 10 characters, hyphens di positions 4 dan 7. Tidak mengvalidasi actual date validity (misalnya February 30).
Parameters:
- date: date string yang akan divalidasi
Returns:
- bool: true jika format valid YYYY-MM-DD, false sebaliknya
Example:
IsValidDateFormat("2024-01-15") // returns true
IsValidDateFormat("2024-1-15") // returns false (missing leading zero)
IsValidDateFormat("01/15/2024") // returns false (wrong separator)
func IsValidUuid ¶
IsValidUuid mengecek apakah string adalah valid UUID tanpa melakukan full parsing. Lebih efficient daripada ParseUUID jika hanya perlu validation. Validates format, length, hyphen positions, dan hex characters.
Parameters:
- s: string yang akan di-check
Returns:
- bool: true jika valid UUID format, false sebaliknya
Example:
if IsValidUuid(userID) {
uuid, _ := ParseUUID(userID)
}
func Json ¶
func Json(w http.ResponseWriter, status int, data interface{}) error
Json menulis JSON response dengan status code dan data yang diberikan. Content-Type header otomatis di-set ke "application/json". Untuk single objects, write langsung tanpa wrapper: {"id": 1, "name": "John"} Untuk arrays, write langsung tanpa wrapper: [{"id": 1, "name": "John"}]
Parameters:
- w: http.ResponseWriter untuk menulis response
- status: HTTP status code (contoh: 200, 400, 500)
- data: data yang akan di-encode sebagai JSON
Returns:
- error: error jika encoding JSON gagal
Example:
user := User{ID: 1, Name: "John", Email: "[email protected]"}
Json(w, 200, user)
func JsonAppError ¶
func JsonAppError(w http.ResponseWriter, appErr *AppError) error
JsonAppError menulis AppError sebagai JSON response. Mengekstrak status code, message, dan field errors dari AppError dan mengirimnya. Convenience function yang wrap JsonError dengan AppError data.
Parameters:
- w: http.ResponseWriter untuk menulis response
- appErr: *AppError yang berisi response data
Returns:
- error: error jika encoding JSON gagal
Example:
appErr := NewAppError("Validasi gagal", 400)
appErr.WithFieldError("email", "Email sudah terdaftar")
JsonAppError(w, appErr)
func JsonError ¶
JsonError menulis error JSON response dengan message dan optional field errors. Response format: {"message": "error message", "errors": {"field": "error message"}} Content-Type header otomatis di-set ke "application/json". Gunakan untuk standard error responses dengan field-level error details.
Parameters:
- w: http.ResponseWriter untuk menulis response
- status: HTTP status code (contoh: 400, 401, 404, 500)
- message: error message string
- errors: optional map dari field names ke error messages
Returns:
- error: error jika encoding JSON gagal
Example:
JsonError(w, 400, "Validasi gagal", map[string]string{
"email": "Email harus valid",
"password": "Password minimal 8 karakter",
})
func JsonPagination ¶
func JsonPagination(w http.ResponseWriter, status int, data interface{}, meta PaginationMeta) error
JsonPagination menulis paginated JSON response dengan data dan pagination metadata. Response format: {"data": [...], "meta": {"page": 1, "per_page": 10, "total": 100, "total_pages": 10}} Content-Type header otomatis di-set ke "application/json".
Parameters:
- w: http.ResponseWriter untuk menulis response
- status: HTTP status code
- data: data array/slice yang akan dipaginate
- meta: PaginationMeta berisi pagination information
Returns:
- error: error jika encoding JSON gagal
Example:
users := []User{{ID: 1, Name: "John"}, {ID: 2, Name: "Jane"}}
meta := PaginationMeta{Page: 1, PerPage: 10, Total: 100, TotalPages: 10}
JsonPagination(w, 200, users, meta)
func LoadEnvFile ¶
LoadEnvFile memuat variabel lingkungan dari file .env yang ditentukan. Fungsi ini membaca file baris per baris, mengabaikan komentar dan baris kosong. Variabel lingkungan hanya akan diatur jika belum ada nilainya.
Parameters:
- filename: Path lengkap ke file .env.
Returns:
- error: Error jika file tidak dapat dibuka atau dibaca. Mengembalikan `nil` jika file tidak ada.
Example:
if err := LoadEnvFile(".env.development"); err != nil {
log.Fatalf("Gagal memuat file .env: %v", err)
}
func LoadEnvFileFromPath ¶
LoadEnvFileFromPath memuat variabel lingkungan dari file .env di dalam direktori yang ditentukan. Ini adalah fungsi pembantu yang membangun path ke .env dan memanggil LoadEnvFile.
Parameters:
- dir: Direktori tempat file .env berada.
Returns:
- error: Error yang sama seperti LoadEnvFile.
Example:
// Memuat .env dari direktori saat ini
LoadEnvFileFromPath(".")
// Memuat .env dari direktori konfigurasi
LoadEnvFileFromPath("./config")
func MiddlewareToHandler ¶
func MiddlewareToHandler(m MiddlewareFunc, next http.Handler) http.Handler
MiddlewareToHandler mengkonversi MiddlewareFunc menjadi http.Handler. Berguna untuk menggunakan middleware dengan standard http patterns dan packages. Wrapper next parameter memungkinkan middleware untuk call next handler jika diperlukan.
Parameters:
- m: MiddlewareFunc yang akan dikonversi
- next: http.Handler yang akan dijalankan setelah middleware
Returns:
- http.Handler: handler yang mengimplementasikan http.Handler interface
Example:
handler := MiddlewareToHandler(LoggerMiddleware, http.DefaultServeMux)
http.ListenAndServe(":8080", handler)
func NoContent ¶
func NoContent(w http.ResponseWriter) error
NoContent menulis 204 No Content response. Berguna untuk successful requests yang tidak mengembalikan data (contoh: DELETE, PUT tanpa response body). Tidak ada response body yang dikirim.
Parameters:
- w: http.ResponseWriter untuk menulis response
Returns:
- error: selalu nil
Example:
NoContent(w) // 204 No Content
func NotFound ¶
func NotFound(w http.ResponseWriter, message string) error
NotFound menulis 404 Not Found error response. Berguna untuk requests ke resource yang tidak ada.
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message
Returns:
- error: error jika encoding JSON gagal
Example:
NotFound(w, "User dengan ID 123 tidak ditemukan")
func OK ¶
func OK(w http.ResponseWriter, data interface{}) error
OK menulis 200 OK response dengan data. Berguna untuk successful GET atau update requests yang mengembalikan data.
Parameters:
- w: http.ResponseWriter untuk menulis response
- data: response data
Returns:
- error: error jika encoding JSON gagal
Example:
users := []User{{ID: 1}, {ID: 2}}
OK(w, users) // 200 OK
func ParseEnvBool ¶
ParseEnvBool mengurai string boolean dari variabel lingkungan. Nilai yang dikenali sebagai `true` (tidak case-sensitive) adalah "true", "yes", "1", "on". Semua nilai lain dianggap `false`.
Parameters:
- s: Nilai string untuk diurai.
Returns:
- bool: Nilai boolean yang diurai.
Example:
debugMode := ParseEnvBool("true") // returns true
featureOn := ParseEnvBool("1") // returns true
disabled := ParseEnvBool("false") // returns false
func ParseEnvDuration ¶
ParseEnvDuration mengurai string durasi dari variabel lingkungan.
Parameters:
- value: Nilai string untuk diurai (misalnya, "30s", "15m", "1h").
Returns:
- time.Duration: Nilai durasi yang diurai. Mengembalikan 0 jika input kosong.
- error: Error jika string durasi tidak valid.
Example:
timeout, err := ParseEnvDuration("30s") // returns 30 * time.Second, nil
invalid, err := ParseEnvDuration("abc") // returns 0, error
func ParseEnvInt ¶
ParseEnvInt mengurai string integer dari variabel lingkungan. Spasi di awal dan akhir akan diabaikan.
Parameters:
- value: Nilai string untuk diurai.
Returns:
- int: Nilai integer yang diurai. Mengembalikan 0 jika input kosong.
- error: Error jika string integer tidak valid.
Example:
port, err := ParseEnvInt(" 8080 ") // returns 8080, nil
invalid, err := ParseEnvInt("abc") // returns 0, error
func PathMatches ¶
PathMatches mengecek apakah path match any pattern dalam list. Supports simple glob patterns dengan * wildcard. Pattern: "*" cocok semua path, "/webhooks/*" cocok /webhooks/anything.
Parameters:
- path: URL path yang akan dicek
- patterns: list pattern untuk matching (exact atau glob)
Returns:
- bool: true jika path cocok dengan any pattern, false sebaliknya
Example:
PathMatches("/webhooks/github", []string{"/webhooks/*"}) // returns true
PathMatches("/admin", []string{"/admin", "/api/*"}) // returns true
PathMatches("/users", []string{"/admin/*"}) // returns false
func Register ¶
func Register(m Migration)
Register mendaftarkan migration ke global registry. Fungsi ini biasanya dipanggil di dalam fungsi init() pada file migration.
func RegisterMIMEType ¶
func RegisterMIMEType(ext, mimeType string)
RegisterMIMEType mendaftarkan custom MIME type untuk file extension.
Ini memungkinkan Anda menambah support untuk custom atau proprietary file types di luar daftar built-in. Custom MIME types dicek terlebih dahulu sebelum built-in types, jadi Anda dapat override default MIME types jika diperlukan.
Fungsi adalah thread-safe dan dapat dipanggil concurrently dari multiple goroutines.
Parameter:
ext - File extension termasuk dot (misal: ".custom", ".myformat") mimeType - MIME type string (misal: "application/x-custom")
Contoh:
RegisterMIMEType(".webmanifest", "application/manifest+json")
RegisterMIMEType(".wasm", "application/wasm")
RegisterMIMEType(".custom", "application/x-custom")
func RollbackMigration ¶
func RollbackMigration(db *PostgresDatabase, migration Migration) error
RollbackMigration membatalkan/rollback migration tertentu dengan menjalankan Down function. Menghapus record migration dari migrations table.
Parameters:
- db: PostgresDatabase instance untuk execute rollback queries
- migration: Migration struct yang akan di-rollback
Returns:
- error: error jika Down function gagal atau gagal menghapus migration record
Example:
err := RollbackMigration(db, migration)
if err != nil {
log.Fatal(err)
}
func RunMigrations ¶
func RunMigrations(db *PostgresDatabase, migrations []Migration) error
RunMigrations menjalankan semua pending migrations yang belum pernah dijalankan. Membuat migrations table jika belum ada, kemudian menjalankan migrations yang baru. Semua migrations di-log menggunakan slog.
Parameters:
- db: PostgresDatabase instance untuk execute migration queries
- migrations: slice dari Migration structs yang berisi Up dan Down functions
Returns:
- error: error jika pembuatan migrations table gagal atau ada migration yang error
Example:
err := RunMigrations(db, migrations)
if err != nil {
log.Fatal(err)
}
func ServeFile ¶
func ServeFile(w http.ResponseWriter, filename, filePath string, statusCode int) error
ServeFile melayani file dari filesystem dengan Content-Type header yang tepat.
Fungsi helper ini mengirim file ke client dengan MIME type yang sesuai yang terdeteksi dari file extension. File dilayani sebagai attachment (download), berarti browser akan meminta user untuk download file daripada menampilkannya secara inline.
Fungsi otomatis mendeteksi Content-Type header yang benar berdasarkan file extension menggunakan DetectContentType().
Parameter:
w - http.ResponseWriter untuk menulis response ke filename - Filename original (digunakan untuk content-type detection) filePath - Path file sebenarnya di filesystem statusCode - HTTP status code (biasanya http.StatusOK atau http.StatusCreated)
Return:
Error jika file tidak dapat dibuka atau dibaca, atau nil jika sukses.
Contoh:
ServeFile(w, "document.pdf", "/tmp/document.pdf", http.StatusOK) ServeFile(w, "report.xlsx", "/data/reports/q1.xlsx", http.StatusOK)
Catatan: Gunakan ServeFileInline() jika Anda ingin file ditampilkan di browser daripada diunduh.
func ServeFileInline ¶
func ServeFileInline(w http.ResponseWriter, filename, filePath string, statusCode int) error
ServeFileInline melayani file dari filesystem untuk inline display.
Fungsi helper ini mengirim file ke client dengan MIME type yang sesuai yang terdeteksi dari file extension. File dilayani sebagai inline content, artinya browser akan mencoba menampilkan file (jika tipe yang didukung seperti images, PDFs, atau videos) daripada meminta download.
Fungsi otomatis mendeteksi Content-Type header yang benar berdasarkan file extension menggunakan DetectContentType().
Parameter:
w - http.ResponseWriter untuk menulis response ke filename - Filename original (digunakan untuk content-type detection) filePath - Path file sebenarnya di filesystem statusCode - HTTP status code (biasanya http.StatusOK)
Return:
Error jika file tidak dapat dibuka atau dibaca, atau nil jika sukses.
Contoh:
ServeFileInline(w, "image.jpg", "/images/photo.jpg", http.StatusOK) ServeFileInline(w, "document.pdf", "/pdfs/report.pdf", http.StatusOK) ServeFileInline(w, "video.mp4", "/videos/tutorial.mp4", http.StatusOK)
Catatan: Gunakan ServeFile() jika Anda ingin file diunduh daripada ditampilkan.
func SetCSRFToken ¶
func SetCSRFToken(w http.ResponseWriter, token string, config CSRFConfig)
SetCSRFToken menyimpan CSRF token dalam cookie response. Cookie di-set dengan HttpOnly=false sehingga accessible dari JavaScript. SameSite=Lax digunakan untuk prevent CSRF attacks sambil tetap allow cross-site form submissions.
Parameters:
- w: http.ResponseWriter untuk menulis cookie
- token: CSRF token string yang akan disimpan
- config: CSRFConfig yang berisi cookie configuration
Example:
token, _ := GenerateCSRFToken(32) SetCSRFToken(w, token, csrfConfig)
func SetContentType ¶
func SetContentType(w http.ResponseWriter, contentType string)
SetContentType menetapkan Content-Type header untuk response. Berguna untuk mengset content type custom selain application/json.
Parameters:
- w: http.ResponseWriter untuk menulis header
- contentType: content type string (contoh: text/plain, text/html, application/xml)
Example:
SetContentType(w, "text/html")
w.Write([]byte("<html><body>Hello</body></html>"))
func SetCookie ¶
func SetCookie(w http.ResponseWriter, cookie *http.Cookie)
SetCookie menetapkan response cookie. Cookie akan dikirim ke client dan disimpan untuk subsequent requests.
Parameters:
- w: http.ResponseWriter untuk menulis cookie
- cookie: *http.Cookie yang akan dikirim
Example:
cookie := &http.Cookie{
Name: "session_id",
Value: "abc123",
HttpOnly: true,
Secure: true,
MaxAge: 3600,
}
SetCookie(w, cookie)
func SetHeader ¶
func SetHeader(w http.ResponseWriter, key, value string)
SetHeader menetapkan single response header. Header dapat di-set sebelum WriteHeader/SetStatus dipanggil.
Parameters:
- w: http.ResponseWriter untuk menulis header
- key: nama header (contoh: X-Custom-Header, Authorization)
- value: header value
Example:
SetHeader(w, "X-Request-ID", "12345") SetHeader(w, "Cache-Control", "no-cache")
func SetHeaders ¶
func SetHeaders(w http.ResponseWriter, headers map[string]string)
SetHeaders menetapkan multiple response headers sekaligus. Convenience function untuk mengset banyak headers dalam satu call. Headers dapat di-set sebelum WriteHeader/SetStatus dipanggil.
Parameters:
- w: http.ResponseWriter untuk menulis headers
- headers: map[string]string dari header names ke values
Example:
SetHeaders(w, map[string]string{
"X-Request-ID": "12345",
"X-Version": "1.0",
"Cache-Control": "no-cache",
})
func SetRequestID ¶
SetRequestID menyimpan unique request ID ke dalam context. Request ID berguna untuk logging dan tracing requests across systems. Biasanya di-set oleh logger middleware di awal request processing.
Parameters:
- r: *http.Request request yang akan diupdate contextnya
- requestID: string unique identifier untuk request ini
Returns:
- *http.Request: request baru dengan requestID disimpan di context
Example:
requestID := GenerateSecureToken(16) req = SetRequestID(req, requestID)
func SetStatus ¶
func SetStatus(w http.ResponseWriter, status int)
SetStatus menulis HTTP response status code. Harus dipanggil sebelum menulis response body. Setelah status ditulis, tidak bisa diubah lagi.
Parameters:
- w: http.ResponseWriter untuk menulis status
- status: HTTP status code (contoh: 200, 400, 500)
Example:
SetStatus(w, 201) // Created
w.Write([]byte(`{"id": 1}`))
func SetUser ¶
func SetUser(r *http.Request, user Authenticatable) *http.Request
SetUser menyimpan user object ke dalam request context. Berguna untuk menyimpan authenticated user info yang dapat diakses di handlers. Returns request baru dengan updated context.
Parameters:
- r: *http.Request request yang akan diupdate contextnya
- user: Authenticatable object yang akan disimpan
Returns:
- *http.Request: request baru dengan user disimpan di context
Example:
req = SetUser(req, user) user, ok := GetUser(req)
func SimpleGlobMatch ¶
SimpleGlobMatch mengimplementasikan basic glob matching dengan * wildcard saja. Supports exact match dan trailing wildcard pattern. Pattern "*" cocok semua path, "/path/*" cocok /path/anything dan /path/anything/nested.
Parameters:
- path: URL path yang akan dicek
- pattern: glob pattern untuk matching
Returns:
- bool: true jika path cocok dengan pattern, false sebaliknya
Example:
SimpleGlobMatch("/webhooks/github", "/webhooks/*") // returns true
SimpleGlobMatch("/admin/users", "/admin") // returns false
SimpleGlobMatch("/anything", "*") // returns true
func StartServer ¶
StartServer starts the HTTP server with graceful shutdown support. It listens on the specified port and serves requests using the provided handler. When a SIGINT or SIGTERM signal is received (or context cancelled), it will attempt to shut down the server gracefully.
Parameters:
- ctx: context to control the server (e.g., from main)
- config: ServerConfig containing port and timeouts.
- handler: http.Handler to serve (usually the Router).
Returns:
- error: error if server fails to start or shutdown error.
Example:
ctx := context.Background()
config := dim.ServerConfig{Port: "8080"}
router := dim.NewRouter()
// ... register routes ...
if err := dim.StartServer(ctx, config, router); err != nil {
log.Fatal(err)
}
func StripComments ¶
StripComments removes SQL comments (-- and /* */) and whitespace from the start of the string. This is an internal helper exposed for testing purposes.
func ToCamelCase ¶
ToCamelCase converts snake_case or anything to CamelCase (PascalCase) example: create_users -> CreateUsers
func TooManyRequests ¶
func TooManyRequests(w http.ResponseWriter, retryAfterSeconds int) error
TooManyRequests menulis 429 Too Many Requests response. Mengatur header Retry-After dan mengirim pesan error standar. Berguna untuk rate limiting middleware.
Parameters:
- w: http.ResponseWriter untuk menulis response
- retryAfterSeconds: jumlah detik yang harus ditunggu client sebelum retry
Returns:
- error: error jika encoding JSON gagal
Example:
TooManyRequests(w, 60)
func Unauthorized ¶
func Unauthorized(w http.ResponseWriter, message string) error
Unauthorized menulis 401 Unauthorized error response. Berguna untuk requests tanpa authentication atau dengan invalid credentials.
Parameters:
- w: http.ResponseWriter untuk menulis response
- message: error message
Returns:
- error: error jika encoding JSON gagal
Example:
Unauthorized(w, "Token tidak valid atau telah expired")
func UploadFiles ¶
func UploadFiles( ctx context.Context, disk storage.Storage, files []*multipart.FileHeader, opts ...UploadOption, ) ([]string, error)
UploadFiles meng-upload multiple file dengan validasi dan pemrosesan concurrent opsional.
Parameter:
- ctx: Context untuk cancellation dan deadlines
- disk: Storage backend (mengimplementasikan interface storage.Storage)
- files: Slice multipart file headers untuk di-upload
- opts: Konfigurasi opsional (WithPath, WithMaxFileSize, dll.)
Return:
- []string: Path file yang berhasil di-upload
- error: Error pertama yang ditemukan (lihat field Errors untuk complete error map)
Validasi:
- Jumlah file dicek terhadap batas maxFiles
- Ekstensi file divalidasi terhadap allowedExts
- Ukuran file dicek terhadap batas maxFileSize
- Content-type divalidasi untuk cocok dengan ekstensi
- Nama file dan path disanitisasi terhadap serangan traversal
Saat Error:
- File yang berhasil di-upload dibersihkan dari storage
- Mengembalikan error dengan jumlah file yang gagal
- Gunakan pesan error untuk menentukan file mana yang gagal
Contoh (Sequential):
paths, err := dim.UploadFiles(
ctx, disk, formFiles,
dim.WithPath("/uploads"),
dim.WithMaxFileSize(10 << 20),
dim.WithAllowedExts(".jpg", ".png", ".pdf"),
)
if err != nil {
log.Printf("Upload failed: %v", err)
return
}
Contoh (Concurrent):
paths, err := dim.UploadFiles(
ctx, disk, formFiles,
dim.WithConcurrent(true),
dim.WithMaxWorkers(5),
dim.WithLogger(logger),
)
func ValidatePasswordStrength ¶
ValidatePasswordStrength memvalidasi password strength menggunakan default rules. Merupakan convenience function yang membuat validator dan langsung validate.
Parameters:
- password: password string yang akan divalidasi
Returns:
- error: AppError jika password tidak memenuhi strength requirements
Example:
err := ValidatePasswordStrength(password)
func VerifyPassword ¶
VerifyPassword memverifikasi plaintext password terhadap hash yang tersimpan. Menggunakan bcrypt untuk aman time-constant comparison.
Parameters:
- hashedPassword: hashed password dari database
- password: plaintext password untuk diverifikasi
Returns:
- error: error jika password tidak cocok dengan hash
Example:
err := VerifyPassword(storedHash, providedPassword)
if err != nil {
return "password tidak valid"
}
func VerifyTokenHash ¶
VerifyTokenHash memverifikasi token terhadap hash yang tersimpan di database. Menggunakan bcrypt compare untuk aman.
Parameters:
- hash: hashed token dari database
- token: actual token string untuk diverifikasi
Returns:
- error: error jika token tidak cocok dengan hash
Example:
err := VerifyTokenHash(storedHash, token)
if err != nil {
return "token tidak valid"
}
Types ¶
type AmountRange ¶
AmountRange: Floating point amount range Example: "100.50" or "100.50,500.75"
type AppError ¶
type AppError struct {
Message string `json:"message"`
StatusCode int `json:"-"`
Errors map[string]string `json:"errors,omitempty"`
}
AppError represents an application error with optional field-specific validation errors
func AsAppError ¶
AsAppError mengkonversi error menjadi AppError jika possible. Type-safe conversion dengan ok flag untuk checking apakah conversion berhasil. Returns nil dan false jika error bukan AppError type. Gunakan dengan IsAppError untuk safe type conversion.
Parameters:
- err: error yang akan dikonversi menjadi AppError
Returns:
- *AppError: AppError pointer jika conversion berhasil, nil jika tidak
- bool: true jika conversion berhasil, false jika error bukan AppError type
Example:
appErr, ok := AsAppError(err)
if ok {
// appErr is safe to use
appErr.WithFieldError("field", "error message")
}
func NewAppError ¶
NewAppError membuat AppError baru dengan message dan HTTP status code. Status code digunakan untuk menentukan HTTP response status saat error di-return ke client. Useful untuk error handling yang consistent dengan HTTP semantics.
Parameters:
- message: error message string dalam bahasa Indonesia
- statusCode: HTTP status code (contoh: 400, 401, 404, 500)
Returns:
- *AppError: AppError instance dengan empty field errors
Example:
appErr := NewAppError("Validasi gagal", 400)
appErr.WithFieldError("email", "Email harus valid")
return appErr
func (*AppError) Error ¶
Error mengimplementasikan error interface. Mengembalikan string representation dari error dengan message dan field errors jika ada. Format: "message" atau "message: {field: error_message, ...}" jika ada field errors.
Returns:
- string: error message string
Example:
appErr := NewAppError("Validasi gagal", 400)
appErr.WithFieldError("email", "Email tidak valid")
fmt.Println(appErr.Error()) // Output: Validasi gagal: map[email:Email tidak valid]
func (*AppError) WithFieldError ¶
WithFieldError menambahkan field-specific error ke AppError. Berguna untuk validation errors yang related ke specific fields. Mendukung method chaining untuk menambahkan multiple field errors. Jika field sudah ada, akan overwrite dengan message baru.
Parameters:
- field: nama field yang memiliki error
- message: error message untuk field ini
Returns:
- *AppError: pointer to AppError untuk method chaining
Example:
appErr := NewAppError("Validasi gagal", 400).
WithFieldError("email", "Email harus valid").
WithFieldError("password", "Password minimal 8 karakter")
func (*AppError) WithFieldErrors ¶
WithFieldErrors menambahkan multiple field-specific errors ke AppError sekaligus. Convenience function untuk menambahkan banyak field errors dalam satu call. Mendukung method chaining untuk kombinasi dengan WithFieldError. Jika fields sudah ada, akan overwrite dengan messages baru.
Parameters:
- errors: map[string]string dari field names ke error messages
Returns:
- *AppError: pointer to AppError untuk method chaining
Example:
appErr := NewAppError("Validasi gagal", 400).
WithFieldErrors(map[string]string{
"email": "Email harus valid",
"password": "Password minimal 8 karakter",
})
type AuthService ¶
type AuthService struct {
// contains filtered or unexported fields
}
AuthService menangani operasi otentikasi seperti login, register, dan manajemen token.
func NewAuthService ¶
func NewAuthService( userStore AuthUserStore, tokenStore TokenStore, blocklist TokenBlocklist, jwtConfig *JWTConfig, ) (*AuthService, error)
NewAuthService membuat instance AuthService baru.
func (*AuthService) Login ¶
Login mengotentikasi pengguna menggunakan email dan password. Mengembalikan access token dan refresh token jika kredensial valid.
Parameters:
- ctx: context request
- email: email pengguna
- password: password pengguna
Returns:
- string: access token
- string: refresh token
- error: error jika kredensial tidak valid atau terjadi kesalahan server
func (*AuthService) Logout ¶
func (s *AuthService) Logout(ctx context.Context, refreshTokenStr string) error
Logout mengeluarkan pengguna dengan membatalkan (revoke) refresh token mereka. Karena kita menggunakan Session ID (sid), kita juga mem-blacklist sid tersebut agar Access Token yang masih hidup (yang memiliki sid sama) ikut tidak valid.
func (*AuthService) RefreshToken ¶
func (s *AuthService) RefreshToken(ctx context.Context, refreshTokenStr string) (string, string, error)
RefreshToken memperbarui access token menggunakan refresh token yang valid. Method ini akan membatalkan refresh token lama dan mengeluarkan pasangan token baru (Token Rotation).
Parameters:
- ctx: context request
- refreshTokenStr: string refresh token yang dikirim oleh client
Returns:
- string: access token baru
- string: refresh token baru
- error: error jika token tidak valid, kadaluarsa, atau sudah dibatalkan
func (*AuthService) RequestPasswordReset ¶
RequestPasswordReset memproses permintaan reset password. Akan membuat token reset dan menyimpannya (pengiriman email dilakukan oleh pemanggil). Mengembalikan token reset yang belum di-hash agar bisa dikirim ke user.
func (*AuthService) ResetPassword ¶
func (s *AuthService) ResetPassword(ctx context.Context, resetTokenStr, newPassword string) error
ResetPassword mereset password pengguna menggunakan token reset yang valid. Setelah berhasil, semua refresh token pengguna akan dihapus untuk alasan keamanan.
func (*AuthService) WithClaimsProvider ¶
func (s *AuthService) WithClaimsProvider(provider ClaimsProvider) *AuthService
WithClaimsProvider mengatur function provider untuk custom claims dan mengembalikan instance service. Method ini menggunakan pola chaining untuk memudahkan konfigurasi.
type AuthUserStore ¶
type AuthUserStore interface {
FindByEmail(ctx context.Context, email string) (Authenticatable, error)
FindByID(ctx context.Context, id string) (Authenticatable, error)
Update(ctx context.Context, user Authenticatable) error
}
AuthUserStore mendefinisikan interface yang dibutuhkan oleh AuthService untuk berinteraksi dengan penyimpanan data pengguna.
type Authenticatable ¶
type Authenticatable interface {
GetID() string
GetEmail() string
GetPassword() string
SetPassword(string)
}
Authenticatable merepresentasikan entitas pengguna yang dapat diotentikasi. Interface ini memungkinkan framework untuk berinteraksi dengan model User apa pun.
func GetUser ¶
func GetUser(r *http.Request) (Authenticatable, bool)
GetUser mengambil user object dari request context. Returns user dan boolean indicating apakah user ada di context. Returns nil user dan false jika user tidak ditemukan.
Parameters:
- r: *http.Request request yang di-check contextnya
Returns:
- Authenticatable: user object dari context, nil jika tidak ada
- bool: true jika user ada, false jika tidak ada
Example:
user, ok := GetUser(req)
if !ok {
return JsonError(w, 401, "Tidak authorized", nil)
}
type CORSConfig ¶
type CORSConfig struct {
AllowedOrigins []string
AllowedMethods []string
AllowedHeaders []string
AllowCredentials bool
MaxAge int
}
CORSConfig holds CORS configuration
type CSRFConfig ¶
type CSRFConfig struct {
Enabled bool
ExemptPaths []string
TokenLength int
CookieName string
HeaderName string
}
CSRFConfig holds CSRF configuration
type ClaimsProvider ¶
type ClaimsProvider func(ctx context.Context, user Authenticatable) (map[string]interface{}, error)
ClaimsProvider adalah fungsi yang mengembalikan custom claims untuk pengguna. Gunakan ini untuk menyisipkan data tambahan ke dalam JWT (seperti workspace_id, role, dll).
type Command ¶
type Command interface {
// Name mengembalikan nama command (contoh: "serve", "migrate", "route:list")
Name() string
// Description mengembalikan deskripsi singkat command untuk help text
Description() string
// Execute menjalankan logika command dengan context yang berisi dependencies
Execute(ctx *CommandContext) error
}
Command adalah interface yang harus diimplementasikan oleh semua CLI commands. Setiap command mendefinisikan nama, deskripsi, dan logika eksekusi.
type CommandContext ¶
type CommandContext struct {
// Args adalah arguments yang tidak termasuk flags (positional arguments)
Args []string
// DB adalah database instance
DB *PostgresDatabase
// Router adalah router instance
Router *Router
// Config adalah application configuration
Config *Config
// Out adalah output writer untuk stdout (default: os.Stdout)
// Digunakan untuk normal output dan testing
Out io.Writer
// Err adalah output writer untuk stderr (default: os.Stderr)
// Digunakan untuk error messages dan warnings
Err io.Writer
}
CommandContext berisi dependencies dan arguments yang dibutuhkan command saat eksekusi.
type Config ¶
type Config struct {
Server ServerConfig
JWT JWTConfig
Database DatabaseConfig
Email EmailConfig
RateLimit RateLimitConfig
CORS CORSConfig
CSRF CSRFConfig
}
Config holds all application configuration
func LoadConfig ¶
LoadConfig memuat konfigurasi aplikasi dari environment variables. Menggabungkan konfigurasi dari semua bagian (Server, JWT, Database, Email, RateLimit, CORS, CSRF).
Returns:
- *Config: struktur konfigurasi lengkap aplikasi
- error: error jika validasi konfigurasi gagal
Example:
config, err := LoadConfig()
if err != nil {
log.Fatal(err)
}
type Console ¶
type Console struct {
// contains filtered or unexported fields
}
Console adalah registry dan executor untuk CLI commands. Console mengelola semua registered commands dan menangani parsing/eksekusi.
func NewConsole ¶
func NewConsole(db *PostgresDatabase, router *Router, config *Config) *Console
NewConsole membuat instance Console baru dengan dependencies yang diperlukan.
Parameter:
- db: database instance (boleh nil jika tidak diperlukan)
- router: router instance (boleh nil jika tidak diperlukan)
- config: application config (boleh nil jika tidak diperlukan)
Mengembalikan:
- *Console: instance console yang siap digunakan
Contoh:
console := dim.NewConsole(db, router, config) console.RegisterBuiltInCommands() console.Run(os.Args[1:])
func (*Console) Register ¶
Register mendaftarkan custom command ke console. Command name harus unik, jika sudah ada akan mengembalikan error.
Parameter:
- cmd: command yang akan didaftarkan
Mengembalikan:
- error: nil jika sukses, error jika command name sudah terdaftar
Contoh:
console.Register(&MyCustomCommand{})
func (*Console) RegisterBuiltInCommands ¶
func (c *Console) RegisterBuiltInCommands()
RegisterBuiltInCommands mendaftarkan semua built-in commands. Dipanggil setelah NewConsole() untuk menambahkan commands bawaan framework.
Contoh:
console := dim.NewConsole(db, router, config) console.RegisterBuiltInCommands()
func (*Console) Run ¶
Run menjalankan command berdasarkan arguments yang diberikan. Jika args kosong, default ke command "serve". Menangani flag parsing untuk FlaggedCommand dan help (-h).
Parameter:
- args: command arguments (biasanya os.Args[1:])
Mengembalikan:
- error: nil jika sukses, error jika command tidak ditemukan atau eksekusi gagal
Contoh:
if err := console.Run(os.Args[1:]); err != nil {
log.Fatal(err)
}
type ConstraintValidator ¶
type ConstraintValidator interface {
// Name returns the constraint name (e.g., "in", "min", "max", "regex").
// Used to match constraint tags in struct fields.
// Must be unique within FilterParser's registered validators.
Name() string
// Validate validates the value(s) against the constraint.
// Called during FilterParser.Parse() for fields with matching constraint.
//
// Parameters:
// - values: slice of string values to validate (may be single element for pointer types)
// - constraint: constraint parameter from tag (e.g., "active|pending" for tag "in:active|pending")
// - fieldType: the target field type (use for type-specific validation logic)
//
// Returns:
// - nil if validation passes
// - error with descriptive message if validation fails
// - Error message appears in fp.Errors() map with key "filters[fieldName]"
Validate(values []string, constraint string, fieldType reflect.Type) error
}
ConstraintValidator defines an interface for custom constraint validation. Enables extensible validation system where users can implement custom constraints without modifying FilterParser.
Design:
- Single interface for all constraint types (extensible)
- Registered via FilterParser.RegisterConstraintValidator()
- Multiple validators per field supported (applied sequentially)
- Unknown constraints gracefully skipped (forward-compatible)
Use Cases:
- Enum validation (built-in "in" constraint)
- Min/max length constraints
- Regex pattern matching
- Custom business rule validation
- Type-specific constraints
Implementations:
- Must be thread-safe (may be used concurrently)
- Should provide clear, actionable error messages
- Can access field type for type-aware validation
Example implementation:
type RegexValidator struct {
patterns map[string]*regexp.Regexp
}
func (v *RegexValidator) Name() string { return "regex" }
func (v *RegexValidator) Validate(values []string, constraint string, _ reflect.Type) error {
pattern := v.patterns[constraint]
for _, v := range values {
if !pattern.MatchString(v) {
return fmt.Errorf("does not match pattern: %s", constraint)
}
}
return nil
}
type Database ¶
type Database interface {
Exec(ctx context.Context, query string, args ...interface{}) error
Query(ctx context.Context, query string, args ...interface{}) (Rows, error)
QueryRow(ctx context.Context, query string, args ...interface{}) Row
Begin(ctx context.Context) (pgx.Tx, error)
Close() error
}
Database is the interface for database operations
type DatabaseConfig ¶
type DatabaseConfig struct {
WriteHost string
ReadHosts []string
Port int
Database string
Username string
Password string
MaxConns int
SSLMode string // SSL mode: "disable", "require", "prefer", "allow", "verify-ca", "verify-full" (default: "disable")
RuntimeParams map[string]string // Custom runtime parameters (search_path, standard_conforming_strings, etc)
QueryExecMode string // Query execution mode: "simple" or "" (default)
}
DatabaseConfig holds database configuration
type DateRange ¶
Type aliases for common range types
DateRange: String format "YYYY-MM-DD" Example: "2024-01-15" or "2024-01-01,2024-12-31"
type ErrorResponse ¶
type ErrorResponse struct {
Message string `json:"message"`
Errors map[string]string `json:"errors,omitempty"`
}
ErrorResponse is the response structure for error responses
type FilterParser ¶
type FilterParser struct {
MaxValuesPerField int // Maximum number of values allowed per filter field (0 = unlimited)
TimestampTimezone *time.Location // Timezone for parsing timestamps (nil = UTC)
// contains filtered or unexported fields
}
FilterParser parses filter parameters from an HTTP request and sets the fields of a target struct accordingly.
func NewFilterParser ¶
func NewFilterParser(r *http.Request) *FilterParser
NewFilterParser creates a new FilterParser instance with unlimited values. Defaults:
- MaxValuesPerField: 0 (unlimited)
- TimestampTimezone: nil (UTC)
- constraintValidator: built-in validators (e.g., "in" for enums)
func (*FilterParser) Errors ¶
func (fp *FilterParser) Errors() map[string]string
Errors returns the errors encountered during parsing. Key format: "filters[fieldName]" (e.g., "filters[ids]"). Returns empty map if no errors occurred.
func (*FilterParser) HasErrors ¶
func (fp *FilterParser) HasErrors() bool
HasErrors returns true if any errors were encountered during parsing. Check this before accessing filter results.
func (*FilterParser) Parse ¶
func (fp *FilterParser) Parse(target interface{}) *FilterParser
Parse parses the filter parameters from the request and sets the fields of the target struct accordingly. Target must be a pointer to a struct with "filter" tags. Returns the receiver for method chaining.
Tag Format: "fieldName" or "fieldName,constraint1:value1,constraint2:value2" Example struct tags:
type Filters struct {
// Basic types
IDs []int64 `filter:"ids"`
Name *string `filter:"name"`
Active *bool `filter:"active"`
Tags []string `filter:"tags"`
// Enum constraint (pipe-separated allowed values)
Status *string `filter:"status,in:active|pending|archived"`
Statuses []string `filter:"statuses,in:active|pending"`
// Range types with From/To validation
Amount AmountRange `filter:"amount"` // single: "100" or range: "100,500"
Price *IntRange `filter:"price"` // integer range with optional pointer
CreatedAt TimestampRange `filter:"created_at"` // date range "2024-01-01,2024-12-31"
Date DateRange `filter:"date"` // string date range
}
Built-in Constraints:
- in:val1|val2|val3 : Enum validation for strings (pipe-separated allowed values)
Custom Constraints:
- Register via RegisterConstraintValidator() to add custom constraint types
- Multiple constraints per field supported
Error Handling:
- Check HasErrors() before accessing filter results
- Call Errors() to get map[string]string with field-specific error messages
- Error keys follow format: "filters[fieldName]"
func (*FilterParser) RegisterConstraintValidator ¶
func (fp *FilterParser) RegisterConstraintValidator(validator ConstraintValidator) *FilterParser
RegisterConstraintValidator registers a custom constraint validator. Replaces any existing validator with the same name (including built-in validators). Returns the receiver for method chaining.
Example - custom length validator:
type MinLengthValidator struct{}
func (v *MinLengthValidator) Name() string { return "min_length" }
func (v *MinLengthValidator) Validate(values []string, constraint string, fieldType reflect.Type) error {
min := 0
fmt.Sscanf(constraint, "%d", &min)
for _, v := range values {
if len(v) < min {
return fmt.Errorf("minimum length %d required", min)
}
}
return nil
}
fp.RegisterConstraintValidator(&MinLengthValidator())
fp.Parse(&filters)
func (*FilterParser) WithMaxValues ¶
func (fp *FilterParser) WithMaxValues(max int) *FilterParser
WithMaxValues sets the maximum number of values allowed per filter field. Use 0 for unlimited (default). Returns the receiver for method chaining.
Example:
fp.WithMaxValues(10).Parse(&filters)
func (*FilterParser) WithTimezone ¶
func (fp *FilterParser) WithTimezone(tz *time.Location) *FilterParser
WithTimezone sets the timezone for parsing timestamp ranges. If nil, UTC is used (default). This affects parseTimestampRange only. Returns the receiver for method chaining.
Example:
jakartaTz, _ := time.LoadLocation("Asia/Jakarta")
fp.WithTimezone(jakartaTz).Parse(&filters)
type FlaggedCommand ¶
type FlaggedCommand interface {
Command
// DefineFlags mendefinisikan flags untuk command ini
DefineFlags(fs *flag.FlagSet)
}
FlaggedCommand adalah interface opsional untuk command yang membutuhkan flags/options. Command yang mengimplementasikan interface ini dapat mendefinisikan flags mereka sendiri.
type HandlerFunc ¶
type HandlerFunc func(http.ResponseWriter, *http.Request)
HandlerFunc is the standard HTTP handler function signature
func Chain ¶
func Chain(handler HandlerFunc, middleware ...MiddlewareFunc) HandlerFunc
Chain membungkus handler dengan multiple middleware functions secara beruntun. Middleware diterapkan dalam urutan maju (pertama di list dijalankan pertama). Contoh: Chain(handler, m1, m2, m3) menghasilkan execution order: m1 -> m2 -> m3 -> handler. Gunakan untuk menerapkan middleware chain ke single handler.
Parameters:
- handler: HandlerFunc yang akan dibungkus dengan middleware
- middleware: variadic list dari MiddlewareFunc yang diterapkan berurutan
Returns:
- HandlerFunc: handler baru dengan middleware chain diterapkan
Example:
finalHandler := Chain(myHandler, LoggerMiddleware, AuthMiddleware, RecoveryMiddleware)
func (HandlerFunc) ServeHTTP ¶
func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP mengimplementasikan http.Handler interface untuk HandlerFunc. Memungkinkan HandlerFunc digunakan di mana http.Handler diexpect. Ini membuatnya transparent untuk menggunakan HandlerFunc dengan standard http patterns.
Parameters:
- w: http.ResponseWriter untuk menulis response
- r: *http.Request request yang diproses
Example:
var h HandlerFunc = myHandler h.ServeHTTP(w, r) // calls h(w, r)
func (HandlerFunc) ToHandler ¶
func (h HandlerFunc) ToHandler() http.Handler
ToHandler mengkonversi HandlerFunc menjadi http.Handler interface. Memungkinkan HandlerFunc digunakan di mana saja yang expect http.Handler. Conversion ini implicit di many Go standard library functions.
Returns:
- http.Handler: http.Handler yang membungkus HandlerFunc
Example:
handler := myHandlerFunc.ToHandler()
http.Handle("/path", handler)
type HelpCommand ¶
type HelpCommand struct {
// contains filtered or unexported fields
}
HelpCommand menampilkan daftar semua command yang tersedia.
func (*HelpCommand) Description ¶
func (c *HelpCommand) Description() string
func (*HelpCommand) Execute ¶
func (c *HelpCommand) Execute(ctx *CommandContext) error
func (*HelpCommand) Name ¶
func (c *HelpCommand) Name() string
type InConstraintValidator ¶
type InConstraintValidator struct{}
InConstraintValidator implements ConstraintValidator for enum validation. Validates that values are in a predefined list of allowed values.
Format:
- Tag: "fieldName,in:value1|value2|value3"
- Separator: pipe (|) between allowed values
- Whitespace: automatically trimmed from values and constraint
Behavior:
- Applied to both pointer string and slice string types
- Single value (pointer) or multiple values (slice) validated
- Returns error if any value not in allowed list
- User-friendly error message listing allowed values
Example usage:
type Filters struct {
Status *string `filter:"status,in:active|pending|archived"`
Statuses []string `filter:"statuses,in:active|pending"`
}
func (*InConstraintValidator) Name ¶
func (v *InConstraintValidator) Name() string
Name returns the constraint name
func (*InConstraintValidator) Validate ¶
func (v *InConstraintValidator) Validate(values []string, constraint string, fieldType reflect.Type) error
Validate checks if values are in the allowed list. Constraint format: "value1|value2|value3" (pipe-separated)
Process:
- Parses constraint string by pipe separator
- Trims whitespace from each allowed value
- Validates each input value exists in allowed set
- Returns first error encountered, or nil if all valid
Error messages:
- "constraint tidak valid: tidak ada nilai yang diizinkan" - empty constraint
- "nilai tidak valid: {value} (diizinkan: {list})" - value not in allowed set
type InMemoryBlocklist ¶
type InMemoryBlocklist struct {
// contains filtered or unexported fields
}
InMemoryBlocklist implementasi TokenBlocklist menggunakan goreus/cache. Cocok untuk single-instance deployment atau testing. PERHATIAN: Data hilang saat restart.
func NewInMemoryBlocklist ¶
func NewInMemoryBlocklist() *InMemoryBlocklist
NewInMemoryBlocklist membuat instance baru InMemoryBlocklist. Menggunakan kapasistas 100,000 dan default eviction 7 hari (aman untuk refresh token).
func (*InMemoryBlocklist) Invalidate ¶
type InMemoryRateLimitStore ¶
type InMemoryRateLimitStore struct {
// contains filtered or unexported fields
}
InMemoryRateLimitStore mengimplementasikan RateLimitStore menggunakan goreus/cache. Cocok untuk deployment single-instance. Data counter disimpan di memori dan hilang saat restart.
func NewInMemoryRateLimitStore ¶
func NewInMemoryRateLimitStore(window time.Duration) *InMemoryRateLimitStore
NewInMemoryRateLimitStore membuat store rate limit in-memory baru.
Parameters:
- window: durasi waktu untuk TTL cache (biasanya sama dengan ResetPeriod)
func (*InMemoryRateLimitStore) Allow ¶
func (s *InMemoryRateLimitStore) Allow(ctx context.Context, key string, limit int, window time.Duration) (bool, error)
Allow mengecek dan menaikkan limit di in-memory cache.
func (*InMemoryRateLimitStore) Close ¶
func (s *InMemoryRateLimitStore) Close() error
Close menutup cache in-memory.
type JWTConfig ¶
type JWTConfig struct {
AccessTokenExpiry time.Duration
RefreshTokenExpiry time.Duration
// Algorithm configuration
SigningMethod string // "HS256" (default), "RS256", "ES256"
// Symmetric Config (HMAC: HS256, HS384, HS512)
HMACSecret string
// Asymmetric Config (RSA/ECDSA: RS256, ES256)
PrivateKey string // PEM content for Signing
PublicKeys map[string]string // Key ID (kid) -> PEM content Public Key (for rotation)
// Remote Verification (JWKS)
JWKSURL string
}
JWTConfig holds JWT configuration
type JWTManager ¶
type JWTManager struct {
// contains filtered or unexported fields
}
JWTManager handles JWT operations
func NewJWTManager ¶
func NewJWTManager(config *JWTConfig) (*JWTManager, error)
NewJWTManager membuat JWT manager baru dengan konfigurasi yang diberikan. Membaca konfigurasi Signing Method dan kunci-kunci yang diperlukan.
Parameters:
- config: pointer ke struct JWTConfig yang berisi preferensi signing dan kunci
Returns:
- *JWTManager: instance manager yang siap digunakan
- error: error jika parsing kunci gagal atau konfigurasi tidak valid
func (*JWTManager) GenerateAccessToken ¶
func (m *JWTManager) GenerateAccessToken(userID string, email string, sessionID string, extraClaims map[string]interface{}) (string, error)
GenerateAccessToken membuat access token JWT baru untuk user dengan expiry yang sudah dikonfigurasi. Token ditandatangani menggunakan metode dan kunci yang aktif saat ini.
Parameters:
- userID: ID unik pengguna (disimpan dalam claim 'sub')
- email: email pengguna (disimpan dalam claim 'email')
- sessionID: ID unik sesi (disimpan dalam claim 'sid')
- extraClaims: map tambahan claims custom yang ingin dimasukkan
Returns:
- string: signed JWT string
- error: error jika signing gagal
func (*JWTManager) GenerateRefreshToken ¶
func (m *JWTManager) GenerateRefreshToken(userID, sessionID string) (string, error)
GenerateRefreshToken membuat refresh token JWT baru untuk user dengan expiry lebih panjang. Digunakan untuk mendapatkan access token baru tanpa login ulang.
Parameters:
- userID: ID unik pengguna (disimpan dalam claim 'sub')
- sessionID: ID unik sesi (disimpan dalam claim 'sid')
Returns:
- string: signed JWT string
- error: error jika signing gagal
func (*JWTManager) GetTokenExpiry ¶
func (m *JWTManager) GetTokenExpiry(tokenString string) (time.Time, error)
GetTokenExpiry mengembalikan waktu expiry dari token. Berguna untuk pengecekan sisi client atau logika refresh otomatis.
Parameters:
- tokenString: raw JWT string
Returns:
- time.Time: waktu kapan token tersebut expired
- error: error jika parsing token gagal
func (*JWTManager) IsTokenExpired ¶
func (m *JWTManager) IsTokenExpired(tokenString string) (bool, error)
IsTokenExpired mengecek apakah token sudah expired atau tidak.
Parameters:
- tokenString: JWT token string
Returns:
- bool: true jika token sudah expired, false jika masih valid
- error: error jika parse token gagal
Example:
isExpired, err := manager.IsTokenExpired(tokenString)
if isExpired {
// get new token
}
func (*JWTManager) VerifyRefreshToken ¶
func (m *JWTManager) VerifyRefreshToken(tokenString string) (string, string, error)
VerifyRefreshToken memverifikasi refresh token dan mengembalikan userID dan sessionID. Memastikan token valid dan belum kedaluwarsa.
Parameters:
- tokenString: raw JWT string
Returns:
- string: userID yang tersimpan dalam claim 'sub'
- string: sessionID yang tersimpan dalam claim 'sid'
- error: error jika token tidak valid
func (*JWTManager) VerifyToken ¶
func (m *JWTManager) VerifyToken(tokenString string) (jwt.MapClaims, error)
VerifyToken memverifikasi access token dan mengembalikan claims di dalamnya. Mendukung rotasi kunci melalui header 'kid'.
Parameters:
- tokenString: raw JWT string yang diterima dari client
Returns:
- jwt.MapClaims: klaim-klaim yang ada di dalam token jika valid
- error: error jika signature tidak valid, token kedaluwarsa, atau format salah
type JsonNull ¶
JsonNull represents a nullable value that distinguishes between: - Field not present in JSON (Present=false) - Field explicitly set to null (Present=true, Valid=false) - Field with a value (Present=true, Valid=true)
This is useful for partial updates in PATCH endpoints where you need to distinguish between "don't update this field" vs "set this field to null" vs "set this field to a new value".
func JsonNullFromPtr ¶
JsonNullFromPtr converts a pointer to JsonNull. nil pointer becomes null, non-nil becomes valid value
func NewJsonNull ¶
NewJsonNull creates a JsonNull with a valid value
func NewJsonNullNull ¶
NewJsonNullNull creates a JsonNull representing an explicit null
type Logger ¶
Logger is a wrapper around slog.Logger for structured logging
func NewLogger ¶
NewLogger membuat logger baru dengan JSON output format dan specified log level. Output dikirim ke stdout (os.Stdout). Gunakan untuk structured logging dalam JSON format yang bisa di-parse oleh log aggregation tools.
Parameters:
- level: slog.Level untuk minimum log level (LevelDebug, LevelInfo, LevelWarn, LevelError)
Returns:
- *Logger: logger instance dengan JSON handler
Example:
logger := NewLogger(slog.LevelInfo)
logger.Info("User login", "user_id", 123, "email", "[email protected]")
func NewLoggerWithWriter ¶
NewLoggerWithWriter membuat logger baru dengan JSON output format dan custom writer. Berguna untuk logging ke file, buffer, atau custom destinations. Output di-encode sebagai JSON untuk structured logging.
Parameters:
- w: io.Writer untuk output destination (file, buffer, etc)
- level: slog.Level untuk minimum log level
Returns:
- *Logger: logger instance dengan JSON handler dan custom writer
Example:
file, _ := os.Create("app.log")
logger := NewLoggerWithWriter(file, slog.LevelInfo)
logger.Info("Application started")
func NewTextLogger ¶
NewTextLogger membuat logger baru dengan text output format dan specified log level. Output dikirim ke stdout (os.Stdout) dalam human-readable text format. Gunakan untuk development environment atau ketika structured JSON tidak diperlukan.
Parameters:
- level: slog.Level untuk minimum log level
Returns:
- *Logger: logger instance dengan text handler
Example:
logger := NewTextLogger(slog.LevelDebug)
logger.Debug("Debug information", "key", "value")
func NewTextLoggerWithWriter ¶
NewTextLoggerWithWriter membuat logger baru dengan text output format dan custom writer. Output dalam human-readable text format ke specified writer. Berguna untuk logging ke file dalam text format.
Parameters:
- w: io.Writer untuk output destination
- level: slog.Level untuk minimum log level
Returns:
- *Logger: logger instance dengan text handler dan custom writer
Example:
file, _ := os.Create("app.log")
logger := NewTextLoggerWithWriter(file, slog.LevelInfo)
logger.Info("User registered", "email", "[email protected]")
func (*Logger) Debug ¶
Debug menulis debug-level log message dengan optional key-value attributes. Debug level digunakan untuk detailed debugging information. Hanya ditampilkan jika logger level di-set ke LevelDebug. Arguments adalah variadic key-value pairs untuk debugging context.
Parameters:
- msg: debug message string
- args: variadic arguments (key-value pairs)
Example:
logger.Debug("Processing request", "method", "GET", "path", "/users/123")
func (*Logger) Error ¶
Error menulis error-level log message dengan optional key-value attributes. Error level digunakan untuk error messages yang perlu attention. Arguments adalah variadic key-value pairs untuk additional context.
Parameters:
- msg: error message string
- args: variadic arguments (key-value pairs)
Example:
logger.Error("Database connection failed", "error", err, "retry_count", 3)
func (*Logger) Info ¶
Info menulis info-level log message dengan optional key-value attributes. Info level digunakan untuk general informational messages (login, request, etc). Arguments adalah variadic key-value pairs (key1, value1, key2, value2, ...).
Parameters:
- msg: log message string
- args: variadic arguments (key-value pairs)
Example:
logger.Info("User login successful", "user_id", 123, "ip", "192.168.1.1")
func (*Logger) Warn ¶
Warn menulis warn-level log message dengan optional key-value attributes. Warn level digunakan untuk warning messages tentang non-critical issues. Arguments adalah variadic key-value pairs untuk additional context.
Parameters:
- msg: warning message string
- args: variadic arguments (key-value pairs)
Example:
logger.Warn("High memory usage detected", "usage_percent", 85.5)
type LoginRequest ¶
LoginRequest merepresentasikan data yang dibutuhkan untuk login.
type MakeMigrationCommand ¶
type MakeMigrationCommand struct {
// contains filtered or unexported fields
}
MakeMigrationCommand generates a new migration file
func (*MakeMigrationCommand) DefineFlags ¶
func (c *MakeMigrationCommand) DefineFlags(fs *flag.FlagSet)
func (*MakeMigrationCommand) Description ¶
func (c *MakeMigrationCommand) Description() string
func (*MakeMigrationCommand) Execute ¶
func (c *MakeMigrationCommand) Execute(ctx *CommandContext) error
func (*MakeMigrationCommand) Name ¶
func (c *MakeMigrationCommand) Name() string
type MiddlewareFunc ¶
type MiddlewareFunc func(HandlerFunc) HandlerFunc
MiddlewareFunc is a function that wraps a handler with middleware
func AllowBearerToken ¶
func AllowBearerToken() MiddlewareFunc
AllowBearerToken adalah middleware pasif yang tidak melakukan apa-apa. Tujuannya adalah untuk secara eksplisit menandai sebuah rute yang memperbolehkan header Authorization, meskipun tidak divalidasi di tingkat middleware. Penggunaannya sangat jarang dan untuk kasus yang sangat spesifik.
func CORS ¶
func CORS(config CORSConfig) MiddlewareFunc
CORS membuat middleware yang handle Cross-Origin Resource Sharing (CORS). Middleware ini set CORS headers untuk allow cross-origin requests dari specified origins. Support preflight requests (OPTIONS method) dan credential requests. Origin checking dilakukan dengan exact match atau wildcard (*).
Parameters:
- config: CORSConfig yang berisi allowed origins, methods, headers, credentials setting
Returns:
- MiddlewareFunc: middleware function yang handle CORS
Example:
corsConfig := CORSConfig{
AllowedOrigins: []string{"https://example.com", "https://app.example.com"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 3600,
}
router.Use(CORS(corsConfig))
func CSRFMiddleware ¶
func CSRFMiddleware(config CSRFConfig) MiddlewareFunc
CSRFMiddleware membuat middleware yang handle CSRF (Cross-Site Request Forgery) protection. Middleware ini verify CSRF token untuk unsafe HTTP methods (POST, PUT, DELETE, PATCH). Safe methods (GET, HEAD, OPTIONS) dan exempt paths di-skip dari CSRF check. Token divalidasi dengan membandingkan value dari header/form dengan value dari cookie. Mengembalikan 403 Forbidden jika token tidak valid atau tidak match.
Parameters:
- config: CSRFConfig yang berisi enabled status, header name, cookie name, exempt paths
Returns:
- MiddlewareFunc: middleware function yang handle CSRF protection
Example:
csrfConfig := CSRFConfig{
Enabled: true,
HeaderName: "X-CSRF-Token",
CookieName: "_csrf",
ExemptPaths: []string{"/api/public/*"},
}
router.Use(CSRFMiddleware(csrfConfig))
func ChainMiddleware ¶
func ChainMiddleware(middleware ...MiddlewareFunc) MiddlewareFunc
ChainMiddleware membuat MiddlewareFunc dari multiple middleware tanpa final handler. Berguna untuk membuat reusable middleware chain yang bisa diterapkan ke multiple routes. Return value adalah MiddlewareFunc yang bisa digunakan di route registration.
Parameters:
- middleware: variadic list dari MiddlewareFunc yang akan di-chain
Returns:
- MiddlewareFunc: middleware function yang combine semua middleware
Example:
authChain := ChainMiddleware(AuthMiddleware, LoggerMiddleware)
router.Get("/users", getUsersHandler, authChain)
func Compose ¶
func Compose(middleware ...MiddlewareFunc) MiddlewareFunc
Compose membuat middleware baru dari multiple middleware functions. Similar dengan Chain tetapi return MiddlewareFunc dan dapat digunakan sebagai single middleware. Berguna untuk membuat composite middleware yang dapat di-reuse di berbagai places.
Parameters:
- middleware: variadic list dari MiddlewareFunc yang akan di-compose
Returns:
- MiddlewareFunc: composed middleware function
Example:
authAndLog := Compose(AuthMiddleware, LoggerMiddleware)
router.Get("/protected", handler, authAndLog)
func ExpectBearerToken ¶
func ExpectBearerToken() MiddlewareFunc
ExpectBearerToken adalah middleware yang hanya memeriksa keberadaan header `Authorization: Bearer <token>`. **TIDAK AMAN**: Middleware ini TIDAK memverifikasi validitas token itu sendiri. Gunakan ini hanya untuk kasus penggunaan lanjutan di mana verifikasi dilakukan secara manual di tempat lain. Untuk keamanan, selalu prioritaskan penggunaan `RequireAuth`.
func HandlerToMiddleware ¶
func HandlerToMiddleware(h http.Handler) MiddlewareFunc
HandlerToMiddleware mengkonversi http.Handler menjadi MiddlewareFunc. Memungkinkan penggunaan standard http.Handler implementations sebagai middleware. Berguna untuk integrasi dengan third-party packages yang implement http.Handler.
Parameters:
- h: http.Handler yang akan dikonversi menjadi middleware
Returns:
- MiddlewareFunc: middleware function yang membungkus http.Handler
Example:
corsHandler := HandlerToMiddleware(corsStandardHandler) router.Use(corsHandler)
func LoggerMiddleware ¶
func LoggerMiddleware(logger *Logger) MiddlewareFunc
LoggerMiddleware membuat middleware yang log HTTP requests dan responses. Middleware ini: 1. Generate unique request ID dan set di context untuk request tracing 2. Wrap response writer untuk capture response status code 3. Measure request duration 4. Log request details termasuk method, path, status code, dan duration Berguna untuk debugging, monitoring, dan audit trail.
Parameters:
- logger: *Logger untuk menulis log entries
Returns:
- MiddlewareFunc: middleware function yang log request/response
Example:
logger := NewLogger(slog.LevelInfo) router.Use(LoggerMiddleware(logger)) // Log output: time=... level=INFO msg="request completed" request_id=abc123 method=GET path=/users status=200 duration_ms=45
func OptionalAuth ¶
func OptionalAuth(jwtManager *JWTManager) MiddlewareFunc
OptionalAuth (sebelumnya OptionalAuthWithManager) adalah middleware yang aman dan direkomendasikan untuk secara opsional memverifikasi token JWT jika ada. Middleware ini tidak akan gagal jika token tidak ada atau tidak valid. Jika token valid, info pengguna akan ditempatkan di konteks. Berguna untuk endpoint yang mendukung konteks pengguna opsional.
Parameters:
- jwtManager: *JWTManager untuk verifikasi token.
Returns:
- MiddlewareFunc: Middleware yang memungkinkan autentikasi opsional dengan verifikasi.
Example:
router.Get("/semi-protected", handler, OptionalAuth(jwtManager))
// Di dalam handler: user, ok := GetUser(req); if ok { /* authenticated */ }
func RateLimit ¶
func RateLimit(config RateLimitConfig, store ...RateLimitStore) MiddlewareFunc
RateLimit membuat middleware yang menerapkan pembatasan kecepatan (rate limiting). Middleware ini mencegah penyalahgunaan API dengan membatasi jumlah request per IP atau per User.
Parameters:
- config: Struct RateLimitConfig yang berisi aturan limit.
- store: (Opsional) Backend storage custom via variadic parameter. Jika kosong, menggunakan InMemoryRateLimitStore. Gunakan NewPostgresRateLimitStore(db) untuk persistensi database.
Returns:
- MiddlewareFunc: Middleware function untuk router.
Example:
// Default In-Memory router.Use(dim.RateLimit(config)) // Dengan Postgres Store store := dim.NewPostgresRateLimitStore(db) router.Use(dim.RateLimit(config, store))
func Recovery ¶
func Recovery(logger *Logger) MiddlewareFunc
Recovery membuat middleware yang recover dari panics dan log mereka. Middleware ini: 1. Catch panic yang terjadi di handler atau downstream middleware 2. Log panic error dengan request details (path, method) untuk debugging 3. Return 500 Internal Server Error response ke client 4. Prevent application crash dan memastikan graceful error handling Berguna untuk production safety dan error monitoring.
Parameters:
- logger: *Logger untuk menulis panic error logs
Returns:
- MiddlewareFunc: middleware function yang recover dari panics
Example:
logger := NewLogger(slog.LevelError) router.Use(Recovery(logger)) // Jika ada panic di handler, akan logged dan 500 response dikirim ke client
func RequireAuth ¶
func RequireAuth(jwtManager *JWTManager, blocklist TokenBlocklist) MiddlewareFunc
RequireAuth adalah middleware yang aman dan direkomendasikan untuk mewajibkan dan memverifikasi token JWT yang valid. Middleware ini menggunakan JWTManager untuk memvalidasi token dan menempatkan info pengguna ke dalam konteks. Juga dapat mengecek TokenBlocklist jika disediakan (opsional). Mengembalikan 401 Unauthorized jika token tidak ada, tidak valid, atau kedaluwarsa.
Parameters:
- jwtManager: *JWTManager untuk verifikasi token.
- blocklist: TokenBlocklist interface (opsional, pass nil jika tidak digunakan).
Returns:
- MiddlewareFunc: Middleware yang memberlakukan autentikasi aman.
Example:
router.Get("/protected", handler, RequireAuth(jwtManager, blocklist))
// Di dalam handler, gunakan GetUser(req) untuk mendapatkan pengguna yang terautentikasi.
type MigrateCommand ¶
type MigrateCommand struct {
// contains filtered or unexported fields
}
MigrateCommand menjalankan semua pending database migrations.
func (*MigrateCommand) DefineFlags ¶
func (c *MigrateCommand) DefineFlags(fs *flag.FlagSet)
func (*MigrateCommand) Description ¶
func (c *MigrateCommand) Description() string
func (*MigrateCommand) Execute ¶
func (c *MigrateCommand) Execute(ctx *CommandContext) error
func (*MigrateCommand) Name ¶
func (c *MigrateCommand) Name() string
type MigrateListCommand ¶
type MigrateListCommand struct{}
MigrateListCommand menampilkan status semua migrations (applied dan pending).
func (*MigrateListCommand) Description ¶
func (c *MigrateListCommand) Description() string
func (*MigrateListCommand) Execute ¶
func (c *MigrateListCommand) Execute(ctx *CommandContext) error
func (*MigrateListCommand) Name ¶
func (c *MigrateListCommand) Name() string
type MigrateRollbackCommand ¶
type MigrateRollbackCommand struct {
// contains filtered or unexported fields
}
MigrateRollbackCommand membatalkan migration yang sudah dijalankan.
func (*MigrateRollbackCommand) DefineFlags ¶
func (c *MigrateRollbackCommand) DefineFlags(fs *flag.FlagSet)
func (*MigrateRollbackCommand) Description ¶
func (c *MigrateRollbackCommand) Description() string
func (*MigrateRollbackCommand) Execute ¶
func (c *MigrateRollbackCommand) Execute(ctx *CommandContext) error
func (*MigrateRollbackCommand) Name ¶
func (c *MigrateRollbackCommand) Name() string
type Migration ¶
type Migration struct {
Version int64
Name string
Up func(*pgxpool.Pool) error
Down func(*pgxpool.Pool) error
}
Migration represents a single migration
func GetFrameworkMigrations ¶
func GetFrameworkMigrations() []Migration
GetFrameworkMigrations mengembalikan semua migrasi bawaan framework dim (User, Token, RateLimit). Migrasi ini mencakup tabel-tabel inti yang diperlukan oleh fitur-fitur framework. Urutan versi: 1. Users 2. Refresh Tokens 3. Password Reset Tokens 4. Token Blocklist 5. Rate Limits
func GetRateLimitMigrations ¶
func GetRateLimitMigrations() []Migration
GetRateLimitMigrations mengembalikan daftar migrasi terkait rate limit. Dimulai dari versi 5 (melanjutkan token migrations).
func GetRegisteredMigrations ¶
func GetRegisteredMigrations() []Migration
GetRegisteredMigrations mengembalikan semua migration yang terdaftar via Register(). Migration akan otomatis diurutkan berdasarkan Version.
func GetTokenMigrations ¶
func GetTokenMigrations() []Migration
GetTokenMigrations mengembalikan daftar migrasi terkait token (refresh, reset, blocklist). Dimulai dari versi 2 (asumsi versi 1 adalah users).
func GetUserMigrations ¶
func GetUserMigrations() []Migration
GetUserMigrations mengembalikan daftar migrasi terkait tabel users. Mencakup pembuatan tabel users dasar.
type MigrationHistory ¶
MigrationHistory represents the migration history table
type MockTokenStore ¶
type MockTokenStore struct {
// contains filtered or unexported fields
}
MockTokenStore is a mock implementation for testing
func NewMockTokenStore ¶
func NewMockTokenStore() *MockTokenStore
NewMockTokenStore membuat mock token store untuk testing. Mock store menyimpan tokens dalam memory dan cocok untuk unit tests.
Returns:
- *MockTokenStore: mock store instance dengan empty token maps
Example:
mockStore := NewMockTokenStore() // use in tests
func (*MockTokenStore) FindPasswordResetToken ¶
func (s *MockTokenStore) FindPasswordResetToken(ctx context.Context, tokenHash string) (*PasswordResetToken, error)
FindPasswordResetToken mencari password reset token dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- tokenHash: hash dari reset token yang akan dicari
Returns:
- *PasswordResetToken: token jika ditemukan, nil jika tidak
- error: error message jika token tidak ditemukan
Example:
token, err := mockStore.FindPasswordResetToken(ctx, tokenHash)
func (*MockTokenStore) FindRefreshToken ¶
func (s *MockTokenStore) FindRefreshToken(ctx context.Context, tokenHash string) (*RefreshToken, error)
FindRefreshToken mencari refresh token dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- tokenHash: hash dari token yang akan dicari
Returns:
- *RefreshToken: token jika ditemukan, nil jika tidak
- error: error message jika token tidak ditemukan
Example:
token, err := mockStore.FindRefreshToken(ctx, tokenHash)
func (*MockTokenStore) MarkPasswordResetUsed ¶
func (s *MockTokenStore) MarkPasswordResetUsed(ctx context.Context, tokenHash string) error
MarkPasswordResetUsed menandai password reset token sebagai used dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- tokenHash: hash dari reset token yang akan ditandai as used
Returns:
- error: selalu nil untuk mock
Example:
err := mockStore.MarkPasswordResetUsed(ctx, tokenHash)
func (*MockTokenStore) RevokeAllUserTokens ¶
func (s *MockTokenStore) RevokeAllUserTokens(ctx context.Context, userID string) error
RevokeAllUserTokens membatalkan semua tokens user dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- userID: ID dari user yang semua token-nya akan di-revoke
Returns:
- error: selalu nil untuk mock
Example:
err := mockStore.RevokeAllUserTokens(ctx, userID)
func (*MockTokenStore) RevokeRefreshToken ¶
func (s *MockTokenStore) RevokeRefreshToken(ctx context.Context, tokenHash string) error
RevokeRefreshToken membatalkan refresh token dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- tokenHash: hash dari token yang akan di-revoke
Returns:
- error: selalu nil untuk mock
Example:
err := mockStore.RevokeRefreshToken(ctx, tokenHash)
func (*MockTokenStore) SavePasswordResetToken ¶
func (s *MockTokenStore) SavePasswordResetToken(ctx context.Context, token *PasswordResetToken) error
SavePasswordResetToken menyimpan password reset token dalam mock store.
Parameters:
- ctx: context (tidak digunakan dalam mock)
- token: PasswordResetToken struct yang akan disimpan
Returns:
- error: selalu nil untuk mock
Example:
err := mockStore.SavePasswordResetToken(ctx, &token)
func (*MockTokenStore) SaveRefreshToken ¶
func (s *MockTokenStore) SaveRefreshToken(ctx context.Context, token *RefreshToken) error
SaveRefreshToken menyimpan refresh token dalam mock store (memory).
Parameters:
- ctx: context (tidak digunakan dalam mock)
- token: RefreshToken struct yang akan disimpan
Returns:
- error: selalu nil untuk mock
Example:
err := mockStore.SaveRefreshToken(ctx, &token)
type Observable ¶
type Observable interface {
AddHook(hook QueryHook)
}
Observable defines specific interface for adding observability hooks
type Pagination ¶
Pagination struct holds the pagination details
type PaginationMeta ¶
type PaginationMeta struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
TotalPages int `json:"total_pages"`
}
PaginationMeta contains pagination information
type PaginationParser ¶
PaginationParser parses pagination parameters
func NewPaginationParser ¶
func NewPaginationParser(defaultLimit, maxLimit int) *PaginationParser
NewPaginationParser creates a new PaginationParser
func (*PaginationParser) Parse ¶
func (p *PaginationParser) Parse(r *http.Request) (*Pagination, error)
Parse parses page[number] and page[size] Also supports page and limit/size query params as fallback or standard simple pagination
type PaginationResponse ¶
type PaginationResponse struct {
Data interface{} `json:"data"`
Meta PaginationMeta `json:"meta"`
}
PaginationResponse is the response structure for paginated data
type PasswordResetToken ¶
type PasswordResetToken struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expires_at"`
UsedAt *time.Time `json:"used_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
PasswordResetToken represents a password reset token entity
type PasswordValidator ¶
type PasswordValidator struct {
// contains filtered or unexported fields
}
PasswordValidator provides password validation utilities
func NewPasswordValidator ¶
func NewPasswordValidator() *PasswordValidator
NewPasswordValidator membuat PasswordValidator baru dengan default settings. Default settings: minLength=8, require uppercase, lowercase, digit, dan special char.
Returns:
- *PasswordValidator: validator instance dengan default rules
Example:
validator := NewPasswordValidator() err := validator.Validate(password)
func (*PasswordValidator) RequireDigit ¶
func (pv *PasswordValidator) RequireDigit(required bool) *PasswordValidator
RequireDigit sets whether digits are required
func (*PasswordValidator) RequireLowercase ¶
func (pv *PasswordValidator) RequireLowercase(required bool) *PasswordValidator
RequireLowercase sets whether lowercase letters are required
func (*PasswordValidator) RequireSpecial ¶
func (pv *PasswordValidator) RequireSpecial(required bool) *PasswordValidator
RequireSpecial sets whether special characters are required
func (*PasswordValidator) RequireUppercase ¶
func (pv *PasswordValidator) RequireUppercase(required bool) *PasswordValidator
RequireUppercase sets whether uppercase letters are required
func (*PasswordValidator) SetMinLength ¶
func (pv *PasswordValidator) SetMinLength(length int) *PasswordValidator
SetMinLength sets the minimum password length
func (*PasswordValidator) Validate ¶
func (pv *PasswordValidator) Validate(password string) error
Validate memvalidasi password terhadap semua configured rules. Return error dengan detail field error jika validasi gagal.
Parameters:
- password: password string yang akan divalidasi
Returns:
- error: AppError dengan field errors jika ada rule yang tidak terpenuhi
Example:
err := validator.Validate("MyPassword123!")
if err != nil {
// handle validation error
}
type PostgresBlocklist ¶
type PostgresBlocklist struct {
// contains filtered or unexported fields
}
PostgresBlocklist implementasi TokenBlocklist menggunakan PostgreSQL UNLOGGED Table. Cocok untuk production & multi-instance deployment.
func NewPostgresBlocklist ¶
func NewPostgresBlocklist(db Database) *PostgresBlocklist
NewPostgresBlocklist membuat instance baru PostgresBlocklist.
func (*PostgresBlocklist) Cleanup ¶
func (p *PostgresBlocklist) Cleanup(ctx context.Context) error
Cleanup menghapus token yang sudah expired dari database. Sebaiknya dijalankan sebagai cron job atau background task.
func (*PostgresBlocklist) InitSchema ¶
func (p *PostgresBlocklist) InitSchema(ctx context.Context) error
InitSchema membuat tabel UNLOGGED 'token_blocklist' jika belum ada. UNLOGGED table tidak ditulis ke WAL (Write Ahead Log), performa lebih cepat (seperti Redis) dengan tradeoff data hilang jika DB crash (yang acceptable untuk cache/blocklist).
func (*PostgresBlocklist) Invalidate ¶
type PostgresDatabase ¶
type PostgresDatabase struct {
// contains filtered or unexported fields
}
PostgresDatabase is the PostgreSQL implementation of Database interface It supports read/write connection splitting with load balancing on read connections
func NewPostgresDatabase ¶
func NewPostgresDatabase(config DatabaseConfig) (*PostgresDatabase, error)
NewPostgresDatabase membuat koneksi database PostgreSQL baru dengan mendukung read/write splitting. Membuat write pool untuk operasi INSERT/UPDATE/DELETE dan read pools untuk operasi SELECT. Jika tidak ada read hosts yang dikonfigurasi, menggunakan write pool untuk reads.
Parameters:
- config: DatabaseConfig berisi konfigurasi koneksi database
Returns:
- *PostgresDatabase: instance database yang siap digunakan
- error: error jika gagal membuat connection pool
Example:
db, err := NewPostgresDatabase(config)
if err != nil {
log.Fatal(err)
}
func (*PostgresDatabase) AddHook ¶
func (db *PostgresDatabase) AddHook(hook QueryHook)
AddHook adds a new query hook to the database. Thread-safe.
func (*PostgresDatabase) Begin ¶
Begin memulai transaction baru di write connection. Semua transaction selalu dibuat di write pool untuk consistency.
Parameters:
- ctx: context untuk membatalkan operasi
Returns:
- pgx.Tx: transaction object yang bisa digunakan untuk execute queries
- error: error jika gagal membuat transaction
Example:
tx, err := db.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
func (*PostgresDatabase) Close ¶
func (db *PostgresDatabase) Close() error
Close menutup semua connection pools (write dan read). Harus dipanggil sebelum aplikasi shutdown untuk cleanup yang proper.
Returns:
- error: selalu nil, tapi disediakan untuk compatibility dengan interface
Example:
defer db.Close()
func (*PostgresDatabase) Exec ¶
func (db *PostgresDatabase) Exec(ctx context.Context, query string, args ...interface{}) error
Exec mengeksekusi write query (INSERT, UPDATE, DELETE) ke write connection pool. Semua operasi write selalu dikirim ke write pool untuk consistency. Gunakan sticky mode jika perlu subsequent reads ke write connection yang sama.
Parameters:
- ctx: context untuk membatalkan operasi
- query: SQL query untuk dieksekusi
- args: parameter untuk query
Returns:
- error: error jika query execution gagal
Example:
err := db.Exec(ctx, "INSERT INTO users (email, name) VALUES ($1, $2)", email, name)
func (*PostgresDatabase) Query ¶
func (db *PostgresDatabase) Query(ctx context.Context, query string, args ...interface{}) (Rows, error)
Query mengeksekusi read query (SELECT) dengan routing based on sticky mode. Menggunakan decision tree untuk menentukan pool mana yang digunakan: 1. Jika query adalah write operation, route ke write pool 2. Jika sticky mode enabled dan ada write dalam request, route ke write pool 3. Otherwise: route ke read pool dengan round-robin load balancing
Parameters:
- ctx: context untuk membatalkan operasi
- query: SQL SELECT query
- args: parameter untuk query
Returns:
- Rows: result set dari query
- error: error jika query execution gagal
Example:
rows, err := db.Query(ctx, "SELECT id, email FROM users WHERE id = $1", userID)
func (*PostgresDatabase) QueryRow ¶
func (db *PostgresDatabase) QueryRow(ctx context.Context, query string, args ...interface{}) Row
QueryRow mengeksekusi read query yang mengembalikan single row dengan routing based on sticky mode. Menggunakan decision tree yang sama dengan Query untuk menentukan pool mana yang digunakan.
Parameters:
- ctx: context untuk membatalkan operasi
- query: SQL SELECT query
- args: parameter untuk query
Returns:
- Row: single row result yang bisa di-scan
Example:
err := db.QueryRow(ctx, "SELECT email FROM users WHERE id = $1", userID).Scan(&email)
func (*PostgresDatabase) WithTx ¶
func (db *PostgresDatabase) WithTx(ctx context.Context, fn TransactionFunc) error
WithTx mengeksekusi function dalam transaction dengan auto rollback/commit. Jika fn return error, transaction di-rollback. Jika sukses, transaction di-commit.
Parameters:
- ctx: context untuk membatalkan operasi
- fn: function yang berisi query operations dalam transaction
Returns:
- error: error dari fn execution atau commit/rollback
Example:
err := db.WithTx(ctx, func(ctx context.Context, tx pgx.Tx) error {
return tx.Exec(ctx, "INSERT INTO users VALUES ($1)", email)
})
type PostgresRateLimitStore ¶
type PostgresRateLimitStore struct {
// contains filtered or unexported fields
}
PostgresRateLimitStore mengimplementasikan RateLimitStore menggunakan PostgreSQL. Cocok untuk deployment multi-instance/cluster. Menggunakan tabel UNLOGGED untuk performa tinggi (data hilang saat crash dapat diterima untuk rate limits).
func NewPostgresRateLimitStore ¶
func NewPostgresRateLimitStore(db Database) *PostgresRateLimitStore
NewPostgresRateLimitStore membuat store rate limit PostgreSQL baru.
Parameters:
- db: koneksi database yang mengimplementasikan interface Database
func (*PostgresRateLimitStore) Allow ¶
func (s *PostgresRateLimitStore) Allow(ctx context.Context, key string, limit int, window time.Duration) (bool, error)
Allow mengecek dan menaikkan limit menggunakan Atomic UPSERT di PostgreSQL.
func (*PostgresRateLimitStore) Close ¶
func (s *PostgresRateLimitStore) Close() error
Close menutup koneksi (no-op untuk implementasi ini karena DB dikelola di luar).
func (*PostgresRateLimitStore) InitSchema ¶
func (s *PostgresRateLimitStore) InitSchema(ctx context.Context) error
InitSchema membuat tabel yang diperlukan untuk rate limiting. Sebaiknya dipanggil saat startup aplikasi atau migrasi.
type PostgresTokenStore ¶
type PostgresTokenStore struct {
// contains filtered or unexported fields
}
PostgresTokenStore is the PostgreSQL implementation of TokenStore
func NewPostgresTokenStore ¶
func NewPostgresTokenStore(db Database) *PostgresTokenStore
NewPostgresTokenStore membuat PostgreSQL token store baru. Store ini menangani operasi CRUD untuk refresh tokens dan password reset tokens.
Parameters:
- db: Database instance untuk execute queries
Returns:
- *PostgresTokenStore: token store instance
Example:
tokenStore := NewPostgresTokenStore(db)
func (*PostgresTokenStore) FindPasswordResetToken ¶
func (s *PostgresTokenStore) FindPasswordResetToken(ctx context.Context, tokenHash string) (*PasswordResetToken, error)
FindPasswordResetToken mencari password reset token berdasarkan hash.
Parameters:
- ctx: context untuk membatalkan operasi
- tokenHash: hash dari reset token yang akan dicari
Returns:
- *PasswordResetToken: PasswordResetToken struct jika ditemukan
- error: error jika token tidak ditemukan atau query gagal
Example:
token, err := tokenStore.FindPasswordResetToken(ctx, tokenHash)
func (*PostgresTokenStore) FindRefreshToken ¶
func (s *PostgresTokenStore) FindRefreshToken(ctx context.Context, tokenHash string) (*RefreshToken, error)
FindRefreshToken mencari refresh token berdasarkan hash.
Parameters:
- ctx: context untuk membatalkan operasi
- tokenHash: hash dari token yang akan dicari
Returns:
- *RefreshToken: RefreshToken struct jika ditemukan
- error: error jika token tidak ditemukan atau query gagal
Example:
token, err := tokenStore.FindRefreshToken(ctx, tokenHash)
func (*PostgresTokenStore) MarkPasswordResetUsed ¶
func (s *PostgresTokenStore) MarkPasswordResetUsed(ctx context.Context, tokenHash string) error
MarkPasswordResetUsed menandai password reset token sudah digunakan dengan set used_at timestamp. Mencegah reuse dari token yang sama untuk reset password.
Parameters:
- ctx: context untuk membatalkan operasi
- tokenHash: hash dari reset token yang akan ditandai sebagai used
Returns:
- error: error jika UPDATE query gagal
Example:
err := tokenStore.MarkPasswordResetUsed(ctx, tokenHash)
func (*PostgresTokenStore) RevokeAllUserTokens ¶
func (s *PostgresTokenStore) RevokeAllUserTokens(ctx context.Context, userID string) error
RevokeAllUserTokens membatalkan semua refresh tokens milik pengguna tertentu. Berguna untuk security setelah password reset atau logout dari semua device.
Parameters:
- ctx: context untuk membatalkan operasi
- userID: ID dari user yang token-nya akan di-revoke
Returns:
- error: error jika UPDATE query gagal
Example:
err := tokenStore.RevokeAllUserTokens(ctx, userID)
func (*PostgresTokenStore) RevokeRefreshToken ¶
func (s *PostgresTokenStore) RevokeRefreshToken(ctx context.Context, tokenHash string) error
RevokeRefreshToken membatalkan/revoke refresh token dengan set revoked_at timestamp.
Parameters:
- ctx: context untuk membatalkan operasi
- tokenHash: hash dari token yang akan di-revoke
Returns:
- error: error jika UPDATE query gagal
Example:
err := tokenStore.RevokeRefreshToken(ctx, tokenHash)
func (*PostgresTokenStore) SavePasswordResetToken ¶
func (s *PostgresTokenStore) SavePasswordResetToken(ctx context.Context, token *PasswordResetToken) error
SavePasswordResetToken menyimpan password reset token ke database. Token disimpan dengan hash dan expiry time untuk password reset flow.
Parameters:
- ctx: context untuk membatalkan operasi
- token: PasswordResetToken struct dengan data yang akan disimpan
Returns:
- error: error jika INSERT query gagal
Example:
err := tokenStore.SavePasswordResetToken(ctx, &resetToken)
func (*PostgresTokenStore) SaveRefreshToken ¶
func (s *PostgresTokenStore) SaveRefreshToken(ctx context.Context, token *RefreshToken) error
SaveRefreshToken menyimpan refresh token ke database. Token disimpan dengan hash, user_agent, ip_address, dan expiry time.
Parameters:
- ctx: context untuk membatalkan operasi
- token: RefreshToken struct dengan data yang akan disimpan
Returns:
- error: error jika INSERT query gagal
Example:
err := tokenStore.SaveRefreshToken(ctx, &refreshToken)
type QueryHook ¶
type QueryHook func(ctx context.Context, query string, args []interface{}, duration time.Duration, err error)
QueryHook is a function that is called after a query execution.
type Range ¶
type Range[T any] struct { From T To T Valid bool // true if format is valid and has non-empty value and From <= To Present bool // true if parameter exists in request }
Range represents a range of values with from and to bounds. Generic type supporting any comparable type for flexible range queries.
Fields:
- From: Start value of range
- To: End value of range
- Valid: true if format is valid, range constraint (From <= To) satisfied, and non-empty
- Present: true if parameter exists in request (even if Invalid)
Behavior:
- Single value (e.g., "100") sets both From and To to same value
- Range format (e.g., "100,500") sets From and To separately
- Invalid format or From > To results in Valid=false but Present=true
- Empty input results in Valid=false and Present=true
type RateLimitConfig ¶
RateLimitConfig holds rate limiting configuration
type RateLimitStore ¶
type RateLimitStore interface {
// Allow mengecek apakah request diizinkan dan menaikkan counter.
// Mengembalikan true jika diizinkan, false jika tidak.
//
// Parameters:
// - ctx: context untuk operasi
// - key: unique key untuk rate limit (misal: "ip:1.2.3.4")
// - limit: batas maksimum request
// - window: durasi waktu reset
Allow(ctx context.Context, key string, limit int, window time.Duration) (bool, error)
// Close membersihkan resource yang digunakan.
Close() error
}
RateLimitStore mendefinisikan interface untuk backend penyimpanan rate limit. Memungkinkan pergantian antara InMemory (single instance) dan Postgres (multi-instance).
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter menangani logika rate limiting dengan backend storage yang dapat dikonfigurasi. Memisahkan logika bisnis dari implementasi middleware.
func NewRateLimiter ¶
func NewRateLimiter(config RateLimitConfig, store RateLimitStore) *RateLimiter
NewRateLimiter membuat instance RateLimiter baru.
Parameters:
- config: Konfigurasi limit (PerIP, PerUser, ResetPeriod).
- store: Backend storage (opsional). Jika nil, akan menggunakan InMemoryRateLimitStore default.
Returns:
- *RateLimiter: Instance rate limiter yang siap digunakan.
Example:
// In-memory limiter := NewRateLimiter(config, nil) // Postgres store := NewPostgresRateLimitStore(db) limiter := NewRateLimiter(config, store)
func (*RateLimiter) CheckIPLimit ¶
CheckIPLimit mengecek apakah IP dalam batas rate limit.
Parameters:
- ctx: context untuk operasi
- ip: alamat IP client
Returns:
- bool: true jika diizinkan, false jika limit terlampaui
- error: error dari storage backend
func (*RateLimiter) CheckUserLimit ¶
CheckUserLimit mengecek apakah user dalam batas rate limit.
Parameters:
- ctx: context untuk operasi
- userKey: unique identifier user (misal: "user:123")
Returns:
- bool: true jika diizinkan, false jika limit terlampaui
- error: error dari storage backend
type RefreshToken ¶
type RefreshToken struct {
ID int64 `json:"id"`
UserID string `json:"user_id"`
TokenHash string `json:"-"`
UserAgent string `json:"user_agent"`
IPAddress string `json:"ip_address"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
RevokedAt *time.Time `json:"revoked_at,omitempty"`
}
RefreshToken represents a refresh token entity
type RouteInfo ¶
type RouteInfo struct {
Method string // HTTP method (GET, POST, dll)
Path string // URL path pattern
Handler string // Nama handler function
Middlewares []string // Daftar nama middleware yang diterapkan
}
RouteInfo menyimpan informasi metadata tentang route yang terdaftar. Digunakan untuk introspeksi route (route:list command).
type RouteListCommand ¶
type RouteListCommand struct{}
RouteListCommand menampilkan semua route yang terdaftar beserta handler dan middleware.
func (*RouteListCommand) Description ¶
func (c *RouteListCommand) Description() string
func (*RouteListCommand) Execute ¶
func (c *RouteListCommand) Execute(ctx *CommandContext) error
func (*RouteListCommand) Name ¶
func (c *RouteListCommand) Name() string
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router adalah router HTTP utama yang dibangun di atas stdlib http.ServeMux dengan dukungan middleware yang ditingkatkan.
func NewRouter ¶
func NewRouter() *Router
NewRouter membuat instance router baru menggunakan stdlib http.ServeMux. Router mendukung pencocokan pola Go 1.22+ modern:
- Route statis: /users
- Parameter path: /users/{id}
- Catch-all: /files/{path...}
- Routing metode: GET /users/{id}
Mengembalikan:
- *Router: instance router yang siap digunakan
Contoh:
router := NewRouter()
router.Get("/users/{id}", getUserHandler)
http.ListenAndServe(":8080", router)
func (*Router) Build ¶
func (r *Router) Build()
Build membuild handler chain secara eksplisit. Disarankan dipanggil di main() sebelum http.ListenAndServe untuk performa terbaik (menghindari locking saat request). Jika tidak dipanggil, handler akan dibangun secara lazy pada request pertama (dengan sedikit overhead locking).
func (*Router) Delete ¶
func (r *Router) Delete(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Delete mendaftarkan route DELETE dengan middleware spesifik route opsional.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Delete("/users/{id}", deleteUserHandler, AuthMiddleware)
func (*Router) Get ¶
func (r *Router) Get(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Get mendaftarkan route GET dengan middleware spesifik route opsional. Path menggunakan pencocokan pola stdlib:
- Statis: /users
- Parameter: /users/{id}
- Catch-all: /files/{path...}
Parameter:
- path: path URL untuk route (contoh: /users, /users/{id}, /files/{path...})
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional yang diterapkan sebelum handler
Contoh:
router.Get("/users", getUsersHandler)
router.Get("/users/{id}", getUserHandler, AuthMiddleware)
func (*Router) GetRoutes ¶
GetRoutes mengembalikan semua route yang terdaftar dengan caching. Thread-safe dan menggunakan in-memory cache untuk performa optimal.
Mengembalikan:
- []RouteInfo: copy dari semua route yang terdaftar
Contoh:
routes := router.GetRoutes()
for _, route := range routes {
fmt.Printf("%s %s -> %s\n", route.Method, route.Path, route.Handler)
}
func (*Router) Group ¶
func (r *Router) Group(prefix string, middleware ...MiddlewareFunc) *RouterGroup
Group membuat RouterGroup baru dengan prefix dan middleware. RouterGroup memudahkan pengelompokan route dengan prefix dan middleware yang sama.
Parameter:
- prefix: path prefix untuk semua route dalam grup
- middleware: middleware level grup opsional yang diterapkan ke semua route
Mengembalikan:
- *RouterGroup: instance grup router untuk menambahkan route
Contoh:
api := router.Group("/api", AuthMiddleware)
api.Get("/users", getUsersHandler) // terdaftar sebagai GET /api/users
func (*Router) Head ¶
func (r *Router) Head(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Head mendaftarkan route HEAD dengan middleware spesifik route opsional.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Head("/users", headHandler)
func (*Router) Options ¶
func (r *Router) Options(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Options mendaftarkan route OPTIONS dengan middleware spesifik route opsional.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Options("/users", optionsHandler)
func (*Router) Patch ¶
func (r *Router) Patch(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Patch mendaftarkan route PATCH dengan middleware spesifik route opsional.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Patch("/users/{id}", patchUserHandler, AuthMiddleware)
func (*Router) Post ¶
func (r *Router) Post(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Post mendaftarkan route POST dengan middleware spesifik route opsional. Path menggunakan pencocokan pola stdlib.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Post("/users", createUserHandler)
router.Post("/upload", uploadFileHandler, AuthMiddleware)
func (*Router) Put ¶
func (r *Router) Put(path string, handler HandlerFunc, middleware ...MiddlewareFunc)
Put mendaftarkan route PUT dengan middleware spesifik route opsional.
Parameter:
- path: path URL untuk route
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Put("/users/{id}", updateUserHandler, AuthMiddleware)
func (*Router) Register ¶
func (r *Router) Register(method, path string, handler HandlerFunc, middleware []MiddlewareFunc)
Register mendaftarkan route dengan metode HTTP, path, handler, dan middleware opsional. Menggunakan stdlib http.ServeMux untuk pencocokan pola. Thread-safe: dilindungi dengan mutex untuk pendaftaran route konkuren. Secara otomatis mengubah metode menjadi huruf besar untuk kepatuhan.
Parameter:
- method: metode HTTP (GET, POST, PUT, DELETE, dll)
- path: path URL dengan pola stdlib (/users/{id}, /files/{path...})
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
router.Register("GET", "/users/{id}", getUserHandler, []MiddlewareFunc{AuthMiddleware})
func (*Router) SPA ¶
func (r *Router) SPA(root fs.FS, index string, middleware ...MiddlewareFunc)
SPA (Single Page Application) melayani aplikasi frontend modern dengan fallback ke index.html. Secara otomatis menambahkan header keamanan dan mematikan cache untuk file index agar user selalu mendapat versi terbaru.
func (*Router) ServeHTTP ¶
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP mengimplementasikan antarmuka http.Handler untuk menangani permintaan HTTP. Menerapkan middleware global dan menggunakan cached handler untuk kinerja yang lebih baik.
Parameter:
- w: http.ResponseWriter untuk menulis respons
- req: *http.Request permintaan yang akan diproses
func (*Router) Static ¶
func (r *Router) Static(prefix string, root fs.FS, middleware ...MiddlewareFunc)
Static melayani file statis dari sistem file (lokal atau embed). Secara otomatis menambahkan header keamanan dasar.
Parameter:
- prefix: path URL prefix (contoh: "/assets/")
- root: fs.FS interface (gunakan os.DirFS("./public") atau embed.FS)
- middleware: middleware tambahan (opsional)
func (*Router) Use ¶
func (r *Router) Use(middleware ...MiddlewareFunc)
Use menambahkan middleware global yang akan diterapkan ke semua route. Middleware diterapkan dalam urutan penambahan dan sebelum middleware spesifik route. Thread-safe: dilindungi dengan mutex untuk akses konkuren.
Parameter:
- middleware: daftar variadic dari MiddlewareFunc yang akan ditambahkan
Contoh:
router.Use(RecoveryMiddleware, LoggerMiddleware)
type RouterGroup ¶
type RouterGroup struct {
// contains filtered or unexported fields
}
RouterGroup merepresentasikan sekelompok route dengan prefix yang sama.
func (*RouterGroup) Delete ¶
func (rg *RouterGroup) Delete(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Delete mendaftarkan route DELETE dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Delete("/users/{id}", deleteUserHandler) // terdaftar sebagai DELETE /api/users/{id}
func (*RouterGroup) Get ¶
func (rg *RouterGroup) Get(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Get mendaftarkan route GET dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route. Menggunakan path.Join untuk menggabungkan path secara aman.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Get("/users", getUsersHandler) // terdaftar sebagai GET /api/users
func (*RouterGroup) Group ¶
func (rg *RouterGroup) Group(prefix string, middleware ...MiddlewareFunc) *RouterGroup
Group membuat grup route bersarang dengan prefix dan middleware gabungan. Prefix dan middleware dari grup induk digabungkan dengan grup baru. Berguna untuk organisasi route hierarkis (contoh: /api/v1/admin). Menggunakan path.Join untuk memastikan format path yang benar (menghindari double slash).
Parameter:
- prefix: sub-prefix untuk grup bersarang
- middleware: middleware level grup opsional
Mengembalikan:
- *RouterGroup: instance grup router bersarang
Example:
api := router.Group("/api")
v1 := api.Group("/v1", AuthMiddleware)
admin := v1.Group("/admin", AdminAuthMiddleware)
admin.Get("/users", listAllUsersHandler) // terdaftar sebagai GET /api/v1/admin/users dengan middleware gabungan
func (*RouterGroup) Head ¶
func (rg *RouterGroup) Head(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Head mendaftarkan route HEAD dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Head("/users", headHandler) // terdaftar sebagai HEAD /api/users
func (*RouterGroup) Options ¶
func (rg *RouterGroup) Options(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Options mendaftarkan route OPTIONS dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Options("/users", optionsHandler) // terdaftar sebagai OPTIONS /api/users
func (*RouterGroup) Patch ¶
func (rg *RouterGroup) Patch(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Patch mendaftarkan route PATCH dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Patch("/users/{id}", patchUserHandler) // terdaftar sebagai PATCH /api/users/{id}
func (*RouterGroup) Post ¶
func (rg *RouterGroup) Post(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Post mendaftarkan route POST dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api", AuthMiddleware)
api.Post("/users", createUserHandler) // terdaftar sebagai POST /api/users dengan AuthMiddleware
func (*RouterGroup) Put ¶
func (rg *RouterGroup) Put(relativePath string, handler HandlerFunc, middleware ...MiddlewareFunc)
Put mendaftarkan route PUT dalam grup dengan prefix grup dan middleware. Prefix grup dan middleware secara otomatis ditambahkan ke route.
Parameter:
- path: path URL relatif terhadap prefix grup
- handler: HandlerFunc yang akan menangani permintaan
- middleware: middleware spesifik route opsional
Contoh:
api := router.Group("/api")
api.Put("/users/{id}", updateUserHandler) // terdaftar sebagai PUT /api/users/{id}
func (*RouterGroup) Use ¶
func (rg *RouterGroup) Use(middleware ...MiddlewareFunc)
Use menambahkan middleware ke dalam group yang sudah ada. Middleware akan diterapkan ke semua route yang didaftarkan SETELAH pemanggilan ini.
Parameter:
- middleware: daftar variadic dari MiddlewareFunc
Example:
api := router.Group("/api")
api.Use(AuthMiddleware)
api.Get("/profile", profileHandler) // AuthMiddleware diterapkan
type Row ¶
type Row interface {
Scan(dest ...interface{}) error
}
Row represents a single query result row
type ServeCommand ¶
type ServeCommand struct {
// contains filtered or unexported fields
}
ServeCommand menjalankan HTTP server dengan konfigurasi yang dapat di-override via flags.
func (*ServeCommand) DefineFlags ¶
func (c *ServeCommand) DefineFlags(fs *flag.FlagSet)
func (*ServeCommand) Description ¶
func (c *ServeCommand) Description() string
func (*ServeCommand) Execute ¶
func (c *ServeCommand) Execute(ctx *CommandContext) error
func (*ServeCommand) Name ¶
func (c *ServeCommand) Name() string
type ServerConfig ¶
type ServerConfig struct {
Port string
ReadTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
ShutdownTimeout time.Duration
}
ServerConfig holds server configuration
type SortParser ¶
SortParser parses sort parameters from the request
func NewSortParser ¶
func NewSortParser(allowedFields []string) *SortParser
NewSortParser creates a new SortParser with allowed fields
type TimestampRange ¶
TimestampRange: Unix timestamp in seconds (from date string parsing) Input format: "YYYY-MM-DD" converted to Unix timestamp Example: "2024-01-15" or "2024-01-01,2024-12-31"
type TokenBlocklist ¶
type TokenBlocklist interface {
// Invalidate memasukkan token/session ke daftar hitam.
// identifier: Unique identifier (bisa JTI atau SID).
// expiresIn: Sisa durasi hidup token tersebut (sampai exp).
Invalidate(ctx context.Context, identifier string, expiresIn time.Duration) error
// IsRevoked mengecek apakah identifier ada di daftar hitam dan belum expired.
IsRevoked(ctx context.Context, identifier string) (bool, error)
}
TokenBlocklist mendefinisikan interface untuk mekanisme pencabutan token (denylist). Digunakan untuk menyimpan identifier (JTI atau Session ID) dari token yang di-invalidate sebelum waktunya.
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
}
TokenResponse merepresentasikan respons token setelah login berhasil.
type TokenStore ¶
type TokenStore interface {
SaveRefreshToken(ctx context.Context, token *RefreshToken) error
FindRefreshToken(ctx context.Context, tokenHash string) (*RefreshToken, error)
RevokeRefreshToken(ctx context.Context, tokenHash string) error
RevokeAllUserTokens(ctx context.Context, userID string) error
SavePasswordResetToken(ctx context.Context, token *PasswordResetToken) error
FindPasswordResetToken(ctx context.Context, tokenHash string) (*PasswordResetToken, error)
MarkPasswordResetUsed(ctx context.Context, tokenHash string) error
}
TokenStore defines the interface for token storage operations
type TokenUser ¶
type TokenUser struct {
ID string
Email string
Password string // Usually empty for token-derived users
Claims map[string]interface{}
}
TokenUser represents a minimal user entity derived from a token
func (*TokenUser) GetPassword ¶
func (*TokenUser) SetPassword ¶
type TransactionFunc ¶
TransactionFunc is a function that performs operations within a transaction
type UUID ¶
type UUID [16]byte
func NewUuid ¶
func NewUuid() UUID
NewUuid menghasilkan UUID baru menggunakan v7 (time-based) atau v4 (random) sebagai fallback. Prefer v7 karena sortable berdasarkan timestamp, lebih efficient untuk database indexing. Falls back ke v4 jika random generation untuk v7 gagal.
Returns:
- UUID: newly generated UUID
Example:
id := NewUuid() user.ID = id.String()
func NewV4 ¶
func NewV4() UUID
NewV4 menghasilkan UUID v4 (random-based). Format: random (4 bytes) | version 4 (4 bits) | random (12 bits) | variant (2 bits) | random (62 bits). UUID v4 adalah fully random dan tidak sortable berdasarkan time. Returns zero UUID jika random generation gagal (rare edge case).
Returns:
- UUID: newly generated v4 UUID
Example:
id := NewV4() session.ID = id.String()
func NewV7 ¶
NewV7 menghasilkan UUID v7 (time-based dengan random component). Format: timestamp (48 bits) | version 7 (4 bits) | random (12 bits) | variant (2 bits) | random (62 bits). UUID v7 adalah sortable berdasarkan timestamp untuk efficient database operations. Berguna untuk primary keys dalam relational databases.
Returns:
- UUID: newly generated v7 UUID
- error: error jika random generation gagal
Example:
id, err := NewV7()
if err != nil {
return err
}
log.Println(id.String())
func ParseUUIDFromString ¶
ParseUUIDFromString adalah alias untuk ParseUUID untuk consistency dengan naming conventions. Mengparse UUID string dalam standard format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Parameters:
- s: UUID string untuk di-parse
Returns:
- UUID: parsed UUID
- error: error jika string bukan valid UUID format
Example:
uuid, err := ParseUUIDFromString("550e8400-e29b-41d4-a716-446655440000")
func ParseUuid ¶
ParseUUID mengparse UUID string dalam standard format. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (exactly 36 characters). Case-insensitive hex character validation. Returns error jika format invalid atau string bukan valid UUID.
Parameters:
- s: UUID string untuk di-parse
Returns:
- UUID: parsed UUID
- error: error jika string bukan valid UUID format
Example:
uuid, err := ParseUUID("550e8400-e29b-41d4-a716-446655440000")
if err != nil {
log.Fatal(err)
}
user.ID = uuid
func (UUID) String ¶
String mengembalikan string representation UUID dalam standard format. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (32 hex chars + 4 hyphens = 36 chars).
Returns:
- string: UUID formatted string
Example:
uuid := NewUuid() fmt.Println(uuid.String()) // Output: 550e8400-e29b-41d4-a716-446655440000
type UploadConfig ¶
type UploadConfig struct {
// contains filtered or unexported fields
}
UploadConfig menyimpan konfigurasi untuk upload file.
Fields:
- path: Path direktori untuk menyimpan file yang di-upload (sanitisasi otomatis)
- allowedExts: Daftar ekstensi file yang diizinkan (misalnya ".jpg", ".pdf")
- maxFileSize: Ukuran file maksimal dalam bytes (0 = tanpa batas)
- maxFiles: Jumlah maksimal file untuk di-upload sekaligus
- concurrent: Aktifkan pemrosesan concurrent (false = sequential)
- maxWorkers: Jumlah concurrent workers (jika concurrent = true)
- logger: Logger opsional untuk debugging (bisa nil)
func DefaultConfig ¶
func DefaultConfig() *UploadConfig
DefaultConfig mengembalikan UploadConfig baru dengan nilai default yang masuk akal.
Nilai default:
- path: "/uploads"
- allowedExts: [".jpg", ".jpeg", ".png", ".pdf"]
- maxFileSize: 10 MB (10 << 20 bytes)
- maxFiles: 10
- concurrent: false (pemrosesan sequential)
- maxWorkers: 10
- logger: nil (tanpa logging)
Default ini dapat ditimpa menggunakan fungsi opsi With*.
type UploadOption ¶
type UploadOption func(*UploadConfig)
UploadOption adalah functional option untuk mengkonfigurasi UploadConfig.
func WithAllowedExts ¶
func WithAllowedExts(exts ...string) UploadOption
WithAllowedExts mengatur daftar ekstensi file yang diizinkan.
Contoh:
WithAllowedExts(".jpg", ".jpeg", ".png", ".gif")
Ekstensi tidak case-sensitive. Jika tidak diatur, ekstensi default digunakan.
func WithConcurrent ¶
func WithConcurrent(enabled bool) UploadOption
WithConcurrent mengaktifkan pemrosesan file concurrent.
Saat diaktifkan, menggunakan worker pool untuk upload paralel. Saat dinonaktifkan, memproses file secara sequential (lebih lambat namun lebih dapat diprediksi).
Contoh:
WithConcurrent(true) // Gunakan worker pool WithConcurrent(false) // Pemrosesan sequential
func WithLogger ¶
func WithLogger(logger *slog.Logger) UploadOption
WithLogger mengatur logger opsional untuk debugging operasi upload.
Jika disediakan, logs akan mencakup progres upload, error, dan detail validasi.
Contoh:
logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) WithLogger(logger)
func WithMaxFileSize ¶
func WithMaxFileSize(size uint64) UploadOption
WithMaxFileSize mengatur ukuran file maksimal dalam bytes.
Contoh:
WithMaxFileSize(10 << 20) // 10 MB WithMaxFileSize(100 << 20) // 100 MB
File yang melebihi ukuran ini akan ditolak. Hanya diatur jika size > 0.
func WithMaxFiles ¶
func WithMaxFiles(max uint8) UploadOption
WithMaxFiles mengatur jumlah maksimal file untuk di-upload sekaligus.
Contoh:
WithMaxFiles(5) // Maks 5 file per upload WithMaxFiles(10) // Maks 10 file per upload
Hanya diatur jika max > 0. Default adalah 10.
func WithMaxWorkers ¶
func WithMaxWorkers(max int) UploadOption
WithMaxWorkers mengatur jumlah concurrent workers.
Hanya berlaku jika pemrosesan concurrent diaktifkan. Default adalah 10. Hanya diatur jika max > 0.
Contoh:
WithMaxWorkers(5) // 5 parallel upload workers WithMaxWorkers(20) // 20 parallel upload workers
func WithPath ¶
func WithPath(path string) UploadOption
WithPath mengatur path direktori upload.
Contoh:
WithPath("/uploads/files")
WithPath("uploads") // otomatis diprefiks dengan /
Path otomatis disanitisasi terhadap serangan directory traversal.
type UploadResult ¶
UploadResult berisi hasil dari operasi upload file.
Fields:
- Paths: Daftar path file yang berhasil di-upload
- Errors: Map filename -> error untuk upload yang gagal (file -> alasan error)
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator is a simple validation utility
func NewValidator ¶
func NewValidator() *Validator
NewValidator membuat instance Validator baru dengan empty error map. Gunakan method chaining untuk add validations dan check hasil dengan IsValid().
Returns:
- *Validator: validator instance siap digunakan
Example:
v := NewValidator().
Required("email", email).
Email("email", email).
Required("password", password)
if !v.IsValid() {
return v.ErrorMap()
}
func (*Validator) AddError ¶
AddError menambahkan custom error untuk field tertentu. Jika field sudah ada error, skip (first error wins).
Parameters:
- field: nama field untuk error
- message: error message yang akan ditambahkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.AddError("email", "Email sudah terdaftar")
func (*Validator) Custom ¶
func (v *Validator) Custom(field string, fn func(string) bool, value string, message string) *Validator
Custom memvalidasi menggunakan custom validation function.
Parameters:
- field: nama field untuk error message
- fn: custom validation function yang return true jika valid
- value: string value yang akan divalidasi
- message: error message jika validation gagal
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Custom("username", func(u string) bool { return len(u) > 3 }, username, "Username minimal 4 karakter")
func (*Validator) Email ¶
Email memvalidasi bahwa field adalah valid email format. Menggunakan regex pattern untuk basic email validation.
Parameters:
- field: nama field untuk error message
- value: email string yang akan dicek
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Email("email", email)
func (*Validator) ErrorCount ¶
ErrorCount mengembalikan jumlah fields yang memiliki validation errors.
Returns:
- int: jumlah fields dengan errors, 0 jika tidak ada errors
Example:
if v.ErrorCount() > 0 {
return v.ErrorMap()
}
func (*Validator) ErrorMap ¶
ErrorMap mengembalikan validation errors sebagai map[field]error_message. Cocok untuk API responses untuk return field-specific errors.
Returns:
- map[string]string: map dari field name ke error message
Example:
if !v.IsValid() {
return c.JSON(400, v.ErrorMap())
}
func (*Validator) Errors ¶
Errors mengembalikan semua validation error messages sebagai string slice. Setiap field maksimal memiliki satu error message (first error wins).
Returns:
- []string: slice dari error messages, empty jika tidak ada errors
Example:
if !v.IsValid() {
errors := v.Errors()
for _, err := range errors {
fmt.Println(err)
}
}
func (*Validator) GetError ¶
GetError mengembalikan error message untuk field tertentu.
Parameters:
- field: nama field yang akan diambil error-nya
Returns:
- string: error message untuk field, empty string jika tidak ada error
Example:
errMsg := v.GetError("email")
if errMsg != "" {
return errMsg
}
func (*Validator) HasError ¶
HasError mengecek apakah field tertentu memiliki validation error.
Parameters:
- field: nama field yang akan dicek
Returns:
- bool: true jika field memiliki error, false jika tidak
Example:
if v.HasError("email") {
return "Email tidak valid"
}
func (*Validator) In ¶
In memvalidasi bahwa field value adalah salah satu dari allowed values.
Parameters:
- field: nama field untuk error message
- value: string value yang akan dicek
- allowed: variadic list dari allowed values
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.In("role", role, "admin", "user", "guest")
func (*Validator) IsValid ¶
IsValid mengecek apakah tidak ada validation errors (validation berhasil).
Returns:
- bool: true jika validation valid (no errors), false jika ada errors
Example:
if !v.IsValid() {
return v.ErrorMap()
}
func (*Validator) Length ¶
Length memvalidasi bahwa field memiliki exact length yang ditentukan.
Parameters:
- field: nama field untuk error message
- value: string value yang akan dicek panjangnya
- length: exact length yang dibutuhkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Length("code", code, 6)
func (*Validator) Matches ¶
Matches memvalidasi bahwa dua fields memiliki nilai yang sama. Berguna untuk password confirmation, email verification, dll.
Parameters:
- field: nama field untuk error message
- value: value dari field pertama
- otherField: nama field kedua untuk error message
- otherValue: value dari field kedua
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Matches("password", password, "password_confirmation", passwordConfirm)
func (*Validator) MaxLength ¶
MaxLength memvalidasi bahwa field tidak melebihi maximum length tertentu.
Parameters:
- field: nama field untuk error message
- value: string value yang akan dicek panjangnya
- max: maximum length yang diperbolehkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.MaxLength("name", name, 255)
func (*Validator) MinLength ¶
MinLength memvalidasi bahwa field memiliki minimum length tertentu. Length dihitung setelah trimspace.
Parameters:
- field: nama field untuk error message
- value: string value yang akan dicek panjangnya
- min: minimum length yang dibutuhkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.MinLength("password", password, 8)
func (*Validator) NumRange ¶
NumRange memvalidasi bahwa numeric value berada dalam range min-max.
Parameters:
- field: nama field untuk error message
- value: numeric value yang akan dicek
- min: minimum value (inclusive)
- max: maximum value (inclusive)
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.NumRange("age", age, 18, 120)
func (*Validator) OptionalEmail ¶
OptionalEmail memvalidasi email format hanya jika field present dan valid. Digunakan untuk JsonNull[string] fields dengan logic: - Present=false: skip validation (field tidak dikirim) - Present=true, Valid=false: skip validation (field adalah null) - Present=true, Valid=true: validate email format
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalEmail("alternate_email", emailJsonNull)
func (*Validator) OptionalIn ¶
OptionalIn memvalidasi value dalam allowed list hanya jika field present dan valid.
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
- allowed: variadic list dari allowed values
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalIn("status", statusJsonNull, "active", "inactive")
func (*Validator) OptionalLength ¶
OptionalLength memvalidasi exact length hanya jika field present dan valid.
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
- length: exact length yang dibutuhkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalLength("code", codeJsonNull, 6)
func (*Validator) OptionalMatches ¶
func (v *Validator) OptionalMatches(field string, value JsonNull[string], pattern string) *Validator
OptionalMatches memvalidasi regex pattern hanya jika field present dan valid.
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
- pattern: regex pattern string
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalMatches("phone", phoneJsonNull, "^\\d{10,}$")
func (*Validator) OptionalMaxLength ¶
OptionalMaxLength memvalidasi maximum length hanya jika field present dan valid.
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
- max: maximum length yang diperbolehkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalMaxLength("bio", bioJsonNull, 500)
func (*Validator) OptionalMinLength ¶
OptionalMinLength memvalidasi minimum length hanya jika field present dan valid.
Parameters:
- field: nama field untuk error message
- value: JsonNull[string] field value
- min: minimum length yang dibutuhkan
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.OptionalMinLength("bio", bioJsonNull, 10)
func (*Validator) Pattern ¶
Pattern memvalidasi bahwa field cocok dengan regex pattern yang diberikan.
Parameters:
- field: nama field untuk error message
- value: string value yang akan di-match
- pattern: regex pattern string
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Pattern("phone", phone, "^\\d{10,}$")
func (*Validator) Required ¶
Required memvalidasi bahwa field tidak kosong (setelah trimspace). Jika field sudah ada error, skip validation ini (first error wins).
Parameters:
- field: nama field untuk error message
- value: string value yang akan dicek
Returns:
- *Validator: pointer to validator untuk method chaining
Example:
v.Required("email", email)
Source Files
¶
- auth.go
- config.go
- console.go
- context.go
- database.go
- database_tracer.go
- database_utils.go
- env.go
- error.go
- file.go
- file_upload.go
- help_command.go
- helpers.go
- jsonapi_filter.go
- jsonapi_pagination.go
- jsonapi_sort.go
- jsonull.go
- jwt.go
- logger.go
- middleware.go
- middleware_auth.go
- middleware_cors.go
- middleware_csrf.go
- middleware_logger.go
- middleware_ratelimit.go
- middleware_recovery.go
- migration.go
- migration_command.go
- password.go
- ratelimit.go
- ratelimit_migration.go
- ratelimit_store.go
- response.go
- router.go
- router_command.go
- router_group.go
- server.go
- server_command.go
- token_blocklist.go
- token_migration.go
- token_store.go
- user.go
- user_migration.go
- uuid.go
- validator.go