Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Test WebUI Startup

on: [push, pull_request]

jobs:
test-webui:
runs-on: ubuntu-latest

steps:
- name: Checkout do código
uses: actions/checkout@v3

- name: Instalar dependências de sistema
run: |
sudo apt-get update
sudo apt-get install -y python3-venv curl

- name: Configurar ambiente virtual e dependências Python
run: |
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Iniciar WebUI em background
run: |
source venv/bin/activate
nohup python webui.py > log.txt 2>&1 &

- name: Esperar servidor iniciar
run: |
sleep 20
curl -sf http://127.0.0.1:7860 || (echo "Servidor não respondeu" && cat log.txt && exit 1)

- name: Encerrar servidor (se rodando)
run: |
curl -X POST http://127.0.0.1:7860/sdapi/v1/server-stop || true

- name: Rodar webui e salvar log
run: |
python webui.py > log.txt 2>&1

- name: Mostrar log final do servidor
run: |
cat log.txt || true
224 changes: 91 additions & 133 deletions webui.py
Original file line number Diff line number Diff line change
@@ -1,72 +1,96 @@
from __future__ import annotations

import os
import time
from pathlib import Path
from packaging.version import parse
import gradio

from modules import (
shared,
ui_tempdir,
startup_timer,
initialize_util,
progress,
ui,
ui_extra_networks,
timer,
initialize,
script_callbacks,
cmd_opts
)

from api import create_api


def limpar_temp_dir():
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
startup_timer.record("cleanup temp dir")


def configurar_ui():
shared.demo = ui.create_ui()
startup_timer.record("create ui")
if not cmd_opts.no_gradio_queue:
shared.demo.queue(64)


def decidir_autolancamento():
if os.getenv('SD_WEBUI_RESTARTING') == '1':
return False
if shared.opts.auto_launch_browser == "Remote" or cmd_opts.autolaunch:
return True
if shared.opts.auto_launch_browser == "Local":
return not cmd_opts.webui_is_non_local
return False


def lancar_interface(auto_launch_browser):
gradio_auth_creds = list(initialize_util.get_gradio_auth_creds()) or None
return shared.demo.launch(
share=cmd_opts.share,
server_name=initialize_util.gradio_server_name(),
server_port=cmd_opts.port,
ssl_keyfile=cmd_opts.tls_keyfile,
ssl_certfile=cmd_opts.tls_certfile,
ssl_verify=cmd_opts.disable_tls_verify,
debug=cmd_opts.gradio_debug,
auth=gradio_auth_creds,
inbrowser=auto_launch_browser,
prevent_thread_lock=True,
allowed_paths=cmd_opts.gradio_allowed_path,
app_kwargs={"docs_url": "/docs", "redoc_url": "/redoc"},
root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else "",
)

from modules import timer
from modules import initialize_util
from modules import initialize

startup_timer = timer.startup_timer
startup_timer.record("launcher")

initialize.imports()

initialize.check_versions()


def create_api(app):
from modules.api.api import Api
from modules.call_queue import queue_lock

api = Api(app, queue_lock)
return api


def api_only():
from fastapi import FastAPI
from modules.shared_cmd_options import cmd_opts

initialize.initialize()

app = FastAPI()
def proteger_app(app):
app.user_middleware = [
x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware'
]
initialize_util.setup_middleware(app)
api = create_api(app)

from modules import script_callbacks
script_callbacks.before_ui_callback()
script_callbacks.app_started_callback(None, app)

print(f"Startup time: {startup_timer.summary()}.")
api.launch(
server_name=initialize_util.gradio_server_name(),
port=cmd_opts.port if cmd_opts.port else 7861,
root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else ""
)


def warning_if_invalid_install_dir():
"""
Shows a warning if the webui is installed under a path that contains a leading dot in any of its parent directories.
def configurar_apis(app):
progress.setup_progress_api(app)
ui.setup_ui_api(app)
if cmd_opts.api:
create_api(app)
ui_extra_networks.add_pages_to_demo(app)

Gradio '/file=' route will block access to files that have a leading dot in the path segments.
We use this route to serve files such as JavaScript and CSS to the webpage,
if those files are blocked, the webpage will not function properly.
See https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/13292

This is a security feature was added to Gradio 3.32.0 and is removed in later versions,
this function replicates Gradio file access blocking logic.
def monitorar_comandos():
while True:
server_command = shared.state.wait_for_server_command(timeout=5)
if server_command:
if server_command in ("stop", "restart"):
return server_command
else:
print(f"Unknown server command: {server_command}")

This check should be removed when it's no longer applicable.
"""
from packaging.version import parse
from pathlib import Path
import gradio

def warning_if_invalid_install_dir():
if parse('3.32.0') <= parse(gradio.__version__) < parse('4'):

def abspath(path):
"""modified from Gradio 3.41.2 gradio.utils.abspath()"""
if path.is_absolute():
return path
is_symlink = path.is_symlink() or any(parent.is_symlink() for parent in path.parents)
Expand All @@ -77,81 +101,29 @@ def abspath(path):
print(f'''{"!"*25} Warning {"!"*25}
WebUI is installed in a directory that has a leading dot (.) in one of its parent directories.
This will prevent WebUI from functioning properly.
Please move the installation to a different directory.
Current path: "{webui_root}"
For more information see: https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/13292
Please move the installation to a different directory.
More info: https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/13292
{"!"*25} Warning {"!"*25}''')


def webui():
from modules.shared_cmd_options import cmd_opts

launch_api = cmd_opts.api
initialize.initialize()

from modules import shared, ui_tempdir, script_callbacks, ui, progress, ui_extra_networks

warning_if_invalid_install_dir()

while 1:
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
startup_timer.record("cleanup temp dir")

while True:
limpar_temp_dir()
script_callbacks.before_ui_callback()
startup_timer.record("scripts before_ui_callback")

shared.demo = ui.create_ui()
startup_timer.record("create ui")

if not cmd_opts.no_gradio_queue:
shared.demo.queue(64)

gradio_auth_creds = list(initialize_util.get_gradio_auth_creds()) or None

auto_launch_browser = False
if os.getenv('SD_WEBUI_RESTARTING') != '1':
if shared.opts.auto_launch_browser == "Remote" or cmd_opts.autolaunch:
auto_launch_browser = True
elif shared.opts.auto_launch_browser == "Local":
auto_launch_browser = not cmd_opts.webui_is_non_local

app, local_url, share_url = shared.demo.launch(
share=cmd_opts.share,
server_name=initialize_util.gradio_server_name(),
server_port=cmd_opts.port,
ssl_keyfile=cmd_opts.tls_keyfile,
ssl_certfile=cmd_opts.tls_certfile,
ssl_verify=cmd_opts.disable_tls_verify,
debug=cmd_opts.gradio_debug,
auth=gradio_auth_creds,
inbrowser=auto_launch_browser,
prevent_thread_lock=True,
allowed_paths=cmd_opts.gradio_allowed_path,
app_kwargs={
"docs_url": "/docs",
"redoc_url": "/redoc",
},
root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else "",
)
configurar_ui()
auto_launch_browser = decidir_autolancamento()

app, _, _ = lancar_interface(auto_launch_browser)
startup_timer.record("gradio launch")

# gradio uses a very open CORS policy via app.user_middleware, which makes it possible for
# an attacker to trick the user into opening a malicious HTML page, which makes a request to the
# running web ui and do whatever the attacker wants, including installing an extension and
# running its code. We disable this here. Suggested by RyotaK.
app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware']

initialize_util.setup_middleware(app)

progress.setup_progress_api(app)
ui.setup_ui_api(app)

if launch_api:
create_api(app)

ui_extra_networks.add_pages_to_demo(app)
proteger_app(app)
configurar_apis(app)

startup_timer.record("add APIs")

Expand All @@ -162,26 +134,17 @@ def webui():
print(f"Startup time: {startup_timer.summary()}.")

try:
while True:
server_command = shared.state.wait_for_server_command(timeout=5)
if server_command:
if server_command in ("stop", "restart"):
break
else:
print(f"Unknown server command: {server_command}")
server_command = monitorar_comandos()
except KeyboardInterrupt:
print('Caught KeyboardInterrupt, stopping...')
server_command = "stop"

if server_command == "stop":
print("Stopping server...")
# If we catch a keyboard interrupt, we want to stop the server and exit.
shared.demo.close()
break

# disable auto launch webui in browser for subsequent UI Reload
os.environ.setdefault('SD_WEBUI_RESTARTING', '1')

print('Restarting UI...')
shared.demo.close()
time.sleep(0.5)
Expand All @@ -194,9 +157,4 @@ def webui():


if __name__ == "__main__":
from modules.shared_cmd_options import cmd_opts

if cmd_opts.nowebui:
api_only()
else:
webui()
webui()
Loading