122 lines
3.8 KiB
PHP
122 lines
3.8 KiB
PHP
<?php
|
||
|
||
use App\Http\Controllers\DocumentController;
|
||
use Illuminate\Support\Facades\Route;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Cache;
|
||
|
||
Route::get('/', function () {
|
||
return view('welcome');
|
||
});
|
||
|
||
// 健康检查路由(用于Docker健康检查)
|
||
Route::get('/health', function () {
|
||
$services = [];
|
||
$allHealthy = true;
|
||
|
||
try {
|
||
// 检查数据库连接
|
||
DB::connection()->getPdo();
|
||
$services['database'] = 'connected';
|
||
} catch (Exception $e) {
|
||
$services['database'] = 'disconnected';
|
||
$allHealthy = false;
|
||
}
|
||
|
||
try {
|
||
// 检查Redis连接
|
||
if (config('cache.default') === 'redis') {
|
||
Cache::store('redis')->put('health_check', 'ok', 10);
|
||
Cache::store('redis')->forget('health_check');
|
||
$services['redis'] = 'connected';
|
||
} else {
|
||
$services['redis'] = 'not_configured';
|
||
}
|
||
} catch (Exception $e) {
|
||
$services['redis'] = 'disconnected';
|
||
$allHealthy = false;
|
||
}
|
||
|
||
try {
|
||
// 检查Meilisearch连接
|
||
if (config('scout.driver') === 'meilisearch') {
|
||
$client = new \GuzzleHttp\Client();
|
||
$response = $client->get(config('scout.meilisearch.host') . '/health', [
|
||
'timeout' => 5,
|
||
'headers' => [
|
||
'Authorization' => 'Bearer ' . config('scout.meilisearch.key')
|
||
]
|
||
]);
|
||
|
||
if ($response->getStatusCode() === 200) {
|
||
$services['meilisearch'] = 'connected';
|
||
} else {
|
||
$services['meilisearch'] = 'unhealthy';
|
||
$allHealthy = false;
|
||
}
|
||
} else {
|
||
$services['meilisearch'] = 'not_configured';
|
||
}
|
||
} catch (Exception $e) {
|
||
$services['meilisearch'] = 'disconnected';
|
||
$allHealthy = false;
|
||
}
|
||
|
||
// 检查存储目录是否可写
|
||
try {
|
||
$testFile = storage_path('logs/health_check_test.tmp');
|
||
file_put_contents($testFile, 'test');
|
||
unlink($testFile);
|
||
$services['storage'] = 'writable';
|
||
} catch (Exception $e) {
|
||
$services['storage'] = 'not_writable';
|
||
$allHealthy = false;
|
||
}
|
||
|
||
$status = $allHealthy ? 'ok' : 'degraded';
|
||
$httpCode = $allHealthy ? 200 : 503;
|
||
|
||
return response()->json([
|
||
'status' => $status,
|
||
'timestamp' => now()->toISOString(),
|
||
'services' => $services,
|
||
'version' => config('app.version', '1.0.0')
|
||
], $httpCode);
|
||
})->name('health.check');
|
||
|
||
// 指引步骤渲染(供终端 webview 打开,公开访问)
|
||
Route::get('/guides/pages/{page}', function (\App\Models\GuidePage $page) {
|
||
return view('guides.page', ['page' => $page]);
|
||
})->name('guides.pages.show');
|
||
|
||
// 文档预览和下载路由(需要认证)
|
||
Route::middleware(['auth'])->group(function () {
|
||
Route::get('/documents/{document}/preview', [DocumentController::class, 'preview'])
|
||
->name('documents.preview');
|
||
Route::get('/documents/{document}/download', [DocumentController::class, 'download'])
|
||
->name('documents.download');
|
||
});
|
||
|
||
// 提供 markdown 目录中 media 文件的访问(需要认证)
|
||
// 路径格式: /markdown-media/{path}
|
||
Route::middleware(['auth'])->get('/markdown-media/{path}', function ($path) {
|
||
$path = trim((string) $path, '/');
|
||
|
||
if ($path === '' || str_contains($path, '../')) {
|
||
abort(404);
|
||
}
|
||
|
||
if (!Storage::disk('markdown')->exists($path)) {
|
||
abort(404);
|
||
}
|
||
|
||
$mimeType = Storage::disk('markdown')->mimeType($path);
|
||
if (!is_string($mimeType) || !str_starts_with($mimeType, 'image/')) {
|
||
abort(404);
|
||
}
|
||
|
||
$file = Storage::disk('markdown')->get($path);
|
||
|
||
return response($file, 200)->header('Content-Type', $mimeType);
|
||
})->where('path', '.*')->name('markdown.media');
|