Forum Moderators: phranque

Message Too Old, No Replies

Mod_rewrite issues - trailing slash and relative dir problem

         

stidj

7:23 pm on Oct 30, 2003 (gmt 0)

10+ Year Member



I'm currently using an htaccess redirect to my index.php which automatically includes any html file. My problem is that the relative path is always '/' so if I go to site.com/dir/page.htm and in page.htm I have a reference to "image.jpg" it assumes the true path is '/image.jpg' forcing me to use absolute links in every case which I would like to avoid.

Does anyone know a way to still redirect to the script below but have the current working directory be whatever is in $REQUEST_URI? eg. if $REQUEST_URI is /somedir/
I would like the server to actually look for any relative links such as "file.jpg" in /somedir/ instead of the current way it works which is looking in "/"

I'd also like to know why my server does not add the trailing slash. Without using htaccess and mod_rewrite my server would always add the trailing slash.

Options +FollowSymLinks
RewriteEngine on
RewriteRule!\.(gif¦jpg¦png¦css)$ /home/virtual/site187/fst/var/www/html/index.php

gethan

3:29 pm on Oct 31, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Stidj,

Trailing slash problem is due to:

A "trailing slash" redirect is issued when the server receives a request for a URL http//servername/foo/dirname where dirname is a directory. Directories require a trailing slash, so mod_dir issues a redirect to http//servername/foo/dirname/.
from [httpd.apache.org...]

So I guess that if mod_rewrite is redirecting everything as with your rule then it doesn't issue the redirect.

jdMorgan

9:21 pm on Oct 31, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



stidj,

> Does anyone know a way to still redirect to the script below but have the current working directory be whatever is in $REQUEST_URI? eg. if $REQUEST_URI is /somedir/

That is how it works by default, but your script is changing that behaviour.

I would like the server to actually look for any relative links such as "file.jpg" in /somedir/ instead of the current way it works which is looking in "/".

The server only does what it is told - it looks for any resource at the URL requested by the browser. The browser requests a page, and then it requests each image on that page, and all requests are separate and independent. The browser, not the server, is responsible for resolving relative links on the pages it is rendering.

> I'd also like to know why my server does not add the trailing slash. Without using htaccess and mod_rewrite my server would always add the trailing slash.

Not sure, you could try adding "-Indexes" to your Options below.

Let's examine this code:


Options +FollowSymLinks
RewriteEngine on
RewriteRule !\.(gif¦jpg¦png¦css)$ /home/virtual/site187/fst/var/www/html/index.php

This says, "If the filetype is *not* gif or jpg or png or css, then redirect the request to index.php" Processing of rewrites will continue because you have not told the rewrite engine to stop on a match by using the [L] flag. But clearly, *this* rewriterule cannot be responsible for messing up your image links, since it does nothing with image files.

Jim

stidj

5:14 am on Nov 6, 2003 (gmt 0)

10+ Year Member



Hey guys. I have an issue with my htaccess file below.

DirectoryIndex index.php index.html
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^ab/India/.*$ - [L]
RewriteRule !\.(gif¦jpg¦png¦css)$ /home/virtual/site187/fst/var/www/html/index.php

As you can see it redirects everything to index.php but there are drawbacks to the results it gives me. I use it to automatically include any .html file I go to eg. http://example.com/dir/file.html

The problem is that the relative dir is always in /
so if I go to http://example.com/dir/file.html and have a link "image.jpg" it looks in site.com/ for this link. I would like to somehow ensure relative dir is whereever I point my browser to (REQUEST_URI).

The other problem is that for whatever reason when using this htaccess file any dir I go to must have the trailing slash. eg. http://example.com/dir looks for a file named 'dir'.

Any help would be appreciated.

[edited by: jdMorgan at 5:30 am (utc) on Nov. 6, 2003]
[edit reason] Delinked & examplified URLs [/edit]

stidj

6:48 am on Nov 6, 2003 (gmt 0)

10+ Year Member



That is how it works by default, but your script is changing that behaviour.

:: jdMorgan, I realize this and maybe what you are trying to say is that both are not possible? I would like to have my script redirected to /index.php each time but I would also like it so the actual dir it is in is whatever is in $REQUEST_URI (PHP) while still redirecting all files to /index.php

The server only does what it is told - it looks for any resource at the URL requested by the browser. The browser requests a page, and then it requests each image on that page, and all requests are separate and independent. The browser, not the server, is responsible for resolving relative links on the pages it is rendering.

::

I realize the browser is responsible for resolving relative links on the pages it is rendering. The issue here is that the relative link will always be '/' due to my script but if I go to /dir/file.html I would like the relative dir to be /dir while still having it redirected to index.php

I would like this to change but I still need each html file to be redirected to /index.php

I am not sure if everyone has understood what I am trying to accomplish, maybe it is not possible to do what I am asking for?

hakre

7:22 am on Nov 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



i think i get your point. first i would take the expression of the rewrite rule as a condition:

RewriteCond !\.(gif¦jpg¦png¦css)$

and then i would 'save' the requested filename via the rewriterule in the next line and send it to index.php as parameter:

RewriteRule ^(.*)$ /home/virtual/site187/fst/var/www/html/index.php?old=$1 [L]

in your script you'll then get the variable

$old
containing the filename requested.

it's important that index.php is not part of the next apache subrequest, otherwise you've to exclude that index.php from that rewrite rule or you'll create an indefenite loop.

stidj

7:33 am on Nov 6, 2003 (gmt 0)

10+ Year Member



hackre,

Thanks for the idea but I am not quite sure how or what this does to solve the problems I have?

Maybe I should have been more clear about what I have accomplished. I believe the information you gave me was an easy way to include any requested file?

I have already coded all of this into my php file including the exclusion if index.php is called.

Maybe I should reclarify because I know what I want and I want I mean but I don't think I've made it easy to see.

What does work the way I want it to:
*including any html file I point my browser to

What improvements I want:

*ability for the server to be in any directory I request so relative links work as intended.

eg. if browser goes to site.com/dir/test.html I would like it to be in that directory 'dir'. If I am in site.com/dir/test.html I want a link for any file such as 'file.html' to be found in site.com/dir/file.html just as it normally would if I didn't use htaccess.

Currently (and I have verified by printing out $REQUEST_URI in php) it will always be in '/' since that is where index.php is so any relative links start from '/'.

*to have the server recognize dirs even without the trailing slash. For some reason my code makes it so if you go site.com/dir/ it knows that is a dir but if I go to site.com/dir it thinks it is really a file called 'dir'.

hakre

8:59 am on Nov 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



What improvements I want:

*ability for the server to be in any directory I request so relative links work as intended.

if you're talking about relative links than it's not a server issue at all, it's a browser issue. you have to differ that.

$REQUEST_URI
in php is only on the server. so if that var has the value of '/index.php' then this is true for php on the server but for the client (webbrowser), the url of the document is still 'site.com/dir/test.html', because the rewrite is done internally on the server. the client does not know anything about it.

that means you can easily use links relative to that html document/url. relative links should work as intended.

the only question left for me is then, why doesn't ít work for you?

*ability for the server to be in any directory I request so relative links work as intended.

the same fault. the server is in any directory all times because the directory is based on each request. the browser uses a fully qualified url to retrieve any kind of document from the webserver in each request, even if there are relative links written in the html page returned by the server, because it's the clients work to translate these relative links into a complete url.

stidj

9:20 am on Nov 6, 2003 (gmt 0)

10+ Year Member



hakre,

I do see what you are saying and I also understand what you mean but perhaps to clear things up I should give you an example.

if you have /index.php

and you include /somedir/file.html

basically the resulting html would be as if index.php and file.html were really a single file in /

Please remember that the server will throw any of the html code I go to in /somedir/file.html into /index.php since each html file I go to is redirected there.

I understand $REQUEST_URI is on the server but it determines how the relative links will work, correct? Just beause my browser shows /somedir/file.html it is really not there since the server redirects all of that code in file .html to /index.php (and I include that code).

To prove my point, if I take the same file without using the htaccess file the relative links work fine. It should be no coincidence that if I print out $REQUEST_URI I would see I am inside the dir /somedir instead of the / I get with the htaccess file.

IF I print it out using my htaccess file it will show '/' because that is where the index.php file is since it is redirected there correct?

Does anyone see what I am getting at here or am I on crack?

I do see what those of you mean by the browser determines relaive links, but the path it begins with is determined by the path the server is at which can be misleading in this case given how I include the html.

hakre

9:36 am on Nov 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ok stidj, no it's more clear for me what you do (i hope). there are also links in the index.php which should be relative to the real url (the one in the browser), but you've got no possibility to get this one, right?

if so, i suggested at #6 to pass that request-url to your script (index.php) so that index.php is able to use $old instead of $REQUEST_URI or for debugging purposes you can compare these 2 values.

nevertheless, with my .htaccess doing a quite similar thing, $REQUEST_URI contains the uri requested by the browser anyways. the example i gave @ #6 is not needed for me anyway.

so here is a list of questions i have:
a) are you using RewriteBase in .htaccess?
b) is php running in cgi mode or as a module?
c) do you generate/modify links in index.php or the file which is included by index.php by using the $REQUEST_URI variable? if so, please tell in which of these 2 files.

hakre

9:51 am on Nov 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



some more additions:

I understand $REQUEST_URI is on the server but it determines how the relative links will work, correct?

no that's not true. if you're talking about relative links in html (a href, img src), this will be untouched and $REQUEST_URI does not determine anything for the html.

IF I print it out [$REQUEST_URI] using my htaccess file it will show '/' because that is where the index.php file is since it is redirected there correct?

yes: that is correct. but this doesn't harm links in html nor does it enforces php to do wired stuff. it's just an informative variable the server creates and you can use it in your script forwhatever reason. at first this is just informative.
no: nothing is redirected. you don't do a redirect, you create a new subrequest internally on apache with that rewrite rule. redirect would be by using the [R] flag.

I do see what those of you mean by the browser determines relaive links, but the path it begins with is determined by the path the server is at which can be misleading in this case given how I include the html.

i don't think so. the browser has got only one path, and that's the one in the url you see in the address bar. what the server is doing after the request by the browser is not the browsers business. this is very important while using RewriteRule. the one you're using is not(!) a redirect, it creates an internal (only within apache) subrequest.
to make it clear again: the browser does not know where the file is located on the server. the browser has only it's own url.
so there is no "the path the server is at" like you wrote.

stidj

10:01 am on Nov 6, 2003 (gmt 0)

10+ Year Member



ok hakre,

Thanks for clearing things up a little. I am still confused as to why I'm having these problems though.

To answer your questions:

No: a) are you using RewriteBase in .htaccess?

Not sure but I think module (I did use phpinfo() but don't know what to look for
b) is php running in cgi mode or as a module?

I do get some links from $REQUEST_URI in the sense that I include links from .html files.

I do slightly modify them but I had this issue before modifying them.
c) do you generate/modify links in index.php or the file which is included by index.php by using the $REQUEST_URI variable? if so, please tell in which of these 2 files.

The php dealing with the $REQUEST_URI is below:
if(file_exists($DOCUMENT_ROOT.$REQUEST_URI)
and ($SCRIPT_FILENAME!=$DOCUMENT_ROOT.$REQUEST_URI)
and ($REQUEST_URI!=$SCRIPT_FILENAME)
and (!is_dir($DOCUMENT_ROOT.$REQUEST_URI))
and ($REQUEST_URI!='/'))
{
include($DOCUMENT_ROOT.$REQUEST_URI);
}
elseif(is_dir($DOCUMENT_ROOT.$REQUEST_URI)
and ($REQUEST_URI!='/')
and ($SCRIPT_FILENAME!=$DOCUMENT_ROOT.$REQUEST_URI)
and
( file_exists($DOCUMENT_ROOT.$REQUEST_URI.'index.php')
or
file_exists($DOCUMENT_ROOT.$REQUEST_URI.'index.html')))
{
if ( file_exists($DOCUMENT_ROOT.$REQUEST_URI.'index.php'))
{
include($DOCUMENT_ROOT.$REQUEST_URI.'index.php');
}
else
{
include($DOCUMENT_ROOT.$REQUEST_URI.'index.html');
}
}
else
{
include($DOCUMENT_ROOT.'/body.html');
}
?>

hakre

10:54 am on Nov 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



i see the code. you defenetly need to sort things out there ;).

first of all, forget about

$REQUEST_URI
. what you know is that whenever index.php is executed via .htaccess, it has the value '/' so you can not use it in your script - it's useless (i know that's unfair to say, but let's start sorting things out).

on the other hand you would like to have a variable containing the path to the html-file in the servers filesystem. let's go ahead and name it

$includefile
.

right now, this is empty but let us do not care about that fact, just state it has 'that right value in' you're seeking since hours. ok, tons of trouble out. your script might look like that now:


if(file_exists($includefile)) {
if(!is_dir($includefile)) {
if ($SCRIPT_FILENAME==$includefile) {
// includefile is 'me' (index.php)
// skip this here, because it should not include itself - that will produce a loop!
} else {
// fine, let's include!
include($includefile)
}
} else {
// it's not a file, it's a directory
// maybe make your own dir-listing here
}
} else {
// there is not such a file to include
// display an error message maybe
}

doesn't it look a bit more clean? ok, so now the logik is in: if the requested file exists and it isn't a directory and it isn't itself (index.php), then it's included.

what still missing is the value of

$includefile
. for testing purposes i suggest to add in front a line of code creating a test-value for
$includefile
to check wether that little script works right or not. could be something like that:
$includefile = $DOCUMENT_ROOT.'/dir/test.html';

please change the value to a file you know it exists and then for a second scenario to a value you know the file does not exists. that way you can simply check if the include logic works.

after that testing we need to find a way to get that truly needed value. but before, it's important to understand what has changed and how the problem is going to be solved: before getting the needed value, you just behave like you've already got it. that way you can check that index.php is working right. but take care: relative links in the included file will still not work - no panic, this will be solved soon.

give me a note if you could follow me until now.

stidj

3:57 am on Nov 9, 2003 (gmt 0)

10+ Year Member



Thanks so much hakre. That makes a lot more sense.

I will test ASAP. Sorry for the late reply but I am busy.

stidj

2:20 am on Nov 19, 2003 (gmt 0)

10+ Year Member



hakre:

after that testing we need to find a way to get that truly needed value. but before, it's important to understand what has changed and how the problem is going to be solved: before getting the needed value, you just behave like you've already got it. that way you can check that index.php is working right. but take care: relative links in the included file will still not work - no panic, this will be solved soon.

give me a note if you could follow me until now.

--

I think you are bringing me into the right direction but I am scared to play with the outline of your code because my site at least works at the moment, unfortunately not the way I like it to.

Could we try to figure out how to get the proper value of the include file? Also I am still unclear what is causing my trailing slash and relative directory problem. I know my code is not the best but I cannot see how it is causing a relative directory problem.

No matter I try the files seem to be relative to '/' all the time. If I can fix that problem then I think that is all I need.

Any ideas?