Hello,
I am trying to get json RPCs running. simpleequests seem to work, but I can't figure out how to pass parameters. For example
curl --header 'Content-Type: application/json' --data-binary '{"id": 1,"jsonrpc": "2.0", "method": "ul.db_users" }' http://localhost:8081/RPC/
{ "jsonrpc": "2.0", "error": { "code": 500, "message": "Not enough parameters (table to lookup)" }, "id": 1 }
According to http://www.kamailio.org/docs/docbooks/3.2.x/rpc_api/rpc_api.html#rpc.getting... parameters dont have names and according to http://www.kamailio.org/docs/modules/devel/modules/usrloc.html#usrloc.r.db_u... 1 parameter is required.
I guessed adding "params":"location" => no error anymore, but still no result:
curl --header 'Content-Type: application/json' --data-binary '{"id": 1,"jsonrpc": "2.0", "method": "ul.db_users", "params":"location"}' http://localhost:8081/RPC/ { "jsonrpc": "2.0", "result": { }, "id": 1 }
Same result (no error) if I pass "params":"nonsense", so "params" seems to be kind of ignored ...
What's the correct json syntax here or in general?
Best regards, Volker
Hi Volker
An Example by which I query a profile counter:
curl -X POST http://VoiceSwitch:8080/RPC -H 'Content-Type: application/json' -d '{"jsonrpc": "2.0", "method": "dlg.profile_get_size", "params" : ["channels-inuse", "Customer-XXXX"], "id": 1}'
I think, with jsonrpc 2.0 you could pass an array of named parameters, but I also struggled with that, just passing an array of parameters in the right order did it for me.
Perl Snippel I just had at hand while elaborating how to use the output and using the JSON::RPC2::Client and LWP::UserAgent modules.
my $ua = LWP::UserAgent->new(); my $h = HTTP::Headers->new( Content_Type => 'application/json' ); my $client = JSON::RPC2::Client->new();
[...]
$method = "ul.dump"; @params = ();
($json_request, $call) = $client->call($method, @params);
$req = HTTP::Request->new('POST', $reguri . $kamapi, $h, $json_request); $res = $ua->request($req);
print "=== KAM RPC: $method ===\n";
#print $res->decoded_content; print "\n";
my $ul = decode_json($res->decoded_content);
#print Dumper($ul);
#print Dumper($ul->{'result'}->{'Domains'}[0]->{'Domain'});
my @aors = @{$ul->{'result'}->{'Domains'}[0]->{'Domain'}->{'AoRs'}};
foreach my $aor (@aors) { print "======== AOR [$aor->{'Info'}->{'AoR'}] =========\n"; my @contacts = @{$aor->{'Info'}->{'Contacts'}}; foreach my $contact (@contacts) { print "\t == contact ==\n"; print "\tAddress:\t$contact->{'Contact'}->{'Address'}\n"; print "\tExpires:\t$contact->{'Contact'}->{'Expires'}\n"; print "\tUser Agent:\t$contact->{'Contact'}->{'User-Agent'}\n"; } }
Mit freundlichen Grüssen
-Benoît Panizzon-
Hello,
On 14.03.23 14:08, Benoit Panizzon wrote:
Hi Volker
An Example by which I query a profile counter:
curl -X POST http://VoiceSwitch:8080/RPC -H 'Content-Type: application/json' -d '{"jsonrpc": "2.0", "method": "dlg.profile_get_size", "params" : ["channels-inuse", "Customer-XXXX"], "id": 1}'
I think, with jsonrpc 2.0 you could pass an array of named parameters, but I also struggled with that, just passing an array of parameters in the right order did it for me.
Perl Snippel I just had at hand while elaborating how to use the output and using the JSON::RPC2::Client and LWP::UserAgent modules.
my $ua = LWP::UserAgent->new(); my $h = HTTP::Headers->new( Content_Type => 'application/json' ); my $client = JSON::RPC2::Client->new();
[...]
$method = "ul.dump"; @params = ();
($json_request, $call) = $client->call($method, @params);
$req = HTTP::Request->new('POST', $reguri . $kamapi, $h, $json_request); $res = $ua->request($req);
print "=== KAM RPC: $method ===\n";
#print $res->decoded_content; print "\n";
my $ul = decode_json($res->decoded_content);
#print Dumper($ul);
#print Dumper($ul->{'result'}->{'Domains'}[0]->{'Domain'});
my @aors = @{$ul->{'result'}->{'Domains'}[0]->{'Domain'}->{'AoRs'}};
foreach my $aor (@aors) { print "======== AOR [$aor->{'Info'}->{'AoR'}] =========\n"; my @contacts = @{$aor->{'Info'}->{'Contacts'}}; foreach my $contact (@contacts) { print "\t == contact ==\n"; print "\tAddress:\t$contact->{'Contact'}->{'Address'}\n"; print "\tExpires:\t$contact->{'Contact'}->{'Expires'}\n"; print "\tUser Agent:\t$contact->{'Contact'}->{'User-Agent'}\n"; } }
the parameters have to be provided as positional values in an array -- practically the order matters. That's because the RPC commands are implementer independent of the transport and command format, it is the same code executed for binrpc, jsonrpc and xmlrpc. jsonrpc specs allow named parameters, but the binrpc, which was implemented in first phase, does not. I am not sure if the xmlrpc can have named parameters.
If you want to provide names to the parameters when sending the command, it should work with jsonrpcs module, but the names are only aesthetical, the position of the values is relevant. You can look at the readme of the jsonrpcs module for some examples of jsonrpcs commands.
Cheers, Daniel
Hello,
I'm trying to use python KEMI script with Kamailio (5.6.4). This is python 2.7.5.
I have some weird behaviour with string formatting. This works fine:
KSR.info("si: [%s]\n" % KSR.pv.get("$si"))
But with this:
KSR.info("si: {}\n".format(KSR.pv.get("$si")))
=> This works but only for 1/2 of the SIP requests. Otherwise I get the following error:
1(111858) ERROR: PY2 {INVITE} app_python [python_support.c:154]: python_handle_exception(): apy_exec: ksr_request_route((null)): Unhandled exception in the Python code: Traceback (most recent call last): File "kamailio-routing-kemi.py", line 74, in ksr_request_route KSR.info("si: {}\n".format( str(KSR.pv.get("$si")) )) TypeError: an integer is required
What could be the problem ?
Regards, Nicolas.
This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message in error, please notify the sender immediately and delete all copies of this message.
Hello,
Just a quick follow-up: the problem does not appear anymore. I was trying to use KEMI export KSR.pv.sets to assign integer values or None, which is wrong. (my first steps using KEMI...)
I was confused because after that a log with "%" works fine but not with "format" (it triggers a "python_handle_exception"). (I still don't know why, but the cause was not the log itself but my incorrectly using the KEMI export before that)
Regards, Nicolas.
-----Message d'origine----- De : Chaigneau, Nicolas nicolas.chaigneau@capgemini.com
Hello,
I'm trying to use python KEMI script with Kamailio (5.6.4). This is python 2.7.5.
I have some weird behaviour with string formatting. This works fine:
KSR.info("si: [%s]\n" % KSR.pv.get("$si"))
But with this:
KSR.info("si: {}\n".format(KSR.pv.get("$si")))
=> This works but only for 1/2 of the SIP requests. Otherwise I get the following error:
1(111858) ERROR: PY2 {INVITE} app_python [python_support.c:154]: python_handle_exception(): apy_exec: ksr_request_route((null)): Unhandled exception in the Python code: Traceback (most recent call last): File "kamailio-routing-kemi.py", line 74, in ksr_request_route KSR.info("si: {}\n".format( str(KSR.pv.get("$si")) )) TypeError: an integer is required
What could be the problem ?
Regards, Nicolas. This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message in error, please notify the sender immediately and delete all copies of this message.
Thank you Benoit and Daniel, your comments were helpful, now I am 1 step further and reached the next challenge: https://lists.kamailio.org/mailman3/hyperkitty/list/sr-users@lists.kamailio....
Best regards, Volker
Hi Volker
your comments were helpful, now I am 1 step further and reached the next challenge: https://lists.kamailio.org/mailman3/hyperkitty/list/sr-users@lists.kamailio....
Did you enable one of the DB modes?
/* enable DB persistency for location entries */ modparam("usrloc", "db_url", DBLOCAL) modparam("usrloc", "db_mode", 2) modparam("usrloc", "use_domain", 0)
RPC functions are restricted in the reply size. I found by try and error, that this limit is at about 1MB and I found no way to increase that limit.
We therefore took another approach and started building our own API using the jansson module to directly access the database and only return the information we are (or our customer service using our diagnosis service) is interested in.
Here the snippet with might be interesting for you.
event_route[xhttp:request] { route(DEBUGINIT); if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route): XHTTP Request to URI: $hu Port: $Rp BODY: $rb\n"); } if ($Rp != 8080) { xhttp_reply("403", "Forbidden", "text/html", "<html><body>Talk SIP to me dude!</body></html>"); exit; } if ($hu =~ "^/RPC") {
### KAMAILIO JSONRCP passthrough
jsonrpc_dispatch(); } else if ($hu =~ "^/API") {
### CUSTOM API
$var(json_reply) = "{}"; jansson_get("method","$rb","$var(method)"); jansson_get("id","$rb","$var(id)"); jansson_set("string","jsonrpc","2.0","$var(json_reply)"); jansson_set("string","id","$var(id)","$var(json_reply)"); jansson_set("obj","result","{}","$var(json_reply)");
[...]
} else if ($var(method) == "location.lookup.by_aor") { # Registration Lookup by AoR jansson_get("params[0]","$rb","$var(aor)"); $var(query) = "SELECT username,contact,last_modified,expires,callid,user_agent from location" " where username = '" + $var(aor) + "'"; $var(query_result) = sql_query("localacc", "$var(query)","sql_res"); if($dbr(sql_res=>rows)>0) { $var(i)=0; $var(aor_a) = '[]'; while($var(i)<$dbr(sql_res=>rows)) { $var(aor_o) = '{}'; jansson_set("string","username", "$dbr(sql_res=>[$var(i),0])","$var(aor_o)"); jansson_set("string","contact", "$dbr(sql_res=>[$var(i),1])","$var(aor_o)"); jansson_set("string","last_modified","$dbr(sql_res=>[$var(i),2])","$var(aor_o)"); jansson_set("string","expires", "$dbr(sql_res=>[$var(i),3])","$var(aor_o)"); jansson_set("string","callid", "$dbr(sql_res=>[$var(i),4])","$var(aor_o)"); jansson_set("string","user_agent", "$dbr(sql_res=>[$var(i),5])","$var(aor_o)"); jansson_append("obj","","$var(aor_o)","$var(aor_a)"); $var(i) = $var(i) + 1; } jansson_set("array","result","$var(aor_a)","$var(json_reply)"); sql_result_free("sql_res"); } else { jansson_set("string","result.error","No entries","$var(json_reply)"); sql_result_free("sql_res"); } } else if ($var(method) == "location.list_all") {
[...]
} else { jansson_set("string","result.error","Unknown api call","$var(json_reply)"); }
### SEND REPLY
if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route): XHTTP Request to URI: $hu Method: $var(method) OK\n"); } xhttp_reply("200", "OK", "application/json", "$var(json_reply)"); } else {
if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route): XHTTP Request to URI: $hu NOT FOUND\n"); } xhttp_reply("404", "Not found", "", ""); } return; }