diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 84289dd4..27512442 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -1676,7 +1676,7 @@ api_operations_post(clicon_handle h, if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0) goto done; /* Local error: return it and quit */ - if ((xe = xpath_first(xret, "//rpc-error")) != NULL){ + if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) != NULL){ if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; @@ -1685,7 +1685,7 @@ api_operations_post(clicon_handle h, else { /* Send to backend */ if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0) goto done; - if ((xe = xpath_first(xret, "rpc-error")) != NULL){ + if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) != NULL){ if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; diff --git a/example/clixon-example@2019-01-13.yang b/example/clixon-example@2019-01-13.yang index c664a0ab..da038f31 100644 --- a/example/clixon-example@2019-01-13.yang +++ b/example/clixon-example@2019-01-13.yang @@ -65,12 +65,12 @@ module clixon-example { This is a clixon implementation detail: some rpc:s are better processed by the client for API or perf reasons"; input { - leaf request { + leaf x { type string; } } output { - leaf result{ + leaf x { type string; } } diff --git a/example/example_netconf.c b/example/example_netconf.c index 742b1d98..5a5710f0 100644 --- a/example/example_netconf.c +++ b/example/example_netconf.c @@ -65,13 +65,34 @@ plugin_exit(clicon_handle h) /*! Local example netconf rpc callback */ int netconf_client_rpc(clicon_handle h, - cxobj *xn, + cxobj *xe, cbuf *cbret, void *arg, void *regarg) { - clicon_debug(1, "%s restconf", __FUNCTION__); - cprintf(cbret, "ok"); + int retval = -1; + cxobj *x = NULL; + char *namespace; + + /* get namespace from rpc name, return back in each output parameter */ + if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){ + clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe)); + goto done; + } + cprintf(cbret, ""); + if (!xml_child_nr_type(xe, CX_ELMNT)) + cprintf(cbret, ""); + else while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) { + if (xmlns_set(x, NULL, namespace) < 0) + goto done; + if (clicon_xml2cbuf(cbret, x, 0, 0) < 0) + goto done; + } + cprintf(cbret, ""); + retval = 0; + done: + return retval; + return 0; } diff --git a/example/example_restconf.c b/example/example_restconf.c index e49a48f4..e6e395c5 100644 --- a/example/example_restconf.c +++ b/example/example_restconf.c @@ -268,15 +268,33 @@ example_restconf_credentials(clicon_handle h, */ int restconf_client_rpc(clicon_handle h, - cxobj *xn, + cxobj *xe, cbuf *cbret, void *arg, void *regarg) { - // FCGX_Request *r = (FCGX_Request *)arg; - clicon_debug(1, "%s", __FUNCTION__); - cprintf(cbret, "ok"); - return 0; + int retval = -1; + cxobj *x = NULL; + char *namespace; + + /* get namespace from rpc name, return back in each output parameter */ + if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){ + clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe)); + goto done; + } + cprintf(cbret, ""); + if (!xml_child_nr_type(xe, CX_ELMNT)) + cprintf(cbret, ""); + else while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) { + if (xmlns_set(x, NULL, namespace) < 0) + goto done; + if (clicon_xml2cbuf(cbret, x, 0, 0) < 0) + goto done; + } + cprintf(cbret, ""); + retval = 0; + done: + return retval; } /*! Start example restonf plugin. Set authentication method diff --git a/test/test_netconf.sh b/test/test_netconf.sh index 60ce0214..eb3c0ed6 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -192,7 +192,7 @@ new "netconf empty rpc" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf client-side rpc" -expecteof "$clixon_netconf -qf $cfg" 0 'example]]>]]>' '^ok]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 'val42]]>]]>' '^val42]]>]]>$' if [ $BE -eq 0 ]; then exit # BE diff --git a/test/test_restconf.sh b/test/test_restconf.sh index 6f41f6f7..462ac83f 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -228,6 +228,7 @@ new2 "restconf rpc using POST json" expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"x":42}}' http://localhost/restconf/operations/clixon-example:example)" '{"clixon-example:output": {"x": "42","y": "42"}} ' +new2 "restconf rpc using POST json wrong" expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/clixon-example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}} ' new2 "restconf rpc non-existing rpc without namespace" @@ -254,8 +255,8 @@ new2 "restconf rpc using wrong prefix" expecteq "$(curl -s -X POST -d '{"wrong:input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/wrong:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}} ' new "restconf local client rpc using POST xml" -ret=$(curl -s -i -X POST -H "Accept: application/yang-data+xml" -d '{"clixon-example:input":{"request":"example"}}' http://localhost/restconf/operations/clixon-example:client-rpc) -expect='ok' +ret=$(curl -s -i -X POST -H "Accept: application/yang-data+xml" -d '{"clixon-example:input":{"x":"example"}}' http://localhost/restconf/operations/clixon-example:client-rpc) +expect='example' match=`echo $ret | grep -EZo "$expect"` if [ -z "$match" ]; then err "$expect" "$ret"