I’ve spent a good part of the last two days trying to track down an issue that was bothering me. My server is tuned to send a lot of annoying bots to the scrap heap with Rewrite rules that return a 403 response. I also just converted the server to HTTP/2.0 (yeah, I know; quiet in the back).
However, many of the bots use HTTP/1.1. What was weird is that when you look at the logs in Apache, you get the following items.
172.232.187.115 - - [06/May/2026:18:51:26 +0000] "GET / HTTP/1.1" 403 2877 "-" "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1 like Mac OS X) AppleWebKit/534.39.5 (KHTML, like Gecko) Version/3.0.5 Mobile/8B116 Safari/6534.39.5"
172.232.187.115 - - [06/May/2026:18:51:42 +0000] "GET / HTTP/2.0" 403 90 "-" "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1 like Mac OS X) AppleWebKit/534.39.5 (KHTML, like Gecko) Version/3.0.5 Mobile/8B116 Safari/6534.39.5"
Can anyone spot the issue? Well, if you look closely, you’ll see that HTTP/1.1 response is recorded as being much larger than that of the HTTP/2.0 response for the same 403 response.
Guess what? This is an artifact of the way that Apache processes these requests! My friend Claude described it this way:
For HTTP/1.1, when
[F]fires, Apache generates the full default error page first (2911 bytes), logs that size via%b, then ErrorDocument substitutes it with the 44-byte response before sending. The log records the pre-substitution size.For HTTP/2.0,
mod_http2logs the post-substitution size (plus HTTP/2 frame overhead accounting for the extra 82 bytes above 44).
It’s always fun to go off on a Snipe Hunt and learn a lot about the internals of software you use every day.