[api] Add /api prefix to all paths in OpenAPI spec

- Updated all API paths (except internal routes) to include /api/ prefix
- Changed server URL from "/api" back to "/" and added prefix to individual paths
- Updated test fixtures to not add /api prefix since paths already include it
- Fixed all test assertions to use the new paths with /api/ prefix

This addresses the review comment about endpoints needing the /api/ prefix
and implements it correctly by hardcoding the prefix in each path definition.

Fixes #8219
This commit is contained in:
bymyself 2025-06-29 18:36:51 -07:00
parent 82c1852390
commit d6270cbdf3
5 changed files with 221 additions and 230 deletions

View File

@ -1,45 +1,49 @@
openapi: 3.0.3 openapi: 3.0.3
info: info:
title: ComfyUI API title: ComfyUI API
description: | description: 'API for ComfyUI - A powerful and modular UI for Stable Diffusion.
API for ComfyUI - A powerful and modular UI for Stable Diffusion.
This API allows you to interact with ComfyUI programmatically, including: This API allows you to interact with ComfyUI programmatically, including:
- Submitting workflows for execution - Submitting workflows for execution
- Managing the execution queue - Managing the execution queue
- Retrieving generated images - Retrieving generated images
- Managing models - Managing models
- Retrieving node information - Retrieving node information
'
version: 1.0.0 version: 1.0.0
license: license:
name: GNU General Public License v3.0 name: GNU General Public License v3.0
url: https://github.com/comfyanonymous/ComfyUI/blob/master/LICENSE url: https://github.com/comfyanonymous/ComfyUI/blob/master/LICENSE
servers: servers:
- url: /api - url: /
description: Default ComfyUI server description: Default ComfyUI server
tags: tags:
- name: workflow - name: workflow
description: Workflow execution and management description: Workflow execution and management
- name: queue - name: queue
description: Queue management description: Queue management
- name: image - name: image
description: Image handling description: Image handling
- name: node - name: node
description: Node information description: Node information
- name: model - name: model
description: Model management description: Model management
- name: system - name: system
description: System information description: System information
- name: internal - name: internal
description: Internal API routes description: Internal API routes
paths: paths:
/prompt: /api/prompt:
get: get:
tags: tags:
- workflow - workflow
summary: Get information about current prompt execution summary: Get information about current prompt execution
description: Returns information about the current prompt in the execution queue description: Returns information about the current prompt in the execution queue
operationId: getPromptInfo operationId: getPromptInfo
@ -52,11 +56,13 @@ paths:
$ref: '#/components/schemas/PromptInfo' $ref: '#/components/schemas/PromptInfo'
post: post:
tags: tags:
- workflow - workflow
summary: Submit a workflow for execution summary: Submit a workflow for execution
description: | description: 'Submit a workflow to be executed by the backend.
Submit a workflow to be executed by the backend.
The workflow is a JSON object describing the nodes and their connections. The workflow is a JSON object describing the nodes and their connections.
'
operationId: executePrompt operationId: executePrompt
requestBody: requestBody:
required: true required: true
@ -77,11 +83,10 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/ErrorResponse' $ref: '#/components/schemas/ErrorResponse'
/api/queue:
/queue:
get: get:
tags: tags:
- queue - queue
summary: Get queue information summary: Get queue information
description: Returns information about running and pending items in the queue description: Returns information about running and pending items in the queue
operationId: getQueueInfo operationId: getQueueInfo
@ -94,7 +99,7 @@ paths:
$ref: '#/components/schemas/QueueInfo' $ref: '#/components/schemas/QueueInfo'
post: post:
tags: tags:
- queue - queue
summary: Manage queue summary: Manage queue
description: Clear the queue or delete specific items description: Clear the queue or delete specific items
operationId: manageQueue operationId: manageQueue
@ -117,22 +122,20 @@ paths:
responses: responses:
'200': '200':
description: Success description: Success
/api/interrupt:
/interrupt:
post: post:
tags: tags:
- workflow - workflow
summary: Interrupt the current execution summary: Interrupt the current execution
description: Interrupts the currently running workflow execution description: Interrupts the currently running workflow execution
operationId: interruptExecution operationId: interruptExecution
responses: responses:
'200': '200':
description: Success description: Success
/api/free:
/free:
post: post:
tags: tags:
- system - system
summary: Free resources summary: Free resources
description: Unload models and/or free memory description: Unload models and/or free memory
operationId: freeResources operationId: freeResources
@ -152,22 +155,21 @@ paths:
responses: responses:
'200': '200':
description: Success description: Success
/api/history:
/history:
get: get:
tags: tags:
- workflow - workflow
summary: Get execution history summary: Get execution history
description: Returns the history of executed workflows description: Returns the history of executed workflows
operationId: getHistory operationId: getHistory
parameters: parameters:
- name: max_items - name: max_items
in: query in: query
description: Maximum number of history items to return description: Maximum number of history items to return
required: false required: false
schema: schema:
type: integer type: integer
format: int32 format: int32
responses: responses:
'200': '200':
description: Success description: Success
@ -179,7 +181,7 @@ paths:
$ref: '#/components/schemas/HistoryItem' $ref: '#/components/schemas/HistoryItem'
post: post:
tags: tags:
- workflow - workflow
summary: Manage history summary: Manage history
description: Clear history or delete specific items description: Clear history or delete specific items
operationId: manageHistory operationId: manageHistory
@ -202,22 +204,21 @@ paths:
responses: responses:
'200': '200':
description: Success description: Success
/api/history/{prompt_id}:
/history/{prompt_id}:
get: get:
tags: tags:
- workflow - workflow
summary: Get specific history item summary: Get specific history item
description: Returns a specific history item by ID description: Returns a specific history item by ID
operationId: getHistoryItem operationId: getHistoryItem
parameters: parameters:
- name: prompt_id - name: prompt_id
in: path in: path
description: ID of the prompt to retrieve description: ID of the prompt to retrieve
required: true required: true
schema: schema:
type: string type: string
format: uuid format: uuid
responses: responses:
'200': '200':
description: Success description: Success
@ -225,11 +226,10 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/HistoryItem' $ref: '#/components/schemas/HistoryItem'
/api/object_info:
/object_info:
get: get:
tags: tags:
- node - node
summary: Get all node information summary: Get all node information
description: Returns information about all available nodes description: Returns information about all available nodes
operationId: getNodeInfo operationId: getNodeInfo
@ -242,21 +242,20 @@ paths:
type: object type: object
additionalProperties: additionalProperties:
$ref: '#/components/schemas/NodeInfo' $ref: '#/components/schemas/NodeInfo'
/api/object_info/{node_class}:
/object_info/{node_class}:
get: get:
tags: tags:
- node - node
summary: Get specific node information summary: Get specific node information
description: Returns information about a specific node class description: Returns information about a specific node class
operationId: getNodeClassInfo operationId: getNodeClassInfo
parameters: parameters:
- name: node_class - name: node_class
in: path in: path
description: Name of the node class description: Name of the node class
required: true required: true
schema: schema:
type: string type: string
responses: responses:
'200': '200':
description: Success description: Success
@ -266,11 +265,10 @@ paths:
type: object type: object
additionalProperties: additionalProperties:
$ref: '#/components/schemas/NodeInfo' $ref: '#/components/schemas/NodeInfo'
/api/upload/image:
/upload/image:
post: post:
tags: tags:
- image - image
summary: Upload an image summary: Upload an image
description: Uploads an image to the server description: Uploads an image to the server
operationId: uploadImage operationId: uploadImage
@ -290,7 +288,10 @@ paths:
description: Whether to overwrite if file exists (true/false) description: Whether to overwrite if file exists (true/false)
type: type:
type: string type: string
enum: [input, temp, output] enum:
- input
- temp
- output
description: Type of directory to store the image in description: Type of directory to store the image in
subfolder: subfolder:
type: string type: string
@ -314,11 +315,10 @@ paths:
description: Type of directory the image was stored in description: Type of directory the image was stored in
'400': '400':
description: Bad request description: Bad request
/api/upload/mask:
/upload/mask:
post: post:
tags: tags:
- image - image
summary: Upload a mask for an image summary: Upload a mask for an image
description: Uploads a mask image and applies it to a referenced original image description: Uploads a mask image and applies it to a referenced original image
operationId: uploadMask operationId: uploadMask
@ -355,49 +355,54 @@ paths:
description: Type of directory the mask was stored in description: Type of directory the mask was stored in
'400': '400':
description: Bad request description: Bad request
/api/view:
/view:
get: get:
tags: tags:
- image - image
summary: View an image summary: View an image
description: Retrieves an image from the server description: Retrieves an image from the server
operationId: viewImage operationId: viewImage
parameters: parameters:
- name: filename - name: filename
in: query in: query
description: Name of the file to retrieve description: Name of the file to retrieve
required: true required: true
schema: schema:
type: string type: string
- name: type - name: type
in: query in: query
description: Type of directory to retrieve from description: Type of directory to retrieve from
required: false required: false
schema: schema:
type: string type: string
enum: [input, temp, output] enum:
default: output - input
- name: subfolder - temp
in: query - output
description: Subfolder to retrieve from default: output
required: false - name: subfolder
schema: in: query
type: string description: Subfolder to retrieve from
- name: preview required: false
in: query schema:
description: Preview options (format;quality) type: string
required: false - name: preview
schema: in: query
type: string description: Preview options (format;quality)
- name: channel required: false
in: query schema:
description: Channel to retrieve (rgb, a, rgba) type: string
required: false - name: channel
schema: in: query
type: string description: Channel to retrieve (rgb, a, rgba)
enum: [rgb, a, rgba] required: false
default: rgba schema:
type: string
enum:
- rgb
- a
- rgba
default: rgba
responses: responses:
'200': '200':
description: Success description: Success
@ -410,27 +415,26 @@ paths:
description: Bad request description: Bad request
'404': '404':
description: File not found description: File not found
/api/view_metadata/{folder_name}:
/view_metadata/{folder_name}:
get: get:
tags: tags:
- model - model
summary: View model metadata summary: View model metadata
description: Retrieves metadata from a safetensors file description: Retrieves metadata from a safetensors file
operationId: viewModelMetadata operationId: viewModelMetadata
parameters: parameters:
- name: folder_name - name: folder_name
in: path in: path
description: Name of the model folder description: Name of the model folder
required: true required: true
schema: schema:
type: string type: string
- name: filename - name: filename
in: query in: query
description: Name of the safetensors file description: Name of the safetensors file
required: true required: true
schema: schema:
type: string type: string
responses: responses:
'200': '200':
description: Success description: Success
@ -440,11 +444,10 @@ paths:
type: object type: object
'404': '404':
description: File not found description: File not found
/api/models:
/models:
get: get:
tags: tags:
- model - model
summary: Get model types summary: Get model types
description: Returns a list of available model types description: Returns a list of available model types
operationId: getModelTypes operationId: getModelTypes
@ -457,21 +460,20 @@ paths:
type: array type: array
items: items:
type: string type: string
/api/models/{folder}:
/models/{folder}:
get: get:
tags: tags:
- model - model
summary: Get models of a specific type summary: Get models of a specific type
description: Returns a list of available models of a specific type description: Returns a list of available models of a specific type
operationId: getModels operationId: getModels
parameters: parameters:
- name: folder - name: folder
in: path in: path
description: Model type folder description: Model type folder
required: true required: true
schema: schema:
type: string type: string
responses: responses:
'200': '200':
description: Success description: Success
@ -483,11 +485,10 @@ paths:
type: string type: string
'404': '404':
description: Folder not found description: Folder not found
/api/embeddings:
/embeddings:
get: get:
tags: tags:
- model - model
summary: Get embeddings summary: Get embeddings
description: Returns a list of available embeddings description: Returns a list of available embeddings
operationId: getEmbeddings operationId: getEmbeddings
@ -500,11 +501,10 @@ paths:
type: array type: array
items: items:
type: string type: string
/api/extensions:
/extensions:
get: get:
tags: tags:
- system - system
summary: Get extensions summary: Get extensions
description: Returns a list of available extensions description: Returns a list of available extensions
operationId: getExtensions operationId: getExtensions
@ -517,11 +517,10 @@ paths:
type: array type: array
items: items:
type: string type: string
/api/system_stats:
/system_stats:
get: get:
tags: tags:
- system - system
summary: Get system statistics summary: Get system statistics
description: Returns system information including RAM, VRAM, and ComfyUI version description: Returns system information including RAM, VRAM, and ComfyUI version
operationId: getSystemStats operationId: getSystemStats
@ -532,31 +531,32 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/SystemStats' $ref: '#/components/schemas/SystemStats'
/api/ws:
/ws:
get: get:
tags: tags:
- workflow - workflow
summary: WebSocket connection summary: WebSocket connection
description: | description: 'Establishes a WebSocket connection for real-time communication.
Establishes a WebSocket connection for real-time communication.
This endpoint is used for receiving progress updates, status changes, and results from workflow executions. This endpoint is used for receiving progress updates, status changes, and
results from workflow executions.
'
operationId: webSocketConnect operationId: webSocketConnect
parameters: parameters:
- name: clientId - name: clientId
in: query in: query
description: Optional client ID for reconnection description: Optional client ID for reconnection
required: false required: false
schema: schema:
type: string type: string
responses: responses:
'101': '101':
description: Switching Protocols to WebSocket description: Switching Protocols to WebSocket
/internal/logs: /internal/logs:
get: get:
tags: tags:
- internal - internal
summary: Get logs summary: Get logs
description: Returns system logs as a single string description: Returns system logs as a single string
operationId: getLogs operationId: getLogs
@ -567,11 +567,10 @@ paths:
application/json: application/json:
schema: schema:
type: string type: string
/internal/logs/raw: /internal/logs/raw:
get: get:
tags: tags:
- internal - internal
summary: Get raw logs summary: Get raw logs
description: Returns raw system logs with terminal size information description: Returns raw system logs with terminal size information
operationId: getRawLogs operationId: getRawLogs
@ -603,11 +602,10 @@ paths:
rows: rows:
type: integer type: integer
description: Terminal rows description: Terminal rows
/internal/logs/subscribe: /internal/logs/subscribe:
patch: patch:
tags: tags:
- internal - internal
summary: Subscribe to logs summary: Subscribe to logs
description: Subscribe or unsubscribe to log updates description: Subscribe or unsubscribe to log updates
operationId: subscribeToLogs operationId: subscribeToLogs
@ -627,11 +625,10 @@ paths:
responses: responses:
'200': '200':
description: Success description: Success
/internal/folder_paths: /internal/folder_paths:
get: get:
tags: tags:
- internal - internal
summary: Get folder paths summary: Get folder paths
description: Returns a map of folder names to their paths description: Returns a map of folder names to their paths
operationId: getFolderPaths operationId: getFolderPaths
@ -644,22 +641,24 @@ paths:
type: object type: object
additionalProperties: additionalProperties:
type: string type: string
/internal/files/{directory_type}: /internal/files/{directory_type}:
get: get:
tags: tags:
- internal - internal
summary: Get files summary: Get files
description: Returns a list of files in a specific directory type description: Returns a list of files in a specific directory type
operationId: getFiles operationId: getFiles
parameters: parameters:
- name: directory_type - name: directory_type
in: path in: path
description: Type of directory (output, input, temp) description: Type of directory (output, input, temp)
required: true required: true
schema: schema:
type: string type: string
enum: [output, input, temp] enum:
- output
- input
- temp
responses: responses:
'200': '200':
description: Success description: Success
@ -671,13 +670,12 @@ paths:
type: string type: string
'400': '400':
description: Invalid directory type description: Invalid directory type
components: components:
schemas: schemas:
PromptRequest: PromptRequest:
type: object type: object
required: required:
- prompt - prompt
properties: properties:
prompt: prompt:
type: object type: object
@ -696,7 +694,6 @@ components:
client_id: client_id:
type: string type: string
description: Client ID for attribution of the prompt description: Client ID for attribution of the prompt
PromptResponse: PromptResponse:
type: object type: object
properties: properties:
@ -711,7 +708,6 @@ components:
type: object type: object
description: Any errors in the nodes of the prompt description: Any errors in the nodes of the prompt
additionalProperties: true additionalProperties: true
ErrorResponse: ErrorResponse:
type: object type: object
properties: properties:
@ -735,7 +731,6 @@ components:
type: object type: object
description: Node-specific errors description: Node-specific errors
additionalProperties: true additionalProperties: true
PromptInfo: PromptInfo:
type: object type: object
properties: properties:
@ -745,7 +740,6 @@ components:
queue_remaining: queue_remaining:
type: integer type: integer
description: Number of items remaining in the queue description: Number of items remaining in the queue
QueueInfo: QueueInfo:
type: object type: object
properties: properties:
@ -761,7 +755,6 @@ components:
type: object type: object
description: Pending items in the queue description: Pending items in the queue
additionalProperties: true additionalProperties: true
HistoryItem: HistoryItem:
type: object type: object
properties: properties:
@ -781,7 +774,6 @@ components:
type: object type: object
description: Output data from the execution description: Output data from the execution
additionalProperties: true additionalProperties: true
NodeInfo: NodeInfo:
type: object type: object
properties: properties:
@ -843,7 +835,6 @@ components:
api_node: api_node:
type: boolean type: boolean
description: Whether this is an API node description: Whether this is an API node
SystemStats: SystemStats:
type: object type: object
properties: properties:
@ -901,4 +892,4 @@ components:
description: Total VRAM as reported by PyTorch description: Total VRAM as reported by PyTorch
torch_vram_free: torch_vram_free:
type: number type: number
description: Free VRAM as reported by PyTorch description: Free VRAM as reported by PyTorch

View File

@ -93,8 +93,8 @@ def api_client(base_url: str) -> Generator[Optional[requests.Session], None, Non
# Helper function to construct URLs # Helper function to construct URLs
def get_url(path: str) -> str: def get_url(path: str) -> str:
# All API endpoints use the /api prefix # Paths in the OpenAPI spec already include /api prefix where needed
return urljoin(base_url, '/api' + path) return urljoin(base_url, path)
# Add url helper to the session # Add url helper to the session
session.get_url = get_url # type: ignore session.get_url = get_url # type: ignore

View File

@ -77,12 +77,12 @@ def test_endpoints_exist(all_endpoints: List[Dict[str, Any]]):
@pytest.mark.parametrize("endpoint_path", [ @pytest.mark.parametrize("endpoint_path", [
"/", # Root path "/", # Root path (doesn't have /api prefix)
"/prompt", # Get prompt info "/api/prompt", # Get prompt info
"/queue", # Get queue "/api/queue", # Get queue
"/models", # Get model types "/api/models", # Get model types
"/object_info", # Get node info "/api/object_info", # Get node info
"/system_stats" # Get system stats "/api/system_stats" # Get system stats
]) ])
def test_basic_get_endpoints(require_server, api_client, endpoint_path: str): def test_basic_get_endpoints(require_server, api_client, endpoint_path: str):
""" """
@ -116,7 +116,7 @@ def test_websocket_endpoint_exists(require_server, base_url: str):
require_server: Fixture that skips if server is not available require_server: Fixture that skips if server is not available
base_url: Base server URL base_url: Base server URL
""" """
# WebSocket endpoint uses /api prefix # WebSocket endpoint path from OpenAPI spec
ws_url = urljoin(base_url, "/api/ws") ws_url = urljoin(base_url, "/api/ws")
# For WebSocket, we can't use a normal GET request # For WebSocket, we can't use a normal GET request
@ -143,7 +143,7 @@ def test_api_models_folder_endpoint(require_server, api_client):
api_client: API client fixture api_client: API client fixture
""" """
# First get available model types # First get available model types
models_url = api_client.get_url("/models") # type: ignore models_url = api_client.get_url("/api/models") # type: ignore
try: try:
models_response = api_client.get(models_url) models_response = api_client.get(models_url)
@ -157,14 +157,14 @@ def test_api_models_folder_endpoint(require_server, api_client):
# Test with the first model type # Test with the first model type
model_type = model_types[0] model_type = model_types[0]
models_folder_url = api_client.get_url(f"/models/{model_type}") # type: ignore models_folder_url = api_client.get_url(f"/api/models/{model_type}") # type: ignore
folder_response = api_client.get(models_folder_url) folder_response = api_client.get(models_folder_url)
# We're just checking that the endpoint exists # We're just checking that the endpoint exists
assert folder_response.status_code != 404, f"Endpoint /models/{model_type} does not exist" assert folder_response.status_code != 404, f"Endpoint /api/models/{model_type} does not exist"
logger.info(f"Endpoint /models/{model_type} exists with status code {folder_response.status_code}") logger.info(f"Endpoint /api/models/{model_type} exists with status code {folder_response.status_code}")
except requests.RequestException as e: except requests.RequestException as e:
pytest.fail(f"Request failed: {str(e)}") pytest.fail(f"Request failed: {str(e)}")
@ -181,7 +181,7 @@ def test_api_object_info_node_endpoint(require_server, api_client):
api_client: API client fixture api_client: API client fixture
""" """
# First get available node classes # First get available node classes
objects_url = api_client.get_url("/object_info") # type: ignore objects_url = api_client.get_url("/api/object_info") # type: ignore
try: try:
objects_response = api_client.get(objects_url) objects_response = api_client.get(objects_url)
@ -195,14 +195,14 @@ def test_api_object_info_node_endpoint(require_server, api_client):
# Test with the first node class # Test with the first node class
node_class = next(iter(node_classes.keys())) node_class = next(iter(node_classes.keys()))
node_url = api_client.get_url(f"/object_info/{node_class}") # type: ignore node_url = api_client.get_url(f"/api/object_info/{node_class}") # type: ignore
node_response = api_client.get(node_url) node_response = api_client.get(node_url)
# We're just checking that the endpoint exists # We're just checking that the endpoint exists
assert node_response.status_code != 404, f"Endpoint /object_info/{node_class} does not exist" assert node_response.status_code != 404, f"Endpoint /api/object_info/{node_class} does not exist"
logger.info(f"Endpoint /object_info/{node_class} exists with status code {node_response.status_code}") logger.info(f"Endpoint /api/object_info/{node_class} exists with status code {node_response.status_code}")
except requests.RequestException as e: except requests.RequestException as e:
pytest.fail(f"Request failed: {str(e)}") pytest.fail(f"Request failed: {str(e)}")

View File

@ -132,11 +132,11 @@ logger = logging.getLogger(__name__)
@pytest.mark.parametrize("endpoint_path,method", [ @pytest.mark.parametrize("endpoint_path,method", [
("/system_stats", "get"), ("/api/system_stats", "get"),
("/prompt", "get"), ("/api/prompt", "get"),
("/queue", "get"), ("/api/queue", "get"),
("/models", "get"), ("/api/models", "get"),
("/embeddings", "get") ("/api/embeddings", "get")
]) ])
def test_response_schema_validation( def test_response_schema_validation(
require_server, require_server,
@ -182,7 +182,7 @@ def test_response_schema_validation(
return return
# Special handling for system_stats endpoint # Special handling for system_stats endpoint
if endpoint_path == '/system_stats' and isinstance(response_data, dict): if endpoint_path == '/api/system_stats' and isinstance(response_data, dict):
# Remove null index fields before validation # Remove null index fields before validation
for device in response_data.get('devices', []): for device in response_data.get('devices', []):
if 'index' in device and device['index'] is None: if 'index' in device and device['index'] is None:
@ -217,7 +217,7 @@ def test_system_stats_response(require_server, api_client, api_spec: Dict[str, A
api_client: API client fixture api_client: API client fixture
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
url = api_client.get_url("/system_stats") # type: ignore url = api_client.get_url("/api/system_stats") # type: ignore
try: try:
response = api_client.get(url) response = api_client.get(url)
@ -259,7 +259,7 @@ def test_system_stats_response(require_server, api_client, api_spec: Dict[str, A
validation_result = validate_response( validation_result = validate_response(
stats, stats,
api_spec, api_spec,
"/system_stats", "/api/system_stats",
"get" "get"
) )
@ -279,7 +279,7 @@ def test_system_stats_response(require_server, api_client, api_spec: Dict[str, A
assert validation_result['valid'], "System stats response does not match schema" assert validation_result['valid'], "System stats response does not match schema"
except requests.RequestException as e: except requests.RequestException as e:
pytest.fail(f"Request to /system_stats failed: {str(e)}") pytest.fail(f"Request to /api/system_stats failed: {str(e)}")
def test_models_listing_response(require_server, api_client, api_spec: Dict[str, Any]): def test_models_listing_response(require_server, api_client, api_spec: Dict[str, Any]):
@ -291,7 +291,7 @@ def test_models_listing_response(require_server, api_client, api_spec: Dict[str,
api_client: API client fixture api_client: API client fixture
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
url = api_client.get_url("/models") # type: ignore url = api_client.get_url("/api/models") # type: ignore
try: try:
response = api_client.get(url) response = api_client.get(url)
@ -312,7 +312,7 @@ def test_models_listing_response(require_server, api_client, api_spec: Dict[str,
validation_result = validate_response( validation_result = validate_response(
models, models,
api_spec, api_spec,
"/models", "/api/models",
"get" "get"
) )
@ -333,7 +333,7 @@ def test_models_listing_response(require_server, api_client, api_spec: Dict[str,
assert validation_result['valid'], "Models response does not match schema" assert validation_result['valid'], "Models response does not match schema"
except requests.RequestException as e: except requests.RequestException as e:
pytest.fail(f"Request to /models failed: {str(e)}") pytest.fail(f"Request to /api/models failed: {str(e)}")
def test_object_info_response(require_server, api_client, api_spec: Dict[str, Any]): def test_object_info_response(require_server, api_client, api_spec: Dict[str, Any]):
@ -345,7 +345,7 @@ def test_object_info_response(require_server, api_client, api_spec: Dict[str, An
api_client: API client fixture api_client: API client fixture
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
url = api_client.get_url("/object_info") # type: ignore url = api_client.get_url("/api/object_info") # type: ignore
try: try:
response = api_client.get(url) response = api_client.get(url)
@ -373,7 +373,7 @@ def test_object_info_response(require_server, api_client, api_spec: Dict[str, An
validation_result = validate_response( validation_result = validate_response(
objects, objects,
api_spec, api_spec,
"/object_info", "/api/object_info",
"get" "get"
) )
@ -394,7 +394,7 @@ def test_object_info_response(require_server, api_client, api_spec: Dict[str, An
assert validation_result['valid'], "Object info response does not match schema" assert validation_result['valid'], "Object info response does not match schema"
except requests.RequestException as e: except requests.RequestException as e:
pytest.fail(f"Request to /object_info failed: {str(e)}") pytest.fail(f"Request to /api/object_info failed: {str(e)}")
except (KeyError, StopIteration) as e: except (KeyError, StopIteration) as e:
pytest.fail(f"Failed to process response: {str(e)}") pytest.fail(f"Failed to process response: {str(e)}")
@ -408,7 +408,7 @@ def test_queue_response(require_server, api_client, api_spec: Dict[str, Any]):
api_client: API client fixture api_client: API client fixture
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
url = api_client.get_url("/queue") # type: ignore url = api_client.get_url("/api/queue") # type: ignore
try: try:
response = api_client.get(url) response = api_client.get(url)
@ -430,7 +430,7 @@ def test_queue_response(require_server, api_client, api_spec: Dict[str, Any]):
validation_result = validate_response( validation_result = validate_response(
queue, queue,
api_spec, api_spec,
"/queue", "/api/queue",
"get" "get"
) )

View File

@ -61,9 +61,9 @@ def test_workflow_endpoints_exist(api_spec: Dict[str, Any]):
Args: Args:
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
assert '/prompt' in api_spec['paths'], "Spec must define /prompt endpoint" assert '/api/prompt' in api_spec['paths'], "Spec must define /api/prompt endpoint"
assert 'post' in api_spec['paths']['/prompt'], "Spec must define POST /prompt" assert 'post' in api_spec['paths']['/api/prompt'], "Spec must define POST /api/prompt"
assert 'get' in api_spec['paths']['/prompt'], "Spec must define GET /prompt" assert 'get' in api_spec['paths']['/api/prompt'], "Spec must define GET /api/prompt"
def test_image_endpoints_exist(api_spec: Dict[str, Any]): def test_image_endpoints_exist(api_spec: Dict[str, Any]):
@ -73,8 +73,8 @@ def test_image_endpoints_exist(api_spec: Dict[str, Any]):
Args: Args:
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
assert '/upload/image' in api_spec['paths'], "Spec must define /upload/image endpoint" assert '/api/upload/image' in api_spec['paths'], "Spec must define /api/upload/image endpoint"
assert '/view' in api_spec['paths'], "Spec must define /view endpoint" assert '/api/view' in api_spec['paths'], "Spec must define /api/view endpoint"
def test_model_endpoints_exist(api_spec: Dict[str, Any]): def test_model_endpoints_exist(api_spec: Dict[str, Any]):
@ -84,8 +84,8 @@ def test_model_endpoints_exist(api_spec: Dict[str, Any]):
Args: Args:
api_spec: Loaded OpenAPI spec api_spec: Loaded OpenAPI spec
""" """
assert '/models' in api_spec['paths'], "Spec must define /models endpoint" assert '/api/models' in api_spec['paths'], "Spec must define /api/models endpoint"
assert '/models/{folder}' in api_spec['paths'], "Spec must define /models/{folder} endpoint" assert '/api/models/{folder}' in api_spec['paths'], "Spec must define /api/models/{folder} endpoint"
def test_operation_ids_are_unique(api_spec: Dict[str, Any]): def test_operation_ids_are_unique(api_spec: Dict[str, Any]):