1

I have this folder structure:

/fonts
  /myfont.eot
  /myfont.svg
  /myfont.ttf
  /myfont.woff
  /myfont.woff2
/content
  /page1
    /files
      /logo.png
      /style.css
    /index.html
  /page2
    /files
      /logo.png
      /style.css
    /index.html
  /page3
    /files
      /logo.png
      /style.css
    /a
      /index.html
    /b
      /index.html
  ...

The URLs one would call look like this:

  • example.com/content/page1
  • example.com/content/page2
  • example.com/content/page3/a
  • example.com/content/page3/b

Now all I want to achieve with an .htaccess file located in /page3 is that whoever visits example.com/content/page3 is properly redirect to example.com/content/page3/a (or example.com/content/page3/a/index.html, I don't mind whether the file name is in the URL or not).

I tried

DirectoryIndex /content/page3/a/index.html

but in this case when I open example.com/content/page3 all relative references in the /a/index.html file are broken because of the missing directory level in the URL. Furthermore, while calling example.com/content/page3/a works, example.com/content/page3/b gives 403 Forbidden.

I tried

Redirect 301 /content/page3 /content/page3/a

but this obviously results in an endless redirect spiral to example.com/content/page3/a/a/a/a/a/a/...... until the server stops trying.

So I figured I need some RedirectCond and RedirectRule configuration. Unfortunately, I don't understand the syntax, and all examples I looked at are doing it on the top-level with more complex stuff like redirecting files and sub-folders, sometimes off to another domain etc.

I tried this

RewriteEngine On

RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$
RewriteCond %{REQUEST_URI} ^/content/page3/$
RewriteRule ^/content/page3/?$ /content/page3/a [L]

because I figured this would replace "/content/page3" with "/content/page3/a", but to no avail, it doesn't do anything.

I now went with using

DirectoryIndex /content/page3/a/index.html index.html

and replaced the relative references in the document with absolute ones. This works.

But firstly I would still prefer if the references could remain relative, so the document doesn't break in case the page3 folder is ever renamed, and secondly I'd rather have the /a subdirectory in the URL for clarity as to what is displayed.

How can I achieve this?

1 Answer 1

0

I would still prefer if the references could remain relative

In that case you really need an external redirect, not an internal rewrite or internal subrequest (which is what you are essentially doing with the DirectoryIndex directive). And if you'd "rather have the /a subdirectory in the URL" then you definitely need an external redirect.

The URLs one would call look like this:

  • example.com/content/page1
  • example.com/content/page2
  • example.com/content/page3/a
  • example.com/content/page3/b

I note that you've not included trailing slashes on any of these URLs that map to physical directories. These should contain trailing slashes for what you are trying to do i.e. link to example.com/content/page1/, not example.com/content/page1. The reason being is that Apache (mod_dir) will otherwise "fix" the URL with a 301 redirect to append the trailing slash. If you do want to omit the trailing slash on these "directory" URLs then you have more work to do.

an .htaccess file located in /page3

Using mod_rewrite you could do the following:

RewriteEngine On
RewriteRule ^$ /content/page3/a/ [R,L]

This is a temporary (302) redirect. ^$ matches an empty URL-path. It is "empty" because it is relative to the current directory. mod_dir will then issue the subrequest for the DirectoryIndex, i.e. index.html.

Alternatively, use mod_alias RedirectMatch:

RedirectMatch 302 ^/content/page3/?$ /content/page3/a/
RewriteRule ^/content/page3/?$ /content/page3/a [L]

This would never work because in a directory context (i.e. .htaccess) the URL-path that is matched by the RewriteRule pattern does not start with a slash.

If you wrote this in the root .htaccess file, it should read:

RewriteEngine On
RewriteRule ^content/page3/?$ /content/page3/a/ [R,L]

The two preceding conditions are not required - unless you have multiple domains?

The corresponding mod_alias directive would be the same as above (regardless of where the .htaccess file is located).


The DirectoryIndex should simply be set to:

DirectoryIndex index.html

In order to serve the index.html document out of the requested directory.


Redirect 301 /content/page3 /content/page3/a

This will create a redirect loop because the mod_alias Redirect directive is prefix matching, and everything after the match is appended onto the target URL i.e. The redirected URL /content/page3/a matches the source URL /content/page3 and /a is appended onto the end of the target (/content/page3/a) to become /content/page3/a/a etc.

Note that 301 (permanent) redirects are cached persistently by the browser. You will need to clear your browser cache. Always test with 302 (temporary) redirects and only change to 301 (permanent) - if that is the intention - once you have confirmed that it works OK.

6
  • Thank you so far. I've read your reply and am still trying to wrap my head around all the stuff you wrote. I don't know what that "mod_rewrite" is exactly, but I think it's maybe a server module? In this it should be installed by my hoster because the Rewrite### configs did have an effect for other stuff I tried (but it produced really messy paths including the server-internal directories etc.) Maybe the problem is me not realizing the whole patterns are relative to the directory, maybe that's the point I was missing. I will test around a bit, thanks!
    – LWChris
    Apr 9, 2019 at 15:37
  • On the path: I don't mind at all if the server adds the trailing slash. It's not so much about cosmetics of the URL, more about consistency. When you see content a, the path should ideally contain the /a part. If that's /a or /a/or /a/index.html is not that important.
    – LWChris
    Apr 9, 2019 at 15:45
  • Yes, mod_rewrite is Apache's URL rewriting module (which also does redirects). RewriteRule (and RewriteCond) are part of mod_rewrite. mod_rewrite is very powerful, but with that power comes additional complexity. Whereas Redirect and RedirectMatch are part of mod_alias. Redirect and RedirectMatch are for "simple" redirects only. You should avoid mixing rewrites/redirects from both modules as you can get unexpected conflicts due to way different modules are executed.
    – MrWhite
    Apr 9, 2019 at 16:45
  • "I don't mind at all if the server adds the trailing slash." - But if you let the server do this then you end up with an undesirable additional redirect. Which is why you should always include the trailing slash on these URLs that map directory to a physical directory. (If these URLs did not map to the file system then personally I avoid the trailing slash - but that is not the case here.) It is generally preferred to avoid having index.html (the DirectoryIndex) in the URL - it is unnecessary and just adds complexity to the "visible" URL.
    – MrWhite
    Apr 9, 2019 at 16:53
  • I don't mind what the "visible URL" is, so if the trailing slash ends up being there that's okay. But I cannot guarantee people will put it there when visiting my site, so it has to work for both cases. That's what I intended to say. Sorry if that was unclear. "you end up with an undesirable additional redirect" - what's the problem with that? Is one automated and one configured redirect in combination bad?
    – LWChris
    Apr 10, 2019 at 22:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .