ai-dock/stable-diffusion-webui

How to use Automatic1111 API with this container?

meliache opened this issue · 6 comments

I extend the webui flags with --api --listen to enable the webui API by setting the environment variable WEBUI_FLAGS="--api --listen". In the logs I see that the command line flag is used. Usually the API runs on the same port as the GUI.

In the past I had run stable diffusion in a paperspace notebook without a container and just relying on a custom notebook. It just generated a gradle URL the API just worked with that URL. Recently I transitioned to vast.ai and use the Automatic1111 Jupyter template provided there, which uses this docker container. I tried both the cloudfare quick tunnel and direct-access URLs but didn't work with either.

I'm no API/networking expert, I just had used project which allows for generating images if you give it an SD API URL. But for debugging I tested the URL in Python:

requests.post(
   url="<Same URL as WebUI GUI>",
   json={"prompt": "maltese puppy", "steps": 5},
).content.decode()

And got a return of '{"detail":"Method Not Allowed"}'. Is maybe cloudfare blocking API access? Am I missing something in the container configuration, e.g. should I forward/allow some more ports?

Btw, I thought maybe the html auth is messing with the UI, so I tried WEB_ENABLE_AUTH=false. Though I think I could just use user:pw@url for the API request.

Not sure if this is the right place to ask but I just can't figure that out...

Are you certain you are posting to the correct URL (including /sdapi/v1/txt2img)

If so then this is probably a CORS issue that I'll need to fix by applying settings to the reverse proxy as described at https://enable-cors.org/server_caddy.html

Incidentally, you could also use a cloudflare named tunnel which you can use to connect directly to the locally bound service on port 17860 thereby completely bypassing the proxy, which is present to provide the basic auth. You don't need that when tunnelling as cloudflare can handle the security for you.

Thanks for the quick reply, super helpful!

In the project that I wanted to use the WebUI API for, the URL was correct. The project uses a text field for the UI and it Automatically adds the /sdapi/v1/txt2img suffix. But I had totally forgotten to add in in Python when I tried to debug the issue 🤦. So this explains why my Python debugging didn't work.

Not sure via the API initially didn't work in my application via the tunnel, but now it works. Maybe I had fixed my initial problems by myself and not noticed it because I was just debugging with Python.

If it works, there shouldn't be a performance penalty of sending images over the cloudfare proxy, right?

No problem at all. Happy it's working for you!

As far as I'm aware there should not be any real performance penalty, although the quick tunnels carry no uptime guarantee from cloudflare.

I have found that using the tunnels on vast is more reliable as some hosts do have difficulty in forwarding ports properly and the HTTPS without installing the vast certificate is a bonus.

@robballantyne Can you please give some instructions on how to do it?
I use vast.ai and CF tunnel to run your image, I set these env vars:

-e WEB_USER=user -e WEB_PASSWORD=password -e WEBUI_BRANCH=master -e WEBUI_FLAGS="--xformers --no-half --no-half-vae --enable-insecure-extension-access --api" -e PROVISIONING_SCRIPT="myscript.sh" -p 22:22 -p 1111:1111 -p 1122:1122 -p 7860:7860 -e OPEN_BUTTON_TOKEN=1 -e OPEN_BUTTON_PORT=1111 -e CF_QUICK_TUNNELS=false -e CF_TUNNEL_TOKEN=token -e TUNNEL_TRANSPORT_PROTOCOL=http2

And when I connect to it programmatically I get 302 Found error with headers:

Location: http://machine_address:port/login
Server: Caddy
Date: Wed, 27 Mar 2024 20:45:12 GMT
Content-Length: 0

During the API call I use basic auth, like that:

with httpx.Client(timeout=120000) as client:
        r = client.request(
            method="POST",
            url=f"{api_host}/sdapi/v1/{endpoint}",
            json=data,
            auth=("user", "password")
        )

Where api_host is the CF tunnel host. As you can see, after this request I get a redirect response with the location of the hosting machine address. What am I doing wrong?

Probably nothing. Basic auth isn't fully supported - you can pass Basic [hash] as a header but credentials aren't requested. Httpx may be expecting a challenge.

I'd recommend using a Bearer token. You can find the required WEB_TOKEN with env | grep WEB_

Ok, thanks! I chose to disable web auth at all for now, but it may be not a good choice. I'll try WEB_TOKEN next time.