Redirect Plugin

The Redirect plugin provides URL redirection with regex pattern matching and configurable HTTP status codes. It enables URL rewriting, legacy URL support, and conditional redirects based on request characteristics.

Overview

URL redirection is a common requirement for web applications - whether for SEO-friendly URLs, maintaining backward compatibility, or routing traffic between different services. This plugin uses regular expressions for flexible pattern matching and supports all standard HTTP redirect status codes. It can handle simple redirects, complex URL rewriting with capture groups, and conditional redirects based on protocol or other factors.

Key Features

Configuration

The redirect plugin is configured as part of the plugin pipeline in your host configuration:

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    <meta itemprop="redirect_rule_1_pattern" content="^/old-page$">
    <meta itemprop="redirect_rule_1_replacement" content="/new-page">
    <meta itemprop="redirect_rule_1_status" content="301">
</li>

Configuration Parameters

Parameter Type Required Default Description
default_status_code Integer No 302 Default redirect status code for rules without explicit status
redirect_rule_N_pattern String (Regex) Yes* - Regular expression pattern to match URLs
redirect_rule_N_replacement String Yes* - Replacement URL (supports $1, $2 capture groups)
redirect_rule_N_status Integer No default_status_code HTTP status code for this rule
redirect_rule_N_condition String No - Comma-separated conditions: "https_only", "http_only"

* At least one redirect rule is required; N is a number starting from 1

Redirect Status Codes

Code Name Method Preservation Cacheable Use Case
301 Moved Permanently No (GET/HEAD only) Yes Permanent URL changes, SEO
302 Found No (GET/HEAD only) No Temporary redirects
303 See Other No (always GET) No POST-redirect-GET pattern
307 Temporary Redirect Yes No Temporary, preserve method
308 Permanent Redirect Yes Yes Permanent, preserve method

Plugin Pipeline Placement

Important: Place the redirect plugin early in the pipeline, typically after CORS but before authentication and content-serving plugins.

Typical pipeline order:

1. cors.so            → CORS headers
2. redirect.so        → URL redirects ✓
3. basic-auth.so      → Authentication
4. file-handler.so    → Content serving

Examples

Simple Page Redirect

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    <meta itemprop="redirect_rule_1_pattern" content="^/about-us\.html$">
    <meta itemprop="redirect_rule_1_replacement" content="/about">
    <meta itemprop="redirect_rule_1_status" content="301">
</li>

URL Pattern Rewriting

<!-- Redirect /products/123 to /shop/item/123 -->
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    <meta itemprop="redirect_rule_1_pattern" content="^/products/(\d+)$">
    <meta itemprop="redirect_rule_1_replacement" content="/shop/item/$1">
    <meta itemprop="redirect_rule_1_status" content="301">
</li>

Multiple Redirect Rules

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    
    <!-- Old blog URLs to new structure -->
    <meta itemprop="redirect_rule_1_pattern" content="^/blog/(\d{4})/(\d{2})/(.+)$">
    <meta itemprop="redirect_rule_1_replacement" content="/posts/$1-$2/$3">
    <meta itemprop="redirect_rule_1_status" content="301">
    
    <!-- Legacy API endpoints -->
    <meta itemprop="redirect_rule_2_pattern" content="^/api/v1/(.*)$">
    <meta itemprop="redirect_rule_2_replacement" content="/api/v2/$1">
    <meta itemprop="redirect_rule_2_status" content="302">
    
    <!-- Remove trailing slashes -->
    <meta itemprop="redirect_rule_3_pattern" content="^(.+)/$">
    <meta itemprop="redirect_rule_3_replacement" content="$1">
    <meta itemprop="redirect_rule_3_status" content="301">
</li>

HTTPS Enforcement

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    
    <!-- Redirect all HTTP to HTTPS -->
    <meta itemprop="redirect_rule_1_pattern" content="^(.*)$">
    <meta itemprop="redirect_rule_1_replacement" content="https://example.com$1">
    <meta itemprop="redirect_rule_1_status" content="301">
    <meta itemprop="redirect_rule_1_condition" content="http_only">
</li>

Domain Migration

<!-- Redirect old domain to new domain preserving paths -->
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/redirect.so</span>
    <meta itemprop="redirect_rule_1_pattern" content="^(.*)$">
    <meta itemprop="redirect_rule_1_replacement" content="https://newdomain.com$1">
    <meta itemprop="redirect_rule_1_status" content="301">
</li>

Regular Expression Patterns

Common Patterns

Pattern Description Example Match
^/old-page$ Exact match /old-page
^/blog/.* Prefix match /blog/anything
^/item/(\d+)$ Numeric ID capture /item/123 → $1=123
^/(.+)\.html$ Extension removal /page.html → $1=page
^/(.*)/index\.html$ Index file removal /dir/index.html → $1=dir

Capture Groups

Use parentheses to capture parts of the URL for use in replacements:

# Pattern: ^/user/(\w+)/post/(\d+)$
# URL: /user/alice/post/42
# Captures: $1=alice, $2=42
# Replacement: /u/$1/p/$2
# Result: /u/alice/p/42

Testing Redirects

Using curl

# Test redirect without following
curl -I http://localhost:3000/old-page

# Test redirect and follow
curl -L http://localhost:3000/old-page

# Verbose output to see redirect chain
curl -v -L http://localhost:3000/old-page 2>&1 | grep -E "(< HTTP|< Location)"

Browser Testing

Use browser developer tools:

  1. Open Network tab
  2. Visit the old URL
  3. Check for redirect status codes
  4. Verify final destination

Automated Testing Script

#!/bin/bash
# test-redirects.sh

declare -A redirects=(
    ["/old-page"]="/new-page"
    ["/products/123"]="/shop/item/123"
    ["/blog/2024/01/hello"]="/posts/2024-01/hello"
)

for old_url in "${!redirects[@]}"; do
    expected="${redirects[$old_url]}"
    
    # Get redirect location
    location=$(curl -s -I "http://localhost:3000$old_url" | grep -i "location:" | awk '{print $2}' | tr -d '\r')
    
    if [[ "$location" == "$expected" ]]; then
        echo "✓ $old_url → $expected"
    else
        echo "✗ $old_url → $location (expected: $expected)"
    fi
done

Best Practices

SEO Considerations

Performance Impact

Troubleshooting

Common Issues

Issue Cause Solution
Redirect not working Pattern doesn't match Test regex pattern, check for typos
Infinite redirect loop Rule redirects to itself Check replacement doesn't match pattern
Wrong destination Capture group mismatch Verify $1, $2 match parentheses in pattern
HTTPS condition ignored Proxy not sending headers Check X-Forwarded-Proto header
Rules not loading Configuration syntax Check rule numbering is sequential

Debug Logging

Run the server with -v flag to see redirect matches:

./rusty-beam -v config.html

[Redirect] /old-page → /new-page (301)

Advanced Patterns

Query String Handling

<!-- Preserve query strings -->
<meta itemprop="redirect_rule_1_pattern" content="^/search$">
<meta itemprop="redirect_rule_1_replacement" content="/find">
<!-- Query string is automatically preserved -->

Case Normalization

<!-- Redirect uppercase URLs to lowercase -->
<!-- Note: Regex is case-sensitive by default -->
<meta itemprop="redirect_rule_1_pattern" content="^/About$">
<meta itemprop="redirect_rule_1_replacement" content="/about">

Multiple Capture Groups

<!-- Restructure date-based URLs -->
<meta itemprop="redirect_rule_1_pattern" content="^/(\d{4})-(\d{2})-(\d{2})/(.+)$">
<meta itemprop="redirect_rule_1_replacement" content="/archive/$1/$2/$3/$4">
<!-- /2024-01-15/post → /archive/2024/01/15/post -->

Integration with Other Plugins

Authorization Plugin

Redirects happen before authorization, so you can redirect to login pages for protected resources.

File-Handler Plugin

Use redirects to create clean URLs that map to actual files with extensions.

Access-Log Plugin

Both the redirect response (301/302) and the final destination request are logged.

See Also