bend_puzzle/server/public-health.js
33333-33333 9d70afb4cc
Some checks failed
BEND FIELD CI / release (push) Has been cancelled
BEND FIELD CI / production-bridge (push) Has been cancelled
t
2026-08-01 22:31:04 +09:00

37 lines
2.2 KiB
JavaScript

'use strict';
function deploymentBase(value){
const raw=String(value||'').trim();
if(!raw)return null;
const base=new URL(raw.endsWith('/')?raw:`${raw}/`);
if(!['http:','https:'].includes(base.protocol))throw new Error('LinkField public URL must use HTTP or HTTPS');
return base;
}
async function fetchChecked(url,{accept='application/json',timeoutMs=10_000}={}){
const response=await fetch(url,{headers:{accept},signal:AbortSignal.timeout(timeoutMs)});
return response;
}
async function checkPublicDeployment(publicUrl,{appVersion,timeoutMs=10_000}={}){
const base=deploymentBase(publicUrl);if(!base)return null;
const pageUrl=new URL('',base),apiUrl=new URL('api/cloud/status',base),bridgeUrl=new URL('api-bridge.php?path=/api/cloud/status',base);
const page=await fetchChecked(pageUrl,{accept:'text/html',timeoutMs}),pageBody=await page.text();
if(!page.ok||!pageBody.includes('LinkField'))throw new Error(`Public page failed at ${pageUrl.href}: HTTP ${page.status}`);
const disclosed=page.headers.get('server')||'';if(/\//.test(disclosed))throw new Error(`Public server discloses a detailed version: ${disclosed}`);
for(const relative of ['server.js','package.json','scripts/service-control.js','.linkfield-deployment.json']){
const url=new URL(relative,base),response=await fetchChecked(url,{accept:'text/plain',timeoutMs});
if(![403,404].includes(response.status))throw new Error(`Private deployment file is public at ${url.href}: HTTP ${response.status}`);
await response.body?.cancel().catch(()=>{});
}
const results=[];
for(const [kind,url] of [['API',apiUrl],['PHP bridge',bridgeUrl]]){
const response=await fetchChecked(url,{timeoutMs}),body=await response.json().catch(()=>({}));
if(!response.ok||body?.available!==true||body?.appVersion!==appVersion)throw new Error(`Public ${kind} failed at ${url.href}: HTTP ${response.status}`);
if(kind==='PHP bridge'&&response.headers.get('x-linkfield-bridge')!=='php')throw new Error(`Public PHP bridge did not identify itself at ${url.href}`);
results.push({kind,url:url.href,status:response.status});
}
return{base:base.href,page:pageUrl.href,api:results[0].url,bridge:results[1].url};
}
module.exports=Object.freeze({deploymentBase,checkPublicDeployment});