22import json
33import logging
44from collections .abc import Callable , Generator
5- from typing import TypeVar
5+ from typing import Any , TypeVar
66
7- import requests
7+ import httpx
88from pydantic import BaseModel
9- from requests .exceptions import HTTPError
109from yarl import URL
1110
1211from configs import dify_config
@@ -47,29 +46,56 @@ def _request(
4746 data : bytes | dict | str | None = None ,
4847 params : dict | None = None ,
4948 files : dict | None = None ,
50- stream : bool = False ,
51- ) -> requests .Response :
49+ ) -> httpx .Response :
5250 """
5351 Make a request to the plugin daemon inner API.
5452 """
55- url = plugin_daemon_inner_api_baseurl / path
56- headers = headers or {}
57- headers ["X-Api-Key" ] = dify_config .PLUGIN_DAEMON_KEY
58- headers ["Accept-Encoding" ] = "gzip, deflate, br"
53+ url , headers , prepared_data , params , files = self ._prepare_request (path , headers , data , params , files )
5954
60- if headers .get ("Content-Type" ) == "application/json" and isinstance (data , dict ):
61- data = json .dumps (data )
55+ request_kwargs : dict [str , Any ] = {
56+ "method" : method ,
57+ "url" : url ,
58+ "headers" : headers ,
59+ "params" : params ,
60+ "files" : files ,
61+ }
62+ if isinstance (prepared_data , dict ):
63+ request_kwargs ["data" ] = prepared_data
64+ elif prepared_data is not None :
65+ request_kwargs ["content" ] = prepared_data
6266
6367 try :
64- response = requests .request (
65- method = method , url = str (url ), headers = headers , data = data , params = params , stream = stream , files = files
66- )
67- except requests .ConnectionError :
68+ response = httpx .request (** request_kwargs )
69+ except httpx .RequestError :
6870 logger .exception ("Request to Plugin Daemon Service failed" )
6971 raise PluginDaemonInnerError (code = - 500 , message = "Request to Plugin Daemon Service failed" )
7072
7173 return response
7274
75+ def _prepare_request (
76+ self ,
77+ path : str ,
78+ headers : dict | None ,
79+ data : bytes | dict | str | None ,
80+ params : dict | None ,
81+ files : dict | None ,
82+ ) -> tuple [str , dict , bytes | dict | str | None , dict | None , dict | None ]:
83+ url = plugin_daemon_inner_api_baseurl / path
84+ prepared_headers = dict (headers or {})
85+ prepared_headers ["X-Api-Key" ] = dify_config .PLUGIN_DAEMON_KEY
86+ prepared_headers .setdefault ("Accept-Encoding" , "gzip, deflate, br" )
87+
88+ prepared_data : bytes | dict | str | None = (
89+ data if isinstance (data , (bytes , str , dict )) or data is None else None
90+ )
91+ if isinstance (data , dict ):
92+ if prepared_headers .get ("Content-Type" ) == "application/json" :
93+ prepared_data = json .dumps (data )
94+ else :
95+ prepared_data = data
96+
97+ return str (url ), prepared_headers , prepared_data , params , files
98+
7399 def _stream_request (
74100 self ,
75101 method : str ,
@@ -78,17 +104,38 @@ def _stream_request(
78104 headers : dict | None = None ,
79105 data : bytes | dict | None = None ,
80106 files : dict | None = None ,
81- ) -> Generator [bytes , None , None ]:
107+ ) -> Generator [str , None , None ]:
82108 """
83109 Make a stream request to the plugin daemon inner API
84110 """
85- response = self ._request (method , path , headers , data , params , files , stream = True )
86- for line in response .iter_lines (chunk_size = 1024 * 8 ):
87- line = line .decode ("utf-8" ).strip ()
88- if line .startswith ("data:" ):
89- line = line [5 :].strip ()
90- if line :
91- yield line
111+ url , headers , prepared_data , params , files = self ._prepare_request (path , headers , data , params , files )
112+
113+ stream_kwargs : dict [str , Any ] = {
114+ "method" : method ,
115+ "url" : url ,
116+ "headers" : headers ,
117+ "params" : params ,
118+ "files" : files ,
119+ }
120+ if isinstance (prepared_data , dict ):
121+ stream_kwargs ["data" ] = prepared_data
122+ elif prepared_data is not None :
123+ stream_kwargs ["content" ] = prepared_data
124+
125+ try :
126+ with httpx .stream (** stream_kwargs ) as response :
127+ for raw_line in response .iter_lines ():
128+ if raw_line is None :
129+ continue
130+ line = raw_line .decode ("utf-8" ) if isinstance (raw_line , bytes ) else raw_line
131+ line = line .strip ()
132+ if line .startswith ("data:" ):
133+ line = line [5 :].strip ()
134+ if line :
135+ yield line
136+ except httpx .RequestError :
137+ logger .exception ("Stream request to Plugin Daemon Service failed" )
138+ raise PluginDaemonInnerError (code = - 500 , message = "Request to Plugin Daemon Service failed" )
92139
93140 def _stream_request_with_model (
94141 self ,
@@ -139,7 +186,7 @@ def _request_with_plugin_daemon_response(
139186 try :
140187 response = self ._request (method , path , headers , data , params , files )
141188 response .raise_for_status ()
142- except HTTPError as e :
189+ except httpx . HTTPStatusError as e :
143190 logger .exception ("Failed to request plugin daemon, status: %s, url: %s" , e .response .status_code , path )
144191 raise e
145192 except Exception as e :
0 commit comments