mirror of https://github.com/langgenius/dify.git
chore: enhance the hint when the user triggers an invalid webhook request (#28671)
This commit is contained in:
parent
490b7ac43c
commit
1241cab113
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import time
|
||||
|
||||
from flask import jsonify
|
||||
from flask import jsonify, request
|
||||
from werkzeug.exceptions import NotFound, RequestEntityTooLarge
|
||||
|
||||
from controllers.trigger import bp
|
||||
|
|
@ -28,8 +28,14 @@ def _prepare_webhook_execution(webhook_id: str, is_debug: bool = False):
|
|||
webhook_data = WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
|
||||
return webhook_trigger, workflow, node_config, webhook_data, None
|
||||
except ValueError as e:
|
||||
# Fall back to raw extraction for error reporting
|
||||
webhook_data = WebhookService.extract_webhook_data(webhook_trigger)
|
||||
# Provide minimal context for error reporting without risking another parse failure
|
||||
webhook_data = {
|
||||
"method": request.method,
|
||||
"headers": dict(request.headers),
|
||||
"query_params": dict(request.args),
|
||||
"body": {},
|
||||
"files": {},
|
||||
}
|
||||
return webhook_trigger, workflow, node_config, webhook_data, str(e)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import secrets
|
|||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
import orjson
|
||||
from flask import request
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import select
|
||||
|
|
@ -169,7 +170,7 @@ class WebhookService:
|
|||
- method: HTTP method
|
||||
- headers: Request headers
|
||||
- query_params: Query parameters as strings
|
||||
- body: Request body (varies by content type)
|
||||
- body: Request body (varies by content type; JSON parsing errors raise ValueError)
|
||||
- files: Uploaded files (if any)
|
||||
"""
|
||||
cls._validate_content_length()
|
||||
|
|
@ -255,14 +256,21 @@ class WebhookService:
|
|||
|
||||
Returns:
|
||||
tuple: (body_data, files_data) where:
|
||||
- body_data: Parsed JSON content or empty dict if parsing fails
|
||||
- body_data: Parsed JSON content
|
||||
- files_data: Empty dict (JSON requests don't contain files)
|
||||
|
||||
Raises:
|
||||
ValueError: If JSON parsing fails
|
||||
"""
|
||||
raw_body = request.get_data(cache=True)
|
||||
if not raw_body or raw_body.strip() == b"":
|
||||
return {}, {}
|
||||
|
||||
try:
|
||||
body = request.get_json() or {}
|
||||
except Exception:
|
||||
logger.warning("Failed to parse JSON body")
|
||||
body = {}
|
||||
body = orjson.loads(raw_body)
|
||||
except orjson.JSONDecodeError as exc:
|
||||
logger.warning("Failed to parse JSON body: %s", exc)
|
||||
raise ValueError(f"Invalid JSON body: {exc}") from exc
|
||||
return body, {}
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -118,10 +118,8 @@ class TestWebhookServiceUnit:
|
|||
"/webhook", method="POST", headers={"Content-Type": "application/json"}, data="invalid json"
|
||||
):
|
||||
webhook_trigger = MagicMock()
|
||||
webhook_data = WebhookService.extract_webhook_data(webhook_trigger)
|
||||
|
||||
assert webhook_data["method"] == "POST"
|
||||
assert webhook_data["body"] == {} # Should default to empty dict
|
||||
with pytest.raises(ValueError, match="Invalid JSON body"):
|
||||
WebhookService.extract_webhook_data(webhook_trigger)
|
||||
|
||||
def test_generate_webhook_response_default(self):
|
||||
"""Test webhook response generation with default values."""
|
||||
|
|
@ -435,6 +433,27 @@ class TestWebhookServiceUnit:
|
|||
assert result["body"]["message"] == "hello" # Already string
|
||||
assert result["body"]["age"] == 25 # Already number
|
||||
|
||||
def test_extract_and_validate_webhook_data_invalid_json_error(self):
|
||||
"""Invalid JSON should bubble up as a ValueError with details."""
|
||||
app = Flask(__name__)
|
||||
|
||||
with app.test_request_context(
|
||||
"/webhook",
|
||||
method="POST",
|
||||
headers={"Content-Type": "application/json"},
|
||||
data='{"invalid": }',
|
||||
):
|
||||
webhook_trigger = MagicMock()
|
||||
node_config = {
|
||||
"data": {
|
||||
"method": "post",
|
||||
"content_type": "application/json",
|
||||
}
|
||||
}
|
||||
|
||||
with pytest.raises(ValueError, match="Invalid JSON body"):
|
||||
WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
|
||||
|
||||
def test_extract_and_validate_webhook_data_validation_error(self):
|
||||
"""Test unified data extraction with validation error."""
|
||||
app = Flask(__name__)
|
||||
|
|
|
|||
Loading…
Reference in New Issue