Redirrection in .htaccess to set Semantic URLs - php

I'm trying to set Semantic URLs via .htaccess (on local server). I've already replaced index.php?id=# with page# by the means of:
RewriteRule ^/?page([0-9]+)$ index.php?id=$1
It is working. That means that .htaccess is connected properly and runs. Now I want to "glue" the produced link with the original one. That is, to redirect from index.php?id=# on page#. Can't deal with it.
For example, I take only the page with id=0 and make this:
RewriteCond %{HTTP_HOST} ^site\.loc\/index\.php?id=0$ [NC]
RewriteRule ^(.*)$ http://site.loc/page0$1 [R=301,L]
Tell me, please, what is wrong with the rows above.

See also https://stackoverflow.com/a/31280108/345031 on "Ping-Pong" rewrites and how to enable the RewriteLog (or compare access/error.log) to debug such issues.
Your approach was on the right track. But I think for the old-to-new URL redirects you should cut it down to:
optional escape \?
↓ ↓
RewriteCond %{REQUEST_URI} ^/(?:index\.php)?\?id=(\d+)$
RewriteRule .* http://example.org/page%1 [R,END]
↑
Safer than [L] flag
The REQUEST_URI contains the ?-separated QUERY_STRING already. So the RewriteCond can match both. It's best to optionalize the index.php there, because that's not part of the incoming request URL.
(Capturing the page=id parameter per \d+ and %1 was already correct.)
Just use the [END] flag for both Ping-Pong rules. Make your existing internal/pretty-URL RewriteRule last. Otherwise they'd likely interact.

This should work :
RewriteEngine On
RewriteCond %{THE_REQUEST} /index\.php\?id=([^\s]+) [NC]
RewriteRule page%1? [NC,R,L]
RewriteRule ^/?page([0-9]+)/?$ index.php?id=$1 [NC,L]

Related

Apache - Rewriting trailing extension with .htaccess

To remove trailing extension (a .php in this case), I have tried the following two set of rules
RewriteCond %{THE_REQUEST} (\S*?)/(.*?)\.php [NC]
RewriteRule ^ %1/%2 [L,R=301]
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteRule !\.php$ %1.php [NC,L]
and
RewriteRule ^(.*?)\.php$ $1 [NC,L,R=301]
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteRule !\.php$ %1.php [NC,L]
To convert a url like test.com/test.php to test.com/test, the first one works while the second one ends up looping infinitely. The rewrite_log is just confusing, so can anyone tell what is the problem with the second set?
PS: The rules might be inefficient or even not sufficient for a case like test.com but that's not the issue. I just want to understand how the rewrite is working BTS.
As mentioned in the comments, in the first case, there is no looping using %{THE_REQUEST} as the value is static and doesn't change once it is received by the server even after redirecting / "looping". So the rule will remove trailing .php and redirect. As the rewrite rule is substituting values from %{THE_REQUEST} in the rewritecond, after redirection, the value will not contain the trailing .php and thus proceed on to the second rewritecond and then finally redirect internally. After a second redirect, both the conditions will fail to match thus stopping the process
Whereas in the second case, the rewrite rule checks values from the uri which will remove .php and redirect. After redirection, the second rule will internally redirect back to the uri with php extension. Then finally in the supposed third final check which is supposed to not match both the rules, the first rule will again be matching thus infinitely looping the entire process.

.htaccess mod rewrite help needed

I have written this little piece of code. I am very new to this so i am not sure it is all correct. but basically it lets me access urls with the php extension. When people get on the site they are being redirected from the geo ip page to the correct language which like looks like this
main.php?lang=uk or nl or en or eu etc.
right now i can also use it like this
main/?lang=uk or nl or en or eu etc.
I would like to be able to to also remove the variable in the url ?lang=uk.
How would i do this. My .htaccess code is below
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
DirectorySlash On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=301,L]
# remove trailing slash
RewriteRule ^(.*)\/(\?.*)?$ $1$2 [R=301,L]
RewriteRule ^([\w\/-]+)(\?.*)?$ $1.php$2 [L,T=application/x-httpd-php]
</IfModule>
Thanks too anyone willing to help.
The first argument of RewriteRule does match anything after the domain name and prefix* and before any query string if that exists. In http://localhost/this/is/my/test?lang=123 with a .htaccess file in the this/is/ directory it would match my/test. To match a query string, you have to use the %{QUERY_STRING} variable.
If the second argument (the rewritten url) of RewriteRule does not contain a query string, it will automatically append the query string of the original url to the new url.
In the code below I use %{THE_REQUEST}. This is the string that is used to make the request for a page. It is in the form of GET /my/resource?query=string HTTP/1.1. It does not change when rewriting things, which makes it useful to prevent infinite loops.
In your php file make sure that the language is read from a cookie instead of a get variable, then do the following:
#Set cookie for language
RewriteCond %{QUERY_STRING} ^(.*?)&?lang=([^&]+)&?(.*?)$
RewriteRule ^ %{REQUEST_URI}?%1&%3 [CO=lang:%2:127.0.0.1:1:/:0:1,R,L]
#Remove potential prefix or suffix & from query string
RewriteCond %{QUERY_STRING} ^&(.*?)$ [OR]
RewriteCond %{QUERY_STRING} ^(.*?)&$
RewriteRule ^ %{REQUEST_URI}?%1 [R,L]
#External requests with \.php should be without that.
RewriteCond %{THE_REQUEST} \.php
RewriteRule ^(.*)\.php$ $1 [R=301,L]
#Try to load php page if resource does not alreay have an extension
RewriteCond %{REQUEST_URI} !\.[a-z]+$
RewriteRule ^(.*)$ $1.php [L]

Rewriting urls with .htaccess?

I'm trying to rewrite a url but I can't seem to make it happen.
I just want one working example so I can move on to all pages of my website.
So I have this link:
www.domain.com/article.php?id=1
And I can to change it to:
www.domain.com/article/1/
That's ok for now, later I'll replace the number with the article title.
This is what I have on my .htaccess file:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^article\.php\?id=([0-9]+)$ article/$1/
What is wrong it it? I heard that the .htaccess file needs to be in ASCII if using FTP to save in on the server but I don't know how to do it since I created it by myself.
You can't match against the query string in a rewrite rule, you need to match against %{QUERY_STRING} in a condition:
RewriteEngine On # Turn on the rewriting engine
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^article\.php$ article/%1/? [L]
This internally rewrites your request to /article/1/. The browser will still see the old URL.
What you are more likely looking for is to match against the request:
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /+article\.php\?id=([0-9]+)
RewriteRule ^ /article/%1/? [L,R=301]
RewriteRule ^article/([0-9]+)/?$ /article.php?id=$1 [L,QSA]
You are doing this backwards, quite literally.
RewriteRule ^article/([0-9]+)$ /article.php?id=$1

how to fix mod rewirte

i have problem with mod rewrite
i made htaccess to convert url from php to html
and every thing fine
but problem is some file i dont need to convert like form.php
this is my htaccess
RewriteCond %{REQUEST_URI} !^(.*)form.php(.*)$
RewriteCond %{REQUEST_URI} !^(.*)sitemap\.xml(.*)$
RewriteCond %{THE_REQUEST} ^[A-Z]+\s([^/]+)\.php\s
RewriteRule .* %1.html [R=301,L]
RewriteRule ^([^/]*)\.html$ $1.php
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^.*$ - [L]
RewriteRule ^index.php$ http://%{http_host} [R=301,L]
i dont need convert sitemap.xml and form.php
but i got error when i try to see file form.php
HTTP Error 500 (Internal Server Error): An unexpected condition was encountered while the server was attempting to fulfill the request.
what i can do?
Checking logs is the best place to start as Marc B suggests. You should enable more verbose mod_rewrite logging as so:
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
RewriteLogLevel 3
Don't take the verbosity of the RewriteLogLevel higher than 3.
So, reading your rules, I think I may know what you mean. You should try this:
RewriteCond %{REQUEST_URI} !form\.php$
I do not think Apache cares about the query string that may follow at the URL. There is a %{QUERY_STRING} variable you can use in addition to %{REQUEST_URI}. Unless you have some weird URLs that may have "php" in them, I presume that all of them will end with ".php".
Since "sitemap.xml" seems OK, it is likely the case that you should follow its example and escape out the period character (".") the same way with "\."
A day later, I had some time to think about these rules.
# Use simpler rules, not all that jazz you prepend, appended.
#
RewriteCond %{REQUEST_URI} form\.php$ [OR]
RewriteCond %{REQUEST_URI} sitemap\.xml$
# If %{REQUEST_URI} matches either of the previous rule,
# we skip a certain number of RewriteRules that follow.
# If you add more rules, and need to skip more, you *need* to adjust this number.
RewriteRule . - [S=2]
# Your original line reads:
#
# RewriteCond %{THE_REQUEST} ^[A-Z]+\s([^/]+)\.php\s
#
# Using "%{THE_REQUEST}" variable means you are processing
# a string like this
#
# "GET /something.html HTTP/1.1"
#
# Did you really need the HTTP method and the protocol version?
# Do something simpler. Match the the "http://host/foo/bar/baz/" portion
# Then match the first part of the PHP file name. So, if URL ends in "something.php"
# The second parenthesis will match "something". Then append ".html"
RewriteRule (^.*\/)([^/]+)(\.php)$ $1$2.html [R=301,L]
# **Then** you are trying to rewrite your HTML files to PHP? Why?
# In any case, do something similar as the last RewriteRule.
RewriteRule (^.*\/)([^/]+)(\.html)$ $1$2.php [R=301,L]
# I do not understand RewriteCond %{ENV:REDIRECT_STATUS} 200 at all
# I don't see you using this environmental variable later on in this
# snippet. Recommend the use of "PT" in case you have other stuff running
# that you want to send the rewrite target to be passed back to the
# URL mapping engine.
RewriteRule ^.*$ - [PT, QSA]
# You neglected to add the leading slash in this pattern
RewriteRule ^/index.php$ http://%{http_host} [R=301,L]

my .htaccess redirection fails

htaccess is enabled, i have the canonicalization running (no-www to www.)
I'm trying to use htaccess to do the following
www.domain.com/page.php?i=Page1
www.domain.com/page.php?i=Page2
To
www.domain.com/Page1
www.domain.com/Page2
I tried using this code snippet, with no luck so far:
rewriterule ^([a-zA-Z0-9_-]+)/$ page.php?i=$1
However I think I'm going the reverse way. I can't find example for this.
I have this but I can't make it work.
Try this:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/page\.php$
RewriteCond %{QUERY_STRING} ^i=([a-zA-Z0-9_-]+)$
RewriteRule ^(.*)$ http://www.domain.com/%1? [R=302,L]
taken from: http://www.simonecarletti.com/blog/2009/01/apache-query-string-redirects/
You want www.domain.com/Page1 to be visible in the browser's address bar, but internally that url should actually /page.php?i=Page1. In that case the problem is the trailing / in your regex:
Rewriterule ^([a-zA-Z0-9_-]+)/$ page.php?i=$1
^---here
Your desired /Page1 url has no trailing slash, yet your rewrite regex requires one, so the pattern doesn't match, and no rewriting occurs. Try removing the / and see if that helps any:
Rewriterule ^([a-zA-Z0-9_-]+)$ page.php?i=$1
^---no /
In order to parse out the query string you need to access it in a RewriteCond
# We need this line because /page.php?i=page.php will cause an infinite loop
RewriteCond %{QUERY_STRING} !i=page.php
# Now we parse out the value of i from the query string
RewriteCond %{QUERY_STRING} i=([^&]+)
RewriteRule ^page.php /%1 [L]

Categories