Files
Gnuboard7/public/install/api/sse-probe.php
T
HeuJung 01d319e74b fix(core,installer): 프로세스 출력 인코딩으로 인한 JSON 빈 응답 차단
한국어 Windows 에서 whoami 가 CP949 로 출력해 계정명에 한글이 있으면
invalid UTF-8 이 응답 배열에 실리고 json_encode 가 false 를 반환한다.
echo false 는 빈 문자열이라 HTTP 200 + 빈 본문이 나가는데 예외도 로그도
남지 않아, 설치 마법사 2단계가 진행 불가 상태로 멈춘다.

2026-07 수정(7.0.2)은 로그 축 4곳만 막았다. 출처에서 정규화하고(1차),
응답 경계를 단일 헬퍼로 닫고(2차), 실패 시 문제 필드 경로를 로그에
남기도록(3차) 세 층으로 처리해 다른 경로가 열린 채 남지 않게 했다.

정규화는 복원 가능한 코드페이지 출력을 먼저 되살리므로, 종전 mb_scrub
단독 처리와 달리 한글이 U+FFFD 로 훼손되지 않는다.

같은 원인으로 한국어 Windows 에서 관리자 환경설정의 시스템 정보가
500 이 되던 것도 함께 막았다.
2026-08-29 15:13:14 +09:00

71 lines
2.4 KiB
PHP

<?php
/**
* 그누보드7 웹 인스톨러 — SSE 호환성 사전 체크 API
*
* 클라이언트가 본 엔드포인트로 EventSource 연결을 만들고, 서버가 보내는 두 phase
* "probe" 이벤트의 도착 timing 차이로 환경의 streaming 호환성을 판정한다.
*
* Phase 1: 메시지 1 송신 + flush
* Sleep 2 초
* Phase 2: 메시지 2 송신 + flush
*
* 호환 환경은 두 메시지가 약 2초 간격으로 도착. mod_fcgid/proxy 등이 응답 종료까지
* buffer 보유하는 환경에서는 두 메시지가 거의 동시에 도착 (응답 종료 시점에 일괄 flush).
* 이 timing 차이로 client 가 streaming 가능 여부를 정확히 판정.
*
* 본 endpoint 는 lock / state.json 갱신 / task 실행을 일체 수행하지 않는다.
* 사이드 이펙트 없음.
*
* 응답 형식:
* event: probe
* data: {"phase":1,"server_ts":1234567890.123}
* (sleep 2s)
* event: probe
* data: {"phase":2,"server_ts":1234567892.456}
*
* @method GET
*/
// 설치 완료 시 인스톨러 비즈니스 로직 진입 차단
require_once __DIR__.'/../includes/utf8.php';
require_once __DIR__.'/_guard.php';
installer_guard_or_410();
// SSE 헤더 설정 (install-worker.php 와 동일 — 호환성 검증의 정확도 보장)
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');
// 출력 버퍼 비활성화 — 응답 즉시 송신
@ini_set('output_buffering', 'off');
@ini_set('zlib.output_compression', false);
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', 1);
}
while (ob_get_level() > 0) {
ob_end_clean();
}
@ob_implicit_flush(true);
// 짧은 timeout 으로 충분 — probe 자체가 즉시 종료 (sleep 2초 포함)
@set_time_limit(10);
ignore_user_abort(false);
// Phase 1 — 즉시 송신
echo "event: probe\n";
echo 'data: '.installer_json_encode(['phase' => 1, 'server_ts' => microtime(true)], JSON_UNESCAPED_UNICODE)."\n\n";
@flush();
// 클라이언트는 두 phase 도착 시각 차이로 streaming 호환성 판정.
// streaming 환경은 약 2초 간격으로 도착 / buffer 환경은 거의 동시 도착.
sleep(2);
// Phase 2 — 송신 후 즉시 종료
echo "event: probe\n";
echo 'data: '.installer_json_encode(['phase' => 2, 'server_ts' => microtime(true)], JSON_UNESCAPED_UNICODE)."\n\n";
@flush();
exit;