Overview
The extractors package provides standardized value extraction utilities for Fiber middleware. Extractors help you retrieve data from various HTTP request sources with consistent behavior, security awareness, and RFC compliance.
Extractors are primarily used by middleware (KeyAuth, Session, CSRF) but can also be used in your application code.
Extractors provide several benefits:
- Consistency - Same extraction logic across all middleware
- Security Awareness - Built-in warnings for insecure patterns
- RFC Compliance - Standards-compliant parsing (Authorization header, token validation)
- Fallback Support - Try multiple sources with automatic fallback
- Source Tracking - Know where values came from for security decisions
Extract values from HTTP headers:
import "github.com/gofiber/fiber/v3/extractors"
app.Use(func(c fiber.Ctx) error {
extractor := extractors.FromHeader("X-API-Key")
apiKey, err := extractor.Extract(c)
if err == extractors.ErrNotFound {
return c.Status(401).SendString("API key required")
}
// Use apiKey for authentication
return c.Next()
})
Extract from Authorization header with RFC 9110/7235 compliance:
// Extract Bearer token
extractor := extractors.FromAuthHeader("Bearer")
token, err := extractor.Extract(c)
// Input: "Authorization: Bearer abc123"
// Output: "abc123"
// Validates token68 format:
// ✅ "Bearer abc123" -> "abc123"
// ✅ "Bearer token-123.xyz" -> "token-123.xyz"
// ❌ "Bearer abc def" -> ErrNotFound (space in token)
// ❌ "Bearer ab=cd" -> ErrNotFound (padding in middle)
Token Validation
The Authorization header extractor enforces strict RFC compliance:
- Allowed characters: A-Z, a-z, 0-9, -, ., _, ~, +, /, =
- Padding rules: = only at the end
- Whitespace: Only single space between scheme and token
- Case-insensitive: Scheme matching (Bearer/bearer/BEARER)
// Raw header extraction (no validation)
extractor := extractors.FromAuthHeader("")
value, _ := extractor.Extract(c)
// Input: "Authorization: CustomScheme anything goes"
// Output: "CustomScheme anything goes"
FromCookie
Extract values from cookies:
extractor := extractors.FromCookie("session_id")
sessionID, err := extractor.Extract(c)
if err != nil {
return c.Status(401).SendString("Session required")
}
FromQuery
Extract from URL query parameters:
extractor := extractors.FromQuery("token")
token, err := extractor.Extract(c)
// URL: /api/data?token=abc123
// Output: "abc123"
Query parameters appear in URLs, which can leak sensitive data through logs, browser history, and referrer headers. Use headers or cookies for sensitive values.
FromParam
Extract from URL path parameters:
// Route: /users/:userId
extractor := extractors.FromParam("userId")
userID, err := extractor.Extract(c)
// URL: /users/123
// Output: "123"
Extract from form data:
extractor := extractors.FromForm("username")
username, err := extractor.Extract(c)
// Form: username=john&password=secret
// Output: "john"
FromCustom
Create custom extraction logic:
extractor := extractors.FromCustom("computed", func(c fiber.Ctx) (string, error) {
// Complex extraction logic
if value := c.Locals("computed_token"); value != nil {
return value.(string), nil
}
// Fallback to environment
if token := os.Getenv("DEFAULT_TOKEN"); token != "" {
return token, nil
}
return "", extractors.ErrNotFound
})
value, err := extractor.Extract(c)
Custom extractors break source awareness. Middleware cannot determine security implications or provide source-based warnings.
The Chain function tries multiple extractors in order:
// Try header first, then cookie, then query
extractor := extractors.Chain(
extractors.FromHeader("X-API-Key"),
extractors.FromCookie("api_key"),
extractors.FromQuery("api_key"),
)
apiKey, err := extractor.Extract(c)
if err != nil {
return c.Status(401).SendString("API key required")
}
Chain Behavior
- Returns first successful extraction (non-empty value, no error)
- Skips extractors with nil Extract functions
- Returns last error if all fail
- Returns
ErrNotFound if no extractors provided
// Chain stops at first success
extractor := extractors.Chain(
extractors.FromHeader("X-Key"), // Not found
extractors.FromCookie("key"), // Found: "abc123" ✓ (returns this)
extractors.FromQuery("key"), // Never checked
)
Middleware Integration
KeyAuth Middleware
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/keyauth"
"github.com/gofiber/fiber/v3/extractors"
)
app.Use(keyauth.New(keyauth.Config{
// Try multiple sources
Extractor: extractors.Chain(
extractors.FromAuthHeader("Bearer"),
extractors.FromHeader("X-API-Key"),
extractors.FromQuery("api_key"),
),
Validator: func(c fiber.Ctx, key string) (bool, error) {
return key == "valid-key", nil
},
}))
Session Middleware
import (
"github.com/gofiber/fiber/v3/middleware/session"
"github.com/gofiber/fiber/v3/extractors"
)
store := session.New(session.Config{
Extractor: extractors.FromCookie("session_id"),
})
app.Get("/profile", func(c fiber.Ctx) error {
sess, err := store.Get(c)
if err != nil {
return err
}
userID := sess.Get("user_id")
return c.JSON(fiber.Map{"user_id": userID})
})
CSRF Middleware
import (
"github.com/gofiber/fiber/v3/middleware/csrf"
"github.com/gofiber/fiber/v3/extractors"
)
app.Use(csrf.New(csrf.Config{
// Prefer header, fallback to form
Extractor: extractors.Chain(
extractors.FromHeader("X-CSRF-Token"),
extractors.FromForm("_csrf"),
),
}))
Security Considerations
Source Security Characteristics
Headers (Most Secure)
- Not visible in URLs
- Not logged by default
- May be stripped by proxies
- Best for: API keys, auth tokens
Cookies (Good for Sessions)
- Secure with proper flags (Secure, HttpOnly, SameSite)
- Automatically sent by browsers
- Protected from JavaScript (with HttpOnly)
- Best for: Session IDs, remember-me tokens
Query Parameters (Use Sparingly)
- Visible in URLs
- Logged by servers/proxies
- Stored in browser history
- Sent in Referer headers
- Best for: Non-sensitive parameters, public identifiers
Form Data (Context Dependent)
- Not visible in URLs (if POST)
- May be logged
- Requires correct content type
- Best for: User input, file uploads
Ordering Strategy
Order extractors by security preference:
// Good: Most secure first
extractors.Chain(
extractors.FromAuthHeader("Bearer"), // Most secure
extractors.FromHeader("X-API-Key"), // Secure
extractors.FromCookie("auth_token"), // Moderately secure
extractors.FromQuery("token"), // Least secure
)
// Bad: Least secure first
extractors.Chain(
extractors.FromQuery("token"), // Will leak in logs!
extractors.FromAuthHeader("Bearer"), // Never reached if query exists
)
Common Security Issues
API Keys in URLs
// ❌ DON'T: API keys visible in logs
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromQuery("api_key"),
}))
// ✅ DO: API keys in headers
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromHeader("X-API-Key"),
}))
Session Tokens in Query Parameters
// ❌ DON'T: Session tokens can be bookmarked
store := session.New(session.Config{
Extractor: extractors.FromQuery("session"),
})
// ✅ DO: Session tokens in cookies
store := session.New(session.Config{
Extractor: extractors.FromCookie("session_id"),
})
Advanced Usage
Extractors provide metadata for introspection:
extractor := extractors.Chain(
extractors.FromHeader("X-Key"),
extractors.FromCookie("key"),
)
fmt.Println("Primary source:", extractor.Source) // SourceHeader
fmt.Println("Primary key:", extractor.Key) // "X-Key"
fmt.Println("Chain length:", len(extractor.Chain)) // 2
for i, e := range extractor.Chain {
fmt.Printf("Extractor %d: source=%v, key=%s\n", i, e.Source, e.Key)
}
Source Constants
const (
SourceHeader Source = iota // HTTP headers
SourceAuthHeader // Authorization header
SourceForm // Form data
SourceQuery // Query parameters
SourceParam // URL parameters
SourceCookie // Cookies
SourceCustom // Custom extraction
)
extractor := extractors.FromCustom("conditional", func(c fiber.Ctx) (string, error) {
// Use different sources based on client type
if c.Get("User-Agent") == "MobileApp/1.0" {
return c.Get("X-Mobile-Token"), nil
}
return c.Cookies("web_session"), nil
})
Best Practices
- Use HTTPS - Encrypt all traffic to protect extracted values
- Choose appropriate sources - Match source to security requirements
- Order chains by security - Most secure sources first
- Validate extracted values - Always validate and sanitize
- Avoid query parameters for secrets - Use headers or cookies
- Document your API - Specify where clients should send values
- Monitor extraction failures - Track patterns of missing values
- Use standard headers - Follow conventions (Authorization, X-API-Key)
Troubleshooting
Value Not Found
extractor := extractors.FromHeader("X-API-Key")
value, err := extractor.Extract(c)
if err == extractors.ErrNotFound {
// Check request headers
fmt.Println("Headers:", c.GetReqHeaders())
// Verify header name (case-insensitive)
fmt.Println("X-API-Key:", c.Get("X-API-Key"))
fmt.Println("x-api-key:", c.Get("x-api-key"))
}
Chain Not Working
extractor := extractors.Chain(
extractors.FromHeader("X-Key"),
extractors.FromCookie("key"),
)
value, err := extractor.Extract(c)
if err != nil {
// Debug each extractor
for i, e := range extractor.Chain {
v, err := e.Extract(c)
fmt.Printf("Extractor %d: value=%q, error=%v\n", i, v, err)
}
}
extractor := extractors.FromAuthHeader("Bearer")
token, err := extractor.Extract(c)
if err == extractors.ErrNotFound {
// Check header format
authHeader := c.Get("Authorization")
fmt.Println("Raw header:", authHeader)
// Common issues:
// - Missing space: "Bearertoken"
// - Wrong scheme: "Basic abc123"
// - Invalid characters: "Bearer abc def"
// - Padding in middle: "Bearer ab=cd"
}
See Also