htaccess Rewriterule for multiple Parameters - .htaccess

I have an URL that Looks like:
https://www.example.com/project/api/read.php?uid=1234567&dvc=ABCDE
I would like to establish a rewrite rule that turns the URL in:
https://www.example.com/project/api/read/1234567/ABCDE
My try Looks like this:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^read/([0-9a-zA-Z_-]*)([0-9a-zA-Z_-]*)$ read.php?uid=$1&dvc=$2 [NC,L,QSA]

RewriteRule ^read/([0-9a-zA-Z_-]*)([0-9a-zA-Z_-]*)$ read.php?uid=$1&dvc=$2 [NC,L,QSA]
You are missing a slash between the path segments in the RewriteRule pattern.
Assuming your .htaccess file is located inside the /project/api subdirectory (as implied by your directive) then try the following instead:
# MultiViews must be disabled for the rewrite to work
Options -MultiViews
# Turn on the rewriting engine
RewriteEngine On
RewriteRule ^read/([\w-]+)/([\w-]*)$ read.php?uid=$1&dvc=$2 [L,QSA]
\w is a shorthand character class that is the same as [0-9a-zA-Z_], to which we add the hyphen (-).
Since the URL /read maps directly to the file /read.php MultiViews must be disabled, otherwise mod_negotiation "rewrites" the request to /read.php (before mod_rewrite) without any URL parameters.
Note that I changed the quantifier from * to + in the first path segment, since this would seem to be mandatory in your URL?
Your example URL (/read/1234567/ABCDE) shows digits in the first path segment and letters in the second. If this is an accurate reflection of the type of URL then the regex should be made more restrictive to check just for this data type.
Aside:
RewriteEngine On # Turn on the rewriting engine
Note that Apache does not support line-end comments. This may be "OK" in this instance because the text after RewriteEngine On is simply ignored. In other cases you might get a 500 internal server error.

Related

How can I Rewrite Query String to Path and remove %20 in url with dash (-)? [duplicate]

So here's my problem. I took over a site that has has a bunch of pages indexed that have %20 indexed in Google. This is simply because the person decided to just use the tag name as the title and url slug. So, the urls were something like this:
http://www.test.com/tag/bob%20hope
http://www.test.com/tag/bob%20hope%20is%20funny
I have added a new field for the url slug and string replaced all spaces with dashes. While I have no problem linking to these new pages and getting the data, I need to 301 redirect the old URLs to the new URLs, which would be something like:
http://www.test.com/tag/bob-hope
http://www.test.com/tag/bob-hope-is-funny
So, it needs to be able to account for multiple spaces. Any questions? :)
Use these rules in your .htaccess file:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteBase /
# keep replacing space to hyphen until there is no space use internal rewrite
RewriteRule ^([^\s%20]*)[\s%20]+(.*)$ $1-$2 [E=NOSPACE:1]
# when there is no space make an external redirection
RewriteCond %{ENV:NOSPACE} =1
RewriteRule ^([^\s%20]+)$ $1 [R=301,L]
This will replace all space characters (\s or %20) to hyphen -
So a URI of /tag/bob%20hope%20is%20funny will become /tag/bob-hope-is-funny with 301
Brief Explanation: If there are more than 1 space in URI then 1st RewriteRule is fired recursively replacing each space character with hyphen - until there is no space left. This rule will only rewrite internally.
Once no space is left 2nd RewriteRule is fired which just uses a 301 redirect to the converted URI.
Building on #anhubhava's answer, it's close, but that will also match %,2 or 0 in the URL, and it can cause a loop on apache 2.2 if you don't use the DPI parameter. The full script should look like this:
Options FollowSymlinks MultiViews
RewriteEngine on
RewriteBase /
# keep replacing space to hyphen until there is no space use internal rewrite
RewriteRule ^([^\s%20]*)(?:\s|%20)+(.*)$ $1-$2 [N,E=NOSPACE:1,DPI]
# when there is no space make an external redirection
RewriteCond %{ENV:NOSPACE} =1
RewriteRule ^([^\s%20]+)$ $1 [R=301,L]
I've also added the N (Next) parameter as this then forces the rules to be re-evaluated from the start straight after this rule if it matches. If this isn't there, you can get problems if you're using apache as a reverse proxy as it's unlikely that it'll get to the end of the rewrites before something else happens.

URL rewrite on core PHP

I want to rewrite URL from
example.com/file.php?id=yes
To
example.com/file.php/yes
Website is on core PHP
I have tried the below code in .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([0-9]+).html /abc.php?id=$1 [QSA,L]
Yes, I have, Now I just want to redirect example.com/file.php?id=yes to example.com/file.php/yes
In order to preserve SEO, having changed the URL structure you could implement an external redirect like this, at the top of your .htaccess file:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=(\w+)
RewriteRule ^file\.php$ /$0/%1 [QSD,R=301,L]
The $0 backreference contains the complete match from the RewriteRule pattern (ie. file.php). And the %1 backreference (note the %) contains the value of the id URL parameter from the preceding CondPattern.
The QSD flag is necessary to discard the original query string from the redirected request.
Note you should test first with a 302 (temporary) redirect in order to avoid potential caching issues.
Aside:
Actually i want to do it due to cosmetic reason and also make this SEO friendly
Although, there's not really any difference SEO-wise between these two URLs. In fact, simply changing the URL structure you could have a short term negative effect on SEO.
RewriteRule ^([0-9]+).html /abc.php?id=$1 [QSA,L]
This appears to do the opposite and something quite different from your intended action...
It would internally rewrite (not "redirect") a URL of the form /0123456789.html?foo=1 to /abc.php?id=0123456789&foo=1

How can I use htaccess to redirect a URL based on it's segments?

I have some old URLs that have since changed. Right now they are going to my 404 page, so I need to redirect them to the new URLs. The original URLs look like this:
http://example.com/en/blog/events-private/name-of-event
The new URLs look like this, without the "blog" segment:
http://example.com/en/events-private/name-of-event
This is what I'm trying but it's not working:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/en/blog/events-private/(.*) /en/events-private/$1
</IfModule>
What am I missing?
This isn't using mod_rewrite but this seems to work:
RedirectMatch 301 ^/en/blog/events-private/(.*) /en/events-private/$1
RewriteRule ^/en/blog/events-private/(.*) /en/events-private/$1
In .htaccess the RewriteRule pattern matches against the URL-path after the directory-prefix (that leads to the .htaccess file) has first been removed. The directory-prefix always ends in a slash, so the URL-path that is matched here never starts with a slash. In other words, you simply need to remove the slash prefix:
RewriteRule ^en/blog/events-private/(.*) /en/events-private/$1 [R=301,L]
(and don't forget the R and L flags.)
Note that this contrasts the use of mod_rewrite in a server (or virtualhost) context. In this context you do need the slash prefix! Because in a server context, the pattern matches against the full URL-path.
Also, the RewriteBase directive in this example is superfluous (since you aren't using a relative substitution). And the <IfModule mod_rewrite.c> wrapper should probably be removed (unless this is intended to function on systems without mod_rewrite).

.htaccess regular expression in Yii when having path url format

I am trying to set the regular expressions to get some parameters from the url. here is one url example:
mydomain.com/files/images/versions/large/uploadedGal/1-36.png
and I need to get two parameters out of this large and 36 and make a url like this:
mydomain.com/index.php?r=image/default/create&id=36&version=large
This is the my regular expression in the htaccess:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# If the requested file or directory does not exist...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# ...and if the source URL points to an image, we redirect to the create image URL.
RewriteRule versions/([^/]+)/[^\-\d]*\-?(\d+)\.(gif|jpg|png)$ index.php?r=image/default/create&id=$2&version=$1 [L,R,QSA]
</IfModule>
Which doesn't work... I cannot figure out where is the problem, I think it doesn't get the parameters write, and I get the error 404 not found. I am using urlFormat as path BTW.
Well ... your pattern is wrong/bad. Considering your example URL
files/images/versions/large/uploadedGal/1-36.png
and how it needs to be transformed/rewritten
index.php?r=image/default/create&id=36&version=large
try this one (definitely works, but you may need to adjust it for different URL types, since you have provided only 1 URL example):
versions/([^/]+)/[^\-\d]*(?:\d+\-)?(\d+)\.(gif|jpg|png)$
or like this (really depends on other possible URLs, but most likely this is what you wanted in first place)
versions/([^/]+)/[^\-]*\-?(\d+)\.(gif|jpg|png)$
Your current pattern will match only up to this part files/images/versions/large/uploadedGal/.

mod_rewrite doesn't actually... re-write the URL

Basically, I've been trying to make some friendly URL's via .htaccess using mod_rewrite - and I've managed to get it to work... but only with basic stuff like:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php http://www.google.co.uk [L]
So mod_rewrite works, and I can re-direct to other sites, other files/directories in my server, etc. - but it seems to not work when I use this:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
Any help on this would be great, as I pretty much suck at mod_rewrite, but it's something I need to learn.
Cheers!
Change your [L] to [R,L] to force an actual HTTP redirect. Otherwise it just does the rewriting internally (when possible), which only affects the mapping from the URI to the filesystem. (See the description of the [R] flag at http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteflags.)
Wrong.
## rewriting from to
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
Should be
## rewriting from to
RewriteRule ^profile/user/([^/]+)$ profile.php?user=$1 [L]
Your configuration currently is this:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
In the RewriteRule you swapped the from and to parameters.
Assuming that on your server there is a directory structure like this:
/var/www/htdocs/profile/user/albert
/var/www/htdocs/profile/user/bob
Then you can use the following rule:
RewriteCond ${QUERY_STRING} ^user=(\w+)$
RewriteRule ^profile\.php$ profile/user/%1 [L]
There are some points that you got wrong here:
The request to "/profile.php?user=bob" first gets split into the Request URI and the Query String. Only the Request URI will be used by mod_rewrite. Therefore you have to handle the query string separately.
I restricted the user name to only [A-Za-z0-9_]. If I had allowed all characters, an attacker could easily call /profile.php?user=../../config.php, which would be rewritten to profile/user/../../config.php, and you probably don't want to share that file with the world.
The arguments to the RewriteRule directive are completely different regarding their syntax.
The first argument (the from part) is a regular expression, which usually starts with a caret ^ and ends with a dollar $.
The second argument (the to part) is the replacement, which is almost only a simple string, with only some special features. This string usually doesn't start with a caret, but looks rather like a pathname.

Resources