fix: ensure custom headers are ignored when using bearer or basic authorization (#23584)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -276,7 +276,8 @@ class Executor:
|
|||||||
encoded_credentials = credentials
|
encoded_credentials = credentials
|
||||||
headers[authorization.config.header] = f"Basic {encoded_credentials}"
|
headers[authorization.config.header] = f"Basic {encoded_credentials}"
|
||||||
elif self.auth.config.type == "custom":
|
elif self.auth.config.type == "custom":
|
||||||
headers[authorization.config.header] = authorization.config.api_key or ""
|
if authorization.config.header and authorization.config.api_key:
|
||||||
|
headers[authorization.config.header] = authorization.config.api_key
|
||||||
|
|
||||||
# Handle Content-Type for multipart/form-data requests
|
# Handle Content-Type for multipart/form-data requests
|
||||||
# Fix for issue #23829: Missing boundary when using multipart/form-data
|
# Fix for issue #23829: Missing boundary when using multipart/form-data
|
||||||
|
@@ -160,6 +160,177 @@ def test_custom_authorization_header(setup_http_mock):
|
|||||||
|
|
||||||
assert "?A=b" in data
|
assert "?A=b" in data
|
||||||
assert "X-Header: 123" in data
|
assert "X-Header: 123" in data
|
||||||
|
# Custom authorization header should be set (may be masked)
|
||||||
|
assert "X-Auth:" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
|
def test_custom_auth_with_empty_api_key_does_not_set_header(setup_http_mock):
|
||||||
|
"""Test: In custom authentication mode, when the api_key is empty, no header should be set."""
|
||||||
|
from core.workflow.entities.variable_pool import VariablePool
|
||||||
|
from core.workflow.nodes.http_request.entities import (
|
||||||
|
HttpRequestNodeAuthorization,
|
||||||
|
HttpRequestNodeData,
|
||||||
|
HttpRequestNodeTimeout,
|
||||||
|
)
|
||||||
|
from core.workflow.nodes.http_request.executor import Executor
|
||||||
|
from core.workflow.system_variable import SystemVariable
|
||||||
|
|
||||||
|
# Create variable pool
|
||||||
|
variable_pool = VariablePool(
|
||||||
|
system_variables=SystemVariable(user_id="test", files=[]),
|
||||||
|
user_inputs={},
|
||||||
|
environment_variables=[],
|
||||||
|
conversation_variables=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create node data with custom auth and empty api_key
|
||||||
|
node_data = HttpRequestNodeData(
|
||||||
|
title="http",
|
||||||
|
desc="",
|
||||||
|
url="http://example.com",
|
||||||
|
method="get",
|
||||||
|
authorization=HttpRequestNodeAuthorization(
|
||||||
|
type="api-key",
|
||||||
|
config={
|
||||||
|
"type": "custom",
|
||||||
|
"api_key": "", # Empty api_key
|
||||||
|
"header": "X-Custom-Auth",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
headers="",
|
||||||
|
params="",
|
||||||
|
body=None,
|
||||||
|
ssl_verify=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create executor
|
||||||
|
executor = Executor(
|
||||||
|
node_data=node_data, timeout=HttpRequestNodeTimeout(connect=10, read=30, write=10), variable_pool=variable_pool
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get assembled headers
|
||||||
|
headers = executor._assembling_headers()
|
||||||
|
|
||||||
|
# When api_key is empty, the custom header should NOT be set
|
||||||
|
assert "X-Custom-Auth" not in headers
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
|
def test_bearer_authorization_with_custom_header_ignored(setup_http_mock):
|
||||||
|
"""
|
||||||
|
Test that when switching from custom to bearer authorization,
|
||||||
|
the custom header settings don't interfere with bearer token.
|
||||||
|
This test verifies the fix for issue #23554.
|
||||||
|
"""
|
||||||
|
node = init_http_node(
|
||||||
|
config={
|
||||||
|
"id": "1",
|
||||||
|
"data": {
|
||||||
|
"title": "http",
|
||||||
|
"desc": "",
|
||||||
|
"method": "get",
|
||||||
|
"url": "http://example.com",
|
||||||
|
"authorization": {
|
||||||
|
"type": "api-key",
|
||||||
|
"config": {
|
||||||
|
"type": "bearer",
|
||||||
|
"api_key": "test-token",
|
||||||
|
"header": "", # Empty header - should default to Authorization
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"headers": "",
|
||||||
|
"params": "",
|
||||||
|
"body": None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result = node._run()
|
||||||
|
assert result.process_data is not None
|
||||||
|
data = result.process_data.get("request", "")
|
||||||
|
|
||||||
|
# In bearer mode, should use Authorization header (value is masked with *)
|
||||||
|
assert "Authorization: " in data
|
||||||
|
# Should contain masked Bearer token
|
||||||
|
assert "*" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
|
def test_basic_authorization_with_custom_header_ignored(setup_http_mock):
|
||||||
|
"""
|
||||||
|
Test that when switching from custom to basic authorization,
|
||||||
|
the custom header settings don't interfere with basic auth.
|
||||||
|
This test verifies the fix for issue #23554.
|
||||||
|
"""
|
||||||
|
node = init_http_node(
|
||||||
|
config={
|
||||||
|
"id": "1",
|
||||||
|
"data": {
|
||||||
|
"title": "http",
|
||||||
|
"desc": "",
|
||||||
|
"method": "get",
|
||||||
|
"url": "http://example.com",
|
||||||
|
"authorization": {
|
||||||
|
"type": "api-key",
|
||||||
|
"config": {
|
||||||
|
"type": "basic",
|
||||||
|
"api_key": "user:pass",
|
||||||
|
"header": "", # Empty header - should default to Authorization
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"headers": "",
|
||||||
|
"params": "",
|
||||||
|
"body": None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result = node._run()
|
||||||
|
assert result.process_data is not None
|
||||||
|
data = result.process_data.get("request", "")
|
||||||
|
|
||||||
|
# In basic mode, should use Authorization header (value is masked with *)
|
||||||
|
assert "Authorization: " in data
|
||||||
|
# Should contain masked Basic credentials
|
||||||
|
assert "*" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
|
def test_custom_authorization_with_empty_api_key(setup_http_mock):
|
||||||
|
"""
|
||||||
|
Test that custom authorization doesn't set header when api_key is empty.
|
||||||
|
This test verifies the fix for issue #23554.
|
||||||
|
"""
|
||||||
|
node = init_http_node(
|
||||||
|
config={
|
||||||
|
"id": "1",
|
||||||
|
"data": {
|
||||||
|
"title": "http",
|
||||||
|
"desc": "",
|
||||||
|
"method": "get",
|
||||||
|
"url": "http://example.com",
|
||||||
|
"authorization": {
|
||||||
|
"type": "api-key",
|
||||||
|
"config": {
|
||||||
|
"type": "custom",
|
||||||
|
"api_key": "", # Empty api_key
|
||||||
|
"header": "X-Custom-Auth",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"headers": "",
|
||||||
|
"params": "",
|
||||||
|
"body": None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result = node._run()
|
||||||
|
assert result.process_data is not None
|
||||||
|
data = result.process_data.get("request", "")
|
||||||
|
|
||||||
|
# Custom header should NOT be set when api_key is empty
|
||||||
|
assert "X-Custom-Auth:" not in data
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
@@ -239,6 +410,7 @@ def test_json(setup_http_mock):
|
|||||||
assert "X-Header: 123" in data
|
assert "X-Header: 123" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
def test_x_www_form_urlencoded(setup_http_mock):
|
def test_x_www_form_urlencoded(setup_http_mock):
|
||||||
node = init_http_node(
|
node = init_http_node(
|
||||||
config={
|
config={
|
||||||
@@ -285,6 +457,7 @@ def test_x_www_form_urlencoded(setup_http_mock):
|
|||||||
assert "X-Header: 123" in data
|
assert "X-Header: 123" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
def test_form_data(setup_http_mock):
|
def test_form_data(setup_http_mock):
|
||||||
node = init_http_node(
|
node = init_http_node(
|
||||||
config={
|
config={
|
||||||
@@ -334,6 +507,7 @@ def test_form_data(setup_http_mock):
|
|||||||
assert "X-Header: 123" in data
|
assert "X-Header: 123" in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
def test_none_data(setup_http_mock):
|
def test_none_data(setup_http_mock):
|
||||||
node = init_http_node(
|
node = init_http_node(
|
||||||
config={
|
config={
|
||||||
@@ -366,6 +540,7 @@ def test_none_data(setup_http_mock):
|
|||||||
assert "123123123" not in data
|
assert "123123123" not in data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
def test_mock_404(setup_http_mock):
|
def test_mock_404(setup_http_mock):
|
||||||
node = init_http_node(
|
node = init_http_node(
|
||||||
config={
|
config={
|
||||||
@@ -394,6 +569,7 @@ def test_mock_404(setup_http_mock):
|
|||||||
assert "Not Found" in resp.get("body", "")
|
assert "Not Found" in resp.get("body", "")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True)
|
||||||
def test_multi_colons_parse(setup_http_mock):
|
def test_multi_colons_parse(setup_http_mock):
|
||||||
node = init_http_node(
|
node = init_http_node(
|
||||||
config={
|
config={
|
||||||
|
Reference in New Issue
Block a user