fix: real listener restart + remove listen_port editing from UI

Reviewer concerns:
1. POST /api/proxy/restart only saved config (reload), did not restart
   the listener. Now it touches data/restart.signal; proxy watcher
   polls that file separately and force-restarts the listener even
   when config is unchanged.
2. Editing proxy.listen_port via UI could break Docker port mapping
   (compose publishes 25565:25565 only). UI now shows it read-only;
   README documents how to change it together with compose.

- proxy/main.py: ProxyState.check_restart_signal() + watcher uses it
- api/config_io.py: touch_restart_signal() helper
- api/routes/status.py: /api/proxy/restart -> touch_restart_signal()
- frontend Settings: disabled listen_port input + 프록시 재시작 button
- README + .gitignore updated
This commit is contained in:
2026-05-20 16:47:42 +09:00
parent d10dae5cb9
commit 4b0d790748
7 changed files with 82 additions and 19 deletions

View File

@@ -31,16 +31,11 @@ export default function Settings() {
<h2>프록시</h2>
<label>
리스닝 포트
<input
type="number"
value={cfg.proxy.listen_port}
onChange={(e) =>
setCfg({
...cfg,
proxy: { ...cfg.proxy, listen_port: +e.target.value },
})
}
/>
<input type="number" value={cfg.proxy.listen_port} disabled />
<span className="muted">
컨테이너 외부와 매핑된 포트라 docker-compose ports 매핑과 함께 바꿔야 합니다.
대시보드에서는 표시만 합니다.
</span>
</label>
<label className="inline">
<input
@@ -83,6 +78,21 @@ export default function Settings() {
</section>
<div className="actions">
<button onClick={save}>저장</button>
<button
className="ghost"
onClick={async () => {
try {
await api.restart()
setMsg('프록시 listener 재시작 신호 전송')
setError(null)
setTimeout(() => setMsg(null), 2500)
} catch (e) {
setError(e.message)
}
}}
>
프록시 재시작
</button>
{msg && <span className="ok">{msg}</span>}
</div>
</div>

View File

@@ -149,7 +149,14 @@ button {
}
button:hover { filter: brightness(1.1); }
button.danger { background: var(--danger); }
button.ghost {
background: transparent;
color: var(--text);
border: 1px solid var(--border);
}
button.ghost:hover { background: var(--panel-2); filter: none; }
button.mt { margin-top: 12px; }
input:disabled { opacity: 0.7; cursor: not-allowed; }
input,
select {