Skip to main content

Overview

The secure middleware enforces HTTPS connections and adds security headers. It’s a comprehensive security solution that combines SSL redirect with security header management. Use it when you need:
  • Automatic HTTP to HTTPS redirect
  • Security headers in one middleware
  • Flexible security configuration
  • Development/production toggle

Installation

import "github.com/go-mizu/mizu/middlewares/secure"

Quick Start

app := mizu.New()

// Default security settings
app.Use(secure.New())

Configuration

Options

OptionTypeDefaultDescription
SSLRedirectbooltrueRedirect HTTP to HTTPS
SSLHoststring""Host for SSL redirect
SSLTemporaryRedirectboolfalseUse 307 instead of 301
STSSecondsint640HSTS max-age (0 = disabled)
STSIncludeSubdomainsboolfalseHSTS includeSubDomains
STSPreloadboolfalseHSTS preload
ForceSTSHeaderboolfalseSend HSTS on HTTP
ContentTypeNosniffbooltrueX-Content-Type-Options
FrameDenybooltrueX-Frame-Options: DENY
CustomFrameOptionsstring""Custom X-Frame-Options
XSSProtectionstring"1; mode=block"X-XSS-Protection
ContentSecurityPolicystring""CSP header
ReferrerPolicystring""Referrer-Policy
IsDevelopmentboolfalseDisable all features
ProxyHeaders[]string["X-Forwarded-Proto"]Headers for HTTPS detection

Examples

Basic HTTPS Redirect

// Redirect all HTTP to HTTPS
app.Use(secure.New())

Production Configuration

app.Use(secure.WithOptions(secure.Options{
    SSLRedirect:         true,
    STSSeconds:          31536000, // 1 year
    STSIncludeSubdomains: true,
    STSPreload:          true,
    ContentTypeNosniff:  true,
    FrameDeny:           true,
    ContentSecurityPolicy: "default-src 'self'",
    ReferrerPolicy:      "strict-origin-when-cross-origin",
}))

Development Mode

app.Use(secure.WithOptions(secure.Options{
    IsDevelopment: true, // Disables all security features
}))

Behind a Proxy

app.Use(secure.WithOptions(secure.Options{
    SSLRedirect: true,
    ProxyHeaders: []string{
        "X-Forwarded-Proto",
        "X-Forwarded-SSL",
    },
}))

Custom SSL Host

// Redirect to different host
app.Use(secure.WithOptions(secure.Options{
    SSLRedirect: true,
    SSLHost:     "secure.example.com",
}))

Temporary Redirect

// Use 307 for testing, preserves method
app.Use(secure.WithOptions(secure.Options{
    SSLRedirect:          true,
    SSLTemporaryRedirect: true,
}))

Frame Options

// Allow framing from same origin
app.Use(secure.WithOptions(secure.Options{
    FrameDeny:          false,
    CustomFrameOptions: "SAMEORIGIN",
}))

Environment-Based Configuration

func setupSecurity(app *mizu.App) {
    isDev := os.Getenv("ENV") == "development"

    app.Use(secure.WithOptions(secure.Options{
        IsDevelopment:       isDev,
        SSLRedirect:         !isDev,
        STSSeconds:          31536000,
        STSIncludeSubdomains: true,
        ContentTypeNosniff:  true,
        FrameDeny:           true,
    }))
}

Full Security Setup

app.Use(secure.WithOptions(secure.Options{
    // SSL
    SSLRedirect:          true,
    SSLTemporaryRedirect: false,

    // HSTS
    STSSeconds:           31536000,
    STSIncludeSubdomains: true,
    STSPreload:           true,

    // Security Headers
    ContentTypeNosniff:    true,
    FrameDeny:             true,
    XSSProtection:         "1; mode=block",
    ContentSecurityPolicy: "default-src 'self'; script-src 'self'",
    ReferrerPolicy:        "strict-origin-when-cross-origin",

    // Proxy support
    ProxyHeaders: []string{"X-Forwarded-Proto"},
}))

API Reference

Functions

// New creates middleware with default options
func New() mizu.Middleware

// WithOptions creates middleware with custom options
func WithOptions(opts Options) mizu.Middleware

Headers Set

The middleware sets these headers based on configuration:
HeaderConditionValue
Strict-Transport-SecuritySTSSeconds > 0max-age=X; includeSubDomains; preload
X-Content-Type-OptionsContentTypeNosniffnosniff
X-Frame-OptionsFrameDeny or CustomDENY or custom
X-XSS-ProtectionXSSProtection setConfigured value
Content-Security-PolicyCSP setConfigured policy
Referrer-PolicyReferrerPolicy setConfigured policy

Technical Details

Implementation Overview

The secure middleware implements a comprehensive security layer that:
  1. HTTPS Detection: Checks for secure connections via:
    • Direct TLS connection (r.TLS != nil)
    • Proxy headers (X-Forwarded-Proto, X-Forwarded-SSL, etc.)
    • Case-insensitive header matching using strings.EqualFold
  2. SSL Redirection: When HTTP is detected and SSLRedirect is enabled:
    • Constructs HTTPS URL: https:// + host + requestURI
    • Uses SSLHost if specified, otherwise uses request host
    • Returns 301 (permanent) or 307 (temporary) redirect based on SSLTemporaryRedirect
  3. Security Header Application: Sets headers conditionally based on:
    • Connection security (HTTPS vs HTTP)
    • Configuration options
    • Development mode (bypasses all security when IsDevelopment is true)

Header Construction

Strict-Transport-Security (HSTS):
max-age=<STSSeconds>[; includeSubDomains][; preload]
  • Only set on HTTPS connections unless ForceSTSHeader is true
  • Requires STSSeconds > 0 to be enabled
X-Frame-Options:
  • Priority: CustomFrameOptions > FrameDeny > none
  • FrameDeny sets “DENY”, CustomFrameOptions allows “SAMEORIGIN” or other values
Default Headers (when using New()):
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • SSLRedirect: enabled

Proxy Support

The middleware checks proxy headers in order:
for _, header := range opts.ProxyHeaders {
    if strings.EqualFold(r.Header.Get(header), "https") {
        isSSL = true
        break
    }
}
Common proxy headers:
  • X-Forwarded-Proto (default)
  • X-Forwarded-SSL
  • Front-End-Https

Performance Optimization

The middleware uses a custom itoa function instead of strconv.Itoa for integer-to-string conversion:
  • Avoids heap allocations
  • Uses fixed-size array [20]byte for conversion
  • Handles negative numbers and zero efficiently

Security Considerations

  1. HSTS Commitment - Once set, browsers remember for max-age duration
  2. SSL Certificate - Ensure valid certificate before enabling HSTS
  3. Subdomains - Only enable STSIncludeSubdomains if all subdomains support HTTPS
  4. Preload - Apply at hstspreload.org for browser built-in list

HSTS Timeline

// Start with short duration
app.Use(secure.WithOptions(secure.Options{
    STSSeconds: 3600, // 1 hour for testing
}))

// Increase gradually
// STSSeconds: 86400    // 1 day
// STSSeconds: 604800   // 1 week
// STSSeconds: 31536000 // 1 year (production)

Best Practices

  • Start with short HSTS duration, increase gradually
  • Test thoroughly before enabling preload
  • Use IsDevelopment flag for local development
  • Configure ProxyHeaders when behind load balancers

Testing

The secure middleware includes comprehensive test coverage for all features:
Test CaseDescriptionExpected Behavior
TestNewDefault middleware with SSL redirectRedirects HTTP to HTTPS with 301 status, Location header set to https://example.com/
TestWithOptions_NoSSLRedirectMiddleware with SSL redirect disabled but security headers enabledReturns 200 OK, sets X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection: 1; mode=block
TestWithOptions_HSTSHSTS configuration with all options enabledSets Strict-Transport-Security header with max-age=31536000; includeSubDomains; preload
TestWithOptions_CustomFrameOptionsCustom frame options instead of default DENYSets X-Frame-Options: SAMEORIGIN
TestWithOptions_CSPContent Security Policy configurationSets Content-Security-Policy: default-src ‘self’
TestWithOptions_ReferrerPolicyReferrer policy configurationSets Referrer-Policy: strict-origin-when-cross-origin
TestWithOptions_SSLHostSSL redirect to custom host with temporary redirectRedirects with 307 status to https://secure.example.com/path?q=1
TestWithOptions_ProxyHeaderRequest behind proxy with X-Forwarded-Proto: httpsDoes not redirect (200 OK) since connection is detected as HTTPS via proxy header
TestWithOptions_IsDevelopmentDevelopment mode enabledBypasses all security features, returns 200 OK without redirect or headers