Skip to content
This repository was archived by the owner on Nov 27, 2020. It is now read-only.

redirect /app.php to prevent duplicate content #497

Merged
merged 3 commits into from
Feb 22, 2013
Merged

redirect /app.php to prevent duplicate content #497

merged 3 commits into from
Feb 22, 2013

Conversation

Tobion
Copy link
Contributor

@Tobion Tobion commented Feb 18, 2013

bc break: no
fix #469

@@ -5,6 +5,9 @@
# RewriteBase /
#</IfModule>

#RewriteRule ^app\.php$ / [R=301,L]
RewriteRule ^app\.php/(.*)$ /$1 [R=301,L]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works correctly. But the line above does not. When requesting /app.php only it gives "Too many redirects".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot get it working for both cases whatever I try. It's not understandable what the heck apache is doing here.
@stof @vicb any idea?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried to "END" the rewrite rule below to prevent recursion (see the mod_rewrite docs).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, thanks. I think that's it. I thought this is what L does but there is a difference between END and L.

@Tobion
Copy link
Contributor Author

Tobion commented Feb 22, 2013

@fabpot finished and tested.

@vicb
Copy link
Contributor

vicb commented Feb 22, 2013

What about removing the L flag altogether ?

@Tobion
Copy link
Contributor Author

Tobion commented Feb 22, 2013

Right we can do that because END includes L

Using the [END] flag terminates not only the current round of rewrite processing (like [L]) ...

@Tobion
Copy link
Contributor Author

Tobion commented Feb 22, 2013

@vicb done.

@@ -5,6 +5,10 @@
# RewriteBase /
#</IfModule>

# redirect to URI without front controller to prevent duplicate content
RewriteRule ^app\.php(/(.*)|$) /$2 [R=301,END]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think (.*) is useless here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just kidding :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when $2 is undefined ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Params in subpattern are usually initialized emty. Anyway, I tested it and no problems encountered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok then looks all good to me. Thanks.

fabpot added a commit that referenced this pull request Feb 22, 2013
This PR was merged into the 2.2 branch.

Commits
-------

99106de added info about changed .htaccess
b46c01a removed QSA flag that is not needed
7da3383 redirect /app.php to prevent duplicate content

Discussion
----------

redirect /app.php to prevent duplicate content

bc break: no
fix #469

---------------------------------------------------------------------------

by Tobion at 2013-02-22T12:43:02Z

@fabpot finished and tested.

---------------------------------------------------------------------------

by vicb at 2013-02-22T12:59:01Z

What about removing the L flag altogether ?

---------------------------------------------------------------------------

by Tobion at 2013-02-22T13:00:53Z

Right we can do that because END includes L

> Using the [END] flag terminates not only the current round of rewrite processing (like [L]) ...

---------------------------------------------------------------------------

by Tobion at 2013-02-22T13:12:06Z

@vicb done.
@fabpot fabpot merged commit 99106de into symfony:2.2 Feb 22, 2013
@Tobion Tobion deleted the patch-2 branch February 22, 2013 14:00
@gimler
Copy link

gimler commented Feb 23, 2013

Please add a note that the 'END' Flag is only available for apache >2.4. With Apach 2.2 you get a error.

[alert] web/.htaccess: RewriteRule: unknown flag 'END

@Tobion
Copy link
Contributor Author

Tobion commented Feb 23, 2013

Thanks for the info. Do you know if it's possible to achieve the same without END flag? I didn't find another solution.
Also would it be possible to make it conditional when END is available?

@vicb
Copy link
Contributor

vicb commented Feb 23, 2013

Via an env var maybe.

Tobias Schultze [email protected] wrote:

Thanks for the info. Do you know if it's possible to achieve the same
without END flag? I didn't find another solution.
Also would it be possible to make it conditional when END is available?


Reply to this email directly or view it on GitHub:
#497 (comment)

@mdavis1982
Copy link

[END] flag is available only in Apache 2.3.9 and greater - this fails on a standard Apache install on Mountain Lion 10.8. We need to find a more portable fix.

fabpot added a commit that referenced this pull request Feb 26, 2013
This reverts commit 507a3f9, reversing
changes made to de036c8.
@fabpot
Copy link
Member

fabpot commented Feb 26, 2013

reverted as it only works on Apache 2.4

fabpot added a commit that referenced this pull request Mar 21, 2013
This PR was merged into the 2.2 branch.

Commits
-------

ea255c0 made the startpage work when mod_rewrite is not available
e97e7fa redirect /app.php to prevent duplicate content

Discussion
----------

redirect /app.php to prevent duplicate content

Improved version of #497. This time it's compatible with Apache < 2.3.9 by not using the END flag. It also features default compatibility with apache aliases (inspired by [Zend](https://github.com/zendframework/ZendSkeletonApplication/blob/master/public/.htaccess)). And it improves the rewriting performance for the homepage by preventing the process to apply to each DirectoryIndex file.

Now I also could also make the startpage work when mod_rewrite is not available.

I tested it thoroughly and also debugged apache rewriting to see what's happening.
It was quite hard to find out how to achieve all that. [This resource](http://stackoverflow.com/questions/7798099/how-to-block-multiple-mod-rewrite-passes-or-infinite-loops-in-a-htaccess-cont) helped quite a bit.

May be good if someone else can confirm all works.

Example behavior for each scenario:

With mod_rewrite:
- `/` -> internally rewritten to use front controller (`app.php`)
- `/path` -> internally rewritten to use front controller
- `/app.php/path` -> external permanent redirect to `/path` to prevent duplicate content
- `/app.php` or `/app.php/`-> external permanent redirect to `/` to prevent duplicate content
- `/app.phpF` stays as-is

Without mod_rewrite but with mod_alias (default module):
- `/` -> external temporary redirect to `/app.php/` so it's explicit and all generated links on the startpage also work with the base path prepended
- `/path` -> stays as-is and would probably return a 404 (we cannot safely and easily redirect with mod_alias to `/app.php/path` because we don't know if the request references a real file like CSS)
- `/app.php/path` -> stays as-is and works because the front controller is given
- `/app.php` -> stays as-is and works because the front controller is given

In an aliased environment with mod_rewrite:
- `/myproject/` -> internally rewritten to use front controller (`app.php`)
- `/myproject/path` -> internally rewritten to use front controller
- `/myproject/app.php/path` -> external permanent redirect to `/myproject/path` to prevent duplicate content
- `/myproject/app.php` -> external permanent redirect to `/myproject/` to prevent duplicate content

In an aliased environment without mod_rewrite:
- `/myproject/` -> stays as-is and works because it uses the DirectoryIndex definition (but the links will not work)
- `/myproject/path` -> stays as-is and would probably return a 404 (except there is such a file)
- `/myproject/app.php/path` -> stays as-is and works because the front controller is given
- `/myproject/app.php` -> stays as-is and works because the front controller is given

---------------------------------------------------------------------------

by colinfrei at 2013-03-01T12:10:59Z

Tested as well on Apache 2.2.16

---------------------------------------------------------------------------

by Tobion at 2013-03-01T12:42:58Z

ping @gimler @vxf @neilferreira considering you commented on the intial PR

---------------------------------------------------------------------------

by gimler at 2013-03-01T12:51:35Z

it works for me server version: Apache/2.2.22 (Ubuntu)

---------------------------------------------------------------------------

by Tobion at 2013-03-01T14:33:20Z

@gimler did you also test it in an aliased environment?

---------------------------------------------------------------------------

by gimler at 2013-03-01T14:38:27Z

no only simple vhost

---------------------------------------------------------------------------

by jalliot at 2013-03-02T15:48:08Z

@Tobion if it is merged here, you should also probably submit an equivalent PR to symfony's [ApacheMatcherDumper](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php).

---------------------------------------------------------------------------

by Tobion at 2013-03-02T21:11:40Z

@jalliot you are right. Thanks for the hint. The apache dumper is also quite strange. For example if you request it with `/app.php/...` the dumped routes wont even be used.

---------------------------------------------------------------------------

by Tobion at 2013-03-21T14:27:51Z

Now I also could also make the startpage work when mod_rewrite is not available.
I also updated the examples in the PR description. @fabpot it's tested and should be ready.
@FabRondeau
Copy link

Hi,
I've just migrated my SF2 application from 2.1 version to 2.2. It was easiest than I could imagine. In developement environment it seams OK (I've just tested navigation in URLs) but in production environment, when I replace in the urls app_dev.php by app.php, the original URL (localhost/applicationsf22/web/app_dev.php/contacts/personne) is redirected in this one : localhost/contacts/personne. Are you sure that the new .htacces is OK ?
Thank you for reply.

@Tobion
Copy link
Contributor Author

Tobion commented Apr 9, 2013

@calamityjane this PR has been reverted. The new one is #503. Which do you refer to?

fabpot added a commit that referenced this pull request Apr 11, 2013
* 2.2: (28 commits)
  added missing license and type in composer.json (refs #527)
  updated VENDORS for 2.2.1
  Add commented framework.validation.cache = apc to prod config
  added loader variable typehint for easier manipulation in IDEs
  updated VENDORS for 2.1.9
  add info about changed htaccess file
  made the startpage work when mod_rewrite is not available
  Refactoring isMethod, bind and Flash
  removed useless "use" statement
  redirect /app.php to prevent duplicate content
  updated VENDORS for 2.2.0
  enabled the HTTP method override by default to be more BC (closes sensio/SensioGeneratorBundle#165)
  Revert "merged branch Tobion/patch-2 (PR #497)"
  Fragments typo
  updated VENDORS for 2.2.0-RC3
  updated VENDORS for 2.1.8
  Update composer.json
  added info about changed .htaccess
  removed QSA flag that is not needed
  redirect /app.php to prevent duplicate content
  ...

Conflicts:
	composer.json
	composer.lock
	src/Acme/DemoBundle/Controller/DemoController.php
@fredpeaks
Copy link

I've got the same problem here (like calamityjane) : the new htaccess redirect to the localhost root without the base folders (in xampp 1.8.1 on windows 8).

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

@fredpeaks again, to which htacess version do you refer to? this one or #503?
Also please give your apache configuration.

@fredpeaks
Copy link

I use the #503 version. What do you want to know about my apache configuration ?
The mod_rewrite module is activated.

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

Your complete apache config for the symfony project. Are you using a vhost or an alias?
How do you access it? Whats the document root?

@fredpeaks
Copy link

I'm not using vhost or alias.
The url of the site is http://localhost:8080/symfonytest/web/app.php/ and it is redirected to localhost:8080/.

Here is my httpd.conf : http://pastebin.com/qakNdE37
It's a basic conf for xampp on windows.

@RomainTweaks
Copy link

I have the same problem as fredpeaks.... :(

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

I see. So you have just put symfony standard in the default htdocs folder of xampp. Remember to not do something like that in production.

@FabRondeau
Copy link

Hi, I think my installation is the same for Wamp. So, what do you suggest for production installation ?

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

Define a virtual host that has the correct document root for the project (/myproject/web/).

@fredpeaks
Copy link

Thank you for your answer. But I think it's a regression to not be able to test production environment without a virtual host. I work with Symfony2 from the beginning and I've always been able to use production environment with xampp and no virtual host.
Of course when I'm not working locally (in "real" production) I don't have that problem because the domain root is on the web folder. But I think it's important to be able to test my projects locally in production environment.
And someone could want to create sites which are not at root of a server (example: thing.com/mywebsite/).

I found a way to make this htaccess work with my configuration but it's not clean cause it depends on the path to the project.
I replace
RewriteRule ^app.php(/(.*)|$) %{CONTEXT_PREFIX}/$2 [R=301,L]

with
RewriteRule ^app.php(/(.*)|$) %{CONTEXT_PREFIX}/path_to_my_project_in_htdocs/web/$2 [R=301,L]

@FabRondeau
Copy link

OK, thank you fr your reply. I'll try this solution as soon as possible.

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

Well you have a non-standard setup that is also not recommended (even if it's only local).
You can either make it work by manually changing the path as you found out. Or you can simply comment the redirect. But in both cases your htaccess would be different from what you should use on the production server. This is why, the local dev environment should be equal to the production one.
Btw, with the old htacess you would need to change the RewriteBase also manually with your setup to make use of mod_rewrite functionality, don't you?

I'll try to find a way to make it work out-of-the-box for your case as well.

@fredpeaks
Copy link

With the old htaccess I didn't have to change the RewriteBase, I think it's only necessary with some configurations.

I understand that it's not recommended but it's a very often used setup. And my local dev environment cannot be the same as production because I work on windows and the production servers are very often on linux. Symfony is able to use relative path to include files or create url in order to prevent problems like this. So I don't understand why we need to break this behavior with this rewriting.

@fredpeaks
Copy link

So cool if you find a way to make it work with my case, I think you would make a lot of people happy :).

But if it's very bad to setup like I did and this modification of the htaccess is to force people to adopt recommended method I understand this. If you have more information about why this is a bad practice, please share !
And thanks for the work

@stof
Copy link
Member

stof commented Apr 16, 2013

@Tobion at least, the old htaccess was allowing to access app.php explicitly when working on such a setup locally whereas it is broken now.

and note that the getting started page of the doc shows an example where the website is accessed this way

@sargath
Copy link

sargath commented Apr 16, 2013

I think that fredpeaks got a little right, because .htaccess (2.2) forces us to make changes in vhosts, and that's not always possible on every hosting place. Besides in old .htaccess I had only need to change the / Rewrite Base and if I wanted to rewrite for dev front so I simply put app_dev.php and it was enough.

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

I think I found a solution. But @fredpeaks does mod_rewrite work in your setup at all? When I try it with your setup it does not work. It gives me a 500. So when you try to access http://localhost/symfonytest/web/mypage (without app.php and app_dev.php) does it work (considerering there is a /mypage path)? And http://localhost/symfonytest/web/ does not work either for me. NVM, was my cache problem.

@Tobion
Copy link
Contributor Author

Tobion commented Apr 16, 2013

I've opened #530 to fix it for installations in subdirectories. Please test it guys as well.

@fredpeaks With the old htaccess you didn't have to change the RewriteBase, but then mod_rewrite wouldn't work. So you would be able to call it with /app.php but not without. With my new PR, the redirect works now for your setup and mod_rewrite also works automatically without manually needing to adjust the RewriteBase.

@fredpeaks
Copy link

Ok I'm testing it.
I've restested the old .htaccess today with an old project and I assure you the rewriting is working without RewriteBase and in a subdirectory.
But thanks for the new version.

@donasnake
Copy link

Hi! I'have the same problem on xampp! in dev mode it's all right, but when i try localhost://../symfony/web/app.php i'm redirect in the welcome page of xampp, and if i try localhost://../symfony/web/app.php/mysite i have a 404. I don't understand what is the solition for this problem. I hope you can help me! Thank you

cordoval pushed a commit to cordoval/symfony-bootstrap that referenced this pull request Nov 6, 2013
This PR was merged into the 2.2 branch.

Discussion
----------

fix redirect when project is installed in subdirectory

When neither a vhost with proper document root nor an apache alias is configured, the redirect was to the wrong location (without the path prefix). The context_prefix env variable was not available then, so we need to use the logic to determine the RewriteBase automatically as we have done it to resolve the app.php file too.

BC break: no
fixes: symfony/symfony-standard#497 (comment) and following

Commits
-------

3a4f0e7 fix redirect when project is installed in subdirectory
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.