Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
2008986f
Unverified
Commit
2008986f
authored
Mar 11, 2024
by
Yeuoly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat
parent
1a57951d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
197 additions
and
20 deletions
+197
-20
ssrf_proxy.py
api/core/helper/ssrf_proxy.py
+0
-1
http_executor.py
api/core/workflow/nodes/http_request/http_executor.py
+17
-2
http_request_node.py
api/core/workflow/nodes/http_request/http_request_node.py
+6
-4
http.py
api/tests/integration_tests/workflow/nodes/__mock/http.py
+9
-6
test_http.py
api/tests/integration_tests/workflow/nodes/test_http.py
+165
-7
No files found.
api/core/helper/ssrf_proxy.py
View file @
2008986f
...
@@ -26,7 +26,6 @@ httpx_proxies = {
...
@@ -26,7 +26,6 @@ httpx_proxies = {
}
if
SSRF_PROXY_HTTP_URL
and
SSRF_PROXY_HTTPS_URL
else
None
}
if
SSRF_PROXY_HTTP_URL
and
SSRF_PROXY_HTTPS_URL
else
None
def
get
(
url
,
*
args
,
**
kwargs
):
def
get
(
url
,
*
args
,
**
kwargs
):
print
(
url
,
kwargs
)
return
_get
(
url
=
url
,
*
args
,
proxies
=
httpx_proxies
,
**
kwargs
)
return
_get
(
url
=
url
,
*
args
,
proxies
=
httpx_proxies
,
**
kwargs
)
def
post
(
url
,
*
args
,
**
kwargs
):
def
post
(
url
,
*
args
,
**
kwargs
):
...
...
api/core/workflow/nodes/http_request/http_executor.py
View file @
2008986f
...
@@ -43,6 +43,7 @@ class HttpExecutor:
...
@@ -43,6 +43,7 @@ class HttpExecutor:
self
.
params
=
{}
self
.
params
=
{}
self
.
headers
=
{}
self
.
headers
=
{}
self
.
body
=
None
self
.
body
=
None
self
.
files
=
None
# init template
# init template
self
.
_init_template
(
node_data
,
variables
)
self
.
_init_template
(
node_data
,
variables
)
...
@@ -248,10 +249,24 @@ class HttpExecutor:
...
@@ -248,10 +249,24 @@ class HttpExecutor:
server_url
+=
f
'?{urlencode(self.params)}'
server_url
+=
f
'?{urlencode(self.params)}'
raw_request
=
f
'{self.method.upper()} {server_url} HTTP/1.1
\n
'
raw_request
=
f
'{self.method.upper()} {server_url} HTTP/1.1
\n
'
for
k
,
v
in
self
.
headers
.
items
():
headers
=
self
.
_assembling_headers
()
for
k
,
v
in
headers
.
items
():
raw_request
+=
f
'{k}: {v}
\n
'
raw_request
+=
f
'{k}: {v}
\n
'
raw_request
+=
'
\n
'
raw_request
+=
'
\n
'
raw_request
+=
self
.
body
or
''
# if files, use multipart/form-data with boundary
if
self
.
files
:
boundary
=
'----WebKitFormBoundary7MA4YWxkTrZu0gW'
raw_request
=
f
'--{boundary}
\n
'
+
raw_request
for
k
,
v
in
self
.
files
.
items
():
raw_request
+=
f
'Content-Disposition: form-data; name="{k}"; filename="{v[0]}"
\n
'
raw_request
+=
f
'Content-Type: {v[1]}
\n\n
'
raw_request
+=
v
[
1
]
+
'
\n
'
raw_request
+=
f
'--{boundary}
\n
'
raw_request
+=
'--
\n
'
else
:
raw_request
+=
self
.
body
or
''
return
raw_request
return
raw_request
\ No newline at end of file
api/core/workflow/nodes/http_request/http_request_node.py
View file @
2008986f
...
@@ -28,13 +28,13 @@ class HttpRequestNode(BaseNode):
...
@@ -28,13 +28,13 @@ class HttpRequestNode(BaseNode):
# invoke http executor
# invoke http executor
response
=
http_executor
.
invoke
()
response
=
http_executor
.
invoke
()
except
Exception
as
e
:
except
Exception
as
e
:
import
traceback
print
(
traceback
.
format_exc
())
return
NodeRunResult
(
return
NodeRunResult
(
status
=
WorkflowNodeExecutionStatus
.
FAILED
,
status
=
WorkflowNodeExecutionStatus
.
FAILED
,
inputs
=
variables
,
inputs
=
variables
,
error
=
str
(
e
),
error
=
str
(
e
),
process_data
=
http_executor
.
to_raw_request
()
process_data
=
{
'request'
:
http_executor
.
to_raw_request
()
}
)
)
return
NodeRunResult
(
return
NodeRunResult
(
...
@@ -45,7 +45,9 @@ class HttpRequestNode(BaseNode):
...
@@ -45,7 +45,9 @@ class HttpRequestNode(BaseNode):
'body'
:
response
,
'body'
:
response
,
'headers'
:
response
.
headers
'headers'
:
response
.
headers
},
},
process_data
=
http_executor
.
to_raw_request
()
process_data
=
{
'request'
:
http_executor
.
to_raw_request
(),
}
)
)
...
...
api/tests/integration_tests/workflow/nodes/__mock/http.py
View file @
2008986f
...
@@ -3,6 +3,7 @@ import pytest
...
@@ -3,6 +3,7 @@ import pytest
import
requests.api
as
requests
import
requests.api
as
requests
import
httpx._api
as
httpx
import
httpx._api
as
httpx
from
requests
import
Response
as
RequestsResponse
from
requests
import
Response
as
RequestsResponse
from
httpx
import
Request
as
HttpxRequest
from
yarl
import
URL
from
yarl
import
URL
from
typing
import
Literal
from
typing
import
Literal
...
@@ -12,8 +13,8 @@ from json import dumps
...
@@ -12,8 +13,8 @@ from json import dumps
MOCK
=
os
.
getenv
(
'MOCK_SWITCH'
,
'false'
)
==
'true'
MOCK
=
os
.
getenv
(
'MOCK_SWITCH'
,
'false'
)
==
'true'
class
MockedHttp
:
class
MockedHttp
:
def
requests_request
(
self
,
method
:
Literal
[
'GET'
,
'POST'
,
'PUT'
,
'DELETE'
,
'PATCH'
,
'OPTIONS'
],
def
requests_request
(
method
:
Literal
[
'GET'
,
'POST'
,
'PUT'
,
'DELETE'
,
'PATCH'
,
'OPTIONS'
],
url
:
str
,
url
:
str
,
**
kwargs
)
->
RequestsResponse
:
**
kwargs
)
->
RequestsResponse
:
"""
"""
Mocked requests.request
Mocked requests.request
"""
"""
...
@@ -41,13 +42,15 @@ class MockedHttp:
...
@@ -41,13 +42,15 @@ class MockedHttp:
response
.
_content
=
resp
response
.
_content
=
resp
return
response
return
response
def
httpx_request
(
self
,
method
:
Literal
[
'GET'
,
'POST'
,
'PUT'
,
'DELETE'
,
'PATCH'
,
'OPTIONS'
],
def
httpx_request
(
method
:
Literal
[
'GET'
,
'POST'
,
'PUT'
,
'DELETE'
,
'PATCH'
,
'OPTIONS'
],
url
:
str
,
**
kwargs
)
->
httpx
.
Response
:
url
:
str
,
**
kwargs
)
->
httpx
.
Response
:
"""
"""
Mocked httpx.request
Mocked httpx.request
"""
"""
response
=
httpx
.
Response
()
response
=
httpx
.
Response
(
response
.
url
=
str
(
URL
(
url
)
%
kwargs
.
get
(
'params'
,
{}))
status_code
=
200
,
request
=
HttpxRequest
(
method
,
url
)
)
response
.
headers
=
kwargs
.
get
(
'headers'
,
{})
response
.
headers
=
kwargs
.
get
(
'headers'
,
{})
if
url
==
'http://404.com'
:
if
url
==
'http://404.com'
:
...
@@ -67,7 +70,7 @@ class MockedHttp:
...
@@ -67,7 +70,7 @@ class MockedHttp:
resp
=
b
'OK'
resp
=
b
'OK'
response
.
status_code
=
200
response
.
status_code
=
200
response
.
content
=
resp
response
.
_
content
=
resp
return
response
return
response
@
pytest
.
fixture
@
pytest
.
fixture
...
...
api/tests/integration_tests/workflow/nodes/test_http.py
View file @
2008986f
...
@@ -2,7 +2,6 @@ from calendar import c
...
@@ -2,7 +2,6 @@ from calendar import c
import
pytest
import
pytest
from
core.app.entities.app_invoke_entities
import
InvokeFrom
from
core.app.entities.app_invoke_entities
import
InvokeFrom
from
core.workflow.entities.variable_pool
import
VariablePool
from
core.workflow.entities.variable_pool
import
VariablePool
from
core.workflow.nodes.http_request.entities
import
HttpRequestNodeData
from
core.workflow.nodes.http_request.http_request_node
import
HttpRequestNode
from
core.workflow.nodes.http_request.http_request_node
import
HttpRequestNode
from
tests.integration_tests.workflow.nodes.__mock.http
import
setup_http_mock
from
tests.integration_tests.workflow.nodes.__mock.http
import
setup_http_mock
...
@@ -21,13 +20,16 @@ pool.append_variable(node_id='1', variable_key_list=['123', 'args1'], value=1)
...
@@ -21,13 +20,16 @@ pool.append_variable(node_id='1', variable_key_list=['123', 'args1'], value=1)
pool
.
append_variable
(
node_id
=
'1'
,
variable_key_list
=
[
'123'
,
'args2'
],
value
=
2
)
pool
.
append_variable
(
node_id
=
'1'
,
variable_key_list
=
[
'123'
,
'args2'
],
value
=
2
)
@
pytest
.
mark
.
parametrize
(
'setup_http_mock'
,
[[
'none'
]],
indirect
=
True
)
@
pytest
.
mark
.
parametrize
(
'setup_http_mock'
,
[[
'none'
]],
indirect
=
True
)
def
test_get
_param
(
setup_http_mock
):
def
test_get
(
setup_http_mock
):
node
=
HttpRequestNode
(
config
=
{
node
=
HttpRequestNode
(
config
=
{
'id'
:
'1'
,
'id'
:
'1'
,
'data'
:
{
'data'
:
{
'title'
:
'http'
,
'title'
:
'http'
,
'desc'
:
''
,
'desc'
:
''
,
'variables'
:
[],
'variables'
:
[{
'variable'
:
'args1'
,
'value_selector'
:
[
'1'
,
'123'
,
'args1'
],
}],
'method'
:
'get'
,
'method'
:
'get'
,
'url'
:
'http://example.com'
,
'url'
:
'http://example.com'
,
'authorization'
:
{
'authorization'
:
{
...
@@ -38,14 +40,170 @@ def test_get_param(setup_http_mock):
...
@@ -38,14 +40,170 @@ def test_get_param(setup_http_mock):
'header'
:
'api-key'
,
'header'
:
'api-key'
,
}
}
},
},
'headers'
:
''
,
'headers'
:
'
X-Header:123
'
,
'params'
:
''
,
'params'
:
'
A:b
'
,
'body'
:
None
,
'body'
:
None
,
}
}
},
**
BASIC_NODE_DATA
)
},
**
BASIC_NODE_DATA
)
result
=
node
.
run
(
pool
)
result
=
node
.
run
(
pool
)
print
(
result
)
data
=
result
.
process_data
.
get
(
'request'
,
''
)
assert
1
==
2
assert
'?A=b'
in
data
\ No newline at end of file
assert
'api-key: Basic ak-xxx'
in
data
assert
'X-Header: 123'
in
data
@
pytest
.
mark
.
parametrize
(
'setup_http_mock'
,
[[
'none'
]],
indirect
=
True
)
def
test_template
(
setup_http_mock
):
node
=
HttpRequestNode
(
config
=
{
'id'
:
'1'
,
'data'
:
{
'title'
:
'http'
,
'desc'
:
''
,
'variables'
:
[{
'variable'
:
'args1'
,
'value_selector'
:
[
'1'
,
'123'
,
'args2'
],
}],
'method'
:
'get'
,
'url'
:
'http://example.com/{{args1}}'
,
'authorization'
:
{
'type'
:
'api-key'
,
'config'
:
{
'type'
:
'basic'
,
'api_key'
:
'ak-xxx'
,
'header'
:
'api-key'
,
}
},
'headers'
:
'X-Header:123
\n
X-Header2:{{args1}}'
,
'params'
:
'A:b
\n
Template:{{args1}}'
,
'body'
:
None
,
}
},
**
BASIC_NODE_DATA
)
result
=
node
.
run
(
pool
)
data
=
result
.
process_data
.
get
(
'request'
,
''
)
assert
'?A=b'
in
data
assert
'Template=2'
in
data
assert
'api-key: Basic ak-xxx'
in
data
assert
'X-Header: 123'
in
data
assert
'X-Header2: 2'
in
data
@
pytest
.
mark
.
parametrize
(
'setup_http_mock'
,
[[
'none'
]],
indirect
=
True
)
def
test_json
(
setup_http_mock
):
node
=
HttpRequestNode
(
config
=
{
'id'
:
'1'
,
'data'
:
{
'title'
:
'http'
,
'desc'
:
''
,
'variables'
:
[{
'variable'
:
'args1'
,
'value_selector'
:
[
'1'
,
'123'
,
'args1'
],
}],
'method'
:
'post'
,
'url'
:
'http://example.com'
,
'authorization'
:
{
'type'
:
'api-key'
,
'config'
:
{
'type'
:
'basic'
,
'api_key'
:
'ak-xxx'
,
'header'
:
'api-key'
,
}
},
'headers'
:
'X-Header:123'
,
'params'
:
'A:b'
,
'body'
:
{
'type'
:
'json'
,
'data'
:
'{"a": "{{args1}}"}'
},
}
},
**
BASIC_NODE_DATA
)
result
=
node
.
run
(
pool
)
data
=
result
.
process_data
.
get
(
'request'
,
''
)
assert
'{"a": "1"}'
in
data
assert
'api-key: Basic ak-xxx'
in
data
assert
'X-Header: 123'
in
data
def
test_x_www_form_urlencoded
(
setup_http_mock
):
node
=
HttpRequestNode
(
config
=
{
'id'
:
'1'
,
'data'
:
{
'title'
:
'http'
,
'desc'
:
''
,
'variables'
:
[{
'variable'
:
'args1'
,
'value_selector'
:
[
'1'
,
'123'
,
'args1'
],
},
{
'variable'
:
'args2'
,
'value_selector'
:
[
'1'
,
'123'
,
'args2'
],
}],
'method'
:
'post'
,
'url'
:
'http://example.com'
,
'authorization'
:
{
'type'
:
'api-key'
,
'config'
:
{
'type'
:
'basic'
,
'api_key'
:
'ak-xxx'
,
'header'
:
'api-key'
,
}
},
'headers'
:
'X-Header:123'
,
'params'
:
'A:b'
,
'body'
:
{
'type'
:
'x-www-form-urlencoded'
,
'data'
:
'a:{{args1}}
\n
b:{{args2}}'
},
}
},
**
BASIC_NODE_DATA
)
result
=
node
.
run
(
pool
)
data
=
result
.
process_data
.
get
(
'request'
,
''
)
assert
'a=1&b=2'
in
data
assert
'api-key: Basic ak-xxx'
in
data
assert
'X-Header: 123'
in
data
def
test_form_data
(
setup_http_mock
):
node
=
HttpRequestNode
(
config
=
{
'id'
:
'1'
,
'data'
:
{
'title'
:
'http'
,
'desc'
:
''
,
'variables'
:
[{
'variable'
:
'args1'
,
'value_selector'
:
[
'1'
,
'123'
,
'args1'
],
},
{
'variable'
:
'args2'
,
'value_selector'
:
[
'1'
,
'123'
,
'args2'
],
}],
'method'
:
'post'
,
'url'
:
'http://example.com'
,
'authorization'
:
{
'type'
:
'api-key'
,
'config'
:
{
'type'
:
'basic'
,
'api_key'
:
'ak-xxx'
,
'header'
:
'api-key'
,
}
},
'headers'
:
'X-Header:123'
,
'params'
:
'A:b'
,
'body'
:
{
'type'
:
'form-data'
,
'data'
:
'a:{{args1}}
\n
b:{{args2}}'
},
}
},
**
BASIC_NODE_DATA
)
result
=
node
.
run
(
pool
)
data
=
result
.
process_data
.
get
(
'request'
,
''
)
assert
'form-data; name="a"'
in
data
assert
'1'
in
data
assert
'form-data; name="b"'
in
data
assert
'2'
in
data
assert
'api-key: Basic ak-xxx'
in
data
assert
'X-Header: 123'
in
data
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment