Forum Moderators: phranque

Message Too Old, No Replies

.htaccess to remove .php and redirect

         

achshar

2:27 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



Hello

i have url like:
[1]http://example.com/foo.php

i want to have it like:
[2]http://example.com/foo

and also the url [1] when entered redirects to url [2]
i know this is not alot of coding but i dont know about .htaccess. and frankly speaking i dont really want to learn it too :P

If any one out there can help...

also i have a bit of confusion.. what if there also exists an directory with name foo? what would get preference by the server? and any common solution for this?

thanks :)

jdMorgan

3:23 pm on Jun 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> and frankly speaking i dont really want to learn it too

Then we're sorry, but this is not the right forum in which to post such a request. Please review our Forum Charter.

As a start, if you want to change a URL, then you must edit the Web page that links to that URL, or modify the script that generates that Web page if it is a dynamic page. mod_rewrite is useful for 'connecting' a new URL to a previously-existing script filepath, and for speeding up search-engine re-indexing of your new URL(s), but it cannot "change a URL" -- URLs are defined on Web pages, and that is where they must be "changed."

Thanks,
Jim

achshar

4:10 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



oh my! i didnt really meant to offend.
Sorry about that..
what i meant was that i already have the access i just want to make it more easy to remember..
i did a bit of searching and got this which re-writes the url without .php extension.. and it works..

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

now all i need is to redirect the url if .php is already there..

also what if there exists a directory with same name as the file's? which would get priority file or the folder?

i think i presented my question the wrong way.. no offences :)

jdMorgan

4:27 pm on Jun 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> now all i need is to redirect the url if .php is already there..

Right, so what code have your tried (hint: search this forum for "extensionless URLs" or "cruft-free URLs") :)

> also what if there exists a directory with same name as the file's? which would get priority file or the folder?

That depends on how you write the code. Which do you want to take priority?

Jim

achshar

5:05 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



hmm this is a bit tricky but i would take is as simply as possible..

if there exists a slash it MUST look for directory else if the url is clean (without slash) like

http://foo.com/foo or http:// foo. com/foo? foo=foo

(sorry for spaces :( it converts to link)
it MUST look for page.. and return 404 if file not found for what so ever the case is.. this is some thing very similar to what google does..

i searched for it but couldnt do my self any good.. i found code to remove slash or set priority for folder or file (just as you said) but not this one..

thanks alot for your help jdMorgan.. :)

achshar

5:32 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



and yes i found out the code to redirect the .php to extension-less page from one of your posts :)


RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]


but i dont understand how does this work on subdomains?the url only contains my primary domain the url however gives infinite loop if i put the code before the subdomain code which is generated by cpanel


RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^blog\/?(.*)$ "http\:\/\/blog\.example\.com\/$1" [R=301,L]


and works if i put it after the above code.. :O

[edited by: jdMorgan at 7:56 pm (utc) on Jun 7, 2010]
[edit reason] example.com [/edit]

achshar

6:53 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



ok never mind i got that working by putting the sub domain code before the extension removal and redirection code..

now the prob is that the server ignores the presence of slash if both directory and file exists.. no mater what is in the url it shows the directory..

so i need to ensure that the directory page is shown only and only if a slash is present after the name..
and the page is shown in any other case..

edit---------------------

also the foo/index.php --> foo/index which has same content is foo/. So it is a case of duplicate content where foo/ is same as foo/index
help plz, i think i screwed it up!

thanks :)

g1smd

10:48 pm on Jun 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Before your ".php to extensionless" redirect, you need to add another redirect.

This one will redirect external requests for the index.php URL to "example.com/". The code for that has been posted several thousand times before.

So, your code will look like this:

- redirect index.php URL requests to example.com/ 
- redirect .php URL requests to correct extensionless URL (this redirect will never affect index.php because the rule above has already fixed that problem)
- redirect non-www to www (canonical 301 redirect)
- rewrite extensionless URL requests to the correct .php file.


Add the
DirectoryIndex index.php
directive to ensure that URL requests for "/" are served by the index.php file, and you're done.

achshar

11:48 pm on Jun 7, 2010 (gmt 0)

10+ Year Member



ok i hate to say this but i couldnt really find the code to remove index.php :((((

this is what i have


#this should remove index.php but it dosent.. it takes you one level up though
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php


here is what happens if i have this code

the url changes from
http://example.com/index.php?page
to
http://example.com/index?page
but it should have been
http://example.com/?page


so, i can at least take that '.php to extension-less' redirect is working and url rewrite is also working correctly..

but index.php removal is not working. also the problem stated above, if a directory and file exists with same name, the server shows directory page irrespective of weather there is a slash in the end or not

g1smd

7:35 am on Jun 8, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The first block of code is entirely incorrect. It's a rewrite. You require a redirect.

The second and third blocks of code look OK.

The first bit of code should look fairly similar to the second bit of code, but it's pattern should match just index.php and not <anything>.php and the target will be example.com/ and not example.com/$1 too.

That is, make a copy of the second block of code and in the copy, simply replace [^.#?\ ]+ in the first line and [^.]+) in the second line with the word "index". That will be close to what you need.

achshar

12:07 pm on Jun 8, 2010 (gmt 0)

10+ Year Member




RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*index\.php http://example.com/ [R=301,L]

the whole site goes on 500 internal server error.. :(( i am a complete noob when it comes to .htaccess so i might be missing something small here... i also tried adding slashes before index with no good.. :(

achshar

1:58 pm on Jun 8, 2010 (gmt 0)

10+ Year Member



ok but this one does work

#RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
#RewriteRule ^([^/]+/)*index\.php http://example.com/$1 [R=301,L]

i thought the extra parenthesis were not needed and they actually weren't!
but it does not work on subdomains :((
clearly it contains example.com in second line and not something like (.+).example.com..
i am almost there.. :D:D:D:D

jdMorgan

5:55 pm on Jun 8, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The 'extra' parentheses were needed, but the problem appears to be that the number of closing parentheses was one less than the number of opening parentheses. Had you checked your server error log after seeing a 500-error, it would have told you this...

As written, your code will "lose" all but the last --the lowest-level-- subdirectory path-part in any request that contains two or more subdirectory levels.

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+[b]/)*)i[/b]ndex\.ph[b]p$[/b] http://example.com/$1 [R=301,L]

should be correct.

It also seems to me that this project is not correctly specified. You (and we) could try to 'guess' at code for months -- but that would be a complete waste of time, with practically zero chance of success.

Reading between the lines here, you seem to want to

  • Externally redirect direct client requests for <www or blog>.example.com/index.php<? optional query> to <www or blog>.example.com/<?optional query>

  • Externally redirect requests for <www or blog>.example.com/xyz.php (except for index.php previously-handled) to <www or blog>.example.com/xyz

  • Internally rewrite requests for URLs <www or blog>.example.com/<extensionless-page-name> to script filepath+query /index.php?<extensionless-page-name> unless "extensionless-page-name/" exists as a physical subdirectory.

    Is this correct in every detail? Is it a comprehensive description of all desired functions?

    Jim
  • achshar

    7:09 pm on Jun 8, 2010 (gmt 0)

    10+ Year Member



    yes jdMorgan you'v got it exactly what i want.. the second and third points have been achieved and

    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*)index\.php$ http://example.com/$1 [R=301,L]

    also works! yes it does :D :D

    but now that i put it all together, any page which is not index.php or is not directory url give a redirecting loop.. :(

    i.e http://example.com/foo/ works fine

    and so does http://example.com/foo/index.php which correctly gets redirected to foo/

    but http://example.com/foo/something.php is a redirecting loop..

    here is my 'complete' .htaccess.., i dont know if it is safe to publish it publicly r not :O but it only contains the code discussed here and my subdomains..


    RewriteEngine on

    AddType application/x-httpd-php .xml

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^blog\/?(.*)$ "http\:\/\/blog\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^movies\/?(.*)$ "http\:\/\/movies\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^sms\/?(.*)$ "http\:\/\/sms\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^articles\/?(.*)$ "http\:\/\/articles\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^admin\/?(.*)$ "http\:\/\/admin\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^(.*)$ "http\:\/\/example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^resources\/?(.*)$ "http\:\/\/resources\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^images\/?(.*)$ "http\:\/\/images\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^js\/?(.*)$ "http\:\/\/js\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^css\/?(.*)$ "http\:\/\/css\.example\.com\/$1" [R=301,L]

    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^feeds\/?(.*)$ "http\:\/\/feeds\.example\.com\/$1" [R=301,L]

    #this index.php removal works now
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*)index\.php$ http://example.com/$1 [R=301,L]

    #the code below this causes a redirect loop on any page which is not index.php or directory
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}\.php -f
    RewriteRule ^(.*)$ $1.php

    oh yes, putting the code BEFORE the subdomain code doe not help either.. i already checked..

    i really dont know i can i thank you guys enough for helping me out here.. this forum rocks! Thanks alot.. :)

    [edited by: jdMorgan at 2:24 pm (utc) on Jun 18, 2010]
    [edit reason] Example.com [/edit]

    g1smd

    7:45 pm on Jun 8, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Apologies for my cut and paste error with the parentheses.

    achshar

    8:19 pm on Jun 8, 2010 (gmt 0)

    10+ Year Member



    aah never mind :)

    g1smd

    10:11 pm on Jun 8, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    RewriteCond %{HTTP_HOST} ^example.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.example.com$


    can be simplified to:

    RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$


    in one line. DO add the escaping as shown.

    .


    For every target URL in every rule, you also need to remove the escaping and the quotes.

    That is,

    "http\:\/\/blog\.example\.com\/$1"


    should be

    http://blog.example.com/$1

    [edited by: jdMorgan at 2:25 pm (utc) on Jun 18, 2010]
    [edit reason] example.com [/edit]

    achshar

    10:23 pm on Jun 8, 2010 (gmt 0)

    10+ Year Member



    hmm all that coding is done by cpanel.. i didnt do it.. so if i change it, cpanel wont recognise code. And maybe it will screw uo with stats, info, any any other thing that may rely on it..

    you really think it's a good idea coz i dont want to mess things up.. now at-least i can control the subdomains from the cpanel.. if i change the code, they wont show up there and you see i am not that good with .htaccess after all.. php is cool but htaccess codes just dont get into my head.. plus exams coming, alot of homework.. i really cnnot afford reading documentation.. but you guys have helped me alot.. now i can atleast copy-paste small chunks of code to make it work as i want to.. :)

    g1smd

    10:29 pm on Jun 8, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Personally, I want to beat the person who programmed cPanel to a pulp. It produces some of the worst, malformed, inefficient, and just blatantly wrong, .htaccess code on the planet.

    achshar

    10:46 pm on Jun 8, 2010 (gmt 0)

    10+ Year Member



    Oh yeah! we've done it! :D:D:D
    It all works perfectly now..
    it wasnt the code.. i use dreamweaver's login code to pass protect my admin directory and that was creating the problem.. I just had to remove form's action and make it blank action="" from php_self and it all works now... Thanks a ton g1smd and jim.. you made my day... this was the longest ever that i had been at the same problem.. thanks alot... :) :D

    g1smd

    10:50 pm on Jun 8, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Let's see the final code.

    achshar

    10:55 pm on Jun 8, 2010 (gmt 0)

    10+ Year Member




    #this one removes the index.php
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*)index\.php$ http://example.com/$1 [R=301,L]

    #this here removes the .php
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]

    #and this one does an internal rewrite to fetch the desired file
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}\.php -f
    RewriteRule ^(.*)$ $1.php


    how does that look?
    i added comments :)

    g1smd

    7:01 am on Jun 9, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    The third rule needs the [L] flag.

    Add this to the beginning of the third rule:

    RewriteRule %{REQUEST_URI} !\.(gif|jpe?g|png|css|js|zip)$


    because the -f and -d checks read the disk and so are very slow, so you don't want to do those for filetype URLs which are obviously never going to be re-written.

    Between the second and third block of code you could also add the oft-posted standard www to non-www domain canonicalisation code to finish the job off.

    achshar

    12:12 am on Jun 18, 2010 (gmt 0)

    10+ Year Member



    oh sorry i had been out for a while..

    and thanks for that.. :) i've done it and it all seems to work as it should

    and for the www to non-www code, i already have a code, just above all this, that changes www to non www so that should do the thing.. right?

    g1smd

    12:29 am on Jun 18, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    Wrong.

    If you place the www to non-www code any place other than after the second, and before the third bit of code, then you will create a double redirect for some requests. Always avoid this "redirection chain".

    achshar

    12:48 am on Jun 18, 2010 (gmt 0)

    10+ Year Member



    ohkzz yes you are a life saver.. :D
    now when i check the www url was somehow 'urlencoding' the url..
    but when i did a simple cut paste and put the www to non-www code between the second and third block, just as you told me to.. it all worked like a charm..

    here's the code..

    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*)index\.php$ http://example.com/$1 [R=301,L]

    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]

    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^(.*)$ "http\:\/\/example\.com\/$1" [R=301,L]

    RewriteRule %{REQUEST_URI} !\.(gif|jpe?g|png|css|js|zip)$
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}\.php -f
    RewriteRule ^(.*)$ $1.php


    though cpanel no more recognizes that part but at least the site is working.. :)
    thanks again.. :D

    Eidt: oh yes the www does not get removed if none of the redirect codes is brought to work..

    like if i go to www.blog.example.com/stats
    (which shows stats.php)
    nothing happens and www stays there

    but www.blog.example.com/stats.php
    correctly goes to blog.example.com/stats

    [edited by: jdMorgan at 2:27 pm (utc) on Jun 18, 2010]
    [edit reason] example.com [/edit]

    g1smd

    8:08 am on Jun 18, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    ^www.example.com$


    should be

    ^www\.example\.com$


    You must escape literal periods in regular expression patterns.

    .

    "http\:\/\/example\.com\/$1"


    should be

    http://example.com/$1


    You didn't add quotes or slashes on the target URL in the other three rules, and you don't need them here either.

    jdMorgan

    2:32 pm on Jun 18, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Still needs clean-up and a security patch:

    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*index\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*)index\.php$ http://example.com/$1 [R=301,L]
    #
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
    RewriteRule ^(([^/]+/)*[^.]+)\.php http://example.com/$1 [R=301,L]
    #
    RewriteCond %{HTTP_HOST} ^www\.example\.c[b]om[/b]
    RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
    #
    RewriteRule %{REQUEST_URI} !\.(gif|jpe?g|png|css|js|zip)$
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}\.php -f
    RewriteRule ^(.*)$ [b]/$1[/b].php [b][L][/b]

    Jim

    achshar

    10:24 pm on Jun 18, 2010 (gmt 0)

    10+ Year Member



    first of all thanks to both of you for helping me out here..

    @g1smd yes thanks mate i did that and all works fine..

    @Jim if i add that slash in the fourth block before $1..
    RewriteRule ^(.*)$ /$1.php [L]

    pages on my site go 404, but
    RewriteRule ^(.*)$ $1.php [L]

    on the other hand works fine.. :O

    @both..
    the www before subdomains does not get treated if no url rewrite takes place..
    i.e
    if first or second block of code are not brought to use, the third block does not do anything..


    http://www.admin.example.com/stats does not change to http://admin.example.com/stats
    BUT
    http://www.admin.example.com/stats.php or http://www.admin.example.com/index.php
    DO change to http://admin.example.com/stats and http://admin.example.com/ respectively..

    i tried shuffling the order of www to non-www code with my subdomain code but it did not help.. :(

    [edited by: jdMorgan at 1:35 pm (utc) on Jun 19, 2010]
    [edit reason] De-linked [/edit]

    g1smd

    11:03 pm on Jun 18, 2010 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    What sub-domain code?

    This is the first time you mentioned it, so no provision was made in any of the above code for it.

    It is vital to document all requirements before coding commences. That ensures the code does what you want, and caters for all cases.

    The www to non-www code is programmed for exactly "www.example.com" and will never match "www.admin.example.com". You'll need to either modify the existing rule or else add an additional rule to cater for that.
    This 48 message thread spans 2 pages: 48