Forum Moderators: phranque

Message Too Old, No Replies

mod_rewrite, mod_rewrite, mod_rewrite!

Why aren't my clean url's working?

         

yowza

8:22 pm on Jan 26, 2004 (gmt 0)

10+ Year Member



I know that there is a ton of info in these forums on this issue. I think that I have seen all of it, including various other pages. No luck!

My .htaccess looks like this:

RewriteEngine On
RewriteRule ^search/([a-z]+)/([0-9]+) /search.php?artistid=$1
RewriteRule ^search search.php

My urls looks like this:

http*//www.widgets.com/search/artistid/20

From my understanding, mod_rewrite is supposed to take my urls and translate them so that they look like this for my .php page and database query:

http*//www.widgets.com/search.php?artistid=20

However, my database is not returning any info so I assume that mod_rewrite is not doing the correct translation.

Any help would be appreciated.

jdMorgan

8:27 pm on Jan 26, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



yowza,

Your two rules will both be applied unless you tell mod_rewrite to stop after doing the first rewrite. If you look in your error logs, I suspect you'll see that the script requests are getting rewritten by both rules with unexpected results.

To tell mod_rewrite to stop after doing a rewrite, add the [L] flag to the end of the RewriteRule.

Ref: Apache mod_rewrite [httpd.apache.org]

Jim

yowza

8:59 pm on Jan 26, 2004 (gmt 0)

10+ Year Member



Thanks for the quick response.

I just tried with the [L] flag and I am still having no luck.

I checked my logs and found that I am only getting 304's and 200's. Is there another error log that you are talking about? I'm not sure where I should be looking. Thanks.

jdMorgan

9:37 pm on Jan 26, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



yowza,

You have two parenthesized subexpressions in your first rule, one that matches a group of one or more letters, and a second one that matches one or more digits. These will be available as back-references $1 and $2 respectively in the substitution string.

It looks to me like your substitution string should back-reference $2 instead of $1, and further, it looks like you might not even need the first parenthesized subexpression - you could just hard-code "artistid" on both sides of the rule.

The main point being that you either don't need the first parenthesized subexpression, and can just put "artistid" in there, or you may want to back-reference that part of the URL and use it in the new path. The way it is now, it's ambiguous because you created a back-reference and then didn't use it. This won't break anything, but it interferes with my understanding of what you want to do.

I recommend you study the Apache mod_rewrite documentation [httpd.apache.org]; Our examples and advice here can only go so far, and mod_rewrite can affect the reliability of your whole site if you don't get it exactly right.

Jim

yowza

9:44 pm on Jan 26, 2004 (gmt 0)

10+ Year Member



Thanks.

I'll do a little more research.

I didn't hard code artistid because it could be anything including productid, genreid, etc.

Based on your message, I'm taking a quick guess that I should have had something more like this

RewriteRule ^search/([a-z]+)/([0-9]+) /search.php?$1=$2 [L]

.
However, it still doesn't work, so I guess I'll have to do a little more research.

Thanks for your help though!

dannyboy

1:03 am on Jan 27, 2004 (gmt 0)

10+ Year Member



If search.php isn't in your root directory, then there shouldn't be a forward slash prior to search.php.

Try changing this:
RewriteRule ^search/([a-z]+)/([0-9]+) /search.php?$1=$2 [L]

into this:
RewriteRule ^search/([a-z]+)/([0-9]+) search.php?$1=$2 [L]

if that doesn't work, try this:
RewriteRule ^search/([a-z]+)/([0-9]+)$ search.php?$1=$2 [L]

if that doesn't work, try this:
RewriteRule ^search/([a-z]+)/([0-9]+)/$ search.php?$1=$2 [L]
RewriteRule ^search/([a-z]+)/([0-9]+)$ search.php?$1=$2 [L]

yowza

2:49 am on Jan 27, 2004 (gmt 0)

10+ Year Member



dannyboy,

Thanks. I think I already tried all of those combos, but I just tried again anyway. Still doesn't work.

I've looked about everywhere and have tried a million different things. I don't know why it won't work.

If anyone has any other ideas, I'd appreciate them. If I figure it out, I will post the code.

Thanks.

jdMorgan

4:49 am on Jan 27, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



yowza,

Take a look at your raw error log -- What does it say when you've got the code in place and try to fetch one of those static URLs?

You will get an error message that's usually pretty specific. One of the common ones is that you need to add the directive

 Options +FollowSymLinks 

ahead of the RewriteEngine on directive in order to allow mod_rewrite to function. The error log will tell you if this is the case.

Jim

yowza

5:01 am on Jan 27, 2004 (gmt 0)

10+ Year Member



Nothing but 200's. Not a single error code in any of my attempts.

That is actually one of the things that I find strange. I'm not getting any errors for any of my attempts.

Pages always display fine, but nothing displays from the database.

yowza

8:21 pm on Jan 27, 2004 (gmt 0)

10+ Year Member



I just found my error log on this host.

Here are the only two errors caused.

File does not exist: /the/path/here/
Directory index forbidden by rule: /the/path/here/

jdMorgan

4:55 am on Jan 28, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



yowza,

Does the /the/path/here/ relate in any way to the paths you show in your RewriteRules posted above? - We need to make that connection in order to make sense of this.

If a file is requested as "domain.com/some_directory/" with a trailing slash but no filename, then Apache will treat that as a directory request. It looks for a defined default file to serve for that request, such as the common "index.html". If it does not find such a file, then it checks to see if you have enabled directory listings for that directory. If so, it will serve a simple list of files in that directory. If directory listings are disabled, then you will get "403-Forbidden: You are not allowed to view directories on this server", or some such similar message.

The control for enabling or disabling directory listings is the Options directive. You can use Options +Indexes to enable them, or Options -Indexes to disable them. If they are enabled, the server looks for a DirectoryIndex directive to tell it the name of the index file(s) for that directory. It will try to read the filenames listed in the DirectoryIndex directive in order, and will serve the first one it finds. If it doesn't find one, it creates and serves a simple directory listing of that directory.

That may not relate to your problem -- I'm not sure. But we're apparently on different time-schedules, so maybe it'll be useful info.

Jim

yowza

8:07 am on Jan 28, 2004 (gmt 0)

10+ Year Member



jdMorgan:

Thanks for all the help!

Here are the full errors with paths:

Directory index forbidden by rule: /var/www/html/
File does not exist: /var/www/html/search/artistid/21

The url is http*//www.widgets.com/search/artistid/21

Is everything right here? It seems to be right to me, but I'm all mixed up with this.

I'm assuming you are talking about the DirectoryIndex and Options in the httpd.conf file?

I would play with them, but I don't want to mess anything up. Or, can I use Options +Indexes in my .htaccess file?

Thanks

jdMorgan

7:52 pm on Jan 28, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I don't see anything obviously-wrong with the paths, but I don't know your server setup.

> I'm assuming you are talking about the DirectoryIndex and Options in the httpd.conf file?

Yes, and/or in .htaccess.

> I would play with them, but I don't want to mess anything up. Or, can I use Options +Indexes in my .htaccess file?

You can use DirectoryIndex and Options directives in .htaccess, as long as your httpd.conf setup allows it.

Jim

yowza

4:09 am on Jan 29, 2004 (gmt 0)

10+ Year Member



Here is all I found for DirectoryIndex in my httpd.com file.

<IfModule mod_dir.c>
DirectoryIndex default.htm index.cgi .index.cgi index.html index.htm index.shtml index.sht index.mv index.htmv index.php index.php3
</IfModule>

In my .htaccess file I added this: Options +Indexes

I tried all of these:
RewriteRule ^search/([a-z]+)/([0-9]+) /search.php?$1=$2 [L]

RewriteRule ^search/([a-z]+)/([0-9]+) search.php?$1=$2 [L]

RewriteRule ^search/([a-z]+)/([0-9]+)$ search.php?$1=$2 [L]

RewriteRule ^search/([a-z]+)/([0-9]+)/$ search.php?$1=$2 [L]

RewriteRule ^search/([a-z]+)/([0-9]+)$ search.php?$1=$2 [L]

Nothing seems to be working. Any other ideas?

I'm about ready to give up and try one of the PHP solutions I've seen. I'd prefer not to, but it appears that I'm out of options.

Thanks for all the help!

Chris

operafan

4:34 am on Jan 29, 2004 (gmt 0)

10+ Year Member



Hi, I think I have the same problem after successfully getting modrewrite to activate. The problem is you couldnt get the file to connect to the databse right? I couldnt find the solution to my problem either...it's a strange thing :)

jdMorgan

8:44 am on Jan 29, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hmmm...

If you haven't already done so, try adding the [PT] flag to your rules, i.e. [PT,L].

This will leave the internally-rewritten URL-path in URL format, instead of in local filepath format, which is mod_rewrite's default output format.

Also, don't miss the opportunity to try simpler test cases -- to break your problem down... Try an external rewrite so that you can see the URL output in your browser. It won't actually work, but you'll be able to see what your rule is outputting. I mean, do something like:


Options +FollowSymLinks
RewriteEngine on
RewriteRule ^search/([a-z]+)/([0-9]+)$ http://ruletest/search.php?$1=$2 [R=301,L]

You'll get a 404-Not found on the resulting redirected request, but you'll be able to see whether the parameters were put into the query string correctly.

Jim

yowza

7:10 pm on Jan 29, 2004 (gmt 0)

10+ Year Member



Nope.

Nothing working.

This:
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^search/([a-z]+)/([0-9]+)$ [ruletest...] [R=301,L]

doesn't even give me a 404. It seems like some RewriteRule's don't do anything at all. However, I have tried simpler ones like this:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST}!^www\.mydomain\.com
RewriteRule ^(.*)$ [mydomain.com...] [R=permanent,L]

which work fine.

I just don't understand why I wouldn't even get a 404 for the above example.

jdMorgan

5:56 am on Jan 30, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, if your domain-name redirect works, that implies that the pattern in your new rule is not being matched, so it's not invoking the redirect. Just to be clear on expectations, the rule

RewriteRule ^search/([a-z]+)/([0-9]+)$ http://ruletest/search.php?$1=$2 [R=301,L]

will only invoke a redirect in response to a request of the form:

http://www.example.com/search/artistid/20

and not for
http://www.example.com/search/artistid/ -or-
http://www.example.com/search/artistid/20/ -or-
http://www.example.com/search/artistid/20a -or-
http://www.example.com/search/artistid1/20 -or-
http://www.example.com/search/1startistid/20 -or-
http://www.example.com/search/Artistid/20 -or-
http://www.example.com/starch/artistid/20

None of those will match because they don't match the specified pattern.

Jim

yowza

6:34 am on Jan 30, 2004 (gmt 0)

10+ Year Member



Yep. I'm only using:

http*//www.mydomain.com/search/artistid/20

No errors.

The page displays fine, but nothing is displayed from the database query.

jdMorgan

5:42 pm on Jan 30, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Remember that we added the 301 redirect aspect to this rule only as a test; It will not "work properly" because it will no longer apply after the redirect takes place. Its only purpose is as a test.

The test question is whether the query parameters have been moved from the URL into the query string.

In message 16 above, I proposed this test using an invalid target filename, so that you would get a 404 and be able to check the URL-to-querystring rewrite. If you are testing by redirecting to a valid filename, then the code is not valid for testing or for your final application...

Test this first:


RewriteRule ^search/([a-z]+)/([0-9]+)$ http://[b]ruletest[/b]/search.php?$1=$2 [R=301,L]

Request this URL in your browser: http://www.example.com/search/artistid/20

The RewriteRule should be invoked, move the query parameters from the URL to the query string, and then externally redirect your request to the invalid "ruletest" subdirectory. This new URL will now show in your browser address bar, which will automatically issue a new request for it.

You should then see a 404-Not Found response in your browser, because "ruletest" does not exist. But you should also see in your browser address bar that the query string has been correctly formed from the parameters included in the original requested URL.

Make sure the parameters "artistid" and "20" have been removed from the URL, and moved to the query string as expected.

If that works, you can then remove the invalid subdirectory "ruletest" from the rewriterule, and proceed to change the rule back to the desired form

 RewriteRule ^search/([a-z]+)/([0-9]+)$ /search.php?$1=$2 [L]
-or-

RewriteRule ^search/([a-z]+)/([0-9]+)$ /search.php?$1=$2 [PT,L]
which is an internal redirect. Then continue your testing by modifying your script to write the query string variables it receives to a test page. You'll have to progressively work through this, from mod_rewrite, to the script, to the database, using whatever tricks you can find to show you what is happening along the way.

Jim