Freeswitch: mod_curl
Приложение mod_curl
позволяет выполнять HTTP запросы и получать данные в ответ.
Вывод может быть, как простым текстом, так и JSON объектом.
Setup & Configuration
Для того чтобы использовать mod_curl
, вы должны скомпилоировать и загрузить соответствующий модуль.
раскомментируйте в /usr/src/freeswitch/modules.conf:
#applications/mod_curl
Перекомпилируйте Freeswtich:
make make install
И добавьте модуль в автозагрузку в файле modules.conf.xml из директории /usr/local/freeswitch/conf/autoload_configs:
<load module="mod_curl"/>
Для модуля mod_curl
не существует отдельного конфига.
Загрузите модуль:
fs_cli> load mod_curl
2020-03-19 16:33:47.528923 [CONSOLE] switch_loadable_module.c:1804 Successfully Loaded [mod_curl] 2020-03-19 16:33:47.528923 [NOTICE] switch_loadable_module.c:350 Adding Application 'curl' 2020-03-19 16:33:47.528923 [NOTICE] switch_loadable_module.c:350 Adding Application 'curl_sendfile' 2020-03-19 16:33:47.528923 [NOTICE] switch_loadable_module.c:412 Adding API Function 'curl' 2020-03-19 16:33:47.528923 [NOTICE] switch_loadable_module.c:412 Adding API Function 'curl_sendfile'
mod_curl предоставляет команды для вызова, как через API, так и через диалплан:
- curl - сделать запрос и получить какие-то данные с сервера.
- curl_sendfile - передать данные на cервер и получить отчет, если требуется.
Application
Синтаксис приложения curl
:
<action application="curl" data="url [headers|json] [get|head|post [url_encode_data]]"/>
Приложение устанавливает переменные curl_response_data и curl_response_code.
curl_response_data может содержать headers/body или json если запрошено.
<action application="curl" data="http://www.google.com"/> <action application="info"/> <action application="curl" data="http://www.google.com headers"/> <action application="info"/> <action application="curl" data="http://www.google.com json"/> <action application="info"/>
Синтаксис curl_sendfile
может принимать одну из двух следующих форм,
все данные в application data:
<action application="curl_sendfile" data="<url> <filename_post_name=/path/to/filename [nopost|foo1=bar1&foo2=bar2&...fooN=barN [event|none [uuid|identifier]]]"/>
или с предварительно заданными переменными канала:
<action application="set" data="curl_sendfile_report=event"/> <action application="set" data="curl_sendfile_url=http://www.mydomain.com/test_files.php"/> <action application="set" data="curl_sendfile_filename_element=myFile"/> <action application="set" data="curl_sendfile_filename=/tmp/somefile.dmp"/> <action application="set" data="curl_sendfile_extrapost=foo1=bar1&foo2=bar2&testing=a%20pain%20in%20the%20rear"/> <action application="set" data="_sendfile_identifier=1234567890"/> <action application="curl_sendfile"/>
Необходимо применять urlencode для переменных канала _url, _filename, _extrapost или data = "".
Требуется указывать nopost
, если нет дополнительных данных или дополнительные параметры передаются в url.
Если вы укажете uuid
в качестве идентификатора, приложение использует uuid текущего сеанса.
CLI / API
Примеры использования команд API через fs_cli:
curl url [headers|json|content-type <mime-type>|connect-timeout <seconds>|timeout <seconds>] [get|head|post|delete|put [data]]
Вызов из командной строки FS:
curl https://nominatim.openstreetmap.org/?format=xml&addressdetails=1&q=london&format=json&limit=1&pretty=1
Вывод:
[ { "place_id": 100200, "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright", "osm_type": "node", "osm_id": 107775, "boundingbox": [ "51.3473219", "51.6673219", "-0.2876474", "0.0323526" ], "lat": "51.5073219", "lon": "-0.1276474", "display_name": "London, Greater London, England, SW1A 2DX, United Kingdom", "class": "place", "type": "city", "importance": 0.9307827616237295, "icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png", "address": { "city": "London", "state_district": "Greater London", "state": "England", "postcode": "SW1A 2DX", "country": "United Kingdom", "country_code": "gb" } } ]
Headers
curl https://nominatim.openstreetmap.org/?format=xml&addressdetails=1&q=london&format=json&limit=1&pretty=1 headers
Вывод:
json
curl https://nominatim.openstreetmap.org/?format=xml&addressdetails=1&q=london&format=json&limit=1&pretty=1 json
Вывод:
POST и GET запросы.
curl https://asterisk-pbx.ru/wiki/freeswitch/start?do=backlink curl https://asterisk-pbx.ru/wiki/freeswitch/start post do=backlink
Совместно с headers или JSON:
curl https://asterisk-pbx.ru/wiki/start?id=freeswitch%20curl&do=search json curl https://asterisk-pbx.ru/wiki/start headers post id=freeswitch%20mod_curl&do=search
Синтаксис вызвова API - curl_sendfile:
[api/bgapi] curl_sendfile <url> <filenameParamName=filepath> [nopost|postparam1=foo&postparam2=bar... [event|stream|both|none [identifier ]]]
<url
>: Вызываемый URL REST запроса. Должен содержать необходимые GET параметры и URL вызваемого скрипта, который будет обрабатывать параметры.
<filenameParamName=filepath
> : Пара ключ=значение. Ключ это желаемое имя элемента формы. Значение - полный путь к файлу который мы хотим передать, связанный с элементом.
nopost
|postparam1=foo&postparam2=bar
… : Если требуется задать доплнительный набор параметров, вы можете назначить urlencoded:
fs_cli -x 'url_encode param1=foo¶m2=bar'
param1%3Dfoo1%26param2%3Dfoo2
набор вида ключ=значение так, как вы бы это сделали в GET запросе. Если передача дополнительных элементов не требуется, просто укажите nopost
.
event
|stream
|both
|none
: Данный параметр определяет, где отображается вывод полученный после REST запроса. Если указано event
, это присоединит пользовательское (CUSTOM) событие, помеченное как curl_sendfile::ack
и отправит его:
Если вы укажете stream
, он будет выведен в активную сессию, какой бы метод ни использовался для выполнения вызова.
Если both
, то оба вида будут применены.
Если none
, то ничего кроме +HTTP_STATUS_CODE Ok или -HTTP_STATUS_CODE Err отображено не будет.
identifier
: Это произвольный идентификатор, который вы можете использовать для собственных нужд.
Он будет отображен как заголовок события - Command-Execution-Identifier
:
... Event-Sequence: 419544 Command-Execution-Identifier: FOOO Filename: /usr/local/freeswitch/recordings/997b6b21-9637-4a97-9940-b3b33ee4e454.ogg File-Access: Success REST-HTTP-Code: 200 Content-Length: 137 ...
identifier
был корректно обработан, должны быть заданы два предыдущих «необязательных» параметра, иначе парсер не сможет обработать его.
… nopost none identifier
Lua Usage
session:ready()
перед любыми длительными вызовами функций, такими как HTTP-запрос, чтобы ваш сценарий прекратил работу и освободил свои ресурсы как можно скорее, если вызов потерпел неудачу.
GET запрос:
session:execute("curl", "http://www.myhost.com/?name1=value1&name2=value2") curl_response_code = session:getVariable("curl_response_code") curl_response = session:getVariable("curl_response_data")
POST запрос:
session:execute("curl", "http://www.myhost.com/ post name1=value1&name2=value2") curl_response_code = session:getVariable("curl_response_code") curl_response = session:getVariable("curl_response_data")
Установить таймаут в секундах:
session:setVariable("curl_timeout", "10") session:execute("curl", "http://www.myhost.com/ post name1=value1&name2=value2")
Также возможно делать вызов через API интерфейс:
api = freeswitch.API(); get_response = api:execute("curl", "http://www.myhost.com/?name1=value1&name2=value2") post_response = api:execute("curl", "http://www.myhost.com/ post name1=value1&name2=value2")
Все приведенный выше примеры, должны передаваться, как URL encoded.
Submit:
first = "a short value" second = "a slightly longer value"
as:
first=a%20short%20value&second=a%20slightly%20longer%20value
Пример Urlencode для формирования GET/POST запроса:
-- Lua uriencode function -- -- Can take a table, or a string of comma separated values. -- Examples: -- > print(uriencode("this=is,a=/test/,string='quotes'")) -- a=%2Ftest%2F&string=%27quotes%27&this=is -- > print(uriencode({this="is", a="/test/", string="'quotes'"})) -- a=%2Ftest%2F&string=%27quotes%27&this=is -- function uriencode(vals) function escape (s) s = string.gsub( s, '([\r\n"#%%&+:;<=>?@^`{|}%\\%[%]%(%)$!~,/\'])', function (c) return '%'..string.format("%02X", string.byte(c)); end ); s = string.gsub(s, "%s", "+"); return s; end function encode (t) local s = ""; for k , v in pairs(t) do s = s .. "&" .. escape(k) .. "=" .. escape(v); end return string.sub(s, 2); end if type(vals) == 'table' then return encode(vals); else local t = {}; for k, v in string.gmatch(vals, ",?([^=]+)=([^,]+)") do t[k]=v; end return encode(t); end end
(или CGILua's urlcode)
Если вы хотите передать запрос базовой аутентификации, то используейте форму:
local auth_url = "http://username:password@mysecure_web_service.com" local response = api:execute("curl", auth_url)
Source
https://freeswitch.org/confluence/display/FREESWITCH/mod_curl
Feedback
<action application="curl" data="http://localhost/faxapp content-type 'application/JSON' post {"session_id":"9dea8e0d880ec5b0450c2a96766b87","source":"1234XXXXXXX","destination":"56475XXXXXXX"}"
Вышеприведенный пример потерпит неудачу из-за двойных кавычек.
Данная форма записи позволит избежать этого:
<action application="set" data='post={"session_id":"9dea8e0d880ec5b0450c2a96766b87","source":"1234XXXXXXX","destination":"56475XXXXXXX"}' inline="true"/> <action application="curl" data="http://localhost/faxapp content-type 'application/json' post ${post}" inline="true"/>