Apache mod_rewrite 403 Forbidden Error When URL Parameter Exceeds 255 Characters


4 views

When implementing URL rewriting in Apache using mod_rewrite, many developers encounter a puzzling behavior: URLs with parameter strings longer than 255 characters mysteriously fail with 403 Forbidden errors, while direct access to the same parameters works perfectly.

# Working case (short parameter)
http://example.com/1,2,3/foo/

# Failing case (long parameter)
http://example.com/1,2,3,...,256/foo/

This limitation stems from Apache's internal path handling before mod_rewrite even processes the request. The issue occurs because:

  • Apache has a default PATH_MAX limit (typically 255-4096 bytes depending on OS)
  • The check happens before mod_rewrite sees the request
  • No rewrite logs are generated because the failure occurs in earlier processing

Here are three proven approaches to solve this:

1. Adjust LimitRequestLine and LimitRequestFieldSize

# In httpd.conf or virtual host configuration
LimitRequestLine 4094
LimitRequestFieldSize 4094

2. Alternative URL Structure

Consider passing the parameter via POST or splitting into multiple paths:

# Original problematic rule
RewriteRule ^([\d,]+)/foo/$ /foo.php?id=$1 [L,QSA]

# Alternative approach
RewriteRule ^foo/([\d,]+)/?$ /foo.php?id=$1 [L,QSA]

3. Client-Side Compression

For extremely long parameters, implement Base64 encoding in JavaScript:

// JavaScript encode
const params = [1,2,3,...,1000].join(',');
const compressed = btoa(params);
// Send as: example.com/foo/?q=[compressed]

// PHP decode
$compressed = $_GET['q'];
$params = base64_decode($compressed);

To verify your solution works with long parameters:

  1. Create a test script that generates parameter strings of varying lengths
  2. Monitor both access.log and error.log during testing
  3. Use curl with different parameter lengths for validation
# Test command
curl -I "http://localhost/1,2,...,300/foo/"

When adjusting these limits:

  • Increase values gradually rather than setting extremely high numbers
  • Consider security implications of larger buffer sizes
  • Document these non-default settings for future maintenance
  • Test performance impact under load

While working with Apache's mod_rewrite, I encountered a puzzling limitation: rewrite rules fail silently when the parameter length exceeds 255 characters. The server returns a 403 Forbidden error without any rewrite log entries, making debugging particularly challenging.

After extensive testing, I discovered this isn't actually a mod_rewrite limitation, but rather a security feature in Apache called LimitRequestLine. By default, Apache restricts the maximum size of the HTTP request line to 8190 bytes, but some Linux distributions set lower limits in their default configurations.

# Check current limit in your Apache configuration
grep LimitRequestLine /etc/apache2/apache2.conf

Here are three approaches to resolve this:

1. Increasing LimitRequestLine

# In your Apache configuration (httpd.conf or apache2.conf)
LimitRequestLine 16384  # Double the default value

2. Alternative Rewrite Approach

For systems where you can't modify server configuration:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/([0-9,]{256,})/foo/$
RewriteRule ^ /foo.php?id=%1 [L,QSA,NE]

3. Using PATH_INFO Instead

RewriteRule ^/([\\d,]+)/foo/$ /foo.php/$1 [L]
# Then in PHP:
$path = explode('/', $_SERVER['PATH_INFO']);
$ids = $path[1];

Different web servers handle this differently:

  • Nginx: No default limit on request line length
  • IIS: Default limit of 16K
  • Lighttpd: Configurable via server.max-request-size

When dealing with long parameters:

  • Consider using POST instead of GET for large data transfers
  • Implement pagination or chunking for extremely large parameter sets
  • Validate input length in your application code
  • Monitor your server logs for 403 errors

To properly diagnose such issues:

# Enable full rewrite logging
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 9
LogLevel debug