Are you certain there isn’t some other webserver between Caddy and Django intercepting it? Are you actually running Django configured with HTTPS? Or is Heroku doing some HTTPS stuff for you itself? It might be filtering some of the headers.
The log you showed here are the request headers as Caddy receives them. This all looks fine.
After turning on the debug
global option, check the logs for the reverse_proxy
upstream request, which will show you the X-Forwarded-*
headers Caddy adds to request.