I still have no answer about this so I'm posting it here.
I want to match an url in the form of root/language/sub/.../document in a .htaccess file and then rewrite it as root/sub/.../document.php?lang=language
Im close to hit but it seems my regexp doesn't 'catch' the input url. Here it is :
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond ^[a-z]{2}.*$/%{REQUEST_FILENAME}\.php -f
RewriteRule ^([a-z]{2})/(.*)$ $2.php?lang=$1
Can someone point me out what is wrong here ? I'm no expert in regexp nor apache rewrites.
Tyvm
* EDIT *
root stands for domain ie mydomain.net
Here are a few examples :
mydomain.net/fr/contact
should be rewriten to
mydomain.net/contact.php?lang=fr
and
mydomain.net/en/articles/view
should be rewriten
mydomain.net/articles/view.php?lang=en
etc...
I believe you are looking for this configuration:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} ^(.*/|)(en|de|fr)/(.*)$ [NC]
RewriteCond %1%3.php -f
RewriteRule ^(.*/|)(en|de|fr)/(.*)$ $1$3.php?lang=$2 [NC,QSA,L]
Explanation:
RewriteCond %{REQUEST_FILENAME} !-d
Checks if requested url is not a directory. If yes, no rewriting will be processed.
RewriteCond %{REQUEST_FILENAME} ^(.*/|)(en|de|fr)/(.*)$ [NC]
Checks if url contains /xx/ part inside, where xx is one en, de or fr. Flag [NC] allows uppercase and lowercase charactes, so for example EN or Fr will be accepted. If there is no such "language" part in the url, no rewriting will be processed.
RewriteCond %1%3.php -f
Checks if %1%3.php file exists, where %1 is (.*/|) and %3 is (.*) matches from the previous RewriteCond ^(.*/|)(en|de|fr)/(.*)$. If such php file does not exist, no rewriting will be processed.
RewriteRule ^(.*/|)(en|de|fr)/(.*)$ $1$3.php?lang=$2 [NC,QSA,L]
In the RewriteRule left condition will be matched if it came to this line, as it was already checked with RewriteCond, so now it will process rewriting to php file, adding lang part, but because there is also [QSA] flag, it will keep also other GET parameters, so lang will be added to existing parameters. Flag [L] says it is last rewriting rule that should apply and no more rewriting will be processed with this url.
Well I'm not sure what root is doing in there, have you tried
RewriteRule ^root/([a-z]{2})/(.*)$ root/$2.php?lang=$1
What's wrong is the second RewriteCond. But your question is vague. If you mean you're trying to convert
root/foo/sub/.../something.php
to
root/sub/.../something.php?lang=foo
then start fidgeting with this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^root/([^/]+)/sub/(.*)/%{REQUEST_FILENAME}$ root/sub/$2/%{REQUEST_FILENAME}?lang=$1
Related
I have a shop URL like this
https://domain.eu/cz/lp/9200
And I'm trying to rewrite it in .htaccess to https://domain.eu/lp/index.php?id=$2&lang=$1
I came really close with
RewriteRule ^/?(hr|sk|pl|cz|ro|it)/lp/(\d+)?$ /lp/index.php?id=$2&lang=$1
which works ok but I can't seem to find a way to handle the situation when there is no lang in URL.
So this is also valid: https://domain.eu/lp/9200 but in that case I want $1 to just be empty (or have a default value when it's not present)
I know "?" means "one or zero" times that's why I tried
RewriteRule ^/?[(hr|sk|pl|cz|ro|it)?]/lp/(\d+)?$ /lp/index.php?id=$2&lang=$1
But it doesn't work as expected. Any point in the right direction would be appreciated.
With your shown samples, attempts; please have your htaccess Rules file in following manner. Make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Rewrite rule for uris which have only 1 parameter.
RewriteRule ^lp/(\d+)/?$ /lp/index.php?id=$1 [NC,L]
##Rewrite rule for uris which 2 parameters.
RewriteRule ^(hr|sk|pl|cz|ro|it)/lp/(\d+)/?$ /lp/index.php?id=$2&lang=$1 [NC,L]
OR use following solutions, in case uris you are trying to access are non-existent ones. Make sure either use 1st solution OR this one, once at a time only.
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^lp/(\d+)/?$ /lp/index.php?id=$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(hr|sk|pl|cz|ro|it)/lp/(\d+)/?$ /lp/index.php?id=$2&lang=$1 [NC,L]
Im trying to both remove .php extensions. So for example "http://localhost/timetable/login" instead of "http://localhost/timetable/login.php"
But also have
"http://localhost/timetable/38/" instead of
"http://localhost/timetable/index.php?week=38"
Im able to get one or the other working but not both at the same time. Im assuming its because there is a conflict between them but Im not advanced enough to find it.
Here is my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteRule ^([0-9]+)$ index.php?week=$2
RewriteRule ^([0-9]+)/$ index.php?week=$2
If in the address bar I type "http://localhost/timetable/38" it brings me to "http://localhost/38/" and an Object not Found error.
Does anyone know what the problem is ?
UPDATE: I can now go to the page but
echo $_GET['week'];
Is returning empty result, so its ignroing the 40 in "http://localhost/timetable/40"
Instead of using separate rewrite rule for each input, you should consider routing all of them as a single string to some php file.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?page=$1 [L,QSA]
In you php file, you can then separate the string as input and use them as required.
<?php
$inputs = explode('/', $_GET['page']);
You only have one capture group when you try to get the week. So it should be $1 instead of $2.
According to this test tool, the following should work:
RewriteRule ([0-9]+)/?$ index.php?week=$1
I would do something like this:
# rewrite if url ends with a number and possibly a slash
RewriteRule ([0-9]+)/?$ index.php?week=$1 [QSA,L]
# do not append .php if it already ends with .php, other add .php
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ $1.php [QSA,L]
Perhaps a better question would be, is there any way to use server variables in the matching string?
For example, I can't understand why this fails to match:
RewriteCond %{REQUEST_URI} %{REQUEST_URI}
First, two points.
I know this condition servers no purpose as is.
I know I have poor knowledge of both htaccess and regex.
What I want is to generically turn this URL www.example.com/dir/path/info into www.example.com/dir?foo=/path/info for bootstrapping.
I tried to accomplish this by removing the extra path info from the deepest actual directory in the URL. I was trying this code to test the premise:
RewriteEngine On
Options -Multiviews -Indexes +FollowSymLinks
RewriteBase /
DirectorySlash Off
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.+)%{PATH_INFO}
RewriteRule ^(.+?) index.php?dir=%1&path=%2 [L]
No luck. To troubleshoot I reduced it to this:
RewriteCond %{PATH_INFO} (.+)
RewriteRule ^(.+?) index.php?dir=%1 [L]
As expected the query returned foo='/path/info'
So I tried this which I thought would match no matter what:
RewriteCond %{PATH_INFO} %{PATH_INFO}
That failed so as a last attempt, I tried capturing the string:
RewriteCond %{PATH_INFO} (.+)
RewriteCond %{PATH_INFO} %1
That also failed to find a match which has me baffled. %1 should be the complete %{PATH_INFO} string. How could it not match itself???
I don't think it matters but I'm using XAMPP on Windows7 in FastCGI.
Rewrite pattern params only allow regex (tho Condpattern also has special flags for tests and comparisons):
RewriteCond TestString CondPattern
RewriteRule Pattern Substitution
Server variables like %{REQUEST_URI} can only be used in Teststring and Substitution. The following docs outline this usage:
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule
If this will go in your main .htaccess, perhaps try:
RewriteCond %{REQUEST_URI} !index\.php$
RewriteRule ^([^/]+)/(.+)$ index.php?dir=/$1&path=/$2 [L]
Two more Example:
Sample1
RewriteBase /
RewriteRule ^(.+/)?index.php(/.+) index.php?dir=/$1&path=$2 [R,L]
Sample2
RewriteBase /
RewriteRule ^((.+/)?index.php)(/.+) $1?path=$3 [R,L]
Sample3
RewriteBase /
RewriteRule ^(.+/)?(.+\.php)(/.+) $1$2?foo=$3 [R,L]
these all do external rewrite so you can see result in the browser address. To revert to internal rewrite, just remove [R] flag
Ok, I found a way to accomplish this goal.
Basically I was trying to compare two server variables. htaccess won't do that. I wanted to extract part of a "pretty" url which points to an actual file or folder. The variable ${SCRIPT_URL} should do that, but it is either depreciated or not reliable. The work around is to put both variables in the test string and use a regex back reference to find the point of duplication.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} (.*?)(/.+)\2$
RewriteRule ^(.*)$ %1.php?strappath=%2 [QSA,END]
In the above example %1 will be the uri of the file and %2 will be the remaining path after the URI, duplicating %{PATH_INFO}.
Follow with this rule for when there is no extra path info
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)$ $1.php [QSA,END]
If no .php file is found, I want the index of that directory and add the un-found file name to the pathinfo. This is a bit trickier.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php !-f
RewriteCond %{REQUEST_FILENAME} ^(.*)(/.+)$
RewriteCond %1 -d
RewriteCond %1/index.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} ^(.*?)(/.+)\2$ [OR]
RewriteCond %{REQUEST_URI} ^(/.+)(/.+)?$
RewriteCond %1 ^(.*)(/.+)$
RewriteRule ^(.*)$ %1/index.php?strappath=%2%{PATH_INFO} [QSA,END]
The above section fails to catch urls that point directly to an existing folder with an index.php, so to catch those:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteCond ^(.+)$ $1/index.php [QSA,END]
I doubt anyone ever finds this useful but I've seen variations of this question asked over and over with no working solution given.
I'm at my wit's end, Stack Overflowers. Trying to do what I thought was a simple rewrite rule to replace slashes in the URL with tilde, then add a ".html" at the end.
So my .htaccess is thus:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.+)/(.+)$ $1~$2 [N]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]+)$ $1.html [L]
Basically I'm running a repeated rule to replace all slashes with tildes one at time, then my final rule adds the ".html" -- because all our web files need to be in one folder (client request--silly, I know).
I've tested the pattern "part-one/part-two/part-three" here: http://martinmelin.se/rewrite-rule-tester/ and it only works if I chop off the initial slash and remove the rewrite conditions (which makes no sense b/c no filename I put in there should exist on that server), but that's not the case on my local server.
It should eventually read the file "part-one~part-two~part-three.html" but when I look at the Apache error log on my local machine, I get this:
File does not exist: /path/to/website/part-one
So it basically chops off the final two parts and never tries to add a ".html" -- so what on earth is going on?? Please help, mod_rewrite gurus!!
The reason why it wants you to remove the leading / is because the rewrite engine strips off the prefix (the leading slash of an URI) before it runs them through rules in an htaccess file. If you were using apache 1.3 or if the rules were in a non-per-directory context in the server or vhost config, then you'd need the leading slash in the rule's pattern:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/(.+)$ /$1~$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^/]+)$ /$1.html [L]
Additionally, you probably don't want the N flag, as you want rewrite to stop immediately in its current iteration. Also, a condition which first checks if the .html actually exists before you rewrite will prevent 500 internal server errors.
HI guys.
Im using mod_rewrite to do some redirects on a web site.
I want to be able to do the following
mySite.com/ -> Goto Home
mySite.com/foo -> Goto redirect.php and redirect acordingly.
My redirect rule was
RewriteRule (^\w*$) redirect.php?url=$1 [NC]
But im oviously missing something because when I go tomySite.com/ I get sent to redirect.php
I need a regex that allow lower and upper case letters, as well as underscores but it has to ignore "empty" strings so when I go to mySite.com/ the index file is displayed.
Any help?
Thanks!
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^index.php index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ redirect.php?url=$1 [NC]
This might work. By the way, you don't have to use () in regex to get $1 which returns everything by default.