Forum Moderators: phranque

Message Too Old, No Replies

Have a subdirectory "merge" with top-level directory

Serve top-level directory content from a subdirectory?

         

banglo

5:04 am on Sep 13, 2007 (gmt 0)

10+ Year Member



Hi,

I'm knew to apache and was wondering if there was a solution to the problem I'm trying to solve.

I have a bunch of html files that are being stored in a "html" directory on my webserver. Is it possible to make it seem to the outside world that the files are hosted under root instead of the subdirectory?

example:

The file can be accessed and stored in:

www.myurl.com/html/file1.html

but I would like the file to be accessed and indexed via

www.myurl.com/file1.html

without physically placing it in root.

I appreciate your help.

Yusuf

jdMorgan

1:22 pm on Sep 13, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, this is possible with a fairly simple internal rewrite. However, you need to take into account any URLs in the top-level URL-path that you *do not* wish to resolve to files located in the subdirectory. If there are no files in your top-level directory (in other words, if the only thing in your top-level directory is the folder for the /html subdirectory), then something like this will do what you want:

RewriteCond $1 !^html/
RewriteRule (.*) /html/$1 [L]

In some cases, it is necessary to have a "mixed" solution, where some content is taken from the top-level directory, and other content must be taken from the subdirectory. In these cases, it is common to use the approach: If a file or directory does not exist in the top-level directory, try to serve it from the subdirectory. This is commonly coded like this:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /html/$1 [L]

The problem with this approach is that every request now invokes *two* calls to the filesystem -- One to see if the requested URL exists as a file, and another to see if it exists as a directory. This is fairly inefficient, and you'll get much better performance by avoiding it. It is often possible to do so if your files follow some sort of classification scheme, such as "all images are in the subdirectory" or "everything but index.php and robots.txt are in the subdirectory. Specific checks based on the requested path are much more efficient than filesystem "exists" checks.

So for the example files and filetypes I cited above, you might use:


RewriteCond $1 !\.(gif¦jpe?g¦png)$
RewriteCond $1 !^index\.php$
RewriteCond $1 !^robots\.txt$
RewriteRule (.*) /html/$1 [L]

Which would be much more efficient than checking for file-exists and directory-exists.

The code snippets above assume that you already have other working RewriteRules, and so have already installed the directives needed to enable mod_rewrite. If not, you'll need to add either both or only the second of these directives:


Options +FollowSymLinks
RewriteEngine on

at the top of the file before using any other mod_rewrite directives. The first directive is either required and allowed, not required but allowed, not required and not allowed, or required but not allowed, and only testing on your server will tell. Note that in the last case --required but not allowed-- you won't be able to use mod_rewrite on that server.

Replace the broken pipe "¦" characters above with solid pipe characters before use; Posting on this forum modifies the pipe characters.

Jim

banglo

3:47 pm on Sep 13, 2007 (gmt 0)

10+ Year Member



Hey Jim,

Thanks again for helping me on server issues. I will try out what you suggested tonight and let you know what worked for me. I definitely do want the mixed solution where a subset of files under root needs to be accessible as well as the contents of the html folder. So thanks!

sincerely,

Yusuf

banglo

12:10 am on Sep 14, 2007 (gmt 0)

10+ Year Member



Hey Jim,

I've got some bad news(for me). I tried modifying the .htaccess file for the apache server on my laptop to the following (it was blank before) to reflect the htaccess file on my godaddy apache server:

AddHandler x-httpd-php5 .php
AddHandler x-httpd-php .php4

RewriteRule (.*) /html/$1 [L]

# 1 YEAR
<FilesMatch "\.(ico¦pdf¦flv)$">
Header set Cache-Control "max-age=29030400, public"
</FilesMatch>
# 1 WEEK
<FilesMatch "\.(jpg¦jpeg¦png¦gif¦swf)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>
# 2 DAYS
<FilesMatch "\.(xml¦txt¦css¦js)$">
Header set Cache-Control "max-age=172800, proxy-revalidate"
</FilesMatch>
# 1 MIN
<FilesMatch "\.(html¦htm¦php)$">
Header set Cache-Control "max-age=60, private, proxy-revalidate"
</FilesMatch>

But after having done so, I now keep getting asked to download php files because the apache server does not know to interpret them. I changed the.htaccess file back to blank file. But it seems like the behavior is irreversible.

And now I'm getting this situation all over again!
[webmasterworld.com...]

I couldn't resolve the aforementioned problem last time and had to resort to reinstalling the OS. Please tell me this doesn't have to be happen again.

sincerely/desparately,

Yusuf

banglo

3:39 am on Sep 14, 2007 (gmt 0)

10+ Year Member



Good news. Reinstalling MAMP worked this time around. Will cautiously continue to update the .htaccess file..

Just to double check, the changes you suggested were to the.htaccess file right?

Yusuf

jdMorgan

3:51 am on Sep 14, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Glad to hear your PHP is behaving better now.

Yes, the code I posted assumes use in .htaccess, since most readers here are on shared commercial hosting and cannot edit httpd.conf. Generally, code in .htaccess can be adapted for use in httpd.conf simply by adding a leading slash to the RewriteRule patterns. A simple example for rewriting certain URLs to a script would be:

.htaccess

 RewriteRule ^shop/(.+)$ /shop.php?stuff=$1 [L] 

httpd.conf:

 RewriteRule [b]^/s[/b]hop/(.+)$ /shop.php?stuff=$1 [L] 

Be sure to completely flush your browser cache after making any changes to your configuration.

Jim

banglo

4:15 am on Sep 14, 2007 (gmt 0)

10+ Year Member



Hi,

So I've got mod_rewrite running. This is what my .htaccess contains:
Options +FollowSymLinks
RewriteEngine On

RewriteCond $1!^index\.php$
RewriteCond $1!^archive\.html$
RewriteCond $1!^robots\.txt$
RewriteCond $1!^sitemap\.xml$
RewriteCond $1!^skin1\.css$
RewriteRule ^(.*)\.html /html/$1.html [L]

When I try to access an html file via the url:
[localhost:8888...]

I get:
Not Found

The requested URL /html/file1.html was not found on this server.

When I disable the rewrite rule, I am able to access the file via:
[localhost:8888...]

Any ideas?

Yusuf

ps. I did clear the cache.

jdMorgan

4:45 am on Sep 14, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



According to the error message, the rewrite worked, as shown by the fact that the Not Found URL as /html in its path:
The requested URL /html/file1.html was not found on this server.

However, your rule rewrites /html/*.html to itself, creating an 'infinite loop' and that may be complicating things. You need to add another exclusion:


RewriteCond $1 !^html/

Jim

banglo

5:22 am on Sep 14, 2007 (gmt 0)

10+ Year Member



Thanks Jim,

I was about to post my solution but you beat me to the punch :)

I read up on rewrite and learned about the loop issue so I did something very similar to what you suggested: add a NOT condition when something in the html folder is requested. Once again, great job on moderating this forum man and helping people learn about Apache and its 'intricateness' (it ought to be a word).

Thanks,

Yusuf