Invalid api-path syntax error changed from 412 operation-failed to 404 invalid-value.
This commit is contained in:
parent
8c18f2a86d
commit
22307e0a9e
7 changed files with 66 additions and 17 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -10,6 +10,17 @@
|
|||
* If dropped temporary, you can restore privileges with `restore_priv()`
|
||||
|
||||
### API changes on existing features (you may need to change your code)
|
||||
* RESTCONF error reporting
|
||||
* Invalid api-path syntax error changed from 412 operation-failed to 404 invalid-value. For example, change from
|
||||
```
|
||||
HTTP/1.1 412 Precondition Failed
|
||||
{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"No such yang module: badmodule"}}}
|
||||
```
|
||||
to:
|
||||
```
|
||||
HTTP/1.1 404 Not Found
|
||||
{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"No such yang module: badmodule"}}}
|
||||
```
|
||||
* Typical installation should now add a `clicon` user (as well as group)
|
||||
* New clixon-config@2019-09-11.yang revision
|
||||
* Added: CLICON_BACKEND_USER: drop of privileges to user,
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@
|
|||
*/
|
||||
static const map_str2int netconf_restconf_map[] = {
|
||||
{"in-use", 409},
|
||||
{"invalid-value", 400},
|
||||
{"invalid-value", 404},
|
||||
{"invalid-value", 400},
|
||||
{"invalid-value", 406},
|
||||
{"too-big", 413}, /* request */
|
||||
{"too-big", 400}, /* response */
|
||||
|
|
|
|||
|
|
@ -280,12 +280,9 @@ api_data_write(clicon_handle h,
|
|||
if ((cbpath = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
cprintf(cbpath, "/");
|
||||
if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace)) < 0)
|
||||
if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0)
|
||||
goto done;
|
||||
clicon_err_reset();
|
||||
if ((xe = xpath_first(xerr, "rpc-error")) == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -166,8 +166,18 @@ api_data_get2(clicon_handle h,
|
|||
goto done;
|
||||
cprintf(cbpath, "/");
|
||||
/* We know "data" is element pi-1 */
|
||||
if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace)) < 0)
|
||||
if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
clicon_err_reset();
|
||||
if ((xe = xpath_first(xerr, "rpc-error")) == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||
goto done;
|
||||
}
|
||||
if (api_return_err(h, r, xe, pretty, media_out, 0) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (ret == 0){
|
||||
if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ int xml_sanity(cxobj *x, void *arg);
|
|||
int xml_non_config_data(cxobj *xt, void *arg);
|
||||
int xml_spec_populate_rpc(clicon_handle h, cxobj *x, yang_stmt *yspec);
|
||||
int xml_spec_populate(cxobj *x, void *arg);
|
||||
int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, char **namespace);
|
||||
int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, char **namespace, cxobj **xerr);
|
||||
int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, char **namespace);
|
||||
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
|
||||
yang_class nodeclass, int strict, cxobj **xpathp, yang_stmt **ypathp);
|
||||
|
|
|
|||
|
|
@ -2382,11 +2382,12 @@ xml_spec_populate(cxobj *x,
|
|||
* @param[in] yspec Yang spec
|
||||
* @param[in,out] xpath The xpath as cbuf (must be created and may have content)
|
||||
* @param[out] namespace Namespace of xpath (direct pointer don't free)
|
||||
* @param[out] xerr Netconf error message
|
||||
* @retval 1 OK
|
||||
* @retval 0 Invalid api_path or associated XML, clicon_err called
|
||||
* @retval 0 Invalid api_path or associated XML, netconf error xml set
|
||||
* @retval -1 Fatal error, clicon_err called
|
||||
*
|
||||
* @note both retval 0 and -1 set clicon_err, but the later is fatal
|
||||
* @note both retval -1 set clicon_err, retval 0 sets netconf xml msg
|
||||
* @note Not proper namespace translation from api-path 2 xpath
|
||||
* It works like this:
|
||||
* Assume origin incoming path is
|
||||
|
|
@ -2413,7 +2414,8 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
int offset,
|
||||
yang_stmt *yspec,
|
||||
cbuf *xpath,
|
||||
char **namespace)
|
||||
char **namespace,
|
||||
cxobj **xerr)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
|
|
@ -2429,6 +2431,7 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
char **valvec = NULL;
|
||||
int vi;
|
||||
int nvalvec;
|
||||
cbuf *cberr = NULL;
|
||||
|
||||
for (i=offset; i<cvec_len(api_path); i++){
|
||||
cv = cvec_i(api_path, i);
|
||||
|
|
@ -2438,11 +2441,23 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
clicon_debug(1, "%s [%d] cvname: %s:%s", __FUNCTION__, i, prefix?prefix:"", name);
|
||||
if (i == offset){ /* top-node */
|
||||
if (prefix == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "'%s': Expected prefix:name", nodeid);
|
||||
if ((cberr = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cberr, "'%s': Expected prefix:name", nodeid);
|
||||
if (netconf_invalid_value_xml(xerr, "application", cbuf_get(cberr)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
if ((ymod = yang_find_module_by_name(yspec, prefix)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "No such yang module: %s", prefix);
|
||||
if ((cberr = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cberr, "No such yang module: %s", prefix);
|
||||
if (netconf_invalid_value_xml(xerr, "application", cbuf_get(cberr)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
y = yang_find_datanode(ymod, name);
|
||||
|
|
@ -2450,7 +2465,13 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
else
|
||||
y = yang_find_datanode(y, name);
|
||||
if (y == NULL){
|
||||
clicon_err(OE_YANG, errno, "Unknown element: '%s'", name);
|
||||
if ((cberr = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cberr, "Unknown element: '%s'", name);
|
||||
if (netconf_invalid_value_xml(xerr, "application", cbuf_get(cberr)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
/* Check if has value, means '=' */
|
||||
|
|
@ -2506,6 +2527,8 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
*namespace = yang_find_mynamespace(ymod);
|
||||
retval = 1; /* OK */
|
||||
done:
|
||||
if (cberr != NULL)
|
||||
cbuf_free(cberr);
|
||||
if (valvec)
|
||||
free(valvec);
|
||||
if (prefix)
|
||||
|
|
@ -2524,7 +2547,7 @@ api_path2xpath_cvv(cvec *api_path,
|
|||
* @param[out] xpath xpath (use free() to deallocate)
|
||||
* @param[out] namespace Namespace of xpath (direct pointer don't free)
|
||||
* @retval 1 OK
|
||||
* @retval 0 Invalid api_path or associated XML, clicon_err called
|
||||
* @retval 0 Invalid api_path or associated XML, netconf called
|
||||
* @retval -1 Fatal error, clicon_err called
|
||||
* @code
|
||||
* char *xpath = NULL;
|
||||
|
|
@ -2546,16 +2569,22 @@ api_path2xpath(char *api_path,
|
|||
int retval = -1;
|
||||
cvec *cvv = NULL; /* api-path vector */
|
||||
cbuf *xpath = NULL; /* xpath as cbuf (sub-function uses that) */
|
||||
cxobj *xerr = NULL; /* ignored */
|
||||
|
||||
/* Split api-path into cligen variable vector */
|
||||
if (str2cvec(api_path, '/', '=', &cvv) < 0)
|
||||
goto done;
|
||||
if ((xpath = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
if ((retval = api_path2xpath_cvv(cvv, 0, yspec, xpath, namespace)) < 0)
|
||||
if ((retval = api_path2xpath_cvv(cvv, 0, yspec, xpath, namespace, &xerr)) < 0){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
if (retval == 0)
|
||||
}
|
||||
if (retval == 0){
|
||||
/* XXX: xerr ignored */
|
||||
clicon_err(OE_XML, EINVAL, "xml does not adhere to yang");
|
||||
goto fail;
|
||||
}
|
||||
/* prepare output xpath parameter */
|
||||
if (xpathp)
|
||||
if ((*xpathp = strdup(cbuf_get(xpath))) == NULL){
|
||||
|
|
@ -2564,6 +2593,8 @@ api_path2xpath(char *api_path,
|
|||
}
|
||||
retval = 1;
|
||||
done:
|
||||
if (xerr)
|
||||
xml_free(xerr);
|
||||
if (cvv)
|
||||
cvec_free(cvv);
|
||||
if (xpath)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ expecteq "$(curl -sS -X GET http://localhost/restconf/data/clixon-example:state)
|
|||
'
|
||||
|
||||
new "restconf get empty config + state json with wrong module name"
|
||||
expecteq "$(curl -sSG http://localhost/restconf/data/badmodule:state)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"No such yang module: badmodule"}}}
'
|
||||
expectpart "$(curl -siSG http://localhost/restconf/data/badmodule:state)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"No such yang module: badmodule"}}}'
|
||||
|
||||
new "restconf get empty config + state xml"
|
||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/clixon-example:state)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue