【问题标题】:Symfony 4: hide debug stacktrace in non prod environmentSymfony 4:在非 prod 环境中隐藏调试堆栈跟踪
【发布时间】:2019-06-12 14:44:39
【问题描述】:

我有 2 个生产环境,分别是 prod1prod2,它们的配置不同,例如数据库和业务逻辑。基本上是主从关系。

我想像在正常生产环境中一样对用户隐藏调试堆栈跟踪。这应该可以通过在 .env 文件中设置 APP_DEBUG=0 来实现。

APP_DEBUG=0

但我得到了调试屏幕:

但奇怪的是这不起作用,只有当我将 APP_ENV 设置为 prod 时,才会显示调试堆栈跟踪。

我的 .env 文件如下所示:

APP_ENV=prod1
APP_DEBUG=0
APP_SECRET=xxxxxxxaxaxaxa

我检查了public/index.php中的参数,有正确的传输:

$env = 'prod1';
$debug = false;
$kernel = new Kernel($env, $debug);

我正在使用 Symfony 4.2.2 和 symfony/env。

谁能重现这种行为?这可能是 Symfony 或 symfony/env 错误?

【问题讨论】:

    标签: symfony4 production-environment


    【解决方案1】:

    问题是,我在项目中错误配置了ExceptionController

    1. FOSRestBundle 有自己的 ExceptionController 用于显示 json/xml 异常

    您在 config/fos_rest.yaml 中配置它:

    fos_rest
        exception:
            enabled: true
            exception_controller: 'App\Controller\ExceptionController::handleExceptionAction'
    
    1. Twig 是 symfony 的默认异常控制器

    您在 config/twig.yaml 中配置它:

    twig:
        debug: '%kernel.debug%'
        exception_controller: App\Controller\ExceptionController::showException
    

    使用的Exception Handler 是 fos_rest,它在我的 services.yaml 中我配置错误

    App\Controller\ExceptionController:
      - '@fos_rest.view_handler.default'
      - '@fos_rest.exception.messages_map'
      -  true   <------ this should be '%kernel.debug%'
      - '@templating.engine.twig'
      - '@logger'
    

    问题是,这里的第三个参数应该是 %kernel.debug%

    最后,我最终得到了 2 个异常控制器,一个用于具有 json 格式响应的 API,另一个用于 Sonata 后端,即标准的 Twig 异常控制器。唯一的解决方案是将请求从一个控制器转发到另一个:

     <?php
    
    namespace App\Controller;
    
    use Psr\Log\LoggerInterface;
    use Symfony\Component\Debug\Exception\FlattenException;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
    use Symfony\Bundle\TwigBundle\Controller\ExceptionController as TwigExceptionController;
    
    class ExceptionController
    {
        protected $debug;
    
        /**
         * @var TwigExceptionController
         */
        protected $twigExceptionController;
    
        /**
         * @param bool $debug
         * @param TwigExceptionController $twigExceptionController
         */
        public function __construct(
            bool $debug,
            TwigExceptionController $twigExceptionController
        )
        {
            $this->debug = $debug;
            $this->twigExceptionController = $twigExceptionController;
        }
    
        /**
         * Converts an Exception to a Response.
         *
         * @param Request                   $request
         * @param FlattenException     $exception
         * @param LoggerInterface $logger
         *
         * @return Response
         */
        public function handleExceptionAction(Request $request, FlattenException $exception, LoggerInterface $logger): Response
        {    
            if (!stristr( strtolower($request->getUri()), '/api/')) {
                return $this->twigExceptionController->showAction($request, $exception, $logger);
            }
    
            $currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
            if ($currentContent) {
                $logger->error('current content: '.$currentContent);
            }
    
            $code = $this->getStatusCode($exception);
            $response = new JsonResponse();
            $response->setStatusCode($code);
            $response->setData([
                'message' => $exception->getMessage(),
                'code' => $code
            ]);
            return $response;
        }
    
    
        /**
         * Determines the status code to use for the response.
         *
         * @param \Exception $exception
         *
         * @return int
         */
        protected function getStatusCode($exception): int
        {
            if (method_exists($exception, 'getCode') && $exception->getCode() > 0) {
                return $exception->getCode();
            }
            if (method_exists($exception, 'getStatusCode') && $exception->getStatusCode() > 0) {
                return $exception->getStatusCode();
            }
    
            return 500;
        }
    
        /**
         * Gets and cleans any content that was already outputted.
         *
         * This code comes from Symfony and should be synchronized on a regular basis
         * see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
         *
         * @return string
         */
        private function getAndCleanOutputBuffering($startObLevel)
        {
            if (ob_get_level() <= $startObLevel) {
                return '';
            }
            Response::closeOutputBuffers($startObLevel + 1, true);
            return ob_get_clean();
        }
    }
    

    【讨论】:

      【解决方案2】:

      我有几个用 Symfony 4 编写的项目。为了重现您的错误,我将我的一个项目更新为 Symfony 4.2.2。所有 Symfony 依赖项:

      symfony/browser-kit                              v4.2.2             Symfony BrowserKit Component
      symfony/cache                                    v4.2.2             Symfony Cache component with PSR-6, PSR-16, and tags
      symfony/class-loader                             v3.4.21            Symfony ClassLoader Component
      symfony/config                                   v4.2.2             Symfony Config Component
      symfony/console                                  v4.2.2             Symfony Console Component
      symfony/contracts                                v1.0.2             A set of abstractions extracted out of the Symfony components
      symfony/css-selector                             v4.2.2             Symfony CssSelector Component
      symfony/debug                                    v4.2.2             Symfony Debug Component
      symfony/dependency-injection                     v4.2.2             Symfony DependencyInjection Component
      symfony/doctrine-bridge                          v4.2.2             Symfony Doctrine Bridge
      symfony/dom-crawler                              v4.2.2             Symfony DomCrawler Component
      symfony/dotenv                                   v4.2.2             Registers environment variables from a .env file
      symfony/event-dispatcher                         v4.2.2             Symfony EventDispatcher Component
      symfony/filesystem                               v4.2.2             Symfony Filesystem Component
      symfony/finder                                   v4.2.2             Symfony Finder Component
      symfony/flex                                     v1.1.8             Composer plugin for Symfony
      symfony/form                                     v4.2.2             Symfony Form Component
      symfony/framework-bundle                         v4.2.2             Symfony FrameworkBundle
      symfony/http-foundation                          v4.2.2             Symfony HttpFoundation Component
      symfony/http-kernel                              v4.2.2             Symfony HttpKernel Component
      symfony/inflector                                v4.2.2             Symfony Inflector Component
      symfony/intl                                     v4.2.2             A PHP replacement layer for the C intl extension that includes additional data from the ICU library.
      symfony/maker-bundle                             v1.11.3            Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.
      symfony/monolog-bridge                           v4.2.2             Symfony Monolog Bridge
      symfony/monolog-bundle                           v3.3.1             Symfony MonologBundle
      symfony/options-resolver                         v4.2.2             Symfony OptionsResolver Component
      symfony/orm-pack                                 v1.0.6             A pack for the Doctrine ORM
      symfony/polyfill-intl-icu                        v1.10.0            Symfony polyfill for intl's ICU-related data and classes
      symfony/polyfill-mbstring                        v1.10.0            Symfony polyfill for the Mbstring extension
      symfony/polyfill-php72                           v1.10.0            Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
      symfony/process                                  v4.2.2             Symfony Process Component
      symfony/profiler-pack                            v1.0.4             A pack for the Symfony web profiler
      symfony/property-access                          v4.2.2             Symfony PropertyAccess Component
      symfony/routing                                  v4.2.2             Symfony Routing Component
      symfony/security-bundle                          v4.2.2             Symfony SecurityBundle
      symfony/security-core                            v4.2.2             Symfony Security Component - Core Library
      symfony/security-csrf                            v4.2.2             Symfony Security Component - CSRF Library
      symfony/security-guard                           v4.2.2             Symfony Security Component - Guard
      symfony/security-http                            v4.2.2             Symfony Security Component - HTTP Integration
      symfony/stopwatch                                v4.2.2             Symfony Stopwatch Component
      symfony/swiftmailer-bundle                       v3.2.5             Symfony SwiftmailerBundle
      symfony/templating                               v4.2.2             Symfony Templating Component
      symfony/translation                              v4.2.2             Symfony Translation Component
      symfony/twig-bridge                              v4.2.2             Symfony Twig Bridge
      symfony/twig-bundle                              v4.2.2             Symfony TwigBundle
      symfony/validator                                v4.2.2             Symfony Validator Component
      symfony/var-dumper                               v4.2.2             Symfony mechanism for exploring and dumping PHP variables
      symfony/var-exporter                             v4.2.2             A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code
      symfony/web-profiler-bundle                      v4.2.2             Symfony WebProfilerBundle
      symfony/web-server-bundle                        v4.2.2             Symfony WebServerBundle
      symfony/yaml                                     v4.2.2             Symfony Yaml Component
      

      为了清楚起见 - 我在 生产 环境中运行这个项目,我使用 Apache2 来完成这项工作。

      在我的项目中,我只有一个 .env 文件,没有任何带有环境变量的 *.local 文件。该文件如下所示:

      APP_ENV=prod
      APP_SECRET=928374923784mysecretkey92837498273
      

      使用这些设置我看不到调试页面 - 正确的行为

      APP_ENV=prod
      APP_DEBUG=1
      APP_SECRET=928374923784mysecretkey92837498273
      

      如果我添加值为 1 的变量 APP_DEBUG - 将显示调试页面 - 正确的行为

      我添加了一个名为 prod1 的自定义环境:

      APP_ENV=prod1
      APP_SECRET=928374923784mysecretkey92837498273
      

      现在调试页面默认可见 - 正确的行为

      我添加了APP_DEBUG=0:

      APP_ENV=prod1
      APP_DEBUG=0
      APP_SECRET=928374923784mysecretkey92837498273
      

      并且没有出现调试页面 - 正确的行为


      如您所见,我无法重现此错误。在 Symfony 4.2.2 中,一切似乎都正常工作。在您的项目或 Web 服务器配置中搜索错误,因为这是导致问题的原因。我认为您在某处覆盖了 APP_DEBUG 变量。也许在 Apache/Nginx 虚拟主机配置中:

      More informations here

      正如 Siavas 所写,它也可以是缓存。尝试手动删除var/log目录并运行composer install


      很遗憾我没有更多的想法,如果项目不是严格保密的,你可以在github上分享,也许我可以帮助你更多

      【讨论】:

      • 不客气。如果你找到了,你能写出错误的原因吗?它对其他人有用
      【解决方案3】:

      你的配置是正确的。

      这很可能是缓存问题:尝试运行 php bin/console cache:clear

      【讨论】:

      • symfony/web-server-bundle 仅供开发使用。该问题的作者清楚地写道,他正在生产环境中启动 Symfony 4 项目。他可能使用 apache 或 nginx 网络服务器。
      • 谢谢,但这不是缓存问题。任何人都可以重现这种行为吗?
      • @KrzysztofRaciniewski 这是真的,我已经删除了与开发环境相关的部分。 OP,提供有关您的环境的更多信息可能会帮助我们引导您朝着正确的方向前进。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-14
      • 2016-02-19
      • 2017-06-29
      • 1970-01-01
      相关资源
      最近更新 更多