FriendsOfSymfony / FOSJsRoutingBundle

A pretty nice way to expose your Symfony routing to client applications.
1.48k stars 261 forks source link

/js/routing?callback=fos.Router.setData working on `dev` but throws a 500 HTTP Exception on `prod` environment #418

Open DavidGarciaCat opened 2 years ago

DavidGarciaCat commented 2 years ago

Good day everyone,

As I was trying to explain as part of the issue's title, using this bundle works fine on my local development environment, setting the APP_ENV to dev. However, when going to production, the same route throws an internal server error.

Does anyone have any idea about what might be happening? Any potential advice or clue to solve this problem?

Thank you, everyone, in advance,

stof commented 2 years ago

Check your logs to see what the error is when getting a 500 server error. Otherwise, there is no way to help you

DavidGarciaCat commented 2 years ago

Hey @stof

I didn't provide them because I don't see how it might help in this specific car - still, please check the configuration files and exposed logs below:

# cat .env | grep APP_ENV

APP_ENV=prod
# config/packages/prod/monolog.yaml

monolog:
    handlers:
        main:
            type: fingers_crossed
            action_level: error
            handler: nested
            excluded_http_codes: [404, 405]
            buffer_size: 50 # How many messages should be saved? Prevent memory leaks
        nested:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
        console:
            type: console
            process_psr_3_messages: false
            channels: ["!event", "!doctrine"]
$ tail -n 0 -f *.log
==> dev.log <==

==> nginx.access.log <==

==> nginx.error.log <==

==> prod.log <==

==> nginx.access.log <==
172.17.0.1 - development [12/Nov/2021:09:48:02 +0000] "GET /js/routing?callback=fos.Router.setData HTTP/1.0" 500 831 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"

Any idea or suggestion?

DavidGarciaCat commented 2 years ago

By the way, this is the logs output when browsing under the dev environment:

$ tail -n 0 -f *.log
==> dev.log <==

==> nginx.access.log <==

==> nginx.error.log <==

==> prod.log <==

==> nginx.access.log <==
172.17.0.1 - development [12/Nov/2021:09:56:45 +0000] "GET /bundles/fosjsrouting/js/router.min.js?97b41d406b578bb70e0ffb4cc4958ee9d542b383 HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"

==> dev.log <==
[2021-11-12T09:56:46.820364+00:00] php.INFO: User Deprecated: The Liip\ImagineBundle\Templating\FilterTrait trait is deprecated since version 2.7 and will be removed in 3.0; use Twig instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The Liip\\ImagineBundle\\Templating\\FilterTrait trait is deprecated since version 2.7 and will be removed in 3.0; use Twig instead. at /opt/project/vendor/liip/imagine-bundle/Templating/FilterTrait.php:14)"} []
[2021-11-12T09:56:46.820548+00:00] php.INFO: User Deprecated: The Liip\ImagineBundle\Templating\FilterExtension class is deprecated since version 2.7 and will be removed in 3.0; configure "twig_mode" to "lazy" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The Liip\\ImagineBundle\\Templating\\FilterExtension class is deprecated since version 2.7 and will be removed in 3.0; configure \"twig_mode\" to \"lazy\" instead. at /opt/project/vendor/liip/imagine-bundle/Templating/FilterExtension.php:14)"} []
[2021-11-12T09:56:46.820592+00:00] php.INFO: User Deprecated: Since symfony/framework-bundle 5.3: The "session.storage.factory.service" service is deprecated, use "session.storage.factory.native", "session.storage.factory.php_bridge" or "session.storage.factory.mock_file" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/framework-bundle 5.3: The \"session.storage.factory.service\" service is deprecated, use \"session.storage.factory.native\", \"session.storage.factory.php_bridge\" or \"session.storage.factory.mock_file\" instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSession_Storage_Factory_ServiceService.php:22)"} []
[2021-11-12T09:56:46.820627+00:00] php.INFO: User Deprecated: Since symfony/framework-bundle 5.3: The "session.storage.native" service is deprecated, use "session.storage.factory.native" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/framework-bundle 5.3: The \"session.storage.native\" service is deprecated, use \"session.storage.factory.native\" instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSession_Storage_NativeService.php:22)"} []
[2021-11-12T09:56:46.820663+00:00] php.INFO: User Deprecated: Since symfony/framework-bundle 5.3: The "session.storage.metadata_bag" service is deprecated, create your own "session.storage.factory" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/framework-bundle 5.3: The \"session.storage.metadata_bag\" service is deprecated, create your own \"session.storage.factory\" instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSession_Storage_MetadataBagService.php:22)"} []
[2021-11-12T09:56:46.822695+00:00] request.INFO: Matched route "fos_js_routing_js". {"route":"fos_js_routing_js","route_parameters":{"_route":"fos_js_routing_js","_controller":"fos_js_routing.controller::indexAction","_format":"js"},"request_uri":"http://alpha.hiccears.net/js/routing?callback=fos.Router.setData","method":"GET"} []
[2021-11-12T09:56:46.847056+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:46.848902+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:46.850387+00:00] php.INFO: User Deprecated: Since symfony/security-bundle 5.3: The "security.password_encoder" service is deprecated, use "security.user_password_hasher" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-bundle 5.3: The \"security.password_encoder\" service is deprecated, use \"security.user_password_hasher\" instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSecurity_PasswordEncoderService.php:22)"} []
[2021-11-12T09:56:46.850519+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Encoder\UserPasswordEncoder" class is deprecated, use "Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Encoder\\UserPasswordEncoder\" class is deprecated, use \"Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasher\" instead. at /opt/project/vendor/symfony/security-core/Encoder/UserPasswordEncoder.php:19)"} []
[2021-11-12T09:56:46.850622+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface" interface is deprecated, use "Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Encoder\\UserPasswordEncoderInterface\" interface is deprecated, use \"Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface\" instead. at /opt/project/vendor/symfony/security-core/Encoder/UserPasswordEncoderInterface.php:17)"} []
[2021-11-12T09:56:46.850729+00:00] php.INFO: User Deprecated: Since symfony/security-bundle 5.3: The "security.encoder_factory.generic" service is deprecated, use "security.password_hasher_factory" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-bundle 5.3: The \"security.encoder_factory.generic\" service is deprecated, use \"security.password_hasher_factory\" instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSecurity_EncoderFactory_GenericService.php:22)"} []
[2021-11-12T09:56:46.850817+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Encoder\EncoderFactory" class is deprecated, use "Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory\" class is deprecated, use \"Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory\" instead. at /opt/project/vendor/symfony/security-core/Encoder/EncoderFactory.php:20)"} []
[2021-11-12T09:56:46.850911+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface" class is deprecated, use "Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface" instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface\" class is deprecated, use \"Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface\" instead. at /opt/project/vendor/symfony/security-core/Encoder/EncoderFactoryInterface.php:17)"} []
[2021-11-12T09:56:46.852556+00:00] php.INFO: User Deprecated: Since symfony/security-bundle 5.3: The "security.authentication.manager" service is deprecated, use the new authenticator system instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-bundle 5.3: The \"security.authentication.manager\" service is deprecated, use the new authenticator system instead. at /opt/project/var/cache/dev/ContainerCyciQux/getSecurity_Authentication_ManagerService.php:22)"} []
[2021-11-12T09:56:46.852669+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager" class is deprecated, use the new authenticator system instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationProviderManager\" class is deprecated, use the new authenticator system instead. at /opt/project/vendor/symfony/security-core/Authentication/AuthenticationProviderManager.php:27)"} []
[2021-11-12T09:56:46.852797+00:00] php.INFO: User Deprecated: Since symfony/security-core 5.3: The "Symfony\Component\Security\Core\Event\AuthenticationFailureEvent" class is deprecated, use "Symfony\Component\Security\Http\Event\LoginFailureEvent" with the new authenticator system instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Since symfony/security-core 5.3: The \"Symfony\\Component\\Security\\Core\\Event\\AuthenticationFailureEvent\" class is deprecated, use \"Symfony\\Component\\Security\\Http\\Event\\LoginFailureEvent\" with the new authenticator system instead. at /opt/project/vendor/symfony/security-core/Event/AuthenticationFailureEvent.php:18)"} []

==> nginx.access.log <==
172.17.0.1 - development [12/Nov/2021:09:56:47 +0000] "GET /js/routing?callback=fos.Router.setData HTTP/1.0" 200 69298 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"

==> dev.log <==
[2021-11-12T09:56:47.047127+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.052344+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.061345+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.063138+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.064640+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.065940+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.067178+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.068464+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.069707+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.071008+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.072208+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.073788+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.076284+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.078174+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.079596+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.081108+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.082496+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.083986+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.085336+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.086715+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.088056+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.089397+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.090733+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.092146+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.093576+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.094914+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.096209+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.097551+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.099278+00:00] doctrine.DEBUG: ...
[2021-11-12T09:56:47.101072+00:00] doctrine.DEBUG: ...
3mg commented 2 years ago

I have the same issue. Error in logs is

[2021-11-17 14:39:07] request.CRITICAL: Uncaught PHP Exception InvalidArgumentException: "The SessionBagInterface "attributes" is not registered." at .../vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php line 317 {"exception":"[object] (InvalidArgumentException(code: 0): The SessionBagInterface \"attributes\" is not registered. at .../vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:317)"} []

Session handler set to session.handler_id: snc_redis.session.handler

xavibrice commented 2 years ago

Hello @DavidGarciaCat , have you been able to solve the problem?

The same thing happens to me, locally it works correctly and in production it gives me an error.

Thanks

tobias-93 commented 2 years ago

@xavibrice as @stof mentioned there is no way to help you without knowing more about the error, which will be described in your logs. 500 errors on prod can have multitudes of sources, sometimes related to cache not being present on dev, but other reasons are also very well possible.

3mg commented 2 years ago

I have the same issue. Error in logs is

[2021-11-17 14:39:07] request.CRITICAL: Uncaught PHP Exception InvalidArgumentException: "The SessionBagInterface "attributes" is not registered." at .../vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php line 317 {"exception":"[object] (InvalidArgumentException(code: 0): The SessionBagInterface "attributes" is not registered. at .../vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:317)"} []

Session handler set to session.handler_id: snc_redis.session.handler

In my case the problem was in service that called

$bag = $this->sessionStorage->getBag('attributes');

And the reason the error was appeared in /js/routing?callback=fos.Router.setData and not in other routes was the firewall config

firewalls:
        dev:
            logout_on_user_change: true
            pattern:  ^/(_(profiler|wdt)|css|images|js|translations)/
            security: false

No security – empty session storage. sessionStorage->getBag throwed the error. I fixed it by wrapping this line in try/catch

try {
            $bag = $this->sessionStorage->getBag('attributes');
        } catch (\InvalidArgumentException $e) {
            return null;
        }

Also enabling security for that route fixes the error.

The reason why there was no error in dev-envirnoment is that one of the services depends on @session service, so during container initialization \Symfony\Component\HttpFoundation\Session\Session constructor always was called and initialized the session storage.

Hope it helps somebody.

DavidGarciaCat commented 2 years ago

Hello @DavidGarciaCat , have you been able to solve the problem?

The same thing happens to me, locally it works correctly and in production it gives me an error.

Thanks

I actually "hacked" a solution for this issue, as I couldn't get any help and I couldn't wait any longer:

As part of my deployment process, after starting the Docker container I am deploying, I run the Symfony Command that generates and stores the JSON data used by the Bundle:

bin/console fos:js-routing:dump --format=json --target=public/js/fos_js_routes.json

Then, I created a custom Twig Filter as follows:

    // ...

    public function getFilters()
    {
        return [
            // ...
            new TwigFilter('file_get_contents', [$this, 'fileGetContents']),
            // ...
        ];
    }

    // ...

    public function fileGetContents(string $path): ?string
    {
        // Inject the `$this->projectDir` through the constructor, using the built-in Symfony parameter
        $fullPath = sprintf('%s/public/%s', $this->projectDir, $path);
        $fullPath = preg_replace('#//#', '/', $fullPath);

        return file_exists($fullPath) ? file_get_contents($fullPath) : null;
    }

    // ...

And, finally, inside my base.html.twig template, I added the following line:

<script src="{{ asset('bundles/fosjsrouting/js/router.min.js') }}"></script>
{% set fosJsRouting = 'js/fos_js_routes.json'|file_get_contents %}
{% if fosJsRouting is not empty %}
    <script> fos.Router.setData({{ fosJsRouting|raw }}); </script>
{% else %}
    <script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>
{% endif %}

Given the bundle works as expected in my local environment, I just needed to add this "hack" for the production environment. On the other hand, it seems "more efficient" doing it this way because we don't need to keep running a call to a Controller just to create the same list of Routes once after another, as in production we don't change the Routes this often.

Still, I would love to get a proper solution/fix from the maintainers, as even if this is not the case, my impression is the bundle has a bug that causes this error - although I don't know how I can help debugging it.

I hope it helps!

atournayre commented 1 year ago

I faced the same issue, with version 2.8.0.

After long search, I also decide to hack.

In my case

bin/console fos:js-routing:dump --target=public/js/fos_js_routes.js

Then in my template

<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
{% if app.environment == 'dev' %}
    <script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>
{% else %}
    <script src="{{ asset('js/fos_js_routes.js') }}"></script>
{% endif %}

I hate using environement variable I twig, but not choice for this and no more time available.

And alternative to @DavidGarciaCat solution

aszenz commented 1 year ago

For me the issue turned out to be

500 - Unable to create Cache directory /var/www/html/var/cache/prod/fosJsRouting

Fixing the permissions of var directory using the guide at https://symfony.com/doc/current/setup/file_permissions.html fixed the problem.

This also relates to #360

ziggurad commented 11 months ago

I see that I'm not the only one with this problem, I thought it was related to the framework I use - Pimcore https://github.com/pimcore/pimcore/discussions/15805

Does anyone have any other advice/solution? I will test the above suggestions soon

paguii commented 5 days ago

Realized when running php bin/console cache:clear the permissions of the folder inside the cache was changed, i ran:

chown -R www-data:www-data [folder]

in the folders and it worked correctly.

DavidGarciaCat commented 5 days ago

and what if you don't run the command but let the SF logic to run the cache during the first run?