Forum Moderators: phranque
RewriteRule ^blah/(foo|bar)/(.*) /blah/$2?topic=$1 [NC,QSA] # this wouldn't match the original URL, but should match the rewritten URL
RewriteRule ^blah/[^/]+/([0-9]+)/?$ /blah/?id=$1 [NC,QSA]
I'm getting stuck here and I'm not sure what the logic is
Rewrite rules are applied to the results of previous rewrite rules, in the order in which they are defined in the config file. The URL-path or file-system path (see "What is matched?", above) is completely replaced by the Substitution and the rewriting process continues until all rules have been applied, or it is explicitly terminated by an L flag, or other flag which implies immediate termination, such as END or F.
The question is, does this change the value of REQUEST_URI? So the next rule would use the new result (/blah/example/12345?topic=bar), even though the URL didn't actually change?
Meaning, should this next rule match?
[^/]+/([0-9]+)/? [edited by: phranque at 1:21 am (utc) on Apr 14, 2020]
does this change the value of REQUEST_URI?Yes: that’s a key difference between REQUEST_URI (“whatever URI we are working with at this particular instant”) and THE_REQUEST (“what the visitor originally asked for, and will see in their address bar").
But you will be very careful with these [L]-less rules, won't you? ;)
one rule to set ?topic= and removing it from the REQUEST_URICareful! Although THE_REQUEST applies to the whole thing--including query string if you've got old-fashioned URLs that include it in visible form--the internal REQUEST_URI doesn’t. For that you have to use QUERY_STRING (which here doesn’t care whether the query is visible or not).
Let's say I have a REQUEST_URI like:
RewriteRule ^(.+)/$ /$1 there's always the option of mod_rewrite logging...
But it will help if you give an example of the rule in action, and show what happens. At some point there must be an [L]; otherwise what happens at the end with that now-extensionless /blahblah request?
## Remove trailing /
# tried with [L], too, and it still had an infinite loop
RewriteRule ^(.+)/$ /$1
## Classifieds
RewriteRule ^classifieds/[\w-]+?/(\d+)$ /classifieds/view/?id=$1 [QSA,L]
RewriteRule ^(?:classifieds/)?autos$ /classifieds/list.php?cat=autos [QSA,NC,L]
RewriteRule ^(?:classifieds/)?guns$ /classifieds/list.php?cat=guns-hunting [NC,QSA,L]
RewriteRule ^(?:classifieds/)?pets$ /classifieds/list.php?cat=pets-animals [NC,QSA,L]
RewriteRule ^(?:classifieds/)?dogs$ /classifieds/list.php?cat=pets-animals&subcat=dogs [NC,QSA,NE,L]
RewriteRule ^(?:classifieds/)?yardsales$ /classifieds/list.php?cat=yard-sales [NC,QSA,L]
RewriteCond %{REQUEST_URI} !^/classifieds/(thumbs|photos|reviews|yardsales|list|view|includes) [NC]
RewriteRule ^classifieds/([a-z-]+)/?([a-z-]*)$ /classifieds/list.php?cat=$1&subcat=$2 [NC,QSA,NE,L]
I changed LogLevel to "alert", and that told me about code errors (like once when I left out a ])But, but, but--that's the second-highest level. (Apache docs [httpd.apache.org] list an “emerg” even higher than the list you have.) Shouldn't you be setting it to “debug” or even something in the “trace” range? Also try it with and without specifying mod_rewrite, to make double-sure that that’s where the problem is happening:
Specifying a level without a module name will reset the level for all modules to that level. Specifying a level with a module name will set the level for that module only.
RewriteRule ^(.+)/$ /$1
... and then what happens? At what point does the request get converted back into something that yields a physical file? That’s why I asked if these are real, physical directories. If they were--which I hope they aren’t--the request would meet mod_dir and things would keep going around in circles forever.
My options for LogLevel are:
alert
crit
debug
emerg
error
info
notice
warn
http://httpd.apache.org/docs/2.4/mod/core.html#loglevel Is that how WHM is presenting the available options - in alphabetical order (not helpful at all)?! They should be listed in order of severity, as in the Apache docs (that lucy24 links to above), otherwise you don't really know what to set it to. (?)
... and then what happens? At what point does the request get converted back into something that yields a physical file? That’s why I asked if these are real, physical directories. If they were--which I hope they aren’t--the request would meet mod_dir and things would keep going around in circles forever.
RewriteRule ^classifieds/[\w-]+?/(\d+)$ /classifieds/view/?id=$1 [QSA,L] maybe I'm misunderstanding your question.And who could blame you, since I was having a severe brain fart and failed to see what you were doing in all those RewriteRules. My bad.
more exact, it would go to classifieds/view/index.php?id=12345, because index.php is implicit.index.php (or index.anything) is not “implicit”. It is stated in your DirectoryIndex directive, which tells mod_dir what physical file to go looking for when there is a request for, let's say,
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI}/index\.php !-f
RewriteCond %{REQUEST_URI} !-d
RewriteRule ^(.+)/$ /$1 RewriteCond %{REQUEST_URI}/index\.php !-fWouldn’t that make two // slashes? And aren’t the last two lines redundant? If it contains an /index.php file, then by definition it would have to be a real directory. (And, vice versa, every directory would contain an index.php file, unless you need to exclude things like /images/ or perhaps /stylesheets/ depending-on-site.) Contrariwise, the first line is unnecessary, because real physical filenames do not end in / slash.
I'm getting a ton of warnings from obvious botswtf? I thought this was an under-construction site, currently not accessible to anyone except yourself. (And possibly to things like link checkers that you’ve individually authorized.)
I still get the infinite loop, though, and no error for it in the log file.“It isn’t a bug, it’s a feature.” The server is doing precisely what you’ve told it to do, succeeding at every step of the way, so no errors. You do need to look more closely at the RewriteLog--which I realize goes by a different name in 2.4, but someone else will have to help out on details--because that’s where you see if things are getting rewritten the way they’re supposed to, and only the way they’re supposed to.
Wouldn’t that make two // slashes? And aren’t the last two lines redundant? If it contains an /index.php file, then by definition it would have to be a real directory. (And, vice versa, every directory would contain an index.php file, unless you need to exclude things like /images/ or perhaps /stylesheets/ depending-on-site.) Contrariwise, the first line is unnecessary, because real physical filenames do not end in / slash.
In any case I hope those -f and -d tests are just for testing purposes, as they're horribly inefficient: the server has to go physically looking for the file every single time.
wtf? I thought this was an under-construction site, currently not accessible to anyone except yourself. (And possibly to things like link checkers that you’ve individually authorized.)
You do need to look more closely at the RewriteLog--which I realize goes by a different name in 2.4, but someone else will have to help out on details--because that’s where you see if things are getting rewritten the way they’re supposed to, and only the way they’re supposed to.
It kinda sounds as if you are doing all this by some means other than directly editing your config file (keep a copy!) in a text editor. Is that right?
then by definition it would have to be a real directory
RewriteCond %{REQUEST_URI} !-d
RewriteRule ^(.+)/$ /$1 RewriteCond %{REQUEST_URI} !^/(?:foo|bar)/$ [NC]
RewriteRule ^(.+)/$ /$1 The server automatically redirects to example.com/classifieds/ , but I don't know where that happensThat’s mod_dir again, doing its other job: If there is a slashless request for the real, physical
then gives an ERR_TOO_MANY_REDIRECTS error.Who gives the error? The browser, or the server? Does it show up in logs as a long series of requests each getting a 301 response, or as a single request getting a 500 response?
It is, but it's a /ww2/ subdomain on a live site. Changing LogLevel via WHM changed it server-wide, so (as far as I know) the error log for my /ww2/ subdomain is mashed together with the errors from the live domain.What is WHM, anyway? Did you explain it at some point, or is it something I ought to know in any case?
is DirectorySlash On or Off in your config?
Who gives the error? The browser, or the server? Does it show up in logs as a long series of requests each getting a 301 response, or as a single request getting a 500 response?
It is sometimes useful for testing purposes to express a rewrite as an external redirect, because then you can readily see--both in access logs and your browser's address bar--exactly what is being requested at every point.
On the broader scale: I think it might be appropriate from here on to select some individual URL at random, work out exactly what we want to have happen with it--user requests A, server provides content from B--and then once it's hammered into shape we can expand it to a generic pattern.
What is WHM, anyway? Did you explain it at some point, or is it something I ought to know in any case?
Although you cannot set LogLevel in htaccess, you can set it within a directory section (I just re-checked Apache docs).
Doesn’t your ww2 subdomain live in its own physical directory? Seems like it would have to. Does it also have a separate <VirtualHost>? If so, you would be able to designate a separate ErrorLog file (permitted in VirtualHost though not in Directory sections) so you don't have to plow through everything just to get information for the area you're working on.
But you will be very careful with these [L]-less rules, won't you? ;)
RewriteRule ^blah/(foo|bar)/(.*) /blah/$2?topic=$1 [NC,QSA]
RewriteRule ^blah/[^/]+/([0-9]+)/?$ /blah/?id=$1 [NC,QSA,L] RewriteRule ^blah/(foo|bar)/(.*) /blah/$2?topic=$1 [NC,QSA]
RewriteRule ^blah/[^/]+/([0-9]+)/?$ /blah/index.php?id=$1 [NC,QSA,L]
RewriteRule ^blah/favorites/?$ /blah/index.php?favorites=1 [NC,QSA,L]
RewriteRule ^blah/([a-z-]+)/?$ /blah/index.php?p=$1 [NC,QSA,L]
# safety net (not tested)
RewriteCond %{QUERY_STRING} (?:^|&)topic=[a-z-]+ [NC]
RewriteCond %{QUERY_STRING} !(?:^|&)(?:id|favorites|p)= [NC]
RewriteRule ^blah(?:/(.+))? - [NC,QSA,L] For the most part, if I change something in Apache configuration manually then it gets rewritten by WHM when they do another update.Criminy. Isn’t there some way to override this? It’s your own damn server; you should be able to tell it to do what you want, and only what you want.
RewriteRule ^blah/(foo|bar)/(.*) /blah/$2?topic=$1 [NC,QSA]
RewriteRule ^blah/[^/]+/([0-9]+)/?$ /blah/index.php?id=$1 [NC,QSA,L]because a request (if not rewritten) could potentially match both patterns, say