RewriteRule is not working with plus (+ or *) character - regex

RewriteRule ^([a-z]).php$ /index.php?zig=$1 [NC,L] # working
This rule is working correctly. But
RewriteRule ^([a-z]+).php$ /index.php?zig=$1 [NC,L] # not working
or
RewriteRule ^([a-z]\+).php$ /index.php?zig=$1 [NC,L] # not working
Is not working. Difference is (+). How to use + in the code above?

This rule is fine:
RewriteRule ^([a-z]+)\.php$ /index.php?zig=$1 [NC,L]
but will create an infinite loop since rewritten URI /index.php also matches the regex pattern. To prevent this you need couple of changes like preventing files/directories from this rewrite and escape the dot as it is a special regex meta character:
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-z]+)\.php$ index.php?zig=$1 [QSA,NC,L]
QSA (Query String Append) flag preserves existing query parameters while adding a new one.

Related

.htaccess rewriterule with backslashes in regex

I want to 'catch' an URL with .htaccess rewriterule. How can I add backslashes to the rewriterule?
For example:
http://www.example.com/page1 -> index.php?page=page1
http://www.example.com/page1/subpage1 -> index.php?page=page1/subpage1
As you can see, I want the backslash between 'page1' and 'subpage1' IN the rewriterule, because the path can be variable (more subpages).
I tried this:
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
But then I get an Internal Server Error.
Thanks in advance!
You get an Internal Server Error because your rule introduces an infinite redirect loop.
Here is what you want
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
It checks if the url is not a physical folder/file before rewriting it internally

.htaccess: Redirect removing file extensions unless part of a query string

Many answers here come close but none are complete.
I would like .htaccess to redirect and remove php/html extensions and trailing slashes so all files, directories, and bootstraps look the same. The problem is that a URL might, or might not, include a query string with an external URL link which therefore should not be altered.
Scenario 1: Remove ".php" from simple URLs.
This: examle.com/file.PHP
Becomes: examle.com/file
Scenario 2: Remove ".php" from URLs but not the query.
This: examle.com/file.PHP?link=anothersite.com/somefile.PHP
Becomes: examle.com/file?link=anothersite.com/somefile.PHP
I have rewrite conditions which work for one or the other scenario but can find no single solution for both.
This condition works for scenario 1 but fails in scenario 2 in that it also strips the extension from the link in the query string.
RewriteCond %{THE_REQUEST} \/(.+)\.php
This (with a \?) works in scenario 2 but ONLY works if there is a query (a question mark) so it fails in scenario 1.
RewriteCond %{THE_REQUEST} \/(.+)\.php\?
The solution would be a regular expression which looks at the whole string unless there is a question mark. Or possibly somehow parses the string at any question mark. I've tried putting a "zero or one" qualifier at the question mark but it caused a redirect loop.
The completed code looks something close to this.
# Remove extensions shown in address bar
RewriteCond %{THE_REQUEST} "\/(.+)\.(php|jar|html|shtml|htm) [NC]
RewriteRule ^ /%1 [L,R=301]
# Remove trailing slashes
RewriteRule ^(.*)/$ /$1 [R=301,L]
# Display php file if it exist
rewriteCond %{REQUEST_FILENAME}.php -f
rewriteRule ^(.+)$ $1.php [L,QSA]
You can use this redirect rule to make it work for both URLs:
RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=302,NE,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [NE,R=302,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
I've included this final code for any who come here with similar issues related to clean & pretty URLs.
The code below should:
Remove trailing garbage (slashes, question marks, dots etc...)
Hide unwanted extensions and indexes
Display the related index.php / filename.php
Thanks to anubhava for the needed solution.
RewriteEngine On
Options -Multiviews -Indexes +FollowSymLinks
RewriteBase /
DirectorySlash Off
# Remove trailing question marks.
RewriteCond %{THE_REQUEST} \?[\s?] [NC]
RewriteRule ^(.*)$ /$1? [R,L]
# Remove unwanted extensions, dots, "index", punctuation, trailing slash
# First condition group removed from anywhere in the path.
# Second condition group only removed from the end of the path.
# The rule will not alter text in the query.
RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.(php|jar|html|shtml|htm)([^\s]*?)[\s?] [NC,OR]
RewriteCond %{THE_REQUEST} \s/+([^?]+?)(\/index|\/|\.|,|\!])[\s?] [NC]
RewriteRule ^ /%1%3 [R,NE,L]
# If path points to a directory containing an index.php, use it
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteRule ^(.+)$ $1/index.php [L]
# ElseIf path/filename points to a php file, use it
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
################################################################
# Below here is only needed if you want a bootstrap
# Without this, files will display or 404 as normal.
################################################################
# If none of the above conditions are met,
# and the request is not an actual file (.jpg, .svg, etc.),
# display the bootstrap file making the path
# a query string for the bootstrap to parse.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?strappath=$1 [QSA,L]
Thanks and please let me know if there are errors or loopholes.

What does RewriteRule ^(.*)/$ ?path=$1 [QSA,L] mean in my .htaccess?

I need to create rewrite in nginx as is done in my .htaccess and there are some lines which I don't completely understand.
DirectoryIndex index.php
RewriteEngine on
RewriteCond % !-f
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
Can someone explain it to me?
RewriteCond % !-f seems incorrect rule condition and is always evaluating to true.
This rule:
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
Is matching any URI with trailing slash and internally rewriting to /?path=uri-without-slash
So for ex: an URI /foo/ will be rewritten to /?path=foo
QSA - Query String Append
L = Last rule
Reference: Apache mod_rewrite Introduction
UPDATE: Change that incorrect condition to:
# request is not for a file
RewriteCond %{REQUEST_FILENAME} !-f
# request is not for a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
It means if the request isn't to a file, then rewrite everything before a trailing / into index.php?path= followed by what was previously matched.
It should be the last rule (L) and it should append the query string (QSA), as opposed to discarding it because of the replacement's query string.

Matching sequence of numbers in URL after specific text

I'm trying to match a sequence of numbers that comes after "job=" while ignoring what comes before it and after it like "list.php?job=11534&name"
Below I've posted what I have so far, which seems to have no affect on the URL.
Also, will [L] only stop the rewrite engine if the rule matches or no matter what?
Thanks in advance for your help.
Current Rule:
RewriteEngine On
RewriteCond %{QUERY_STRING} (?:^|&)job=([^&]+)
RewriteRule ^([0-9]+)$ /positions/job/$1 [L]
# Removes index.php from ExpressionEngine URLs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
RewriteRule ^([0-9]+)$ will match requests that contain only numbers (/4666), this regular expression should be placed in the RewriteCond instead, %1 will refer to it, and the trailing ? in the rewriterule exclude the query string from the new url (is that what you want?).
L will stop the rewrite engine for the current url only if the rule matches.
RewriteCond %{QUERY_STRING} (?:^|&)job=([0-9]+)
RewriteRule ^.+$ /positions/job/%1? [L]
if you want to redirect the user to the new URL, add R to the rewriterule options ([L,R=301]),
be careful that these directives will redirect any url where the query string matches job=([0-9]+) to the new url, if you wanna to restrict the redirection to certain requests(like /folder/list.php?job=qsd&name=qsd), be sure to include them in the rewrite rule, so the directives would be :
RewriteCond %{QUERY_STRING} (?:^|&)job=([0-9]+)
RewriteRule ^folder/list\.php$ /positions/job/%1? [L]

How to fix mod_rewrite regex from producing 500 and 404 errors

I have the following line in my .htaccess
RewriteRule ^folder/(.*)$ /folder/?value=$1 [L]
This always gives me a 500 internal error when I have anything at http://website.com/folder/value.
If I simply change it to
RewriteRule ^folder/(.*)\.html$ /folder/?value=$1 [L]
It sends me properly to http://website.com/folder/value.html with value.html being set in the $_GET.
I want to be able to accept anything such as value, value.com, value-4, otheritem.
Any ideas on why my regex is 500 Internal Server Error'ing everytime?
You're probably getting 500 errors, because your rules are looping. The target of your rule matches the pattern itself (/folder/?value=value matches ^folder/(.*)$ because the query string is stripped before matching). Try including conditions to apply to the rule, something like:
RewriteCond %{REQUEST_FILENAME !-f
RewriteCond %{REQUEST_FILENAME !-d
RewriteRule ^folder/(.*)$ /folder/?value=$1 [L]
Or:
RewriteCond %{REQUEST_URI} !^/folder/?$
RewriteRule ^folder/(.*)$ /folder/?value=$1 [L]
But technically what #Suku suggested should work:
RewriteRule ^folder/(.+)$ /folder/?value=$1 [L]
In my test apache instance, all of the above works while RewriteRule ^folder/(.*)$ /folder/?value=$1 [L] loops (and returns a 500).
You may try this approach that treats both /folder and value (The value of key "value") as dynamic strings, regardless of their format.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} .*/([^/]+)/([^/]+)/? [NC]
RewriteRule .* %1/?value=%2 [L]
It maps internally a URL like this one:
http://website.com/anyfolder/anyvalue or
http://website.com/any/number/of/folders/anyfolder/anyvalue
To:
http://website.com/anyfolder/?value=anyvalue
Of course /anyfolder must exist in the mapped URL, otherwise there will be a 404 error.
This rule-set was tested in a real server without problems.
Here is what happens with this rule:
RewriteRule ^folder/(.*)$ /folder/?value=$1 [L]
The requested URL /folder/test matches the pattern and rewritten as /folder/?value=test
Rewriting stops because of [L] flag
However, since the path/filename changed (/folder/test became /folder/), mod_rewrite will perform another iteration:
The rewritten URL /folder/?value=test matches the pattern and rewritten as /folder/?value=
Repeat
As mentioned in other comments/answers, change * to + and it should solve the problem. If /folder/ exists and contains index.php then one extra line is needed:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^folder/(.+)$ /folder/?value=$1 [L]
What happens is that after re-writing, Apache serves the default document for the existing directory which fires another iteration of rewriting. The condition prevents mod_rewrite from changing /folder/index.php?value=test back to /folder/?value=index.php.