Generic redirect from www. domains to non-www

Hi,

We’re running a Caddy server to proxy requests from custom domains to an S3 Bucket, containing static sites. This way we can:

  • Use the same S3 bucket to host multiple different sites
  • Create sites dynamically
  • Automatically add https to static sites hosted in S3 using custom domains

Our Caddyfile looks something like this:

:443 {
  tls certificates@example.com {
    max_certs 100
  }
  proxy / http://sites-bucket.s3-website-eu-west-1.amazonaws.com/ {
    policy round_robin
    transparent
    header_upstream Host sites-bucket
  }
  rewrite {
    regexp (.*)
    ext /
    to /{host}/{1}/
  }
  rewrite / {
    regexp (.*)
    to /{host}/{1}
  }
}


:80 {
  proxy / http://sites-bucket.s3-website-eu-west-1.amazonaws.com/ {
    policy round_robin
    transparent
    header_upstream Host sites-bucket
  }
  rewrite {
    regexp (.*)
    ext /
    to /{host}/{1}/
  }
  rewrite / {
    regexp (.*)
    to /{host}/{1}
  }
}

This proxies all requests to a folder in the S3 bucket which name matches the domain name in the request. The main limitation, as you can see, is that there’s a 1-1 mapping between domain names and folders in the S3 bucket, so each folder matches one and only one domain name.

We also want to support accessing those sites using the www. subdomain of those custom domains, therefore my question: is it possible to set a generic redirect rule in Caddy to redirect all www. subdomains to their non-www counterpart?

I thought of creating a new server block using www.*:443 and placing a redirect rule inside, but I’m not sure if/how I can get the non-www domain name from that.

Thanks!
iuri

Hi Iuri!

I don’t believe it’s possible to manipulate the host/domain via Caddyfile currently (such as identifying and removing the www. as you require). rewrite operates on the URI, and redir has no regex functionality.

This would probably require extending Caddy itself.

redir has no regex functionality.

That’s not entirely true. The docs for redir describe an extended syntax where you can specify conditions, and they can use regular expressions.

You got me there. You can’t take matched groups out of the if subdirective to use in the redirect target, though, I understand. That would probably be pretty handy for this use case.

Good point. We’ll probably improve on it in the future, somehow.

We’ve finally opted to add a fastcgi backend with a simple PHP script that does the redirect. Is not optimal, but it’s the only option we found so far.

Just in case someone is interested, this is how the Caddyfile looks like now:

:443 {
  tls certificates@example.com {
    max_certs 100
  }
  proxy / http://sites-bucket.s3-website-eu-west-1.amazonaws.com/ {
    policy round_robin
    transparent
    header_upstream Host sites-bucket
    except /redir.php
  }
  fastcgi /redir.php 127.0.0.1:9000 php {
    root /var/www
  }
  rewrite / {
    regexp .*
    if {host} starts_with www.
    to /redir.php
  }
  rewrite {
    regexp (.*)
    ext /
    to /{host}/{1}/
  }
  rewrite / {
    regexp (.*)
    to /{host}/{1}
  }
}

And this is the PHP script that does the redirect:

<?php

// Get URL parts
$newDomain = substr($_SERVER['HTTP_HOST'], 4);
$requestUri = $_SERVER['REQUEST_URI'];

// Compose new URL
$newUrl = 'https://' . $newDomain . $requestUri;

// Redirect with 301
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $newUrl);

I hope we can achieve this in a simpler way within Caddy in the future :slight_smile:
Thanks for the help.

This is a major bummer for me right now :frowning:
I need generic redirects based on the first part of host name, also to be able to set some context variable for dev.* domain names.
Cheers.

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