htaccess rewrite rule, remove question mark - .htaccess

Let's say I have the following url:
http://example.com/?param
how should I remove the question mark from the URL, ie. rewrite
http://example.com/param
to something like this:
http://example.com/index.php?param
Here is my code, that doesn't work:
RewriteEngine On
RewriteRule ^(.*)$ /index.php?$1 [P]

Two completely different things need to happen. First you need to externally redirect the browser to show something different in the URL address bar. Second when the browser resends the 2nd request, the server internally rewrites the query string back. You can't arbitrarily add or remove things in URLs in the wild, as they are locators. You can create a new locator, tell the browser to use this new one instead of the old one, then internally on the server change the new one back to the old one.
See the top part of this answer for an explanation
To make the browser go to the new URL:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(index\.php)?\?([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]
This takes a request for the URL: http://example.com/?something and redirects the browser to the URL: http://example.com/something
Then you need to internally rewrite it back:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]
When the request is made for http://example.com/something, the server rewrites the URI to /index.php?something. This is internal to the server so the browser knows nothing about it and will continue to display the URL http://example.com/something while the server processes the URI /index.php?something.

Related

.htaccess redirect question mark with no parameters

I have several URLs with question marks that need to be removed. For example, I need to redirect this URL:
http://example.net/?/services
To this URL:
http://example.net/services
I have many more like this, so I would like something that can catch everything with the question mark and properly redirect it. Many of the answers I found were trying to use QUERY_STRING as the condition for the rewrite, but without parameters this does not help. After some digging I found a RewiteCond that works, but the RewriteRule redirects to the homepage, rather than the URL without the question mark. What I have currently is this:
# Remove question mark from string
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(index\.php)?\?([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
The first block is the rewrite that I have so far, and the next two are for the CMS url routing. What seems to be happening is that my rewrite in the first block is not keeping the rest of the url. I have tried several combinations and can't seem to figure out how to keep the rest of the url intact.
Many of the answers I found were trying to use QUERY_STRING as the condition for the rewrite, but without parameters this does not help.
Yes, this is exactly what the first URL, with a question mark, contains. So, I'm not sure why "this does not help"? In the URL http://example.net/?/services, /services is the query string. Whether there are key/value pairs (ie. "parameters") is irrelevant.
To redirect URLs of the form http://example.net/?/services, that consist of no URL-path and only a query string, try something like:
# Remove question mark from string
RewriteCond %{QUERY_STRING} ^/(.+)
RewriteRule ^$ /%1? [R,L]
%1 is a backreference to the captured group in the last matched CondPattern (ie. (.+), which captures services). This assumes that the query string (after the ?) always starts with a slash, as in your example. (Incidentally, this is also what your front controller is doing, in reverse, so I assume it must be correct.)
The trailing ? on the substitution removes the original query string from the request.
Make sure you clear your browser cache, as any earlier/erroneous 301s will have been cached by the browser.
If this is intended to be a permanent (301) redirect then change R to R=301, but only when you are sure it's working OK.

Why isn't this RewriteRule working?

I'm trying to rewrite /user/username to /user-profile/?user=username without changing the URL in the address bar. I have the following code:
RewriteRule ^/?user/(.*?)/?$ /user-profile/?user=$1 [L]
RewriteCond %{THE_REQUEST} ^/user-profile/\?user=([^\&\ ]+)
RewriteRule ^/?user-profile/$ /user/%1? [L,R=301]
This changes /user/username to /user-profile/?user= in the address bar. The query string var "user" is left blank but it somehow loads the correct user profile. So I think the first rule is working but the second rule and it's condition must not be since the URL in the address bar is changing. What can I do to fix it?
Thanks!
A couple of things. You have 2 rules, one that internally rewrites and the other redirects the browser. You must have your redirect come before the rewrite, otherwise the internal rewrite gets reprocessed by the redirect rule. The other thing is the %{THE_REQUEST} variable is literally the first line of the HTTP request, and it starts with a method, not the request URI:
GET /user-profile/?user=qwerty HTTP/1.1
is what it will look something like. That means you need to alter your regex to account for those other parts of the request that's not the URI. Try:
RewriteCond %{THE_REQUEST} ^GET\ /user-profile/\?user=([^\&\ ]+) [NC]
RewriteRule ^ /user/%1? [L,R=301]
RewriteRule ^/?user/(.*?)/?$ /user-profile/?user=$1 [L]

HTaccess dynamic URL to static rewrite that works both ways without loop

I have looked through stack overflow and can't find the exact answer I am looking for so here goes.
I have a URL
http://holtplantandmachinery.co.uk/cat/wheel-loaders which redirects to http://holtplantandmachinery.co.uk/category.php?name=wheel-loaders
However I need it to work the other way around when you enter the dynamic URL it rewrites to the static (folder looking) URL above and vice versa. Essentially whatever one is called it should rewrite to the static one. Now I know I need to setup a rewrite that works the opposite way to the one above and then have a condition to stop an infinite loop but I can't seem to get anything to work please help.
When someone types http://holtplantandmachinery.co.uk/category.php?name=wheel-loaders into the browser's URL address bar, the request sent to the holtplantandmachinery.co.uk server looks something like:
GET /category.php?name=wheel-loaders HTTP/1.1
Host: holtplantandmachinery
some other headers
etc
You can use the %{THE_REQUEST} var to match against the first line:
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD)\ category\.php\?name=([^&\ ]+)
RewriteRule ^ /cat/%2? [L,R=301]
This will redirect the request to http://holtplantandmachinery.co.uk/cat/wheel-loaders and that URL will show up in the browser's URL address bar. The reason why you use %{THE_REQUEST} instead of %{QUERY_STRING} is because when your other rule that rewrites the nicer looking URL to the one with the query string, it'll look and the %{QUERY_STRING} would match, the rule would get applied and cause a redirect loop. Alternatively, you could match against the query string and use a:
RewriteCond %{ENV:REDIRECT_STATUS} !200
To ensure the URI wasn't from a previously rewritten internal redirect.
Then you'd have your internal rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?cat/(.*)$ /category.php?name=$1 [L]

mod_rewrite so that first-level subdirectory is a GET variable

Alright, title is REALLY sloppy.
Here's my problem: I have a news site and when you go to the main page (domain.com) it redirects you to domain.com/news/top?geography=San_Francisco after it figures out your geography.
How do I use the .htaccess so that it goes from domain.com/news/top?geography=San_Francisco domain.com/San_Francisco/news/top ?
There are some similar questions, but I have not found one similar enough in that you're editing the URL as a furtherback subdirectory.
It should also be noted that I am using the Code Igniter framework for PHP and it normally has it as domain.com/index.php/news/top?geography=San_Francisco but I did a mod_rewrite already to get rid of the index.php. The code is as follows for that:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Code I've tried:
RewriteRule ^([^/]+)/news/top$ /news/top?geography=$1 [L,QSA]
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Before the index.php rule that you have, try adding this:
RewriteRule ^([^/]+)/news/top$ /news/top?geography=$1 [L,QSA]
You'll need to make sure the links you generate are in the form of domain.com/San_Francisco/news/top though.
But to take care of the links in the wild that still look like the old way, you have to match against the actual request:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /news/top\?geography=([^&]+)
RewriteRule ^news/top$ /%1/news/top? [L,R=301]
This will 301 redirect the browser if someone goes to the link domain.com/news/top?geography=San_Francisco and make it so the browser's address bar says this: domain.com/San_Francisco/news/top. At which point the browser will send another request for the second URL, and you use the rule above to change it back into the one with a query string.

.htaccess https redirect for a single page (using relative urls)

I need to be able to redirect a single page from standard http to https. For example, I want to go from http://domain.com/quote.php to https://domain.com/quote.php.
So far I'm using this code in my .htaccess file, and it's working for the initial redirect.
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^quote.php https://domain.com/quote.php [R=301,L]
My problem, is that once I have visited the quote.php page and get redirected to the https version, all the other site pages I navigate to continue using the https protocol. This is a potential duplicate content issue, as I now have the same content accessible via http and https.
So what I want to do, is be able to do the above redirect, and then somehow do the same thing in reverse for all pages except quote.php. So if you attempted to access them via https, it would redirect to the default http version.
I use relative URLs throughout the site, so I can't simply hard-code in the https/http prefix. I need to be able to do this via .htacess, if possible.
Any help is greatly appreciated.
RewriteCond %{HTTPS} off
RewriteRule ^quote.php$ https://domain.com/quote.php [R=301,L,QSA]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/quote.php
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L,QSA]
answer to comment:
for adding new page to conndtions just put them parenthesis.like:
RewriteCond %{HTTPS} off
RewriteRule ^(quote|contact).php$ https://domain.com/$1.php [R=301,L,QSA]
question 2: QSA flag add current query string to new URL. it happens by default except in case you change query string. You can delete them now safely but if you have added query string, and wanted to have old one too, put that back.
Edit 2:
code above has a little security issue :(, actually it's more than a little :-D.
when you are using https to transfer html codes and page is using relative paths, so that's fine. but when you put these codes in .htaccess they turn into http and that's the problem:-). put the code below to sove the problem:):
RewriteCond %{HTTPS} off
RewriteRule ^(quote|contact).php$ https://domain.com/$1.php [R=301,L,QSA]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/(quote|contact).php
RewriteCond %{REQUEST_URI} !^/(.*)\.(css|png|js|jpe?g|gif|bmp)$
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L,QSA]
Now, all images,scripts,.. that you are using on secure pages, are transferring securely.

Resources