http 模块
kamailio的http
功能十分丰富,提供了客户端和服务端。对应的模块有:
client |
描述 |
HTTP_CLIENT |
依赖libcurl |
HTTP_ASYNC_CLIENT |
异步client,依赖libcurl 和libevent |
JSONRPCC |
依赖libjson,libevent,glibc |
JANSSONRPCC |
依赖jansson,libevent |
server |
描述 |
JSONRPCS |
支持http,fifo, datagram |
MICROHTTPD |
依赖libmcrohttpd |
XHTTP |
提供http/1.0基础服务 |
XHTTP_PI |
通过kamailio的API提供数据库操作 |
XHTTP_PROM |
为prometheus提供metrics数据 |
XHTTP_RPC |
通过http方式 提供rpc服务 |
本章主要是介绍client模块,版本为:
version: kamailio 5.8.5 (x86_64/linux)
Client
HTTP_CLIENT 模块
支持http和https协议,同步请求
- http配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 302是否重定向, 默认为:1
modparam("http_client", "httpredirect", 0)
# useragent 设置
modparam("http_client", "useragent", "Secret HTTP REST grabber 0.42")
# maxdatasize reponse body的最大大小,默认0,不设置
modparam("http_client", "maxdatasize", 2000)
# connection_timeout 等待服务端返回的超时时间,默认4s,单位是秒还是毫秒,由timeout_mode决定
modparam("http_client", "connection_timeout", 5)
# timeout_mode 0,超时功能不能用 1,表示单位是秒,2,表示单位是毫秒,默认1
modparam("http_client", "timeout_mode", 1)
# keep_connections 0,请求之后关闭连接;1,请求之后保持连接
modparam("http_client", "keep_connections", 1)
# query_result 控制http_client_query的返回结果, 0,返回整个body;1,返回body的第一行,默认1
modparam("http_client", "query_result", 0)
|
- https
1
2
3
4
5
6
7
8
9
10
|
modparam("http_client", "client_cert", "/var/certs/sollentuna.example.com.cert")
modparam("http_client", "client_key", "/var/certs/sollentuna.example.com.key")
# 验证服务端证书,默认1
modparam("http_client", "verify_peer", 1)
# 验证domain,默认2
modparam("http_client", "verify_host", 2)
#tls版本 0,libcurl默认; 1,TLSv1; 2,SSLv2; 3,SSLv3; 4,TLSv1.0; 5,TLSv1.1; 6,TLSv1.2
modparam("http_client", "tlsversion", 6)
# http认证方式,默认3(1+2) 1,BASIC authention; 2,HTTP Digest authentication; 4,GSS-Negotiate authentication; 8, NTLM authentication; 16,HTTP Digest with IE flavour
modparam("http_client", "authmethod", 3)
|
https的配置也可以从文件读取
1
|
modparam("http_client", "config_file", "httpconnections.cfg)
|
httpconnections.cfg
1
2
3
4
5
6
7
8
9
|
[authapiserver]
url = https://api.runbo.example.com/v4.2/auth
timeout = 1
maxdatasize = 4
tlsversion = TLSv1.2
verify_peer = yes
client_key = default_key.pem
client_cert = default_cert.pem
http_follow_redirect = no
|
- 设置
http server
的url
1
2
3
4
|
modparam("http_client", "httpcon", "apione=>http://atlanta.example.com")
modparam("http_client", "httpcon", "apitwo=>http://atlanta.example.com/api/12")
modparam("http_client", "httpcon", "apithree=>http://annabella:mysecret@atlanta.example.com/api/12")
modparam("http_client", "httpcon", "apifour=>http://stockholm.example.com/api/getstuff;timeout=12;failover=apione")
|
- 几个请求函数
- http_connect(connection, url, [content_type, data,] result)
1
2
3
4
5
|
modparam("http_client", "httpcon", "apiserver=>https://kamailio.org/api/");
#POST
$var(res) = http_connect("apiserver", "/mailbox", "application/json", "{ ok, {200, ok}}", "$avp(gurka)");
#GET
$var(res) = http_connect("apiserver", "/mailbox?page=1&&limit=10","$avp(gurka)");
|
默认是GET
方式, POST
方式,需要设置content_type
和data
,只能被用到REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE,BRANCH_ROUTE
- http_connect_raw(connection, url, content_type, data, result)
1
|
$var(res) = http_connect_raw("apiserver", "/mailbox", "application/json", "{ ok, {200, ok}}", "$avp(gurka)");
|
只能发送POST
,可以使用的路由有:REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE
- http_client_query(url, [post-data], [hdrs], result)
1
2
3
4
5
6
|
#GET
http_client_query("http://api.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(fu{s.escape.param})",
"$var(result)");
# POST-Request
http_client_query("http://api.com/index.php", "src=$si",
"Content-Type: text/plain", "$var(result)");
|
可以发送GET
和POST
, POST
就设置post-data
,可以用在ANY ROUTE
.
- http_client_get(url, body, hdrs, respv)
1
2
|
http_client_get("http://api.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(fu{s.escape.param})",
"", "X-Token: abc", "$var(result)");
|
只能GET
, body为空,可以用在ANY ROUTE
.
HTTP_ASYNC_CLIENT 模块
异步请求,支持http和https两种方式
- http配置
1
2
3
4
5
6
7
8
9
10
11
12
|
#多少个worker来发送请求和处理返回,默认1个
modparam("http_async_client", "workers", 2)
# 等待服务端返回的超时时间,单位毫秒,默认500ms
modparam("http_async_client", "connection_timeout", 1000)
# hash_size, 默认2048
modparam("http_async_client", "hash_size", 1024)
modparam("http_async_client", "tcp_keepalive", 1)
# 保持keepalive的时间,单位秒,空闲等待时间,默认60s
modparam("http_async_client", "tcp_ka_idle", 30)
# 保持keepalive的间隔时间,单位秒,默认60s
modparam("http_async_client", "tcp_ka_interval", 120)
|
- https 配置
1
2
3
4
5
6
7
8
|
# tls的版本
modparam("http_async_client", "tls_version", 6)
# 是否验证domain,默认2
modparam("http_async_client", "tls_verify_host", 0)
# 是否验证服务端证书,默认1
modparam("http_async_client", "tls_verify_peer", 0)
modparam("http_async_client", "tls_client_cert", "/etc/kamailio/ssl/clientcert.pem")
modparam("http_async_client", "tls_client_key", "/etc/kamailio/ssl/clientcert.key")
|
- 重要函数介绍
- http_async_query(url, route_name)
支持GET
和POST
, 可以用在ANY ROUTE
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# GET
http_async_query("http://example.com/test.php?r_uri=$rU&f_uri=$fU", "HTTP_REPLY");
...
# POST
$http_req(body) = "{'r_uri':'" + $rU + "', 'f_uri':'" + $fU + "'}";
http_async_query("http://example.com/test.php", "HTTP_REPLY");
···
route[HTTP_REPLY] {
if ($http_ok) {
xlog("L_INFO", "route[HTTP_REPLY]: status $http_rs\n");
xlog("L_INFO", "route[HTTP_REPLY]: body $http_rb\n");
} else {
xlog("L_INFO", "route[HTTP_REPLY]: error $http_err)\n");
}
}
|
- 重要变量介绍
JSONRPCC 模块
JSONRPC是JSON格式HTTP协议下RESTful风格的RPC协议。
使用较简单。
- 配置解析:
1
2
3
4
|
#配置server地址,可配多个,格式"host1:port1,priority1 host2:port2,priority2"
modparam("jsonrpcc", "servers", "localhost:9999,2 10.10.0.1:9999,2 backup.server:9999,1")
# 最大重试次数,-1 一直重连, 0 不重试
modparam("jsonrpcc", "max_conn_attempts", 10)
|
- 关键函数
- jsonrpc_notification(method, parameters)
事件通知,不需要返回值。
1
|
jsonrpc_notification("update_user", "{'id': 1234, 'name': 'Petros'}")
|
- jsonrpc_request(method, parameters, return_route, error_route, result_var)
获取返回值,可以通过这个函数来实现kamctl
的功能。
1
2
3
4
5
6
7
8
9
10
11
|
jsonrpc_request("get_user", "{'id': 1234}", "RESPONSE", "ERROR", "$var(result)");
...
route[RESPONSE] {
xlog("Result received: $var(result)");
...
}
...
route[ERROR] {
xlog("Error received: $var(result)");
...
}
|
JANSSONRPCC 模块
- 配置解析:
1
2
3
4
5
6
|
# 返回值存储位置,默认:$var(jsrpc_result)
modparam("janssonrpcc", "result_pv", "$var(result)")
# 重试的错误码,默认: -32603, -32000..-32099
modparam("janssonrpcc", "retry_codes", "-32603, -32000..-32099");
# keepalive时间,默认: 10
modparam("janssonrpcc", "keep_alive", 10)
|
server端配置方式:
1
2
3
4
|
modparam("janssonrpcc", "server", "conn=tests;srv=_test1._tcp.example.net");
modparam("janssonrpcc", "server", "conn=tests;srv=_test2._tcp.example.net");
modparam("janssonrpcc", "server", "conn=local;addr=localhost;port=8080;priority=10;weight=10");
modparam("janssonrpcc", "server", "conn=user_db;addr=rpc.prod.example.net;port=5060;priority=10;weight=10");
|
- 关键函数
- janssonrpc_notification(conn, method, parameters)
通知函数,不需要返回值。
- janssonrpc_request(conn, method, params[, options]])
json请求函数,可以用在ANY ROUTE
,示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
route {
janssonrpc_request("user_db", "get_user", '{"id": 1234}', "route=RESPONSE;retry=1");
}
route[RESPONSE] {
if(jansson_get("internal_error", $var(jsrpc_result), "$var(internal)")) {
route(INTERNAL);
} else if(jansson_get("error", $var(jsrpc_result), "$var(error)")) {
route(ERROR);
} else if(jansson_get("result", $var(jsrpc_result), "$var(result)")) {
route(RESULT);
}
t_reply("200", "OK");
}
route[RESULT] {
xlog("result is $var(result)\n");
xlog("success\n");
}
route[ERROR] {
xlog("There was an error\n");
if(jansson_get("code", $var(error), "$var(c)")) {
xlog("code is $var(c)\n");
}
if(jansson_get("message", $var(error), "$var(r)")) {
xlog("error is $var(r)\n");
}
if(jansson_get("data", $var(error), "$var(d)")) {
xlog("data is $var(d)\n");
}
}
route[INTERNAL] {
xlog("There was an internal error\n");
jansson_get("code", $var(internal), "$var(c)");
xlog("code is $var(c)\n");
jansson_get("message", $var(internal), "$var(r)");
xlog("error is $var(r)\n");
if(jansson_get("data", $var(internal), "$var(d)")) {
xlog("request is $var(d)\n");
}
}
|