How to insert a dynamic response header?

1. The problem I’m having:

I thought it might be fun to insert a sort-of response header easter egg that includes a random word. The choice is a long story :slight_smile:
e.g. X-Tagalog: Umaga

Turns out it’s a bit tricker than I expected so hoping I can get some guidance.

I thought the easiest way would to spin up a local server that just spits back the X-Color header and then copy that into the response headers but reverse_proxy doesn’t appear to be the way to go.

Another option might be to somehow get the header in using placeholders but I can’t see how you can get external info that way either.

Any pointers appreciated.

2. Error messages and/or full log output:

I don’t have any log files to share at this stage as it’s more of a how-to question

3. Caddy version:

Caddy version: 2.10.2

4. How I installed and ran Caddy:

Via apt which runs via systemd

a. System environment:

This is a standard VM running Ubuntu. No Docker etc involved.

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.3 LTS"

b. Command:

sudo systemctl start caddy.service

c. Service/unit/compose file:

d. My complete Caddy config:

Not a lot to see as very bare bones at the moment.

kinoy.io {
    # redirect to www
    redir https://www.{host}{uri}
}

www.kinoy.io {
    root * /var/www/kinoy.io
    encode

    log {
        output file /var/log/caddy/kinoy.io.log {
            roll_size 10MB # Create new file when size exceeds 10MB
            roll_keep 5 # Keep at most 5 rolled files
            roll_keep_for 30d
                }
        format console
    }
    file_server
}

5. Links to relevant resources:

Python to generate the word is very simple.

from http.server import HTTPServer, BaseHTTPRequestHandler
import random

def load_words(filename="words.txt"):
    """Reads words from a file, one word per line, and returns a list."""
    try:
        with open(filename, 'r') as f:
            # Read all lines, strip whitespace (like the newline character) from each
            words = [line.strip() for line in f if line.strip()]
        return words
    except FileNotFoundError:
        print(f"ERROR: Word file '{filename}' not found. Falling back to default list.")
        return ["maliit", "dalawa", "mahal", "pera", "asawa"] # Fallback

# --- Load the words once when the script starts ---
words = load_words()
num_words = len(words)

# Ensure we have a list to work with
if num_words == 0:
    print("WARNING: Word list is empty. Server will return default.")

# --------------------------------------------------

class HeaderHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if num_words > 0:
            word = random.choice(words)
        else:
            word = "kamali" # tagalog for mistake

        self.send_response(200)
        self.send_header('X-Tagalog', word)
        self.send_header('Content-Type', 'text/plain')
        self.end_headers()
        self.wfile.write(b'')

port = 8080
print(f"Server starting on port {port} with {num_words} words loaded.")
HTTPServer(('localhost', port), HeaderHandler).serve_forever()

You could write your own module to handle all that.

Another option is to define a map with all the words you need and then use {extra.rand.int} to randomly pick from it. Just an idea!

1 Like

You could probably adjust this example to your needs

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.