fix: BACKEND_API_ENDPOINT resolution from env and cloudflared tunnel

This commit is contained in:
Sabiha Khan 2026-01-28 15:26:35 +05:30
parent e3a1e0bf07
commit 2ab43db53c
11 changed files with 669 additions and 72 deletions

View file

@ -11,7 +11,7 @@ from api.enums import OrganizationConfigurationKey, WorkflowRunState
from api.services.campaign.rate_limiter import rate_limiter
from api.services.telephony.base import TelephonyProvider
from api.services.telephony.factory import get_telephony_provider
from api.utils.tunnel import TunnelURLProvider
from api.utils.common import get_backend_endpoints
class CampaignCallDispatcher:
@ -233,10 +233,10 @@ class CampaignCallDispatcher:
# Initiate call via telephony provider
try:
# Construct webhook URL with parameters
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
backend_endpoint, _ = await get_backend_endpoints()
webhook_endpoint = provider.WEBHOOK_ENDPOINT
webhook_url = (
f"https://{backend_endpoint}/api/v1/telephony/{webhook_endpoint}"
f"{backend_endpoint}/api/v1/telephony/{webhook_endpoint}"
f"?workflow_id={campaign.workflow_id}"
f"&user_id={campaign.created_by}"
f"&workflow_run_id={workflow_run.id}"

View file

@ -15,7 +15,7 @@ from api.services.telephony.base import (
NormalizedInboundData,
TelephonyProvider,
)
from api.utils.tunnel import TunnelURLProvider
from api.utils.common import get_backend_endpoints
if TYPE_CHECKING:
from fastapi import WebSocket
@ -91,13 +91,13 @@ class CloudonixProvider(TelephonyProvider):
# Prepare call data using Cloudonix callObject schema
# Note: 'caller-id' is REQUIRED by Cloudonix API
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
backend_endpoint, wss_backend_endpoint = await get_backend_endpoints()
data: Dict[str, Any] = {
"destination": to_number,
"cxml": f"""<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Connect>
<Stream url="wss://{backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}"></Stream>
<Stream url="{wss_backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}"></Stream>
</Connect>
<Pause length="40"/>
</Response>""",
@ -106,7 +106,7 @@ class CloudonixProvider(TelephonyProvider):
# Add status callback if workflow_run_id provided
if workflow_run_id:
callback_url = f"https://{backend_endpoint}/api/v1/telephony/cloudonix/status-callback/{workflow_run_id}"
callback_url = f"{backend_endpoint}/api/v1/telephony/cloudonix/status-callback/{workflow_run_id}"
data["callback"] = callback_url
# Merge any additional kwargs

View file

@ -16,7 +16,7 @@ from api.services.telephony.base import (
NormalizedInboundData,
TelephonyProvider,
)
from api.utils.tunnel import TunnelURLProvider
from api.utils.common import get_backend_endpoints
if TYPE_CHECKING:
from fastapi import WebSocket
@ -75,8 +75,8 @@ class TwilioProvider(TelephonyProvider):
# Add status callback if workflow_run_id provided
if workflow_run_id:
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
callback_url = f"https://{backend_endpoint}/api/v1/telephony/twilio/status-callback/{workflow_run_id}"
backend_endpoint, _ = await get_backend_endpoints()
callback_url = f"{backend_endpoint}/api/v1/telephony/twilio/status-callback/{workflow_run_id}"
data.update(
{
"StatusCallback": callback_url,
@ -158,12 +158,12 @@ class TwilioProvider(TelephonyProvider):
"""
Generate TwiML response for starting a call session.
"""
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
_, wss_backend_endpoint = await get_backend_endpoints()
twiml_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Connect>
<Stream url="wss://{backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}"></Stream>
<Stream url="{wss_backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}"></Stream>
</Connect>
<Pause length="40"/>
</Response>"""
@ -405,8 +405,8 @@ class TwilioProvider(TelephonyProvider):
# Generate StatusCallback URL using same pattern as outbound calls
status_callback_attr = ""
if workflow_run_id:
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
status_callback_url = f"https://{backend_endpoint}/api/v1/telephony/twilio/status-callback/{workflow_run_id}"
backend_endpoint, _ = await get_backend_endpoints()
status_callback_url = f"{backend_endpoint}/api/v1/telephony/twilio/status-callback/{workflow_run_id}"
status_callback_attr = f' statusCallback="{status_callback_url}"'
twiml_content = f"""<?xml version="1.0" encoding="UTF-8"?>

View file

@ -15,7 +15,7 @@ from api.services.telephony.base import (
NormalizedInboundData,
TelephonyProvider,
)
from api.utils.tunnel import TunnelURLProvider
from api.utils.common import get_backend_endpoints
if TYPE_CHECKING:
from fastapi import WebSocket
@ -89,9 +89,9 @@ class VobizProvider(TelephonyProvider):
# Add hangup callback if workflow_run_id provided
if workflow_run_id:
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
hangup_url = f"https://{backend_endpoint}/api/v1/telephony/vobiz/hangup-callback/{workflow_run_id}"
ring_url = f"https://{backend_endpoint}/api/v1/telephony/vobiz/ring-callback/{workflow_run_id}"
backend_endpoint, _ = await get_backend_endpoints()
hangup_url = f"{backend_endpoint}/api/v1/telephony/vobiz/hangup-callback/{workflow_run_id}"
ring_url = f"{backend_endpoint}/api/v1/telephony/vobiz/ring-callback/{workflow_run_id}"
data.update(
{
"hangup_url": hangup_url,
@ -254,11 +254,11 @@ class VobizProvider(TelephonyProvider):
- audioTrack: Which audio to stream (inbound, outbound, both)
- contentType: audio/x-mulaw;rate=8000
"""
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
_, wss_backend_endpoint = await get_backend_endpoints()
vobiz_xml = f"""<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Stream bidirectional="true" keepCallAlive="true" contentType="audio/x-mulaw;rate=8000">wss://{backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}</Stream>
<Stream bidirectional="true" keepCallAlive="true" contentType="audio/x-mulaw;rate=8000">{wss_backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}</Stream>
</Response>"""
return vobiz_xml

View file

@ -18,7 +18,7 @@ from api.services.telephony.base import (
NormalizedInboundData,
TelephonyProvider,
)
from api.utils.tunnel import TunnelURLProvider
from api.utils.common import get_backend_endpoints
if TYPE_CHECKING:
from fastapi import WebSocket
@ -106,8 +106,10 @@ class VonageProvider(TelephonyProvider):
# Add event webhook if workflow_run_id provided
if workflow_run_id:
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
event_url = f"https://{backend_endpoint}/api/v1/telephony/vonage/events/{workflow_run_id}"
backend_endpoint, _ = await get_backend_endpoints()
event_url = (
f"{backend_endpoint}/api/v1/telephony/vonage/events/{workflow_run_id}"
)
data.update({"event_url": [event_url], "event_method": "POST"})
data.update(kwargs)
@ -201,7 +203,7 @@ class VonageProvider(TelephonyProvider):
Generate NCCO response for starting a call session.
NCCO (Nexmo Call Control Objects) is JSON-based, unlike TwiML which is XML.
"""
backend_endpoint = await TunnelURLProvider.get_tunnel_url()
_, wss_backend_endpoint = await get_backend_endpoints()
# NCCO for WebSocket connection
ncco = [
@ -210,7 +212,7 @@ class VonageProvider(TelephonyProvider):
"endpoint": [
{
"type": "websocket",
"uri": f"wss://{backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}",
"uri": f"{wss_backend_endpoint}/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}",
"content-type": "audio/l16;rate=16000", # 16kHz Linear PCM
"headers": {},
}