Skip to content

fix[bug]: handle non-JSON responses and query params in REST tools (#3855, #3857) #3873

Merged
brian-hussey merged 6 commits intomainfrom
issue_3855_rest_tool
Apr 14, 2026
Merged

fix[bug]: handle non-JSON responses and query params in REST tools (#3855, #3857) #3873
brian-hussey merged 6 commits intomainfrom
issue_3855_rest_tool

Conversation

@rakdutta
Copy link
Copy Markdown
Collaborator

@rakdutta rakdutta commented Mar 26, 2026

Closes #3855 and #3857

This PR enhances REST tool robustness by improving error handling, query parameter processing, and input validation. It also streamlines the admin UI tool testing workflow.

Backend Improvements

Non-JSON Response Handling (#3855)

  • New _handle_json_parse_error() helper function for graceful fallback when JSON parsing fails
  • Handles multiple exception types: json.JSONDecodeError, orjson.JSONDecodeError, UnicodeDecodeError, AttributeError
  • Supports REST APIs returning HTML error pages, plain text, XML, or responses with encoding issues
  • Returns raw text as {"response_text": } instead of crashing

Response Truncation (Security Enhancement)

  • New configurable setting: REST_RESPONSE_TEXT_MAX_LENGTH (default: 5000 chars, range: 1000-100000)
  • Truncates non-JSON response text to prevent exposing excessive sensitive data in error responses
  • Applies to both success and error responses
  • Logs warning when truncation occurs with original and truncated lengths

Query Parameter Handling (#3857)

  • GET requests: URL query params merged with input arguments (URL params take precedence on conflicts)
  • POST/PUT/PATCH/DELETE: Query params preserved in URL to support signed URLs (Azure SAS, AWS presigned URLs, webhook signatures)
  • Added conflict warning when URL query params override input arguments for better debugging

jq Filter Validation

  • Added validation to detect simple email addresses mistakenly used as jq filters (e.g., user@example.com)
  • Uses regex pattern ^[^.\[\]|]+@[^.\[\]|]+.[^.\[\]|]+$ to catch basic email patterns without false positives
  • Logs warning and treats invalid filters as empty (returns unfiltered data)

Frontend Enhancements

Admin UI Tool Testing Workflow

  • New invokeTool(toolName) function called by "Invoke" buttons in Tools table
  • Fetches tool details via API (fetchToolDetails) and populates modal dynamically
  • Dynamic form generation from tool input schema (createFormInput, generateToolFormFields)
  • Refactored runToolTest() and runToolValidation() to use consistent tools/call method structure:
    {
    method: "tools/call",
    params: { name: toolName, arguments: {...} }
    }
  • Enhanced error logging for better debugging

Test Coverage

Comprehensive test suite added:

  • TestJqFilterEmailValidation: Email address detection and valid filter preservation
  • TestRestToolQueryParamHandling: GET/POST/PUT/PATCH/DELETE param handling, conflict warnings
  • TestRestToolNonJsonResponses: HTML, plain text, XML, encoding errors, empty responses
  • Truncation tests: large responses, small responses, custom config values

@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch from 18c39b4 to ffaf721 Compare March 27, 2026 04:12
@rakdutta rakdutta changed the title Issue 3855 rest tool fix[bug]: handle non-JSON responses and query params in REST tools (#3855, #3857) Mar 27, 2026
@rakdutta rakdutta marked this pull request as ready for review March 27, 2026 05:23
@rakdutta rakdutta marked this pull request as draft March 27, 2026 08:25
@crivetimihai crivetimihai added bug Something isn't working SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release labels Mar 29, 2026
@crivetimihai crivetimihai added this to the Release 1.1.0 milestone Mar 29, 2026
@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch from 9118d23 to 3cc84d2 Compare March 30, 2026 05:07
@rakdutta rakdutta marked this pull request as ready for review March 30, 2026 05:11
@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch 2 times, most recently from c1b46f9 to 42a7212 Compare March 31, 2026 06:33
TS0713
TS0713 previously approved these changes Apr 2, 2026
Copy link
Copy Markdown
Collaborator

@TS0713 TS0713 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fixes the Admin UI issue where Test/Invoke buttons were not working — the missing invokeTool() and runToolTest() functions are now properly added, and the request format is corrected to tools/call. I verified this flow manually and it’s working end-to-end now.

  • Fixes the REST POST query parameter issue — query params are now correctly preserved in the URL for POST/PUT requests. I tested this as well, and signed URL / query-based APIs are working as expected.

  • Handles non-JSON responses (HTML, text, etc.) — prevents crashes and makes the system more robust.

  • Manually tested on gateway admin UI by adding REST tools - 1 with query params and other returns HTML result as part of final response - Both working as expected

Overall, these are useful fixes across both UI and backend, and everything looks clean and well-tested.

I approve this PR.

@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch 2 times, most recently from 92aa952 to b35348c Compare April 2, 2026 09:30
@rakdutta rakdutta marked this pull request as draft April 2, 2026 10:59
@rakdutta rakdutta marked this pull request as ready for review April 2, 2026 12:33
@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch from afaf664 to 8490829 Compare April 2, 2026 12:55
@crivetimihai crivetimihai force-pushed the issue_3855_rest_tool branch from 8490829 to 416641a Compare April 5, 2026 23:58
crivetimihai
crivetimihai previously approved these changes Apr 5, 2026
Copy link
Copy Markdown
Member

@crivetimihai crivetimihai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work on this one — the core idea of handling non-JSON REST responses and fixing query param handling for signed URLs is solid and well-motivated.

What I changed during rebase

The branch had significant merge conflicts since admin.js was split into ES modules (#3137) after this PR was opened. I rebased onto current main, squashed the 22 commits into one clean commit, and made the following adjustments:

JS changes ported to modular structure

  • All JS changes now target mcpgateway/admin_ui/tools.js and admin_ui/admin.js instead of the old monolithic admin.js
  • Used fetchWithTimeout (already imported) instead of raw fetch + getCookie for consistency with the existing testTool() function
  • Replaced innerHTML assignments with safe DOM methods (removeChild, createElement, textContent) to avoid XSS vectors

Fixed unreachable 4xx/5xx error handling (critical)

The original code placed the non-JSON error response handling after response.raise_for_status(), which throws httpx.HTTPStatusError for 4xx/5xx — making the error branch unreachable for the exact cases #3855 describes.

Fixed by catching HTTPStatusError and handling the error response in the except block:

  • Parses body with the same JSON/non-JSON fallback
  • Includes HTTP status code in the error message ("HTTP 500: <truncated html>")
  • Sets structured_content={"status_code": N} so the retry plugin can distinguish retriable (503) from non-retriable (404) errors — matching the existing pattern at line 5040

The original elif status not in [200, 201, 202, 206] branch is retained for non-standard 2xx codes (203, 205, 207).

Test fix

Updated the HTML error response test to actually raise httpx.HTTPStatusError from raise_for_status() instead of mocking it to no-op — the original test passed but didn't exercise the real production code path.

Verification

  • 290/290 tests in test_tool_service.py pass (18 new)
  • 323/323 tests in test_tool_service_coverage.py pass
  • Linters clean (black, isort, eslint)

Comment thread mcpgateway/admin_ui/tools.js Outdated
Comment thread tests/unit/js/tools.test.js
@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch from 16579f0 to d4a4a95 Compare April 9, 2026 09:31
@gcgoncalves gcgoncalves force-pushed the issue_3855_rest_tool branch 3 times, most recently from 522cf59 to b3b72b9 Compare April 13, 2026 12:21
@rakdutta rakdutta force-pushed the issue_3855_rest_tool branch from b3b72b9 to c529146 Compare April 14, 2026 12:06
rakdutta and others added 6 commits April 14, 2026 14:55
…3857)

Backend:
- Add _handle_json_parse_error() for graceful fallback when REST APIs return
  HTML, plain text, XML, or responses with encoding issues
- Catch json.JSONDecodeError, orjson.JSONDecodeError, UnicodeDecodeError, and
  AttributeError during response parsing (httpx uses stdlib json, not orjson)
- Add configurable REST_RESPONSE_TEXT_MAX_LENGTH (default: 5000, range: 1000-100000)
  to truncate non-JSON response text and limit sensitive data exposure
- Fix query param handling: GET requests merge URL params with input args
  (URL params take precedence on conflicts); POST/PUT/PATCH/DELETE preserve
  query params in URL for signed URL support (Azure SAS, AWS presigned, etc.)
- Add jq filter validation to detect email addresses mistakenly used as filters

Frontend (admin_ui):
- Fix runToolTest/runToolValidation to use tools/call JSON-RPC method
  instead of tool name as method (MCP protocol compliance)
- Add invokeTool() function for "Invoke" button in Tools table
- Port all JS changes to modular admin_ui/ structure (Vite bundled)

Closes #3855
Closes #3857

Signed-off-by: Rakhi Dutta <rakhibiswas@yahoo.com>
Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Signed-off-by: Rakhi Dutta <rakhibiswas@yahoo.com>
Signed-off-by: Gabriel Costa <gabrielcg@proton.me>
…port

Signed-off-by: Rakhi Dutta <rakhibiswas@yahoo.com>
Signed-off-by: Rakhi Dutta <rakhibiswas@yahoo.com>
Signed-off-by: Brian Hussey <brian.hussey@ie.ibm.com>
@brian-hussey brian-hussey force-pushed the issue_3855_rest_tool branch from 7c4bb47 to a27ee1b Compare April 14, 2026 14:08
Copy link
Copy Markdown
Collaborator

@gcgoncalves gcgoncalves left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified, working fine. 👍

@brian-hussey brian-hussey merged commit 2b6a68a into main Apr 14, 2026
26 checks passed
@brian-hussey brian-hussey deleted the issue_3855_rest_tool branch April 14, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][UI]: Admin UI Tool "Invoke" button non-functional — invokeTool() undefined

6 participants