Symfony4 routing inside a subfolder

2020-02-15 14:57发布

I have a symfony app in my /var/www/html/app/ and I'd like to access it via host/app/ but I can't make it work.

I have a conf file with this

<Directory /var/www/html/app>

    AllowOverride All
    Order Allow,Deny

    Allow from All

    <IfModule mod_rewrite.c>

        Options -MultiViews
        RewriteEngine On

#       RewriteCond %{REQUEST_FILENAME} !-f
#       RewriteCond %{REQUEST_FILENAME} !-d

#       RewriteRule ^(.*)$ public/$1 [L]

    </IfModule>
</Directory>

It's commented because I tried to do the redirect here but it didn't worked so I made the following .htaccess.

And this htaccess in /var/www/html/app/.htaccess

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On

    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

With this .htaccess, When I go to ://host/app I go to the symfony app (not the apache directory structure) and that seems to be a good start. But the problem is I'm getting an Exception No Routes found for /app/. That's normal because /app/ is the subfolder in my server, not the start of symfony routes.

How can I make the symfony routes beginning after the /app/ folder path ?

I know there is some questions about symfony2/3 routing in subfolder but the answer requires to separate src and public files, that's not what I'd like to have.

I just want my routes working when accessing ://host/app.

For information, It works great when I access ://host/app/public/*Symfony routes*

Edit: New app.conf Alias /rapp "/var/www/html/app/public"

<Directory /var/www/html/app>

    AllowOverride None
    Order Allow,Deny

    Allow from All

    <IfModule mod_rewrite.c>

        Options -MultiViews
        RewriteEngine On
        #RewriteBase /app

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d

        RewriteRule ^(?!public/index.php)$ public/index.php$1 [L]

    </IfModule>
</Directory>

2条回答
smile是对你的礼貌
2楼-- · 2020-02-15 15:45

The problem is the that your web server's document root (the directory that apache will make public via the url) and your project's document root (the public directory) are not the same. Instead your server points to the project directory. That is why you have to manually go into the project's document root by adding the public/ to the url.

You should avoid making the project directory accessible as this could expose your configuration and thus make your website vulnerable, e.g. by giving people access to your database through the credentials inside the config.

You might be able to achieve your goal by storing the project somewhere else and then only symlink your project's public dir to /var/www/html/app. This will probably require some changes to your apache config, e.g. adding Options FollowSymLinks.

Another, more elaborate, approach could be using mod_proxy. The configuration will roughly look like this:

# Your public server reachable from the outside
<VirtualHost *:80>
    ProxyPass /app http://127.0.0.1:8080/
</VirtualHost>

# Your internal server where the requests are proxied to
<VirtualHost 127.0.0.1:8080>
    <Directory /var/www/html/app/public>
        AllowOverride All
        Order Allow,Deny

        Allow from All
    </Directory>
    ...
</VirtualHost>

As you can see the internal web server points to your project's document root (public dir). You might have to do additional both in the apache setup and app, e.g. make sure trusted proxies are set correctly or adding ProxyPreserveHost On to the apache setup, but roughly this should point you in the right direction.

edit: I missed another obvious solution, using mod_alias to point your symfony app to /app:

Alias /app /var/www/html/app/public
查看更多
Luminary・发光体
3楼-- · 2020-02-15 15:47

I managed to resolve the problem !!!

I'm not sure the config is "proper" though but it seems to work.

Here is my working app.conf file (in /etc/apache2/sties-enabled/app.conf)

Alias /app "/var/www/html/app/public"

<Directory /var/www/html/app>

    AllowOverride None
    Order Allow,Deny

    Allow from All

    <IfModule mod_rewrite.c>

        Options -MultiViews
        RewriteEngine On

        RewriteRule (/public) - [L]

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d

        RewriteRule ^(.*)$ index.php/$1 [L]

    </IfModule>
</Directory>

The first RewriteRule is to prevent from internal Rewrite loop when I rewrite url like example.com/app/page-1 to example.com/app/public/index.php/page-1. As page-1 is not a directory or a file it will loop infinitely. So I assume as soon as I have a /public part, the rewrite worked and we stop the rewrite by doing nothing and end the rewrite with the [L] flag.

I'm not suire why I had to remove the public/ part in the "final" RewriteRule (RewriteRule ^(.*)$ index.php/$1 [L]) though.

If someone have ideas to improve this config, feel free to leave comment.

查看更多
登录 后发表回答