diff --git a/api/core/app/workflow/node_factory.py b/api/core/app/workflow/node_factory.py index c1faeb6a6c..1733ded255 100644 --- a/api/core/app/workflow/node_factory.py +++ b/api/core/app/workflow/node_factory.py @@ -17,7 +17,7 @@ from core.workflow.nodes.base.node import Node from core.workflow.nodes.code.code_node import CodeNode from core.workflow.nodes.code.limits import CodeNodeLimits from core.workflow.nodes.document_extractor import DocumentExtractorNode, UnstructuredApiConfig -from core.workflow.nodes.http_request import HttpRequestNode, HttpRequestNodeConfig +from core.workflow.nodes.http_request import HttpRequestNode, build_http_request_config from core.workflow.nodes.knowledge_retrieval.knowledge_retrieval_node import KnowledgeRetrievalNode from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from core.workflow.nodes.protocols import FileManagerProtocol, HttpClientProtocol @@ -88,15 +88,7 @@ class DifyNodeFactory(NodeFactory): api_key=dify_config.UNSTRUCTURED_API_KEY or "", ) ) - self._http_request_config = http_request_config or HttpRequestNodeConfig( - max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT, - max_read_timeout=dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT, - max_write_timeout=dify_config.HTTP_REQUEST_MAX_WRITE_TIMEOUT, - max_binary_size=dify_config.HTTP_REQUEST_NODE_MAX_BINARY_SIZE, - max_text_size=dify_config.HTTP_REQUEST_NODE_MAX_TEXT_SIZE, - ssl_verify=dify_config.HTTP_REQUEST_NODE_SSL_VERIFY, - ssrf_default_max_retries=dify_config.SSRF_DEFAULT_MAX_RETRIES, - ) + self._http_request_config = http_request_config or build_http_request_config() @override def create_node(self, node_config: NodeConfigDict) -> Node: diff --git a/api/core/workflow/nodes/http_request/__init__.py b/api/core/workflow/nodes/http_request/__init__.py index 92b23310d2..b29099db23 100644 --- a/api/core/workflow/nodes/http_request/__init__.py +++ b/api/core/workflow/nodes/http_request/__init__.py @@ -1,3 +1,4 @@ +from .config import build_http_request_config, resolve_http_request_config from .entities import ( HTTP_REQUEST_CONFIG_FILTER_KEY, BodyData, @@ -16,4 +17,6 @@ __all__ = [ "HttpRequestNodeBody", "HttpRequestNodeConfig", "HttpRequestNodeData", + "build_http_request_config", + "resolve_http_request_config", ] diff --git a/api/core/workflow/nodes/http_request/config.py b/api/core/workflow/nodes/http_request/config.py new file mode 100644 index 0000000000..9a146973c5 --- /dev/null +++ b/api/core/workflow/nodes/http_request/config.py @@ -0,0 +1,26 @@ +from collections.abc import Mapping + +from configs import dify_config + +from .entities import HTTP_REQUEST_CONFIG_FILTER_KEY, HttpRequestNodeConfig + + +def build_http_request_config() -> HttpRequestNodeConfig: + return HttpRequestNodeConfig( + max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT, + max_read_timeout=dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT, + max_write_timeout=dify_config.HTTP_REQUEST_MAX_WRITE_TIMEOUT, + max_binary_size=dify_config.HTTP_REQUEST_NODE_MAX_BINARY_SIZE, + max_text_size=dify_config.HTTP_REQUEST_NODE_MAX_TEXT_SIZE, + ssl_verify=dify_config.HTTP_REQUEST_NODE_SSL_VERIFY, + ssrf_default_max_retries=dify_config.SSRF_DEFAULT_MAX_RETRIES, + ) + + +def resolve_http_request_config(filters: Mapping[str, object] | None) -> HttpRequestNodeConfig: + if not filters: + raise ValueError("http_request_config is required to build HTTP request default config") + config = filters.get(HTTP_REQUEST_CONFIG_FILTER_KEY) + if not isinstance(config, HttpRequestNodeConfig): + raise ValueError("http_request_config must be an HttpRequestNodeConfig instance") + return config diff --git a/api/core/workflow/nodes/http_request/executor.py b/api/core/workflow/nodes/http_request/executor.py index e6c6f00263..8f180b47b5 100644 --- a/api/core/workflow/nodes/http_request/executor.py +++ b/api/core/workflow/nodes/http_request/executor.py @@ -102,12 +102,11 @@ class Executor: self.method = node_data.method self.auth = node_data.authorization self.timeout = timeout - resolved_ssl_verify = ssl_verify if ssl_verify is not None else node_data.ssl_verify - if resolved_ssl_verify is None: - resolved_ssl_verify = self._http_request_config.ssl_verify - if not isinstance(resolved_ssl_verify, bool): + self.ssl_verify = ssl_verify if ssl_verify is not None else node_data.ssl_verify + if self.ssl_verify is None: + self.ssl_verify = self._http_request_config.ssl_verify + if not isinstance(self.ssl_verify, bool): raise ValueError("ssl_verify must be a boolean") - self.ssl_verify = resolved_ssl_verify self.params = None self.headers = {} self.content = None diff --git a/api/core/workflow/nodes/http_request/node.py b/api/core/workflow/nodes/http_request/node.py index 9f3b4ba74c..8d537b4098 100644 --- a/api/core/workflow/nodes/http_request/node.py +++ b/api/core/workflow/nodes/http_request/node.py @@ -17,8 +17,8 @@ from core.workflow.nodes.http_request.executor import Executor from core.workflow.nodes.protocols import FileManagerProtocol, HttpClientProtocol from factories import file_factory +from .config import resolve_http_request_config from .entities import ( - HTTP_REQUEST_CONFIG_FILTER_KEY, HttpRequestNodeConfig, HttpRequestNodeData, HttpRequestNodeTimeout, @@ -33,15 +33,6 @@ if TYPE_CHECKING: from core.workflow.runtime import GraphRuntimeState -def _resolve_http_request_config(filters: Mapping[str, object] | None) -> HttpRequestNodeConfig: - if not filters: - raise ValueError("http_request_config is required to build HTTP request default config") - config = filters.get(HTTP_REQUEST_CONFIG_FILTER_KEY) - if not isinstance(config, HttpRequestNodeConfig): - raise ValueError("http_request_config must be an HttpRequestNodeConfig instance") - return config - - class HttpRequestNode(Node[HttpRequestNodeData]): node_type = NodeType.HTTP_REQUEST @@ -70,7 +61,7 @@ class HttpRequestNode(Node[HttpRequestNodeData]): @classmethod def get_default_config(cls, filters: Mapping[str, object] | None = None) -> Mapping[str, object]: - http_request_config = _resolve_http_request_config(filters) + http_request_config = resolve_http_request_config(filters) default_timeout = http_request_config.default_timeout() return { "type": "http-request", diff --git a/api/services/rag_pipeline/rag_pipeline.py b/api/services/rag_pipeline/rag_pipeline.py index 70c5426283..1e59b7cd7b 100644 --- a/api/services/rag_pipeline/rag_pipeline.py +++ b/api/services/rag_pipeline/rag_pipeline.py @@ -47,7 +47,7 @@ from core.workflow.graph_events import NodeRunFailedEvent, NodeRunSucceededEvent from core.workflow.graph_events.base import GraphNodeEventBase from core.workflow.node_events.base import NodeRunResult from core.workflow.nodes.base.node import Node -from core.workflow.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, HttpRequestNodeConfig +from core.workflow.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, build_http_request_config from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from core.workflow.repositories.workflow_node_execution_repository import OrderConfig from core.workflow.runtime import VariablePool @@ -87,18 +87,6 @@ from services.workflow_draft_variable_service import DraftVariableSaver, DraftVa logger = logging.getLogger(__name__) -def _build_http_request_config() -> HttpRequestNodeConfig: - return HttpRequestNodeConfig( - max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT, - max_read_timeout=dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT, - max_write_timeout=dify_config.HTTP_REQUEST_MAX_WRITE_TIMEOUT, - max_binary_size=dify_config.HTTP_REQUEST_NODE_MAX_BINARY_SIZE, - max_text_size=dify_config.HTTP_REQUEST_NODE_MAX_TEXT_SIZE, - ssl_verify=dify_config.HTTP_REQUEST_NODE_SSL_VERIFY, - ssrf_default_max_retries=dify_config.SSRF_DEFAULT_MAX_RETRIES, - ) - - class RagPipelineService: def __init__(self, session_maker: sessionmaker | None = None): """Initialize RagPipelineService with repository dependencies.""" @@ -397,7 +385,7 @@ class RagPipelineService: node_class = node_class_mapping[LATEST_VERSION] filters = None if node_type is NodeType.HTTP_REQUEST: - filters = {HTTP_REQUEST_CONFIG_FILTER_KEY: _build_http_request_config()} + filters = {HTTP_REQUEST_CONFIG_FILTER_KEY: build_http_request_config()} default_config = node_class.get_default_config(filters=filters) if default_config: default_block_configs.append(dict(default_config)) @@ -418,10 +406,10 @@ class RagPipelineService: return None node_class = NODE_TYPE_CLASSES_MAPPING[node_type_enum][LATEST_VERSION] - resolved_filters = dict(filters) if filters else {} - if node_type_enum is NodeType.HTTP_REQUEST and HTTP_REQUEST_CONFIG_FILTER_KEY not in resolved_filters: - resolved_filters[HTTP_REQUEST_CONFIG_FILTER_KEY] = _build_http_request_config() - default_config = node_class.get_default_config(filters=resolved_filters or None) + final_filters = dict(filters) if filters else {} + if node_type_enum is NodeType.HTTP_REQUEST and HTTP_REQUEST_CONFIG_FILTER_KEY not in final_filters: + final_filters[HTTP_REQUEST_CONFIG_FILTER_KEY] = build_http_request_config() + default_config = node_class.get_default_config(filters=final_filters or None) if not default_config: return None diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index 94e4dc88cd..a33e766780 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -26,7 +26,7 @@ from core.workflow.graph_events import GraphNodeEventBase, NodeRunFailedEvent, N from core.workflow.node_events import NodeRunResult from core.workflow.nodes import NodeType from core.workflow.nodes.base.node import Node -from core.workflow.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, HttpRequestNodeConfig +from core.workflow.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, build_http_request_config from core.workflow.nodes.human_input.entities import ( DeliveryChannelConfig, HumanInputNodeData, @@ -71,18 +71,6 @@ from .human_input_delivery_test_service import ( from .workflow_draft_variable_service import DraftVariableSaver, DraftVarLoader, WorkflowDraftVariableService -def _build_http_request_config() -> HttpRequestNodeConfig: - return HttpRequestNodeConfig( - max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT, - max_read_timeout=dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT, - max_write_timeout=dify_config.HTTP_REQUEST_MAX_WRITE_TIMEOUT, - max_binary_size=dify_config.HTTP_REQUEST_NODE_MAX_BINARY_SIZE, - max_text_size=dify_config.HTTP_REQUEST_NODE_MAX_TEXT_SIZE, - ssl_verify=dify_config.HTTP_REQUEST_NODE_SSL_VERIFY, - ssrf_default_max_retries=dify_config.SSRF_DEFAULT_MAX_RETRIES, - ) - - class WorkflowService: """ Workflow Service @@ -635,7 +623,7 @@ class WorkflowService: node_class = node_class_mapping[LATEST_VERSION] filters = None if node_type is NodeType.HTTP_REQUEST: - filters = {HTTP_REQUEST_CONFIG_FILTER_KEY: _build_http_request_config()} + filters = {HTTP_REQUEST_CONFIG_FILTER_KEY: build_http_request_config()} default_config = node_class.get_default_config(filters=filters) if default_config: default_block_configs.append(default_config) @@ -660,7 +648,7 @@ class WorkflowService: node_class = NODE_TYPE_CLASSES_MAPPING[node_type_enum][LATEST_VERSION] resolved_filters = dict(filters) if filters else {} if node_type_enum is NodeType.HTTP_REQUEST and HTTP_REQUEST_CONFIG_FILTER_KEY not in resolved_filters: - resolved_filters[HTTP_REQUEST_CONFIG_FILTER_KEY] = _build_http_request_config() + resolved_filters[HTTP_REQUEST_CONFIG_FILTER_KEY] = build_http_request_config() default_config = node_class.get_default_config(filters=resolved_filters or None) if not default_config: return {}