Skip to content

Commit cc273c2

Browse files
committed
add form-urlencoded support for OAuth2 gateway testing
Signed-off-by: Shoumi <shoumimukherjee@gmail.com>
1 parent bc5b9d4 commit cc273c2

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

mcpgateway/admin.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8292,8 +8292,31 @@ async def admin_test_gateway(request: GatewayTestRequest, team_id: Optional[str]
82928292
else:
82938293
headers: dict = decode_auth(gateway.auth_value if gateway else None)
82948294

8295+
# Prepare request based on content type
8296+
content_type = getattr(request, 'content_type', 'application/json')
8297+
request_kwargs = {
8298+
"method": request.method.upper(),
8299+
"url": full_url,
8300+
"headers": headers
8301+
}
8302+
8303+
if request.body is not None:
8304+
if content_type == "application/x-www-form-urlencoded":
8305+
# Set proper content type header and use data parameter for form encoding
8306+
headers["Content-Type"] = "application/x-www-form-urlencoded"
8307+
if isinstance(request.body, str):
8308+
# Body is already form-encoded
8309+
request_kwargs["data"] = request.body
8310+
else:
8311+
# Body is a dict, convert to form data
8312+
request_kwargs["data"] = request.body
8313+
else:
8314+
# Default to JSON
8315+
headers["Content-Type"] = "application/json"
8316+
request_kwargs["json"] = request.body
8317+
82958318
async with ResilientHttpClient(client_args={"timeout": settings.federation_timeout, "verify": not settings.skip_ssl_verify}) as client:
8296-
response: httpx.Response = await client.request(method=request.method.upper(), url=full_url, headers=headers, json=request.body)
8319+
response: httpx.Response = await client.request(**request_kwargs)
82978320
latency_ms = int((time.monotonic() - start_time) * 1000)
82988321
try:
82998322
response_body: Union[Dict[str, Any], str] = response.json()

mcpgateway/schemas.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3732,14 +3732,15 @@ def populate_associated_ids(cls, values):
37323732
class GatewayTestRequest(BaseModelWithConfigDict):
37333733
"""Schema for testing gateway connectivity.
37343734
3735-
Includes the HTTP method, base URL, path, optional headers, and body.
3735+
Includes the HTTP method, base URL, path, optional headers, body, and content type.
37363736
"""
37373737

37383738
method: str = Field(..., description="HTTP method to test (GET, POST, etc.)")
37393739
base_url: AnyHttpUrl = Field(..., description="Base URL of the gateway to test")
37403740
path: str = Field(..., description="Path to append to the base URL")
37413741
headers: Optional[Dict[str, str]] = Field(None, description="Optional headers for the request")
37423742
body: Optional[Union[str, Dict[str, Any]]] = Field(None, description="Optional body for the request, can be a string or JSON object")
3743+
content_type: Optional[str] = Field("application/json", description="Content type for the request body")
37433744

37443745

37453746
class GatewayTestResponse(BaseModelWithConfigDict):

mcpgateway/static/admin.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7983,6 +7983,7 @@ async function handleGatewayTestSubmit(e) {
79837983
const baseUrl = formData.get("url");
79847984
const method = formData.get("method");
79857985
const path = formData.get("path");
7986+
const contentType = formData.get("content_type") || "application/json";
79867987

79877988
// Validate URL
79887989
const urlValidation = validateUrl(baseUrl);
@@ -8022,12 +8023,24 @@ async function handleGatewayTestSubmit(e) {
80228023
throw new Error(bodyValidation.error);
80238024
}
80248025

8026+
// Process body based on content type
8027+
let processedBody = bodyValidation.value;
8028+
if (contentType === "application/x-www-form-urlencoded" && bodyValidation.value && typeof bodyValidation.value === 'object') {
8029+
// Convert JSON object to URL-encoded string
8030+
const params = new URLSearchParams();
8031+
Object.entries(bodyValidation.value).forEach(([key, value]) => {
8032+
params.append(key, String(value));
8033+
});
8034+
processedBody = params.toString();
8035+
}
8036+
80258037
const payload = {
80268038
base_url: urlValidation.value,
80278039
method,
80288040
path,
80298041
headers: headersValidation.value,
8030-
body: bodyValidation.value,
8042+
body: processedBody,
8043+
content_type: contentType,
80318044
};
80328045

80338046
// Make the request with timeout
@@ -17387,3 +17400,15 @@ style.textContent = `
1738717400
}
1738817401
`;
1738917402
document.head.appendChild(style);
17403+
17404+
// Function to update body label based on content type selection
17405+
function updateBodyLabel() {
17406+
const bodyLabel = document.getElementById('gateway-test-body-label');
17407+
const contentType = document.getElementById('gateway-test-content-type')?.value;
17408+
17409+
if (bodyLabel) {
17410+
bodyLabel.innerHTML = contentType === 'application/x-www-form-urlencoded'
17411+
? 'Body (JSON)<br><small class="text-gray-500">Auto-converts to form data</small>'
17412+
: 'Body (JSON)';
17413+
}
17414+
}

mcpgateway/templates/admin.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7781,6 +7781,7 @@ <h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-gray-100">
77817781
<form
77827782
id="gateway-test-form"
77837783
class="space-y-4 text-gray-800 dark:text-gray-100"
7784+
novalidate
77847785
>
77857786
<div>
77867787
<label
@@ -7842,14 +7843,33 @@ <h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-gray-100">
78427843
></textarea>
78437844
</div>
78447845

7846+
<div>
7847+
<label
7848+
for="gateway-test-content-type"
7849+
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
7850+
>Content-Type</label
7851+
>
7852+
<select
7853+
id="gateway-test-content-type"
7854+
name="content_type"
7855+
class="mt-1 block w-full rounded-md shadow-sm p-1 bg-gray-200 dark:bg-gray-800"
7856+
onchange="updateBodyLabel()"
7857+
>
7858+
<option value="application/json">application/json</option>
7859+
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
7860+
</select>
7861+
</div>
7862+
78457863
<div>
78467864
<label
78477865
for="gateway-test-body"
78487866
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
7867+
id="gateway-test-body-label"
78497868
>Body (JSON)</label
78507869
>
78517870
<textarea
78527871
id="gateway-test-body"
7872+
name="body"
78537873
class="mt-1 block w-full rounded-md shadow-sm p-1 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-300 placeholder-gray-600 dark:placeholder-gray-400"
78547874
placeholder="Enter request body as JSON"
78557875
></textarea>

0 commit comments

Comments
 (0)