Unverified Commit 2008986f authored by Yeuoly's avatar Yeuoly

feat

parent 1a57951d
...@@ -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):
......
...@@ -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
...@@ -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(),
}
) )
......
...@@ -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
......
...@@ -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\nX-Header2:{{args1}}',
'params': 'A:b\nTemplate:{{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}}\nb:{{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}}\nb:{{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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment