2

We're moving thousands of sub directories, to a sub domain. The exact same slug, but its a sub domain now. All of these sub directories are going to cause a 404.

Using htaccess, how can I take the slug of the 404 at domain.com/slug/ and redirect to slug.domain.com?

I appreciate anyone's time!

  • Is there anything after the /slug/ in the URL-path? – MrWhite Nov 25 '19 at 23:53
  • No never. Its an affiliate system so, domain.com/affiliates-slug/ would become affiliates-slug.domain.com exactly, only difference is sub-dir to sub-domain. – Michael Nov 25 '19 at 23:57
2

Using mod_alias's RedirectMatch

RedirectMatch permanent "^/?([a-z0-9\-]+)/?$" "https://$1.example.com/"

Using mod_rewrite:

RewriteRule "^/?([a-z0-9\-]+)/?$" "https://$1.example.com/" [R=301,L]

This redirects only directories that are made up of the characters that are safe for subdomains (numbers, letters, and dashes -- [a-z0-9\-]). This doesn't check to see if it starts or ends with a dash, (not allowed as a subdomain), so this could be improved a bit. To make sure it doesn't start or end with a dash, you could instead use [a-z0-9]+(-+[a-z0-9]+)* inside the parenthesis.

The slashes are both optional (the ? after each slash). That means it will redirect both /slug and /slug/. The first slash is optional just because it makes the mod_rewrite rule more portable. It will work either in .htaccess or in your Apache .conf file.

The ^ and $ on the rules are "starts with" and "ends with" respectively. That is so the rules don't match partial URL paths.

The parenthesis are used for grouping. The $1 is the text that is pulled from inside the (first set of) parenthesis.

These assume that the subdomains are handled in a different directory and that there are no exceptions. If you do have exceptions you could add them as conditions to the rewrite rule. For example you might want to make exceptions for any actual files that exist. Another exception might be so that they only work on your main host name don't try to re-redirect slugs on the subdomains. Like this:

RewriteCond "%{HTTP_HOST}" "www.example.com" [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule "^/?([a-z0-9\-]+)/?$" "https://$1.example.com/" [R=301,L]
  • Thank you but I don't see how this checks if the sub directory is a 404 or not. We have sub directions which we are removing, which will generate a 404 and if i generates a 404 then I want to redirect to the sub domain. Otherwise, we also have sub directories which will remain, regular pages, so I'm under the impression this htaccess content should some how check if its a 404, before it redirects. Thank you! – Michael Nov 26 '19 at 0:51
  • Those RewriteCond would prevent it from redirecting a file that actually exists. – Stephen Ostermiller Nov 26 '19 at 1:52
  • Amazing, I never realized that it checks whether or not the path exists or not. Thank you! – Michael Nov 26 '19 at 19:20
2

You can do something like the following using mod_rewrite at the top of the root .htaccess file on the main domain:

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/$1 !-d
RewriteRule ^([^./]+)/$ https://$1.example.com/ [R=302,L]

The RewriteRule pattern ^([^./]+)/$ matches just the first (and only) path segment, excluding files (since the pattern excludes dots). The mandatory trailing slash is excluded from the capturing subpattern. Modifying this to only match a valid subdomain pattern, as in @Stephen's answer, would be advisable.

The preceding condition (RewriteCond directive) ensures that the request does not map to an existing directory. (I'm assuming you have valid directories that need to still function.)

$1 is a backreference to the captured path segment from the URL-path, excluding the first and trailing slash, ie. slug in your example.

Note that this is a temporary (302) redirect. Only change it to a permanent (301) - if that is the intention - once you have confirmed that it works OK. This is to avoid any caching issues.

Examples:

Applying the above directives...

A. Request example.com/slug/.

  1. slug/ matches the RewriteRule pattern ^([^./]+)/$
  2. /slug does not exist as a directory on the filesystem.
  3. Redirected to https://slug.example.com/. SUCCESS

B. Request example.com/directory/.

  1. directory/ matches the RewriteRule pattern ^([^./]+)/$
  2. /directory exists as a directory on the filesystem. FAIL

C. Request example.com/directory/something.

  1. directory/something does not match the RewriteRule pattern ^([^./]+)/$. FAIL

D. Request example.com/file.html.

  1. file.html does not match the RewriteRule pattern ^([^./]+)/$. FAIL

E. Request example.com/slug (no trailing slash).

  1. slug does not match the RewriteRule pattern ^([^./]+)/$. FAIL
  • Thank you but I don't see how this checks if the sub directory is a 404 or not. We have sub directions which we are removing, which will generate a 404 and if i generates a 404 then I want to redirect to the sub domain. Otherwise, we also have sub directories which will remain, regular pages, so I'm under the impression this htaccess content should some how check if its a 404, before it redirects. Thank you! – Michael Nov 26 '19 at 0:52
  • I'm re-reading your answer and looks like you actually did address this, I'm just having a hard time processing it. We do in fact have .com/things/ that will remain intact. Then we have countless .com/stuffs/ which will no longer exist but will be replaced by subdomains using a wild card. – Michael Nov 26 '19 at 0:56
  • 1
    The above determines that the request does not map to a physical directory (or a file - assuming all "files" have a "file extension" delimited by a dot). So, if it does not map to a directory or a file then it's a 404... unless... you are are routing URLs through a CMS and 404s are determined by the CMS? If that is the case then you can't do this in .htaccess since it would be impossible to determine what is a 404 or not at the time .htaccess is processed. – MrWhite Nov 26 '19 at 0:59
  • I've added some examples, of what happens when applying those directives to different URL requests. Note that I have assumed that the trailing slash is mandatory, since you've included it on the example URL in your question. – MrWhite Nov 26 '19 at 1:17
  • How did you get on with this? – MrWhite Nov 26 '19 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.