https://github.com/gnuboard/g7/issues/122 제보자의 추가 지적 2건(빌드가 게시본을 지움 / CLI 최초 게시 후 웹 재생성 불가)에 대응하고, 같은 근본 원인을 공유하는 결함을 전수조사로 함께 고친다. - 빌드가 자기 산출물만 교체한다: 루트 vite `emptyOutDir: false` 기본값 true 는 폴백 없는 코어 3번들과 배달된 immutable URL 의 게시본을 함께 지웠다 - 게시 트리 권한을 웹이 이어받는다: 병합 전 프리플라이트 + 부모 그룹 상속·g+w 종전 소유권 정상화는 root 축만 덮어 비-root CLI 계정은 무방비였다 - 갱신 → 생성 → 완전성 확인을 한 묶음으로: 기록 바이트 대조, .old 원자 스왑, rename 일시 거부 재시도, 프론트 JSON 파싱 검증 - 실패를 억제하고 기록한다: 버전 한정 실패 마커 + 사유별 대시보드 알림 + ext-static:status 점검 커맨드 - 파생: catch-all 제외 목록을 에셋 화이트리스트 합집합에서 파생(mjs·webp·otf 누락), 번들 디스크 쓰기 fail-soft·빈 번들 503, 활성 디렉토리 prune 회피
62 lines
2.7 KiB
PHP
62 lines
2.7 KiB
PHP
<?php
|
|
|
|
use App\Http\Controllers\Api\Public\SitemapController;
|
|
use App\Seo\TemplateRouteResolver;
|
|
use App\Support\StaticExtensionPattern;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
// 개발용 라우트 - 디버그 모드 + 관리자 인증 필수
|
|
Route::get('/dev', function () {
|
|
// 1. 디버그 모드 확인
|
|
if (! config('app.debug')) {
|
|
abort(404);
|
|
}
|
|
|
|
// 2. 관리자 인증 확인 (세션 기반 - stateful 미들웨어로 로그인 시 세션 생성)
|
|
$user = Auth::guard('web')->user();
|
|
if (! $user || ! $user->is_super) {
|
|
abort(403, '관리자 권한이 필요합니다.');
|
|
}
|
|
|
|
return view('dev-dashboard');
|
|
})->name('web.dev');
|
|
|
|
// Admin 라우트 - admin 템플릿 의존성 검증
|
|
Route::prefix('admin')
|
|
->middleware('template.dependencies:admin')
|
|
->group(function () {
|
|
Route::get('/{any?}', function (Request $request) {
|
|
// 미등록 경로는 SPA 셸 본문 + HTTP 404 (soft 404 방지 — 공개#47).
|
|
// 본문은 그대로라 클라이언트가 404 레이아웃을 렌더하고, 봇은 404 색인 제외.
|
|
$path = '/'.ltrim($request->getPathInfo(), '/');
|
|
if (! app(TemplateRouteResolver::class)->routeExists($path, 'admin')) {
|
|
return response(view('admin'), 404);
|
|
}
|
|
|
|
return view('admin');
|
|
})->where('any', StaticExtensionPattern::catchAllExclusion());
|
|
});
|
|
|
|
// Sitemap XML 라우트
|
|
// 자식 경로는 SitemapFileStore::childUrl() 이 sitemapindex 의 <loc> 에 기록하는 값과 일치해야 한다.
|
|
// gzip 여부는 manifest 가 결정하므로 .xml / .xml.gz 를 같은 액션에서 처리한다.
|
|
Route::get('/sitemap.xml', [SitemapController::class, 'index'])->name('web.sitemap');
|
|
Route::get('/sitemap-{n}.xml', [SitemapController::class, 'child'])->whereNumber('n')->name('web.sitemap.child');
|
|
Route::get('/sitemap-{n}.xml.gz', [SitemapController::class, 'child'])->whereNumber('n')->name('web.sitemap.child.gz');
|
|
|
|
// User 라우트 - user 템플릿 의존성 검증 + SEO 봇 감지
|
|
Route::middleware(['template.dependencies:user', 'seo'])
|
|
->group(function () {
|
|
Route::get('/{any?}', function (Request $request) {
|
|
// 미등록 경로는 SPA 셸 본문 + HTTP 404 (soft 404 방지 — 공개#47).
|
|
$path = '/'.ltrim($request->getPathInfo(), '/');
|
|
if (! app(TemplateRouteResolver::class)->routeExists($path, 'user')) {
|
|
return response(view('app'), 404);
|
|
}
|
|
|
|
return view('app');
|
|
})->where('any', '(?!admin)(?!api)(?!plugins)'.StaticExtensionPattern::catchAllExclusion());
|
|
});
|