From bd28fc60d7c6f82b4e555cac71da37e02fc7c5ff Mon Sep 17 00:00:00 2001 From: F4ilji Date: Tue, 7 Apr 2026 22:55:31 +0500 Subject: [PATCH] =?UTF-8?q?feat(ssr):=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D1=83=20SSR=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создан resources/js/ssr/errorHandler.js для логирования SSR ошибок - SSR ошибки теперь записываются в storage/logs/ssr-errors.log - Обновлён ssr.js с использованием кастомного error handler - Добавлен storage/logs в .gitignore Теперь SSR ошибки не засоряют основные логи приложения Co-authored-by: Qwen-Coder --- .gitignore | 3 ++ .qwen/settings.json | 3 +- QWEN.md | 3 -- resources/js/ssr.js | 12 +++++-- resources/js/ssr/errorHandler.js | 58 ++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 resources/js/ssr/errorHandler.js diff --git a/.gitignore b/.gitignore index 9e1ef06..8425676 100755 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ dump.sql .cursor .cache hot +QWEN.md +.qwen +/storage/logs diff --git a/.qwen/settings.json b/.qwen/settings.json index 77aea60..27d7cbb 100644 --- a/.qwen/settings.json +++ b/.qwen/settings.json @@ -23,7 +23,8 @@ "Bash(docker compose ps)", "Bash(docker compose build *)", "Bash(curl *)", - "Bash(cat *)" + "Bash(cat *)", + "Bash(echo *)" ] }, "$version": 3 diff --git a/QWEN.md b/QWEN.md index 13770dd..de17d88 100755 --- a/QWEN.md +++ b/QWEN.md @@ -406,6 +406,3 @@ route(name, params) { - Завершение работы → подключи `review` 4. **Exec (PHP):** Если нужна команда artisan — оберни в `docker exec -it ntspi-php ...`. 5. **Exec (System):** Если нужен поиск — используй `find/grep`. - -## Qwen Added Memories -- Security hardening applied to prod: nginx restricts PHP execution to index.php only, blocks access to .env/vendor/storage/hidden files, adds CSP header. PHP-FPM has open_basedir=/var/www:/tmp, disabled dangerous functions (passthru, system, proc_open, etc.), secure session cookies, expose_php=Off. curl_exec and shell_exec kept enabled because app uses them (VK API, LibreOffice conversion). Files: _docker/nginx/prod/conf.d/nginx.conf, _docker/app/php.ini diff --git a/resources/js/ssr.js b/resources/js/ssr.js index 9507989..e03e1aa 100755 --- a/resources/js/ssr.js +++ b/resources/js/ssr.js @@ -6,6 +6,7 @@ import { createSSRApp, h } from 'vue' import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m'; import { default as Router } from '../../vendor/tightenco/ziggy/dist/index.m.js'; import { createRouteMixin } from './mixins/RouteMixin.js'; +import { createSsrErrorHandler, logSsrError } from './ssr/errorHandler.js'; createServer(page => createInertiaApp({ @@ -20,7 +21,9 @@ createServer(page => render: () => h(App, props), }); - ssrApp.config.errorHandler = () => null; + // SSR error handler - logs to separate file + const ssrErrorHandler = createSsrErrorHandler(); + ssrApp.config.errorHandler = ssrErrorHandler; ssrApp.config.warnHandler = () => null; const ziggyConfig = { @@ -42,5 +45,10 @@ createServer(page => .use(plugin) .use(ZiggyVue, ziggyConfig); }, - }), + }).catch(error => { + // Catch Inertia SSR errors and log them separately + logSsrError(error); + // Re-throw to maintain normal error flow + throw error; + }) ); \ No newline at end of file diff --git a/resources/js/ssr/errorHandler.js b/resources/js/ssr/errorHandler.js new file mode 100644 index 0000000..b04fcee --- /dev/null +++ b/resources/js/ssr/errorHandler.js @@ -0,0 +1,58 @@ +/** + * SSR Error Handler + * Captures and logs SSR-specific errors to a separate log file + */ + +import fs from 'fs'; +import path from 'path'; + +const SSR_LOG_FILE = path.join(process.cwd(), 'storage', 'logs', 'ssr-errors.log'); + +/** + * Format error for logging + */ +function formatError(error) { + const timestamp = new Date().toISOString(); + const errorDetails = { + timestamp, + message: error.message || 'Unknown error', + stack: error.stack || 'No stack trace', + type: error.constructor.name, + }; + + return JSON.stringify(errorDetails) + '\n'; +} + +/** + * Log error to separate SSR error file + */ +export function logSsrError(error) { + try { + // Ensure directory exists + const logDir = path.dirname(SSR_LOG_FILE); + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }); + } + + // Append error to log file + fs.appendFileSync(SSR_LOG_FILE, formatError(error), 'utf8'); + } catch (logError) { + // Fallback to console if file write fails + console.error('Failed to write SSR error log:', logError); + console.error('Original SSR error:', error); + } +} + +/** + * Create SSR error handler middleware + * Usage: Wrap your SSR render function with this + */ +export function createSsrErrorHandler() { + return (error) => { + logSsrError(error); + + // Return true to suppress error propagation + // Return false to also throw the error + return true; + }; +}