37 lines
2.2 KiB
JavaScript
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});
|