api refactor: force access control and handle subpaths

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2025-02-14 11:25:29 -05:00
parent 877c488fa8
commit dbf20d1388
19 changed files with 92 additions and 45 deletions
+1 -1
View File
@@ -294,7 +294,7 @@ function selectHistory(id) {
const headers = new Headers();
headers.set('Content-Type', 'application/json');
const init = { method: 'POST', body: { name: id }, headers };
fetch('/sdapi/v1/history', { method: 'POST', body: JSON.stringify({ name: id }), headers });
fetch(`${window.api}/history`, { method: 'POST', body: JSON.stringify({ name: id }), headers });
}
let enDirty = false;
+3 -3
View File
@@ -92,7 +92,7 @@ async function addSeparators() {
async function delayFetchThumb(fn) {
while (outstanding > 16) await new Promise((resolve) => setTimeout(resolve, 50)); // eslint-disable-line no-promise-executor-return
outstanding++;
const res = await fetch(`/sdapi/v1/browser/thumb?file=${encodeURI(fn)}`, { priority: 'low' });
const res = await fetch(`${window.api}/browser/thumb?file=${encodeURI(fn)}`, { priority: 'low' });
if (!res.ok) {
error(`fetchThumb: ${res.statusText}`);
outstanding--;
@@ -334,7 +334,7 @@ async function fetchFilesHT(evt) {
el.status.innerText = `Folder | ${evt.target.name} | in-progress`;
let numFiles = 0;
const res = await fetch(`/sdapi/v1/browser/files?folder=${encodeURI(evt.target.name)}`);
const res = await fetch(`${window.api}/browser/files?folder=${encodeURI(evt.target.name)}`);
if (!res || res.status !== 200) {
el.status.innerText = `Folder | ${evt.target.name} | failed: ${res?.statusText}`;
return;
@@ -412,7 +412,7 @@ async function pruneImages() {
async function galleryVisible() {
// if (el.folders.children.length > 0) return;
const res = await fetch('/sdapi/v1/browser/folders');
const res = await fetch(`${window.api}/browser/folders`);
if (!res || res.status !== 200) return;
el.folders.innerHTML = '';
url = res.url.split('/sdapi')[0].replace('http', 'ws'); // update global url as ws need fqdn
+2 -2
View File
@@ -37,7 +37,7 @@ async function createSplash() {
await preloadImages();
const imgEl = `<div id="spash-img" class="splash-img" alt="logo" style="background-image: url(file=html/logo-bg-${dark ? 'dark' : 'light'}.jpg), url(file=html/logo-bg-${num}.jpg); background-blend-mode: ${dark ? 'multiply' : 'lighten'}"></div>`;
document.getElementById('splash').insertAdjacentHTML('afterbegin', imgEl);
fetch('/sdapi/v1/motd')
fetch(`${window.api}/motd`)
.then((res) => res.text())
.then((text) => {
const motdEl = document.getElementById('motd');
@@ -52,7 +52,7 @@ async function removeSplash() {
log('removeSplash');
const t = Math.round(performance.now() - appStartTime) / 1000;
log('startupTime', t);
xhrPost('/sdapi/v1/log', { message: `ready time=${t}` });
xhrPost(`${window.api}/log`, { message: `ready time=${t}` });
}
window.onload = createSplash;
+2 -2
View File
@@ -70,7 +70,7 @@ async function logMonitor() {
if (!logMonitorEl) return;
const atBottom = logMonitorEl.scrollHeight <= (logMonitorEl.scrollTop + logMonitorEl.clientHeight);
try {
const res = await fetch('/sdapi/v1/log?clear=True');
const res = await fetch(`${window.api}/log?clear=True`);
if (res?.ok) {
logMonitorStatus = true;
const lines = await res.json();
@@ -116,7 +116,7 @@ async function initLogMonitor() {
</table>
`;
el.style.display = 'none';
fetch(`/sdapi/v1/start?agent=${encodeURI(navigator.userAgent)}`);
fetch(`${window.api}/start?agent=${encodeURI(navigator.userAgent)}`);
logMonitor();
log('initLogMonitor');
}
+4 -4
View File
@@ -25,7 +25,7 @@ const loginHTML = `
function forceLogin() {
const form = document.createElement('form');
form.method = 'POST';
form.action = '/login';
form.action = `${location.href}login`;
form.id = 'loginForm';
form.style.cssText = loginCSS;
form.innerHTML = loginHTML;
@@ -39,8 +39,8 @@ function forceLogin() {
const formData = new FormData(form);
formData.append('username', username.value);
formData.append('password', password.value);
console.warn('login', formData);
fetch('/login', {
console.warn('login', location.href, formData);
fetch(`${location.href}login`, {
method: 'POST',
body: formData,
})
@@ -59,7 +59,7 @@ function forceLogin() {
}
function loginCheck() {
fetch('/login_check', {})
fetch(`${location.href}login_check`, {})
.then((res) => {
if (res.status === 200) console.log('login ok');
else forceLogin();
+1 -1
View File
@@ -30,7 +30,7 @@ async function updateNVMLChart(mem, load) {
async function updateNVML() {
try {
const res = await fetch('/sdapi/v1/nvml');
const res = await fetch(`${window.api}/nvml`);
if (!res.ok) {
clearInterval(nvmlInterval);
nvmlEl.style.display = 'none';
+3 -3
View File
@@ -136,16 +136,16 @@ async function getLocaleData(desiredLocale = null) {
// primary
let json = {};
try {
let res = await fetch(`/file=html/locale_${localeData.locale}.json`);
let res = await fetch(`${window.subpath}/file=html/locale_${localeData.locale}.json`);
if (!res || !res.ok) {
localeData.locale = 'en';
res = await fetch(`/file=html/locale_${localeData.locale}.json`);
res = await fetch(`${window.subpath}/file=html/locale_${localeData.locale}.json`);
}
json = await res.json();
} catch { /**/ }
try {
const res = await fetch(`/file=html/override_${localeData.locale}.json`);
const res = await fetch(`${window.subpath}/file=html/override_${localeData.locale}.json`);
if (res && res.ok) json.override = await res.json();
} catch { /**/ }
+1 -1
View File
@@ -152,7 +152,7 @@ async function initModels() {
const el = gradioApp().getElementById('main_info');
const en = gradioApp().getElementById('txt2img_extra_networks');
if (!el || !en) return;
const req = await fetch('/sdapi/v1/sd-models');
const req = await fetch(`${window.api}/sd-models`);
const res = req.ok ? await req.json() : [];
log('initModels', res.length);
const ready = () => `
+7
View File
@@ -1,4 +1,6 @@
/* eslint-disable no-undef */
window.api = '/sdapi/v1';
window.subpath = '';
async function initStartup() {
log('initStartup');
@@ -23,6 +25,11 @@ async function initStartup() {
// make sure all of the ui is ready and options are loaded
while (Object.keys(window.opts).length === 0) await sleep(50);
log('mountURL', window.opts.subpath);
if (window.opts.subpath?.length > 0) {
window.subpath = window.opts.subpath;
window.api = `${window.subpath}/sdapi/v1`;
}
executeCallbacks(uiReadyCallbacks);
initLogMonitor();
setupExtraNetworks();
+3 -3
View File
@@ -385,7 +385,7 @@ function monitorServerStatus() {
<h1>Waiting for server...</h1>
<script>
function monitorServerStatus() {
fetch('/sdapi/v1/progress?skip_current_image=true')
fetch('${window.api}/progress?skip_current_image=true')
.then((res) => { !res?.ok ? setTimeout(monitorServerStatus, 1000) : location.reload(); })
.catch((e) => setTimeout(monitorServerStatus, 1000))
}
@@ -400,7 +400,7 @@ function monitorServerStatus() {
function restartReload() {
document.body.style = 'background: #222222; font-size: 1rem; font-family:monospace; margin-top:20%; color:lightgray; text-align:center';
document.body.innerHTML = '<h1>Server shutdown in progress...</h1>';
fetch('/sdapi/v1/progress?skip_current_image=true')
fetch(`${window.api}/progress?skip_current_image=true`)
.then((res) => setTimeout(restartReload, 1000))
.catch((e) => setTimeout(monitorServerStatus, 500));
return [];
@@ -479,7 +479,7 @@ function toggleCompact(val, old) {
function previewTheme() {
let name = gradioApp().getElementById('setting_gradio_theme').querySelectorAll('input')?.[0].value || '';
fetch('/file=html/themes.json')
fetch(`${window.subpath}/file=html/themes.json`)
.then((res) => {
res.json()
.then((themes) => {