FreeSWITCH 简单图形化界面40 - 使用mod_curl模块进行http请求

FreeSWITCH 简单图形化界面40 - 使用mod_curl模块进行http请求

  • 0、界面预览
  • 00、简介
  • 1、编译安装
    • 1.1 编辑模块配置文件
  • 2、使用
    • 2.1 拨号规则
      • GET 请求
      • POST 请求
      • JSON 数据
    • 2.2 Lua 脚本
      • GET 请求
      • POST 请求
      • JSON 数据
  • 3 、示例
    • 3.1 示例 1:提交 CDR 到第三方接口
    • 3.2 示例 2:提交外呼状态到第三方接口


0、界面预览

http://myfs.f3322.net:8020/
用户名:admin,密码:admin

FreeSWITCH界面安装参考:https://blog.csdn.net/jia198810/article/details/137820796

00、简介

mod_curl是 FreeSWITCH 的一个强大模块,它允许用户通过 HTTP 请求与外部服务进行交互,从而实现数据的获取和提交。无论是简单的 GET 请求,还是复杂的 POST 请求和文件传输,mod_curl都能轻松应对。

1、编译安装

在使用mod_curl之前,需要确保该模块已正确编译并加载到 FreeSWITCH 中。以下是详细的编译和安装步骤:

1.1 编辑模块配置文件

  1. 打开 FreeSWITCH 源代码目录下的modules.conf文件,找到以下行并取消注释:
   #applications/mod_curl

保存文件并退出。

  1. 重新编译 FreeSWITCH

在终端中执行以下命令,重新编译 FreeSWITCH:

   makemake install
  1. 加载模块

编辑 FreeSWITCH 的模块加载配置文件modules.conf.xml(路劲为/usr/local/freeswitch/conf/autoload_configs),添加以下内容:

   <load module="mod_curl"/>

保存文件后,重新加载 FreeSWITCH 以使模块生效。

  1. 验证模块加载

启动 FreeSWITCH 并进入 CLI,执行以下命令以验证mod_curl是否已正确加载:

   module_exists mod_curl

如果返回true,则表示模块加载成功。

2、使用

2.1 拨号规则

mod_curl提供了两种主要的应用方式:curlcurl_sendfile(不常用)。
在拨号规则中,可以通过以下方式调用curl应用:

<action application="curl" data="http://example.com/api?param=value"/>

curl应用的请求,会生成两个通道变量 curl_response_data 和curl_response_code,可以使用${}获取。

GET 请求

通过 URL 参数发送 GET 请求:

  <action application="curl" data="http://example.com/api?param=value"/>

POST 请求

发送 POST 请求并携带数据:

  <action application="curl" data="http://example.com/api post param=value"/>

JSON 数据

发送 JSON 格式的数据:

  <action application="curl" data="http://example.com/api content-type application/json post {\"key\":\"value\"}"/>

2.2 Lua 脚本

mod_curl也可以在 Lua 脚本中使用,通过 FreeSWITCH 的 API 接口调用 HTTP 请求。

GET 请求

在 Lua 脚本中发起 GET 请求的示例如下:

local api = freeswitch.API()local url = "http://example.com/api?param=value"
local response = api:execute("curl", url)freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")

POST 请求

发送 POST 请求的示例如下:

local api = freeswitch.API()local url = "http://example.com/api"
local data = "param=value"
local response = api:execute("curl", url .. " post " .. data)freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")

JSON 数据

发送 JSON 格式数据的示例如下:

local api = freeswitch.API()local url = "http://example.com/api"
local json_data = "{ \"key\": \"value\" }"
local response = api:execute("curl", url .. " content-type application/json post " .. json_data)freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")

3 、示例

3.1 示例 1:提交 CDR 到第三方接口

在呼叫结束后,将通话详情记录(CDR)提交到第三方接口。以下是 Lua 脚本的实现示例:

#!/usr/bin/env lua
-- upload_cdr.lua
-- 2024年6月29日
-- 提交话单信息到第三方接口
-- 拨号规则,提前设置挂机回调
-- session:execute("set", string.format("api_hangup_hook=lua upload_cdr.lua")-- 序列化并打印env对象的所有通话信息,调试专用
-- local call_info = env:serialize()
-- freeswitch.consoleLog("INFO", "所有通话信息:\n" .. call_info)
local mobile = env:getHeader("destination_number") or ""
local caller_ani = env:getHeader("Caller-ANI") or ""
local sip_account = env:getHeader("sip_from_user") or ""
local start_time = env:getHeader("start_stamp") or ""
-- local start_time = env:getHeader("answer_stamp") or ""
local end_time = env:getHeader("end_stamp") or ""
local use_time_length = env:getHeader("billsec") or "0"
local order_no = string.format("freeSWITCH%s%s", sip_account, mobile)
local mobile_hangup_api = env:getHeader("mobile_hangup_api") or ""
local api_timeout = env:getHeader("api_timeout") or "3"-- 打印详细信息,确保变量不为空
if sip_account == mobile thenfreeswitch.consoleLog("INFO", "异常呼叫主叫=被叫,再次获取SIP账号为 : " .. caller_ani .. "\n")sip_account = caller_ani
end
freeswitch.consoleLog("INFO", "CallerANI    : " .. caller_ani .. "\n")
freeswitch.consoleLog("INFO", "SIP账号      : " .. sip_account .. "\n")
freeswitch.consoleLog("INFO", "被叫号码     : " .. mobile .. "\n")
freeswitch.consoleLog("INFO", "开始时间     : " .. start_time .. "\n")
freeswitch.consoleLog("INFO", "结束时间     : " .. end_time .. "\n")
freeswitch.consoleLog("INFO", "通话时长     : " .. use_time_length .. "\n")
freeswitch.consoleLog("INFO", "订单号       : " .. order_no .. "\n")
freeswitch.consoleLog("INFO", "CDR推送接口  : " .. mobile_hangup_api .. "\n")
freeswitch.consoleLog("INFO", "接口超时时间  : " .. api_timeout .. "\n")-- 准备执行命令
local api = freeswitch.API();--[[
-- 使用python提交
local cmd = string.format("/usr/local/python310/bin/python /usr/local/freeswitch/scripts/upload_cdr.py '%s' '%s' '%s' '%s' '%s' '%s' '%s'",mobile, sip_account, start_time, end_time, use_time_length, order_no, mobile_hangup_api)
local response = api:execute("bg_system", cmd)
]]-- 使用curl提交
local cmd = string.format("%s connect-timeout %s timeout %s post mobile=%s&sip_account=%s&start_time='%s'&end_time='%s'&use_time_length=%s&order_no=%s",mobile_hangup_api, api_timeout, api_timeout, mobile, sip_account, start_time, end_time, use_time_length, order_no)
freeswitch.consoleLog("INFO", "推送命令: " .. cmd .. "\n")
local response = api:execute("curl", cmd)
if (response == "") thenfreeswitch.consoleLog("INFO", "推送结果: 无响应,可能连接接口失败!")
elsefreeswitch.consoleLog("INFO", "推送结果: " .. response .. "\n")
end

3.2 示例 2:提交外呼状态到第三方接口

在外呼结束后,将外呼状态提交到第三方接口。以下是 Lua 脚本的实现示例:

#!/usr/bin/env lua
-- handle-callout-result.lua
-- 2025年2月26日
-- 处理外呼结果 
-- 外呼api设置挂机回调。originate {origination_caller_id_number=300,orgination_caller_id_name=outcall,api_hangup_hook='lua handle-callout-result.lua'}sofia/gateway/gw01/172xxxx2122 401 xml Local-Extensions -- local env
-- local freeswitchlocal call_info = env:serialize()
-- -- 序列化并打印env对象的所有通话信息,调试专用
-- freeswitch.consoleLog("INFO", "所有通话信息:\n" .. call_info)-- 开始时间
local start_time = env:getHeader("start_stamp") or ""-- 结束时间
local end_time = env:getHeader("end_stamp") or ""-- 通话时间
local duration = env:getHeader("billsec") or "0"-- SIP中继名称
local trunk_name = env:getHeader("trunk_name") or ""-- 被叫号码
local destination_number = env:getHeader("destination_number") or ""-- 本地号码
local local_number = env:getHeader("rdnis") or ""-- 备用被叫号码
local sip_to_user = env:getHeader("sip_to_user") or ""-- 呼出主叫号码
local outgoing_caller_id_number = env:getHeader("origination_caller_id_number") or ""-- answer api
local answer_api = env:getHeader("answer_api") or ""-- no_answer api
local no_answer_api = env:getHeader("no_answer_api") or ""-- api 超时时间
local api_timeout = 3-- 通话结果
local hangup_cause = env:getHeader("hangup_cause") or ""-- 是否检查主叫号码被占用
local check_number_in_use = env:getHeader("check_number_in_use") or "false"local response
local result
local temp_string-- 打印详细信息,确保变量不为空
if destination_number == "" thenfreeswitch.consoleLog("INFO", string.format("# destination_number未空,使用sip_to_user的值%s\n",sip_to_user))destination_number = sip_to_user
end
freeswitch.consoleLog("INFO", "# ==============API接口外呼挂机处理============= \n")freeswitch.consoleLog("INFO", "# ------------------外呼呼叫信息---------------- \n")
freeswitch.consoleLog("INFO", "# 开始时间  : " .. start_time .. "\n")
freeswitch.consoleLog("INFO", "# 结束时间  : " .. end_time .. "\n")
freeswitch.consoleLog("INFO", "# 通话时长  : " .. duration .. "\n")
freeswitch.consoleLog("INFO", "# 外呼号码  : " .. destination_number .. "\n")
freeswitch.consoleLog("INFO", "# 本地号码  : " .. local_number .. "\n")
freeswitch.consoleLog("INFO", "# 呼出主叫  : " .. outgoing_caller_id_number .. "\n")
freeswitch.consoleLog("INFO", "# 挂机接口  : " .. no_answer_api .. "\n")
freeswitch.consoleLog("INFO", "# ---------------------------------------------\n\n")-- 执行fs api命令
local api = freeswitch.API();-- 应答提交api,在401 xml Local-Extensions中。
-- if (hangup_cause == "ANSWER" or hangup_cause == "NORMAL_CLEARING") then
--     -- 呼叫应答提交
--     freeswitch.consoleLog("INFO", "# 呼叫结果  : 呼叫已经应答,推送应答接口\n")
--     if (answer_api == "") then
--         freeswitch.consoleLog("INFO", "# 推送结果  : 应答接口为空,不提交!\n")
--         return
--     else
--         -- 提交无应答结果
--         temp_string = string.format(
--             "%s connect-timeout %s timeout %s post destination_number=%s",
--             no_answer_api, api_timeout, api_timeout, destination_number)
--         freeswitch.consoleLog("INFO", string.format("# 推送结果  : 请求地址:%s\n",temp_string))--         -- 执行推送
--         response = api:execute("curl",temp_string)
--         if (response == "") then
--             freeswitch.consoleLog("INFO", "# 推送结果  : 接口无响应,可能连接接口失败!\n")
--         else
--             freeswitch.consoleLog("INFO", "# 推送结果  : " .. response .. "\n")
--         end
--     endfreeswitch.consoleLog("INFO", "# ----------------外呼挂机处理-----------------\n")if (hangup_cause  == "BUSY" or hangup_cause == "USER_BUSY" or hangup_cause == "NO_USER_RESPONSE" or hangup_cause == "NO_ROUTE_DESTINATION" or  hangup_cause == "CALL_REJECTED" or hangup_cause == "NO_ANSWER") thenfreeswitch.consoleLog("INFO", "# 挂机结果  : " .. hangup_cause .. "\n")-- 呼叫未应答提交freeswitch.consoleLog("INFO", "# 呼叫结果  : 呼叫未应答,推送未应答接口\n")if (no_answer_api == "") thenfreeswitch.consoleLog("INFO", "# 推送结果  : 未应答接口为空,不提交!\n")returnelse-- 提交无应答结果temp_string = string.format("%s content-type application/json connect-timeout %s timeout %s post {\"destination_number\":\"%s\"}",no_answer_api, api_timeout, api_timeout, destination_number)freeswitch.consoleLog("INFO", string.format("# 推送结果  : 请求地址:%s\n",temp_string))-- 执行推送response = api:execute("curl", temp_string)if (response == "") thenfreeswitch.consoleLog("INFO", "# 推送结果  : 接口无响应,可能连接接口失败!\n")elsefreeswitch.consoleLog("INFO", "# 推送结果  : ".. response.. "\n")endend
elseif (hangup_cause  == "NORMAL_CLEARING") thenfreeswitch.consoleLog("INFO", "# 挂机结果   : " .. hangup_cause .. "\n")freeswitch.consoleLog("INFO", "# 挂机结果   : 通话正常挂断\n")
elsefreeswitch.consoleLog("INFO", "# 挂机结果   : " .. hangup_cause .. "\n")
end
freeswitch.consoleLog("INFO", "# ----------------------------------------------\n")-- 如果要检查主叫号码是否被占用,则呼叫结束后,删除正在使用的主叫号码
if (check_number_in_use == "true") thenfreeswitch.consoleLog("INFO", string.format("# 通话已结束 : 开启了检查主叫号码占用,将释放主叫%s\n",outgoing_caller_id_number))-- 检查号码是否被占用temp_string = string.format("delete/%s/number_in_use_%s",trunk_name, outgoing_caller_id_number)freeswitch.consoleLog("INFO", string.format("# 通话已结束 : 释放正在使用的主叫号码:%s\n",temp_string))result = api:execute("hash",temp_string)freeswitch.consoleLog("INFO", string.format("# 通话已结束 : 释放正在使用的主叫号码:%s\n",result))
end
freeswitch.consoleLog("INFO", "# ===============================================\n\n")
return

祝君好运

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 开发工具

linux中&#xff0c;常见的软件安装方式---下载 yum/apt.rpm安装包安装源码安装 yum 查看软件包 通过yumlist命令可以罗列出当前⼀共有哪些软件包.由于包的数⽬可能⾮常之多,这⾥我们需要使⽤ grep 命令只筛选出我们关注的包.例如: # Centos $ yum list | grep lrzsz lr…

Agent革命:Manus如何用工作流拆解掀起AI生产力革命

一、现象级产品的诞生背景 2025年3月6日&#xff0c;一款名为Manus的AI产品在技术圈引发地震式传播。其官方测试数据显示&#xff1a;在GAIA基准测试中&#xff0c;基础任务准确率达86.5%&#xff08;接近人类水平&#xff09;&#xff0c;中高级任务完成率突破57%。这标志着A…

Linux13-TCP\HTTP

一、TCP粘包问题 1.TCP在接受数据时,多包数据粘在一起 2.原因: 2.1TCP发送数据时,会根据缓冲区数据的情况进行重新组包 2.2TCP接收方,没有及时读走缓冲区数据,导致缓冲区大量数据缓存。 3.如何解决 3.1发指定大小字节 将要发数据,封装在结构体里 struct data { …

网络安全等级保护2.0 vs GDPR vs NIST 2.0:全方位对比解析

在网络安全日益重要的今天&#xff0c;各国纷纷出台相关政策法规&#xff0c;以加强信息安全保护。本文将对比我国网络安全等级保护2.0、欧盟的GDPR以及美国的NIST 2.0&#xff0c;分析它们各自的特点及差异。 网络安全等级保护2.0 网络安全等级保护2.0是我国信息安全领域的一…

oracle通过dmp导入数据

1、创建用户&#xff0c;并赋予sysdba权限 登录sysdba用户 sqlplus / as sysdba 赋予sysdba权限 grant sysdba to your_user; 2、导入dmp文件 imp target_user/passwordip:port/SERVER_NAME fromusersource_user tousertarget_user fileyour.dmp logdmp_file.log statist…

MySQL 面试篇

MySQL相关面试题 定位慢查询 **面试官&#xff1a;**MySQL中&#xff0c;如何定位慢查询? 我们当时做压测的时候有的接口非常的慢&#xff0c;接口的响应时间超过了2秒以上&#xff0c;因为我们当时的系统部署了运维的监控系统Skywalking &#xff0c;在展示的报表中可以看到…

MyBatis 操作数据库

目录 1、MyBatis 是什么2、配置 MyBatis 开发环境2.1、添加 MyBatis 框架支持2.1.1、老项目添加 MyBatis2.1.2、新项目添加 MyBatis 2.2、配置数据库连接字符串2.3、配置 MyBatis 中的 XML 路径 3、添加业务代码3.1、添加实体类3.2、添加 mapper 接口3.3、添加 xml 文件3.4、添…

uniapp使用蓝牙,usb,局域网,打印机打印

使用流程&#xff08;支持安卓和iOS&#xff09; 引入SDK 引入原生插件包地址如下 https://github.com/oldfive20250214/UniPrinterDemo 连接设备 安卓支持经典蓝牙、ble蓝牙、usb、局域网&#xff08;参考API&#xff09; iOS支持ble蓝牙、局域网&#xff08;参考API&…

Jmeter进行http接口测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 本文主要针对http接口进行测试&#xff0c;使用 jmeter工具实现。 Jmeter工具设计之初是用于做性能测试的&#xff0c;它在实现对各种接口的调用方面已经做的比较…

力扣35.搜索插入位置-二分查找

class Solution:def searchInsert(self, nums: List[int], target: int) -> int:# 初始化左右指针left, right 0, len(nums) - 1# 当左指针小于等于右指针时&#xff0c;继续循环while left < right:# 计算中间位置mid (left right) // 2# 如果中间元素等于目标值&…

为AI聊天工具添加一个知识系统 之133 详细设计之74通用编程语言 之4 架构及其核心

本篇继续讨论 通用编程语言。 说明&#xff1a;本阶段的所有讨论都是围绕这一主题展开的&#xff0c;但前面的讨论分成了三个大部分&#xff08;后面列出了这一段的讨论题目的归属关系&#xff09;-区别distinguish&#xff08;各别&#xff09;&#xff1a; 文化和习俗。知识…

PPT 技能:巧用 “节” 功能,让演示文稿更有序

在制作PPT时&#xff0c;你是否遇到过这样的情况&#xff1a;幻灯片越来越多&#xff0c;内容越来越杂&#xff0c;找某一页内容时翻得眼花缭乱&#xff1f;尤其是在处理大型PPT文件时&#xff0c;如果没有合理的结构&#xff0c;编辑和调整都会变得非常麻烦。这时候&#xff0…

刘火良 FreeRTOS内核实现与应用之1——列表学习

重要数据 节点的命名都以_ITEM后缀进行&#xff0c;链表取消了后缀&#xff0c;直接LIST 普通的节点数据类型 /* 节点结构体定义 */ struct xLIST_ITEM { TickType_t xItemValue; /* 辅助值&#xff0c;用于帮助节点做顺序排列 */ struct xLIST_I…

Uniapp项目运行到微信小程序、H5、APP等多个平台教程

摘要&#xff1a;Uniapp作为一款基于Vue.js的跨平台开发框架&#xff0c;支持“一次开发&#xff0c;多端部署”。本文将手把手教你如何将Uniapp项目运行到微信小程序、H5、APP等多个平台&#xff0c;并解析常见问题。 一、环境准备 在开始前&#xff0c;请确保已安装以下工具…

100天精通Python(爬虫篇)——第115天:爬虫在线小工具_Curl转python爬虫代码工具(快速构建初始爬虫代码)

文章目录 一、curl是什么&#xff1f;二、爬虫在线小工具&#xff08;牛逼puls&#xff09;三、实战操作 一、curl是什么&#xff1f; 基本概念&#xff1a;curl 支持多种协议&#xff0c;如 HTTP、HTTPS、FTP、SFTP 等&#xff0c;可用于从服务器获取数据或向服务器发送数据&a…

[内网安全] Windows 域认证 — Kerberos 协议认证

&#x1f31f;想系统化学习内网渗透&#xff1f;看看这个&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;Kerberos 协议简介 Kerberos 是一种网络认证协议&#xff0c;其设计目标是通过密钥系统为客户机 / 服务器应用程序提供强大的认证服务。该认证过…

PyTorch中的损失函数:F.nll_loss 与 nn.CrossEntropyLoss

文章目录 背景介绍F.nll_loss什么是负对数似然损失&#xff1f;应用场景 nn.CrossEntropyLoss简化工作流程内部机制 区别与联系 背景介绍 无论是图像分类、文本分类还是其他类型的分类任务&#xff0c;交叉熵损失&#xff08;Cross Entropy Loss&#xff09;都是最常用的一种损…

案例1_3:流水灯

文章目录 文章介绍原理图&#xff08;同案例1_2&#xff09;代码效果图 文章介绍 原理图&#xff08;同案例1_2&#xff09; 代码 #include <reg51.h> // 包含头文件void delay(unsigned int time) {unsigned int i, j;for (i 0; i < time; i)for (j 0; j < 1…

基于物联网技术的电动车防盗系统设计(论文+源码)

1总体设计 本课题为基于物联网技术的电动车防盗系统&#xff0c;在此将整个系统架构设计如图2.1所示&#xff0c;其采用STM32F103单片机为控制器&#xff0c;通过NEO-6M实现GPS定位功能&#xff0c;通过红外传感器检测电瓶是否离开位&#xff0c;通过Air202 NBIOT模块将当前的数…

学习知识的心理和方法杂记-02

本文简单记录下我个人对大脑学习模式的认识。 人脑的基本能力是什么&#xff1f; 接收输入的能力。语言和声音 视觉图像 触觉 嗅觉 味觉等。 存储能力。人脑存储能力背后的物理化学结构我们人类目前还无法完全认知&#xff0c;但是存储的目标物一定是人可以通过五官获得的形…