Forum Moderators: phranque

Message Too Old, No Replies

mod rewrite, alias multiple directories

         

saschao

3:15 pm on Apr 30, 2009 (gmt 0)

10+ Year Member



Hello everyone,

I coulnd't find a solution in the forum so I created a new thread.
A new homepage (using typo3) is created under the old domain, so I've urls like:
http://example.com/abc
http://example.com/xyz

On the new server the folders must remain the same.
But there are now typo3 source inside the webroot. To not messup the typo3 source I would like to use different folders for 'abc' and 'xyz'.
(note there are multiple folders not just the two I mentioned)

I'm using the standard rules needed for typo3-realurl:
RewriteRule ^(typo3¦typo3temp¦typo3conf¦t3lib¦tslib¦fileadmin¦uploads¦showpic\.php)/ - [L]
RewriteRule ^typo3$ typo3/index_re.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)\.html$ /index.php [L]

I want to make multiple subdirectories accessible in the webroot, because I need to keep old urls as they are.

Let's look at the filesystemlevel:
/webroot/typo3/fileadmin/abc
/webroot/typo3/fileadmin/xyz

basically I want an alias for these directories, so that
it works like this:
http://example.com/abc is same as
http://example.com/fileadmin/abc

But the uri /fileadmin/abc should be invisible to the user.

I thought there might be a solution to not create say 30-50 alias statements in the apache config.
Something I tested is this:
RewriteCond /webroot/typo3/fileadmin/%{REQUEST_URI} -d
RewriteRule ^(.*)[\/+]?$ /webroot/typo3/fileadmin/$1 [L]

this works, but makes the "real" path visible to the user, which it shouldn't.

Hope someone could help me with that.
thanks in advance

Sascha

jdMorgan

3:34 pm on Apr 30, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Your rule appears to have a few problems, but it is not invoking an external redirect by itself. So either there is another rule (or directive) which is forcing an external redirect, or perhaps a problem being caused by this rule which is invoking a mod_dir "fix-up" redirect.

In your new code, the RewriteCond should specify a full filepath, and the substitution should specify a URL-path. I am not sure that "/webroot/typo3" belongs in the RewriteRule substitution. This path will be added automatically by mod_rewrite when it converts the substitution URL-path to a filepath.

Also, remove the slash between "fileadmin" and %{REQUEST_URI} in your RewriteCond. The %{REQUEST_URI} value will already have a slash in front of it.

RewriteCond /webroot/typo3/fileadmin/%{REQUEST_URI} -d
should be
RewriteCond /webroot/typo3/fileadmin%{REQUEST_URI} -d

I also have doubts about the meaning and the intent of using the "[\/+]?" subpattern in your RewriteRule. That subpattern means "Match either a slash or a plus sign at the end of the requested URL-path, but it is optional." At the very least, it could be re-coded as "[/+]?" because slashes do not need to be escaped in mod_rewrite patterns.

Jim

saschao

7:27 am on May 7, 2009 (gmt 0)

10+ Year Member



Thank you Jim for your post.

You're right. The "/" isn't needed.

Maybe I explained my problem wrong.
I have a bunch of directories on the old server.
Example URL view:
http://example.com/abc
http://example.com/xyz
...and so on.

On the old server they were just inside the documentroot of the webserver.

The new server should make these folders available under the same URL.
But this time these folders are under different directories in the filesystem.
Example:
/var/www/fileadmin/abc
/var/www/fileadmin/xyz

Where "/var/www/" ist the webroot.

Normally I would just create an alias like:
alias /abc /fileadmin/abc

But for the bunch of directories it would be a lot of work.
I thought I could do it with the help of mod_rewrite but couldn't find a solution.
Maybe another option would be a rewritemap?

could someone give me suggestions and an example?

Sascha

g1smd

11:05 am on May 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This seems like an easy job for a rewrite:

When something requests the old URLs, rewrite the request to fetch from the new filesystem. The trick is in crafting a pattern that matches the URL requests coming from the browser that will need to be matched to the pattern in the rule.

When something externally directly requests a URL based on the new filesystem (for just those URLs) redirect (301) them to use the old URLs, and fix www at the same time.

Should be fairly simple, and is something that has been tackled several times each month since the forum started.

saschao

2:32 pm on May 7, 2009 (gmt 0)

10+ Year Member



Thank you g1smd for your comments.

I searched again through the forum and found some hints.
Here is my current solution:

RewriteCond $1 !fileadmin/test/$1
RewriteCond /webroot/fileadmin/test%{REQUEST_URI} -d
RewriteRule ^(.*) /fileadmin/test/a/ [L]

As far as I tested it works.
One thing that bothers me is the actual Rule.
As you can see I rewrite the url to /fileadmin/test/a
this is a static one.
The url in the browser is:
http://example.com/a/

so far so good, but if I change the rule to:
RewriteRule ^(.*) /fileadmin/test/$1 [L]

The URL get's rewritten to:
http://example.com/fileadmin/test/a/

But I want it to behave like so:
http://example.com/a/

Could someone give me another hint?

Sascha

jdMorgan

2:44 pm on May 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Remove the "/fileadmin/test" part of the RewriteRule's substitution path?

Jim

g1smd

4:49 pm on May 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Once the rewrite bit is working you need to add the redirect bit in as well: such that if I directly ask for http://example.com/fileadmin/test/a/ or for http://www.example.com/fileadmin/test/a/ then I am sent a redirect to http://example.com/fileadmin/a/ instead.

saschao

6:56 am on May 8, 2009 (gmt 0)

10+ Year Member



Now it works.

Thank you Jim and g1smd.
It's nice to see such guyslike you to help people with there problems. :-)

Here is my solution:
RewriteCond $1 !fileadmin/test/$1
RewriteCond /webroot/fileadmin/test%{REQUEST_URI} -d
RewriteRule ^(.*) /fileadmin/test/$1/ [L]

the first condition is to prevent infinite loops.
the second condition tests if there is a directory below the "test" directory.
If that's the case than an internal redirect is made to it.

Jim, the solution to get the contents of "fileadmin/test/a" under "/a" was to add a "/" after the Variable.
RewriteRule ^(.*) /fileadmin/test/$1/ [L]

saschao

6:57 am on May 8, 2009 (gmt 0)

10+ Year Member



Now it works.

Thank you Jim and g1smd.
It's nice to see such guyslike you to help people with there problems. :-)

Here is my solution:
RewriteCond $1 !fileadmin/test/$1
RewriteCond /webroot/fileadmin/test%{REQUEST_URI} -d
RewriteRule ^(.*) /fileadmin/test/$1/ [L]

the first condition is to prevent infinite loops.
the second condition tests if there is a directory below the "test" directory.
If that's the case than an internal redirect is made to it.

Jim, the solution to get the contents of "fileadmin/test/a" under "/a" was to add a "/" after the Variable.
RewriteRule ^(.*) /fileadmin/test/$1/ [L]

Thanks for your help!

g1smd

7:31 am on May 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Now you need the redirect part, and that needs to force the www. It needs to be a 301 redirect.

saschao

10:21 am on May 8, 2009 (gmt 0)

10+ Year Member



g1smd: Hm, why do I need a redirect?
My intentention was to create an "alias" for multiple directories. The directories from the server I referred to as "oldserver", will be copied to the new server.

But, you're right. I need in another context an url rewrite.
to make http://example.com redirect to [[b]www[...]
I've seen some code snippets which exactly do this.

jdMorgan

1:17 pm on May 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You cannot use $1-$9, %1-%9, or server variables on the right side of a RewriteCond. These characters will be interpreted as literal characters, and your RewriteCond will not match unless the requested URL actually contains "$" and "1", for example.

So, the best you can do is to look for *any* subdirectory of /fileadmin/test/, and disable the rule if that matches.

You can also try using a server variable for the filepath in the second RewriteCond. This will make the code more "portable" should you change servers or in case your host changes your root filepath. However, your original RewriteCond also appeared to be incorrect, since it would only do a rewrite if the requested URL *did* resolve to a physically-existing directory. This is the opposite of the usual logic, and I fixed that here as well.


# Internally rewrite all requests to /fileadmin/test subdirectory, unless
# the requested URL-path resolves to a physically-existing directory.
RewriteCond $1 !^fileadmin/test[b]/[^/]+/[/b]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /fileadmin/test/$1/ [L]

Another way to do this is to do the rewrite only if the "new" directory exists in /fileadmin/test/ :

# Internally rewrite all requests to /fileadmin/test subdirectory if the requested
# URL-path resolves to a physically-existing directory under /fileadmin/test/.
RewriteCond $1 !^fileadmin/test[b]/[^/]+/[/b]
RewriteCond %{DOCUMENT_ROOT}/fileadmin/test/$1 -d
RewriteRule ^(.*)$ /fileadmin/test/$1/ [L]

Note that in both cases, the decision is based only on the presence or absence of directories. If the request is for a file, the logic may not be correct for what you want.

---

In addition, you should add at least two more rules, placing them as your first two rewriterules:


# Redirect only direct client requests for /fileadmin/test/<anything> to www.example.com/<anything>
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /fileadmin/test/[^\ ]*\ HTTP/
RewriteRule ^fileadmin/test/(.*)$ http://www.example.com/$1 [R=301,L]
#
# Redirect all requests for non-canonical hostnames to canonical www.example.com hostname
RewriteCond %{HTTP_HOST} !=www.example.com
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]

The purpose of these rules is to prevent duplicate content. That is, to prevent the same page content from appearing at more than one canonical URL.

Note that at the suggestion of member caterham, an exact string match is used in the RewriteCond of the second rule; This is reportedly faster than using a regular-expressions match.

Jim

saschao

7:23 am on May 11, 2009 (gmt 0)

10+ Year Member



Hello Jim,

your RewriteRules work great.
But the solution to rewrite every request to /fileadmin/test
collides with the following rules used for typo3:
RewriteRule ^(typo3¦typo3temp¦typo3conf¦t3lib¦tslib¦fileadmin¦uploads¦showpic\.php)/ - [L]
RewriteRule ^typo3$ typo3/index_re.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)\.html$ /index.php [L]

The index.php file is now looked up in /fileadmin/test/index.php

Do you have any suggestions for me?

Thank you,
Sascha

g1smd

8:04 am on May 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I guess that you'll need another RewriteCond somewhere to either match or negatively match the requests.

Perhaps the typo3 rules will need a preceding RewriteCond that examines THE_REQUEST to make sure that this is a direct request from the browser, not the result of a previous rewrite.

jdMorgan

3:01 pm on May 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You asked for *all* URLs to be rewritten to /fileadmin/test, and that is what the code does.

If you want the code to do something different, then you must provide some way for mod_rewrite to be able to determine whether or not to rewrite any given requested URL to /fileadmin/test, or to let that request pass through the new rule, to be rewritten to typo3 by the next rule instead.

Generally, some identifiable difference in the URL requested by the browser is required, unless you want to look at cookies or differences in the query strings attached to the requested URL. You could also put typo3 on a subdomain to keep it separate...

Anyway, this is up to you to determine, but mod_rewrite needs *some* kind of information to be provided in the request received from the browser to base its decisions on.

Jim