Forum Moderators: phranque

Message Too Old, No Replies

htaccess rewrite - problem with relative paths

can't make relative paths work with rewrite base

         

butkaj

9:50 am on Jun 30, 2008 (gmt 0)

10+ Year Member



I have a coppermine image gallery installed using simplescripts.

I would like to rewrite:

http://www.example.com/vienna*
http://www.example.com/vienna*/
http://www.example.com/visit/vienna* - only this works, going to the right directory
http://www.example.com/visit/vienna*/

* - means any character

to

www.example.com/visit/index.php?cat=19 (showing one of the urls above)

My rewrite script (first two lines should apply)


RewriteEngine on
RewriteRule ^(visit/)?(vienna安ien)(.*)/?$ /visit/index.php?cat=19&main [L]


RewriteCond %{HTTP_HOST} ^(www.)?example.com$ [OR]
RewriteCond %{HTTP_HOST} ^(www.)?example1.com$
RewriteCond %{QUERY_STRING} !^id=
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?$ /index.php?id=$1$2 [QSA]

PROBLEM
When I use [R,L] at the first line, everything works perfectly for all 4 urls (as it is a redirection). But when I use [L] relative paths for style and images in coppermine gallery are not found properly.

How to avoid this? Is it possible? It may work with RewriteBase, but I wasn't able to solve it successfully. Rest part of the htaccess script is for another purpose which is working fine and I hope it doesn't influence the first line. I cannot change relative paths as the simplescript.com security updates always change the installation to the previous state (using relative paths everywhere in coppermine gallery).

Any help really appreciated.

[edited by: jatar_k at 3:14 pm (utc) on June 30, 2008]
[edit reason] please use example.com [/edit]

jdMorgan

4:40 pm on Jun 30, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> relative paths for style and images in coppermine gallery are not found properly.

It is the client (e.g. robot or browser) which resolves relative links, based on the URL in its address bar. That is why relative links will work when using an external redirect, but not when using an internal rewrite -- because a redirect sends the new URL to the browser, which then constructs and requests the correct URL-paths.

If you cannot use server-relative <img src="/path-to-image"> or canonical <img src="http://www.example.com/path-to-image"> links, then your only choice will be to rewrite the image paths to correct them. This will create multiple URLs for each image, since either the correct URLs or the incorrect URLs will then work. All other solutions will 'expose' your rewritten URLs.

Jim

butkaj

10:20 am on Jul 1, 2008 (gmt 0)

10+ Year Member



Thanks for your quick answer Jim.

No I cannot use canonical urls like 'http://www.example.com' neither server relative ones and now I understand the internal rewrite problem.

My another idea was using a redirect (R=301, which works) when someone types 'http://www.example.com/vienna'

and redirect it with main .htaccess file to
'http://www.example.com/visit' directory

and then REWRITE all requests in this subdirectory (with second subdirectory .htaccess file)

where I rewrite
http://www.example.com/visit/vienna
to
/visit/index.php?cat=19&main [L]

Do you think this would work? I tried and it works but not with urls ending with slash. Do you think, that a symbolic links inside the visit directory can solve the end slash problem? Regular expression /? is not helping :(, perhaps my two .htaccess files scenario is not correct.

Thanks for your help.
Andy

[edited by: jdMorgan at 2:09 pm (utc) on July 1, 2008]
[edit reason] No URLs, please. [/edit]

jdMorgan

2:11 pm on Jul 1, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There's no 'right' answer here... If this method works for you, and you're willing to accept the extra traffic and latency, and search engine 'confusion' imposed by the 301-redirect-every-time approach, then -- well, it works for you.

As for the trailing slash problem, I can't answer that without seeing the code...

Jim

butkaj

7:29 am on Jul 2, 2008 (gmt 0)

10+ Year Member



Jim, thank you for your opinion & smart ideas.

Let's say I agree with search engine confusion and I want to have only www.example.com/visit/vienna and www.example.com/visit/vienna/ accessible. I still can point another domain directly to visit/ subdirectory so www.exampleX.com/vienna should work then.

After you smart tips I still have this trailing slash problem:
I would like to rewrite:
http://www.example.com/visit/vienna*
http://www.example.com/visit/vienna*/

to

www.example.com/visit/index.php?cat=19

It's working without slash. With slash it's still wrong and can be tested at www.<myloginname>.com/visit/vienna/ .

Problem is that internal rewrite and image/css path is www.example.com/visit/vienna/pathtoimage while it should be www.example.com/visit/pathtoimage

Code (one .htacess scenario)


RewriteEngine on
RewriteRule ^(visit/)(vienna安ien)(.*)/?$ /visit/index.php?cat=19&main [L]

RewriteCond %{HTTP_HOST} ^(www.)?exampleX.com$
RewriteRule ^(vienna安ien)(.*)/?$ /visit/index.php?cat=19&main [L]

Is there a solution outthere? :(

jdMorgan

2:07 pm on Jul 2, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, there is a solution. Which *single* URL do you wish to use as the "correct" URL? Pick one:

http://www.example.com/visit/vienna
http://www.example.com/visit/vienna/

Jim

butkaj

9:31 pm on Jul 2, 2008 (gmt 0)

10+ Year Member



I want to use http://www.example.com/visit/vienna as the correct URL.
Another one is used by visitors by mistake...

Really anxious to hear your solution.
Thanks in advance for you expeditious answers.

Andy

jdMorgan

10:06 pm on Jul 2, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




RewriteEngine on
#
# Redirect to remove trailing slash on vienna/wien URLs
RewriteRule ^((vienna安ien)/.+)/$ http://www.example.com/$1 [R=301,L]
#
# Redirect all non-canonical domain requests to canonical domain
RewriteCond %{HTTP_HOST} ^example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
#
# Internally rewrite URLs to script
RewriteRule ^(visit/)?(vienna安ien)/ /visit/index.php?cat=19&main [L]

This will redirect to remove the trailing slash or to correct non-canonical domain requests, and then internally rewrite to the script. I removed several unnecessary 'pieces' to speed up processing.

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

Jim

butkaj

7:17 pm on Jul 3, 2008 (gmt 0)

10+ Year Member



Hi Jim,
Thank you for your work, but unfortunatelly it does not work. I replaced example.com and pipe of course.

Internal rewrite (last line) is not working, but when I remove / after "wien)" internal rewrite works fine (for www.example.com/visit/vienna).

But redirecting www.example.com/visit/vienna/ throws page without style & images. I tried to check whats wrong with redirect and I think the first RewriteRule:

"RewriteRule ^((vienna安ien)/.+)/$"

is somehow wrong. It does nothing with www.example.com/visit/vienna/
but surprisingly it does with www.example.com/vienna/visit/ (vienna & visit switched) - and it throws last slash away.

I was not able to repair this part by myself. Your code is online (with internal rewrite unchanged), can you please check and help what I should change to redirect it successfully?

It still can be checked at "my login name dot com"

butkaj

11:29 am on Jul 21, 2008 (gmt 0)

10+ Year Member



Any idea how to repair jdMorgan code so it works properly?

jdMorgan

2:59 pm on Jul 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



First, that rule requires additonal path information in the URL after "/visit/vienna/". The trailing slash on "vienna/", plus more characters, are required.

You could make that path info optional by using something like:


RewriteRule ^((vienna安ien)(/.+)?)/$ http://www.example.com/$1 [R=301,L]

Second, be sure that all links to objects to be included on you pages are server-relative or canonical URLs. If you try to use page-relative URLs, then the browser will not resolve those links properly.

To be clear, you must use <img src="/images/logo.gif"> or <img src="http://example.com/images/logo.gif">, and you cannot use <img src="images/logo.gif">

Jim

butkaj

6:15 pm on Jul 21, 2008 (gmt 0)

10+ Year Member



Jim,
I have to use src=images/logo.gif as I use 3rd party photogallery which is like that for default. Easy to change but when the new photogallery update comes, i would need to change everything again...

You solution doesn't work for me, nevertheless I was so frustrated that I find a solution somehow (not very good looking though):


RewriteEngine on
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
RewriteRule ^(vienna安ien)(.*)$ http://www.example.com/visit/vienna [L]
RewriteRule ^(visit/)(vienna安ien)(.*)$ /visit/index.php?cat=21&main [L]

First 6 lines - removing slash at the end
Last 2 lines - not very goog looking redirect if URI doesn't contain "visit" and if it contains "visit" string, rewriting to photogallery

Just let me know if you know how to simplify last 2 lines. Or if you have anything on your mind.

Thank you for your help, answers and your time.

Andy

[edited by: jdMorgan at 6:31 pm (utc) on July 21, 2008]
[edit reason] example.com [/edit]

jdMorgan

6:30 pm on Jul 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



To avoid potential domain canonicalization problems, you should include the full URL in any rule that does a redirect with [R=30x] (your second rule, for example).

Also, if a full URL is included in the rule, then [R=301] or [R=302] should be specified (in your fourth rule) -- both to be explicit, and because a 302 redirect is the default, and 302 redirects cause problems with search engine indexing.

So, the two recommended rule forms are
Internal Rewrite : RewriteRule <requested_local_path_pattern> <new_local_path> [L]
External Redirect: RewriteRule <requested_local_path_pattern> http://example.com<new_local_path> [R=301,L]

Jim

[edited by: jdMorgan at 6:37 pm (utc) on July 21, 2008]

butkaj

7:53 pm on Jul 21, 2008 (gmt 0)

10+ Year Member



You are absolutely right, thank you! I hope this is the final version (I added full URL + R=301):


RewriteEngine on
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ http://www.example.com/$1 [R=301,L]
RewriteRule ^(vienna安ien)(.*)$ http://www.example.com/visit/vienna [R=301,L]
RewriteRule ^(visit/)(vienna安ien)(.*)$ /visit/index.php?cat=21&main [L]

jdMorgan

8:02 pm on Jul 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Looks good. I'm glad you got the problem resolved. :)

Jim

butkaj

9:20 pm on Jul 21, 2008 (gmt 0)

10+ Year Member



Jim,
And I am glad i found webmasterworld and very helpful person like you ;)

Andy

walker6o9

8:28 pm on Sep 11, 2008 (gmt 0)

10+ Year Member



I came across this thread and it is similar to the problem I am having so I was hoping either of you could help me out:

I am currently having a problem with a php script that initially generated urls like this:
index.php?pic=1.jpg

I used an this rule to rewrite to clean urls.

RewriteEngine On
RewriteRule ^(.*)/$ index.php?pic=$1

this generates urls like this:
/1.jpg/

but if the user types in /1.jpg
without the trailing slash, they receive a 404 error.

I can add another rule to add the trailing slash automatically:

RewriteEngine On
RewriteRule ^([^/.]+\.(jpg¦gif¦png¦jpeg))$ /$1/ [R=301,L]
RewriteRule ^(.*)/$ index.php?pic=$1

So that /1.jpg becomes /1.jpg

The problem is that I need move this particular php file (and its corresponding images) into a variety of different folders, and give it to less technical people, along with the htaccess file, to drop into folders and run. I can't exactly have them rewrite the htaccess file to the absolute path everytime. Unfortunately, with the new rewrite rule, if I type in
/commercial/test/1.jpg
it goes to /1.jpg/

is there a way to make this a relative path redirect, so that
/commercial/test/1.jpg goes to /commercial/test/1.jpg/

but relative, such the same htaccess file would redirect
/commercial/live/1.jpg goes commercial/test/1.jpg/

jdMorgan

9:07 pm on Sep 11, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The main problem is that you cannot "rewrite to clean URLs."
You change the links on your pages to *define* clean URLs, then you rewrite those URLs, when received in a request from a browser, back to the "ugly" filepath+query-string format needed to invoke your script.
An optional third step is to redirect the "old" ugly URL+query-string URLs to the new "clean" URLs. But note that this is the last step, not the first, and has to do with recovering search engine ranking and old bookmarks, and not with changing the URLs.

See this thread [webmasterworld.com] in our forum library for more detail. Having reviewed and considered that, I think we'll be in a better position to discuss what you might want to do. As it stands now, the implementation is somewhat upside-down and inside-out -- and therefore may seem complicated and impossible.

Jim

walker6o9

9:42 pm on Sep 11, 2008 (gmt 0)

10+ Year Member



Oh, I actually got it to work:

RewriteEngine On
RewriteRule ^[^/.]+\.(jpg¦gif¦png¦jpeg)$ %{REQUEST_URI}/ [R=301,L]
RewriteRule ^(.*)/$ index.php?pic=$1

The only problem I'm having now is if you go to
commercial/test/
when I tries to load the image, for some reason it thinks its in commercial, not test, and tries to load the image
commercial/test/img/1.jpg

instead it tries load the image
commercial/img/1.jpg

which of course does not exist.

Also, the links it tries to go are:
commercial/2.gif/
instead of
commercial/test/2.gif

I do not have these problems if I start out at
commercial/test/1.jpg/
or commercial/test/2.gif/ etc

jdMorgan

9:58 pm on Sep 11, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, you are confusing me because you say things like "of course does not exist" and I have no idea what exists on your site.

The server using mod_rewrite does not "try to go to" links, it externally redirects requested URLs to other URLs, or it internally rewrites requested URLs to filepaths (plus a query string). A rewrite to a script says, "If the client requests this URL, generate and/or serve the content by running the script at this filepath, using this query string."

I have no idea why you would want to redirect /1.jpg to /1.jpg/ since the latter is a malformed URL at best, and may confuse search engines (I don't know if image search is important to you, though).

Please give some more example URLs as requested by a browser clicking a link or loading an image from an <img src> link on your pages, and specify what filepath(s) and query string(s) they should resolve to on your server. As an example -- and I doubt that this is correct, it's just an example:

URL in <img> tag on page --> Path on server and query string
/commercial/test/1.jpg -------> /commercial/index.php?pic=test/1.jpg
.
Giving several examples, so that it is clear which 'pieces' of the URL need to go into the script filepath and the query string, and which pieces should be discarded, will be very helpful.

Also, please explain why you'd ever want a slash on your .jpg URLs?

Jim

walker6o9

10:10 pm on Sep 11, 2008 (gmt 0)

10+ Year Member



So, basically, I have a php script that displays images. I named it index.php and put it in the folder commercial/test.

You go to
/commercial/test/
(which is really commercial/test/index.php)
or whatever folder they are in, and it displays image1, which is in the folder
/commercial/test/img/
When you click on image 1 it goes to image 2. When you go to image 2 however, the url is displays is
/commercial/test/?pic=2.jpg

Which is ugly and my designers hate. The .htaccess rewrite I did initially

RewriteEngine On
RewriteRule ^(.*)/$ index.php?pic=$1

allowed me to go to commercial/test/1.jpg/

and then click on the image and have it take me to

commercial/test/2.jpg/

etc.

Unfortunately, if the user left off the slash mark, they got a 404 error.

I updated my .htaccess file to

RewriteEngine On
RewriteRule ^[^/.]+\.(jpg¦gif¦png¦jpeg)$ %{REQUEST_URI}/ [R=301,L]
RewriteRule ^(.*)/$ index.php?pic=$1

So that if the slash mark was left off, the user would be redirected to the proper url.

This is working fine. The only problem I have is that if you go
commercial/test/,
(which is really commercial/test/index.php)
instead of loading the image /commercial/test/img/1.jpg

it says it tried to load the image /commercial/img/1.jpg

and gives me a 404. Also, if you try to click on the image, instead of going to
/commercial/test/2.jpg/
it goes /commercial/2.jpg/

*This problem still occurs if I take out the slash mark rewrite part (line 2)

jdMorgan

10:27 pm on Sep 11, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Again:

Please give some more example URLs as requested by a browser clicking a link or loading an image from an <img src> link on your pages, and specify what filepath(s) and query string(s) they should resolve to on your server. As an example -- and I doubt that this is correct, it's just an example:

URL in <img> tag on page --> Path on server and query string
/commercial/test/1.jpg -------> /commercial/index.php?pic=test/1.jpg

The "thing on the left" is the URL-path (domain omitted). The "thing on the right" must be the filepath from DocumentRoot to the script, plus the desired query string.

Also, is your server Apache1.x or 2.x? If 2.x, do you have AcceptPathInfo enabled?

I think the problem may be that your internal rewriterule is non-specific: It puts the entire path into the query string, and it may be that you only want the image filename, or part of the path plus the image filename in that query string.

I also think you can do away with the appended-slash junk entirely, and move the "image-format filetype test" into the rewrite. But I cannot offer a solution without knowing what the correct URL-to-script_query mapping is supposed to be.

Again, this is probably not the right solution, but illustrates the URL-parsing:


RewriteRule ^(([^/]+/)*)([^/.]+\.(jpe?g夙if如ng))$ /$1index.php?pic=$3

As shown, this code goes into example.com/.htaccess. The directory path to the image file is used as the index.php script directory, and only the filename is passed to the script in that directory. Note that "jpe?g" matches either jpg or jpeg.

Change all broken pipe "¦" characters in code to solid pipes before use; Posting on this forum modifies the pipe characters.

Jim

walker6o9

10:44 pm on Sep 11, 2008 (gmt 0)

10+ Year Member



2x. I don't know if AcceptPathInfo is enabled.

Are you saying I should add that RewriteRule below my current code:
RewriteEngine On
RewriteRule ^[^/.]+\.(jpg夙if如ng夸peg)$ %{REQUEST_URI}/ [R=301,L]
RewriteRule ^(.*)/$ index.php?pic=$1

So that my .htaccess file would read

2x. I don't know if AcceptPathInfo is enabled.

Are you saying I should add that RewriteRule below my current code:
RewriteEngine On
RewriteRule ^[^/.]+\.(jpg夙if如ng夸peg)$ %{REQUEST_URI}/ [R=301,L]
RewriteRule ^(.*)/$ index.php?pic=$
RewriteRule ^(([^/]+/)*)([^/.]+\.(jpe?g夙if如ng))$ /$1index.php?pic=$3

I'm not sure I fully understand your initial question but I believe the answeer ist

/commercial/test/img/1.jpg -------> /commercial/test/index.php?pic=1.jpg

jdMorgan

1:01 am on Sep 12, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No the code I posted replaces both of your rules, unless there is something else going on.

If your "map specification" of "/commercial/test/img/1.jpg -------> /commercial/test/index.php?pic=1.jpg" is correct, then the rule I provided will do exactly that -- without the unnecessary and deleterious trailing slash stuff.

Don't forget to edit the pipe characters, as noted above.

Jim

jdMorgan

1:45 am on Sep 12, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Oops... The rule for "/commercial/test/img/1.jpg --> /commercial/test/index.php?pic=1.jpg"
would be:

RewriteRule ^(([^/]+/)*)[b]img/[/b]([^/.]+\.(jpe?g夙if如ng))$ /$1index.php?pic=$3

Jim

walker6o9

6:24 pm on Sep 12, 2008 (gmt 0)

10+ Year Member



I tried the first code you posted at 10:27pm, and it didn't change the URLs. The code you wrote at 1:45AM, the last post, gave me an internal server error.

g1smd

8:24 pm on Sep 12, 2008 (gmt 0)

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



Did you change the ¦ pipe ¦ symbols to be the right sort?

Otherwise I can't see what the problem could be.

walker6o9

9:26 pm on Sep 12, 2008 (gmt 0)

10+ Year Member



Oops. I hadn't change the pipe symbols. I fixed them though, and now I get a 404 error when I try to go

/commercial/test/1.jpg/

or

/commercial/test/1.jpg

and the image doesn't load if i go to

/commercial/test/

g1smd

9:35 pm on Sep 12, 2008 (gmt 0)

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



Err. Your requirement was for a URL like this, wasn't it?

/commercial/test/img/1.jpg

If not, review the code supplied by jd again, and drop the bolded img part from the rule.

walker6o9

10:08 pm on Sep 12, 2008 (gmt 0)

10+ Year Member



I tried this but it did the same thing

RewriteEngine On
RewriteRule ^(([^/]+/)*)/([^/.]+\.(jpe?g¦gif¦png))$ /$1index.php?pic=$3

This 34 message thread spans 2 pages: 34