feat: support workflow parameter as JSON object, local filename, or URL in /oneapi/v1/execute API, with local file path resolution

This commit is contained in:
puke
2025-05-23 14:22:36 +08:00
parent 725b79851f
commit 80e31bdadc
4 changed files with 112 additions and 12 deletions
+2
View File
@@ -34,3 +34,5 @@ Thumbs.db
# Cursor
.cursorrules
*.log
+32 -6
View File
@@ -12,7 +12,7 @@ ComfyUI-OneAPI is a plugin that provides simple REST API interfaces for ComfyUI,
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": {...} # Replace with your workflow JSON
"workflow": {...} # Supports JSON object, local filename, or URL
}'
```
@@ -20,7 +20,7 @@ curl -X POST "http://localhost:8188/oneapi/v1/execute" \
```json
{
"workflow": {...} // API version of workflow JSON
"workflow": {...} # Supports JSON object, local filename, or URL
}
```
@@ -87,7 +87,7 @@ POST /oneapi/v1/execute
Request Body:
{
"workflow": {...}, // API version of workflow JSON
"workflow": {...}, // Supports JSON object, local filename, or URL
"params": {...}, // Optional: Parameter mapping
"wait_for_result": true/false, // Optional: Wait for results (default true)
"timeout": 300 // Optional: Timeout in seconds
@@ -119,7 +119,7 @@ Add markers to SaveImage node titles:
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": '"$(cat workflows/example_workflow.json)"',
"workflow": "$(cat workflows/example_workflow.json)", # Supports JSON object, local filename, or URL
"params": {
"prompt": "a cute dog with a red hat"
}
@@ -132,7 +132,7 @@ curl -X POST "http://localhost:8188/oneapi/v1/execute" \
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": '"$(cat workflows/example_img2img_workflow.json)"',
"workflow": "$(cat workflows/example_img2img_workflow.json)", # Supports JSON object, local filename, or URL
"params": {
"prompt": "a cute dog with a red hat",
"image": "https://example.com/input.jpg"
@@ -144,4 +144,30 @@ curl -X POST "http://localhost:8188/oneapi/v1/execute" \
- 🔄 This plugin uses HTTP polling to get results, does not provide WebSocket real-time progress
- ⏱️ Long-running workflows may cause request timeouts, consider setting appropriate timeout values
- 🏷️ Parameter mapping and output marking depend on special markers in node titles
- 🏷️ Parameter mapping and output marking depend on special markers in node titles
## /oneapi/v1/execute API - workflow parameter supports three forms
### Supported forms for the workflow parameter
- 1. Pass workflow as a JSON object (original logic).
- 2. Pass a local workflow filename (e.g. `1.json`), which will be loaded from `user/default/workflows/1.json`.
- 3. Pass a workflow URL (e.g. `http://xxx/1.json`), which will be downloaded and parsed automatically.
How to distinguish:
- If workflow is a dict, use it directly.
- If workflow is a string starting with `http://` or `https://`, treat as URL and download.
- Otherwise, treat as a local filename and load from `user/default/workflows` directory.
**Examples:**
```json
// 1. Pass JSON directly
{"workflow": {"node1": {...}, ...}}
// 2. Pass local filename
// 1.json corresponds to <ComfyUI root>/user/default/workflows/1.json
{"workflow": "1.json"}
// 3. Pass URL
{"workflow": "https://example.com/1.json"}
```
+31 -5
View File
@@ -12,7 +12,7 @@ ComfyUI-OneAPI 是一个为 ComfyUI 提供简单REST API接口的插件,只需
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": {...} # 替换为您的工作流JSON
"workflow": {...} # 支持JSON对象、本地文件名或URL
}'
```
@@ -87,7 +87,7 @@ POST /oneapi/v1/execute
请求体:
{
"workflow": {...}, // 工作流的API版JSON
"workflow": {...}, // 支持JSON对象、本地文件名或URL
"params": {...}, // 可选:参数映射
"wait_for_result": true/false, // 可选:是否等待结果(默认true)
"timeout": 300 // 可选:超时时间(秒)
@@ -119,7 +119,7 @@ POST /oneapi/v1/execute
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": '"$(cat workflows/example_workflow.json)"',
"workflow": "$(cat workflows/example_workflow.json)", # 支持JSON对象、本地文件名或URL
"params": {
"prompt": "a cute dog with a red hat"
}
@@ -132,7 +132,7 @@ curl -X POST "http://localhost:8188/oneapi/v1/execute" \
curl -X POST "http://localhost:8188/oneapi/v1/execute" \
-H "Content-Type: application/json" \
-d '{
"workflow": '"$(cat workflows/example_img2img_workflow.json)"',
"workflow": "$(cat workflows/example_img2img_workflow.json)", # 支持JSON对象、本地文件名或URL
"params": {
"prompt": "a cute dog with a red hat",
"image": "https://example.com/input.jpg"
@@ -144,4 +144,30 @@ curl -X POST "http://localhost:8188/oneapi/v1/execute" \
- 🔄 此插件使用HTTP轮询获取结果,不提供WebSocket实时进度
- ⏱️ 长时间运行的工作流可能导致超时,请设置合适的timeout值
- 🏷️ 参数映射和输出标记依赖于节点标题中的特殊标记
- 🏷️ 参数映射和输出标记依赖于节点标题中的特殊标记
## /oneapi/v1/execute 接口说明
### workflow 参数支持三种形式
- 1. 直接传递 workflow 的 JSON 对象(原有逻辑)。
- 2. 传递本地 workflow 文件名(如 `1.json`),会自动从 `user/default/workflows/1.json` 读取。
- 3. 传递 workflow 的 URL(如 `http://xxx/1.json`),会自动下载并解析。
区分方式:
- 如果 workflow 是 dict,则直接用。
- 如果 workflow 是字符串且以 `http://` 或 `https://` 开头,则当作 URL 下载。
- 否则当作本地文件名,从 `user/default/workflows` 目录加载。
**示例:**
```json
// 1. 直接传 JSON
{"workflow": {"node1": {...}, ...}}
// 2. 传本地文件名
// 1.json 对应的是 <ComfyUI根目录>/user/default/workflows/1.json
{"workflow": "1.json"}
// 3. 传 URL
{"workflow": "https://example.com/1.json"}
```
+47 -1
View File
@@ -15,13 +15,18 @@ import execution
# Get routes
routes = PromptServer.instance.routes
# Get workflow paths
path_custom_nodes = os.path.dirname(os.path.dirname(__file__))
path_comfyui_root = os.path.dirname(path_custom_nodes)
path_workflows = os.path.join(path_comfyui_root, 'user/default/workflows')
@routes.post('/oneapi/v1/execute')
async def execute_workflow(request):
"""
Execute workflow API
Parameters:
- workflow: Workflow JSON
- workflow: Workflow JSON, filename (under user/default/workflows/), or URL
- params: Parameter mapping dictionary
- wait_for_result: Whether to wait for results (default True)
- timeout: Timeout in seconds (default 300)
@@ -50,6 +55,19 @@ async def execute_workflow(request):
params = data.get('params', {})
wait_for_result = data.get('wait_for_result', True)
timeout = data.get('timeout', None)
# Support workflow as local path or URL
if isinstance(workflow, dict):
pass # Use directly
elif isinstance(workflow, str):
if workflow.startswith('http://') or workflow.startswith('https://'):
# URL, download
workflow = await _load_workflow_from_url(workflow)
else:
# Local filename
workflow = _load_workflow_from_local(workflow)
else:
return web.json_response({"error": "Invalid workflow parameter"}, status=400)
if not workflow:
return web.json_response({"error": "Workflow data is missing"}, status=400)
@@ -476,4 +494,32 @@ async def _wait_for_results(prompt_id, timeout=None, request=None, output_id_2_v
# Wait before checking again
await asyncio.sleep(1.0)
# New: Load workflow from local file
def _load_workflow_from_local(filename):
"""
Load workflow JSON from user/default/workflows directory
"""
file_path = os.path.join(path_workflows, filename)
if not os.path.isfile(file_path):
raise Exception(f"Workflow file not found: {file_path}")
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
# New: Load workflow from URL
async def _load_workflow_from_url(url):
"""
Download workflow JSON from URL
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
if response.status != 200:
raise Exception(f"Failed to download workflow: HTTP {response.status}")
text = await response.text()
try:
return json.loads(text)
except Exception as e:
raise Exception(f"Invalid workflow JSON from url: {e}")
print("ComfyUI-OneAPI routes registered")