Rewrite rule preserving post data - apache

I'm trying to build a rewrite rule. I cannot redirect because I need to preserve POST and GET data. In particular, if not present I need to add the string "v1". So:
http://www.example.com/ -> http://www.example.com/v1
I tried:
RewriteEngine On
RewriteRule "/(.*)$" "/v1/$1" [NC,L]
But this is not working. Can you help me please?
EDIT: with the first answer:
RewriteRule !^/?v1/ /v1%{REQUEST_URI} [NC,L]
http://www.example.com -> OK
http://www.example.com/v1 -> not preserving POST data (GET OK)
http://www.example.com/v1/ -> OK, please why (I just added a slash after v1, but this is not the solution I'm looking for)?

Have it this way:
RewriteEngine On
RewriteRule !^/?v1/ /v1%{REQUEST_URI} [NC,L]
EDIT: Since /v1/ is a directory and you're entering http://www.example.com/v1 Apache's mod_dir module adds a trailing / to make it http://www.example.com/v1/ using a 301 redirect. POST data gets lost due to 301 redirect.
To prevent this behavior use this snippet:
DirectorySlash Off
RewriteEngine On
# add a trailing slash to directories silently
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L]
RewriteRule !^/?v1(/.*)?$ /v1%{REQUEST_URI} [NC,L]

Related

RewriteRule unexpectedly return 301

I'm lost, I spent hours into this simple issue and can't figure what I'm doing wrong here.
This works as expected:
RewriteEngine on
RewriteRule ^([A-Za-z0-9-_.]+)/([A-Za-z0-9-_.]+/)$ index.php?eins=$1&%{QUERY_STRING}&zwei=$2&%{QUERY_STRING} [L]
and rewrites this request: https://domain.tld/asdf/asdf/ internally
to https://domain.tld/index.php?eins=asdf&zwei=asdf
so far so good everything as expected.
But if I add this additional 2nd rule
RewriteEngine on
RewriteRule ^([A-Za-z0-9-_.]+)/([A-Za-z0-9-_.]+/)$ index.php?eins=$1&%{QUERY_STRING}&zwei=$2&%{QUERY_STRING} [L]
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
Apache responds to the same request https://domain.tld/asdf/asdf/ with 301 to redirect to https://domain.tld/index.php/?eins=asdf&&zwei=asdghi/
I expected The first RewriteRule should be the L = Last one, but why is it redirecting? Actually I would like to achieve a 301 redirect only if a trailing slash is missing.
Check the RewriteRule Flags L|last,
If you are using RewriteRule in either .htaccess files or in
sections, it is important to have some understanding of
how the rules are processed. The simplified form of this is that once
the rules have been processed, the rewritten request is handed back to
the URL parsing engine to do what it may with it. It is possible that
as the rewritten request is handled, the .htaccess file or
section may be encountered again, and thus the ruleset may be run
again from the start. Most commonly this will happen if one of the
rules causes a redirect - either internal or external - causing the
request process to start over.
If you just want to add the trailing slash only for directory, you could try these rules:
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !(.+)/$
RewriteRule ^(.*) $1/ [L,R=301]

mod_rewrite configuration does not work

I have a page with urls like this:
http://example.com/index.php?site=contact
http://example.com/index.php?site=about
So I try to create custom urls like
http://example.com/contact-the-person
http://example.com/cityname/about
to avoid duplicate content the first url need a permanent redirect into the new code.
this is my code:
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/+index\.php?site=contact[\s?] [NC]
RewriteRule ^/contact-the-person [R=301,L]
RewriteRule ^contact-the-person/?$ index.php?site=contact [L,NC]
Update:
I changed my code into
RewriteEngine on
RewriteRule ^cityname/about$ index.php?site=contact
and it works now. I can open the url with both links
http://example.com/index.php?site=contact
http://example.com/cityname/about
I just need a redirect from the php version to the clean url now, to avoid dublicate content
Get rid of RewriteBase, if your base is / it is redundant and just complicates things. I am not sure what your RewriteCond is doing, but it isn't necessary to do the 2 rewrites you describe in the question, so get rid of it too.
To make /contact-the-person work:
RewriteRule ^/contact-the-person index.php?site=contact [L,NC]
To make /cityname/about work:
RewriteRule ^/cityname/about index.php?site=about [L,NC]
So the complete file:
RewriteEngine On
RewriteRule ^/contact-the-person /index.php?site=contact [L,NC]
RewriteRule ^/cityname/about /index.php?site=about [L,NC]
UPDATE
To also redirect your index.php?site=contact links to the new pretty format, you'll need to do an external redirect, so that the browser actually makes a new request, and the URL in the browser changes. Do that by adding R to the flags. 301 specifies the http response header, and will ensure your link rankings are preserved. For the example you gave, add a new rule:
RewriteRule ^/index.php?site=contact /contact-the-person [L,R=301]

Do I need to add 301 redirects when using htaccess to prettify a URL

I use this simple rule to remove index.php from my site's URLs :
RewriteRule ^.*$ ./index.php
So that http://example.com/index.php/user/me becomes http://example.com/user/me.
Do I need to add [R=301] to avoid 'content duplication' issues from an SEO point of view?
You can add this rule to avoid that:
RewriteCond %{THE_REQUEST} \ /index\.php/([^\?\ ]*)
RewriteRule ^ /%1 [L,R=301]
It'll redirect requests made with the /index.php in it to the one without. Then the rule that you already have will internally rewrite the index.php back in.
Just include link rel="canonical" href="http://example.com/ on every page and enjoy :).
Read more here https://support.google.com/webmasters/answer/139066?hl=en

invisible mod_rewrite is not always invisible!? ("www" and "without subdomain")

My site is on a host using cPanel 11.
Unfortunatly it redirects both "www.e-motiv.net" and "e-motiv.net" to public_html.
I want resp. public_html/www and public_html/ and this invisible to the end user.
I thought the best way was through mod_rewrite, so I did the following.
File space looks like this (from public_html/):
/.htaccess
/index.php
/www/index.html
/www/test/index.html
And I want this (second part invisible!):
e-motiv.net -> /index.php
www.e-motiv.net -> /www/index.php
www.e-motiv.net/test -> /www/test/index.php
I thought this would do it:
RewriteCond %{HTTP_HOST} ^www.e-motiv.net$
RewriteCond %{REQUEST_URI} !/www
RewriteRule ^(.*)$ /www/$1 [NC,L]
1 and 2 work, but although 3 gives the right file, it changes the address!? (so not invisible)
So, in address bar you get: www.e-motiv.net/test -> www.e-motiv.net/www/test/
Huh??
If mod_rewrite is not the best solution, please do tell!
This is because of mod_dir. mod_dir adds the tailing slashed to urls that map to directories. mod_dir is not aware of these 'virtual urls' created with mod_rewrite.
So either disable this behavior by using
DirectorySlash Off
This will however make requests to www.example.com/folder result in a 404 not found. You can fix this with some rewriterule though. So the complete solution would be something like:
DirectorySlash Off
#www dir only
RewriteCond %{DOCUMENT_ROOT}/$0 -d
RewriteRule ^www/(.+[^/])$ /$1/ [R,L]
#other dirs
RewriteCond %{DOCUMENT_ROOT}/$0 -d
RewriteRule ^(.+[^/])$ /$1/ [R,L]

apache RewriteRule requires trailing slash at the end of url to work

Ok so i have a url like
domain.com/item/item_id/item_description/page
when i type the link without
/page
on the url it throws a 404 error and i have to type the trailing slash on the url to make it work..
this is my htaccess code
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^item/([0-9]+)/(.*)/(.*)/?$ item.php?action=item&id=$1&desc=$2&page=$3
i have found this after searching:
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]
which kinda solves my problem but how can i make the trailing slash to be optional by the user if the user wants to add it or not so it wont redirect everytime a slash is not found
You can handle the request using one rewriterule.
RewriteRule ^item(?:\.php)/([0-9]+)/([^/]+)?/?([^/]+)?/?$ item.php?action=item&id=$1&desc=$2&page=$3 [L]
Please note I have added (?:\.php) before ^item, just to be sure this rewriterule works, if your webserver for some reason convert request
domain.com/item/...
into
domain.com/item.php/...
Tip: you can see your current rewriterule behavior enabling RewriteLog:
RewriteLogLevel 9
RewriteLog "/var/log/apache2/dummy-host.example.com-rewrite_log"
Be careful do not use this in production.
Use two rewrite rules (one with and one without "page"):
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^item/([0-9]+)/(.*)/?$ item.php?action=item&id=$1&desc=$2
RewriteRule ^item/([0-9]+)/(.*)/(.*)/?$ item.php?action=item&id=$1&desc=$2&page=$3