Forum Moderators: phranque
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.
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
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
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!
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]
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.
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 Jim
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
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
> 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
<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
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]
Jim
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.
RewriteRule ^search/([a-z]+)/([0-9]+)$ http://ruletest/search.php?$1=$2 [R=301,L]
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
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]
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