fix: proxy HTTP health checks via server to avoid mixed-content block
- Add /api/check?url= endpoint to server.js for server-side HTTP checks - Gitea and Syncthing use proxy:true to route through this endpoint - Fixes Gitea/Syncthing showing DOWN due to https→http mixed content Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4ba31525cb
commit
15b87f3722
|
|
@ -100,6 +100,24 @@ app.get('/api/health', (req, res) => {
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── サービス死活チェックプロキシ (/api/check?url=...) ──────────
|
||||||
|
// ブラウザの mixed-content 制限を回避するためサーバー側から HTTP チェック
|
||||||
|
app.get('/api/check', async (req, res) => {
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
const { url } = req.query;
|
||||||
|
if (!url) return res.status(400).json({ ok: false, error: 'url required' });
|
||||||
|
const t0 = Date.now();
|
||||||
|
try {
|
||||||
|
const ctrl = new AbortController();
|
||||||
|
const timer = setTimeout(() => ctrl.abort(), 5000);
|
||||||
|
const r = await fetch(url, { method: 'HEAD', signal: ctrl.signal });
|
||||||
|
clearTimeout(timer);
|
||||||
|
res.json({ ok: true, status: r.status, latency_ms: Date.now() - t0 });
|
||||||
|
} catch (e) {
|
||||||
|
res.json({ ok: false, error: e.message, latency_ms: Date.now() - t0 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Tailscale証明書を自動検出
|
// Tailscale証明書を自動検出
|
||||||
function findCert() {
|
function findCert() {
|
||||||
const home = os.homedir();
|
const home = os.homedir();
|
||||||
|
|
|
||||||
|
|
@ -311,8 +311,8 @@ const HISTORY_MAX = 20;
|
||||||
const SERVICES = [
|
const SERVICES = [
|
||||||
{id:'posimai-dev',name:'posimai-dev', desc:'ブラウザターミナル + Claude Code',url:HEALTH_URL, isHealth:true},
|
{id:'posimai-dev',name:'posimai-dev', desc:'ブラウザターミナル + Claude Code',url:HEALTH_URL, isHealth:true},
|
||||||
{id:'posimai-api',name:'Posimai API',desc:'Node.js / Express — VPS 本番', url:'https://api.soar-enrich.com', isHealth:false},
|
{id:'posimai-api',name:'Posimai API',desc:'Node.js / Express — VPS 本番', url:'https://api.soar-enrich.com', isHealth:false},
|
||||||
{id:'gitea', name:'Gitea', desc:'ローカル Git バックアップ', url:'http://100.76.7.3:3000', isHealth:false},
|
{id:'gitea', name:'Gitea', desc:'ローカル Git バックアップ', url:'/api/check?url=http://100.76.7.3:3000', isHealth:false, proxy:true},
|
||||||
{id:'syncthing', name:'Syncthing', desc:'ファイル同期 GUI', url:'http://100.77.11.43:8384', isHealth:false},
|
{id:'syncthing', name:'Syncthing', desc:'ファイル同期 GUI', url:'/api/check?url=http://100.77.11.43:8384', isHealth:false, proxy:true},
|
||||||
{id:'vercel', name:'Vercel', desc:'PWA ホスティング (27本)', url:'https://vercel.com', isHealth:false},
|
{id:'vercel', name:'Vercel', desc:'PWA ホスティング (27本)', url:'https://vercel.com', isHealth:false},
|
||||||
{id:'github', name:'GitHub', desc:'ソースコード管理', url:'https://github.com/posimai', isHealth:false},
|
{id:'github', name:'GitHub', desc:'ソースコード管理', url:'https://github.com/posimai', isHealth:false},
|
||||||
];
|
];
|
||||||
|
|
@ -461,11 +461,23 @@ async function checkService(svc){
|
||||||
const t0=Date.now();
|
const t0=Date.now();
|
||||||
try{
|
try{
|
||||||
const ctrl=new AbortController(),timer=setTimeout(()=>ctrl.abort(),7000);
|
const ctrl=new AbortController(),timer=setTimeout(()=>ctrl.abort(),7000);
|
||||||
|
if(svc.proxy){
|
||||||
|
// サーバー経由プロキシチェック(mixed-content 回避)
|
||||||
|
const r=await fetch(svc.url,{signal:ctrl.signal});
|
||||||
|
clearTimeout(timer);
|
||||||
|
const data=await r.json();
|
||||||
|
const ok=data.ok||(data.status&&data.status<500);
|
||||||
|
badge.className='service-badge '+(ok?'ok':'crit');
|
||||||
|
badge.textContent=ok?'OK':'DOWN';
|
||||||
|
latEl.textContent=data.latency_ms?`${data.latency_ms}ms`:'';
|
||||||
|
pushSvcHistory(svc.id,!!ok);
|
||||||
|
}else{
|
||||||
await fetch(svc.url,{method:'HEAD',mode:'no-cors',signal:ctrl.signal});
|
await fetch(svc.url,{method:'HEAD',mode:'no-cors',signal:ctrl.signal});
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
badge.className='service-badge ok'; badge.textContent='OK';
|
badge.className='service-badge ok'; badge.textContent='OK';
|
||||||
latEl.textContent=`${Date.now()-t0}ms`;
|
latEl.textContent=`${Date.now()-t0}ms`;
|
||||||
pushSvcHistory(svc.id,true);
|
pushSvcHistory(svc.id,true);
|
||||||
|
}
|
||||||
}catch(e){
|
}catch(e){
|
||||||
badge.className='service-badge crit'; badge.textContent='DOWN'; latEl.textContent='';
|
badge.className='service-badge crit'; badge.textContent='DOWN'; latEl.textContent='';
|
||||||
pushSvcHistory(svc.id,false);
|
pushSvcHistory(svc.id,false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue