Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Host Locale Feature Not Applied to Static Routes #58086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tugrul opened this issue Aug 25, 2024 · 3 comments
Closed

Host Locale Feature Not Applied to Static Routes #58086

tugrul opened this issue Aug 25, 2024 · 3 comments

Comments

@tugrul
Copy link

tugrul commented Aug 25, 2024

Symfony version(s) affected

6.4.10

Description

The host locale feature in Symfony is intended to set the locale based on the request's host. However, this feature does not work for static routes defined in routing configuration files. While the host locale is correctly applied when using annotation routes, static routes do not respect this configuration, resulting in the inability to serve localized static content like robots.txt based on the domain or subdomain.

How to reproduce

Expected config (it not works)

robots_txt:
  path: /robots.txt
  host:
    en: example.uk
    de: example.de
  defaults:
    _controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
    _format: txt
    template: static/robots.txt.twig

Workaround (it works)

robots_txt.en:
  path: /robots.txt
  host: example.uk
  defaults:
    _locale: en
    _controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
    _format: txt
    _canonical_route: robots_txt
    template: static/robots.txt.twig
robots_txt.de:
  path: /robots.txt
  host: example.de
  defaults:
    _locale: de
    _controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
    _format: txt
    _canonical_route: robots_txt
    template: static/robots.txt.twig

Possible Solution

No response

Additional Context

No response

@xabbuh
Copy link
Member

xabbuh commented Aug 26, 2024

Can you create a small example application that allows to reproduce your issue?

@smnandre
Copy link
Member

I've looked at the code and think i understand what is happening here

In the YamlFileLoader, the

$routes = $this->createLocalizedRoute($collection, $name, $config['path']);
$routes->addDefaults($defaults);
$routes->addRequirements($requirements);
$routes->addOptions($options);
$routes->setSchemes($config['schemes'] ?? []);
$routes->setMethods($config['methods'] ?? []);
$routes->setCondition($config['condition'] ?? null);
if (isset($config['host'])) {
$this->addHost($routes, $config['host']);
}

The following line is the key to the problem

$this->addHost($routes, $config['host']);

This is called on "$routes", which is not the original $collection of the method, but a temporary one, containing the route that was just added to it.

See how createLocalizedRoute works in this specific case ($routes is a fresh instance, not the $collection passed in argument)

$routes->add($namePrefix.$name, $route = $this->createRoute($path));
$collection->add($namePrefix.$name, $route);
return $routes;

        $routes->addDefaults($defaults);
        $routes->addRequirements($requirements);
        $routes->addOptions($options);
        $routes->setSchemes($config['schemes'] ?? []);
        $routes->setMethods($config['methods'] ?? []);
        $routes->setCondition($config['condition'] ?? null);

Theses methods work as expected because they are all implemented to apply the data to all its children

But here is the source of the troubles

        if (isset($config['host'])) {
            $this->addHost($routes, $config['host']);
        }

Because addHost either apply the data to its children or ... removes a route from the collection and adds new ones.

foreach ($routes->all() as $name => $route) {
if (null === $locale = $route->getDefault('_locale')) {
$routes->remove($name);
foreach ($hosts as $locale => $host) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setRequirement('_locale', preg_quote($locale));
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setHost($host);
$routes->add($name.'.'.$locale, $localizedRoute);
}

So in this specific scenario, the $routes variable will contain the correct routes in the end, but not the $collection on which parseRoute is working.


Now, not sure what is the best way to fix this.. maybe try to remove these "temporary collections" ?

@smnandre
Copy link
Member

@xabbuh

On a new symfony app

{# config/routes.yaml #}
robots_txt:
    path: '/robots.txt'
    defaults:
        _controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
        _template: 'robots.txt.twig'
    host:
        en: 'www.example.com'
        nl: 'www.example.nl'
        de: 'www.example.de'
php bin/console debug:router

Expected

 --------------- -------- -------- ----------------- -------------- 
  Name           Method   Scheme   Host              Path          
 --------------- -------- -------- ----------------- -------------- 
  robots_txt.en   ANY      ANY      www.example.com   /robots.txt  
  robots_txt.nl   ANY      ANY      www.example.nl    /robots.txt  
  robots_txt.de   ANY      ANY      www.example.de    /robots.txt  
 --------------- -------- -------- ----------------- -------------- 

Results

 ------------ -------- -------- ------ -------------
  Name         Method   Scheme   Host   Path
 ------------ -------- -------- ------ -------------
  robots_txt   ANY      ANY      ANY    /robots.txt
 ------------ -------- -------- ------ -------------

nicolas-grekas added a commit that referenced this issue Jan 9, 2025
This PR was merged into the 6.4 branch.

Discussion
----------

[Routing] Fix configuring a single route's hosts

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #58086
| License       | MIT

All loaders were affected by this issue: when you configure a route it is immediately added to the main collection **and** in the one returned by the `LocalizedRouteTrait`. Problem is: only the latter is updated when configuring hosts, which means they will be ignored.

This PR merges these two collections, with a twist: after its hosts are configured, a route may have to be removed from the main collection  (like `static` becoming `static.nl` and `static.en` in the tests).

Commits
-------

ecbaff0 [Routing] Fix configuring a single route’ hosts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants