diff --git a/CHANGELOG.md b/CHANGELOG.md index 80cdf30b..088e6482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Major changes: -* (Work in progress) Restconf error handling for get, put and post. Several cornercases remain, including validate/commit. Available both as xml and json (set accept header), pretty-printed and not (set clixon config option). +* Restconf error handling for get, put and post. Several cornercases remain. Available both as xml and json (set accept header), pretty-printed and not (set clixon config option). ### Minor changes: * Add username to rpc calls to prepare for authorization for backend: diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index a2be4db7..5d084403 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -104,24 +104,38 @@ api_data(clicon_handle h, { int retval = -1; char *request_method; + int pretty; + char *media_content_type; + int parse_xml = 0; /* By default expect and parse JSON */ + char *media_accept; + int use_xml = 0; /* By default use JSON */ clicon_debug(1, "%s", __FUNCTION__); request_method = FCGX_GetParam("REQUEST_METHOD", r->envp); clicon_debug(1, "%s method:%s", __FUNCTION__, request_method); + pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); + media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp); + if (strcmp(media_accept, "application/yang-data+xml")==0) + use_xml++; + media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp); + if (media_content_type && + strcmp(media_content_type, "application/yang-data+xml")==0) + parse_xml++; + if (strcmp(request_method, "OPTIONS")==0) retval = api_data_options(h, r); else if (strcmp(request_method, "HEAD")==0) - retval = api_data_head(h, r, pcvec, pi, qvec, username); + retval = api_data_head(h, r, pcvec, pi, qvec, username, pretty, use_xml); else if (strcmp(request_method, "GET")==0) - retval = api_data_get(h, r, pcvec, pi, qvec, username); + retval = api_data_get(h, r, pcvec, pi, qvec, username, pretty, use_xml); else if (strcmp(request_method, "POST")==0) - retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data, username); + retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data, username, pretty, use_xml, parse_xml); else if (strcmp(request_method, "PUT")==0) - retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data, username); + retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data, username, pretty, use_xml, parse_xml); else if (strcmp(request_method, "PATCH")==0) retval = api_data_patch(h, r, api_path, pcvec, pi, qvec, data, username); else if (strcmp(request_method, "DELETE")==0) - retval = api_data_delete(h, r, api_path, pi, username); + retval = api_data_delete(h, r, api_path, pi, username, pretty, use_xml); else retval = notfound(r); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); @@ -150,14 +164,29 @@ api_operations(clicon_handle h, { int retval = -1; char *request_method; + int pretty; + char *media_content_type; + int parse_xml = 0; /* By default expect and parse JSON */ + char *media_accept; + int use_xml = 0; /* By default use JSON */ clicon_debug(1, "%s", __FUNCTION__); request_method = FCGX_GetParam("REQUEST_METHOD", r->envp); clicon_debug(1, "%s method:%s", __FUNCTION__, request_method); + pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); + media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp); + if (strcmp(media_accept, "application/yang-data+xml")==0) + use_xml++; + media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp); + if (media_content_type && + strcmp(media_content_type, "application/yang-data+xml")==0) + parse_xml++; + if (strcmp(request_method, "GET")==0) - retval = api_operations_get(h, r, path, pcvec, pi, qvec, data, username); + retval = api_operations_get(h, r, path, pcvec, pi, qvec, data, username, pretty, use_xml); else if (strcmp(request_method, "POST")==0) - retval = api_operations_post(h, r, path, pcvec, pi, qvec, data, username); + retval = api_operations_post(h, r, path, pcvec, pi, qvec, data, username, + pretty, use_xml, parse_xml); else retval = notfound(r); return retval; diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 5ff69548..c5032c8b 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -211,6 +211,8 @@ api_return_err(clicon_handle h, * @param[in] pi Offset, where path starts * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML * @param[in] head If 1 is HEAD, otherwise GET * @code * curl -G http://localhost/restconf/data/interfaces/interface=eth0 @@ -235,6 +237,8 @@ api_data_get2(clicon_handle h, int pi, cvec *qvec, char *username, + int pretty, + int use_xml, int head) { int retval = -1; @@ -244,19 +248,12 @@ api_data_get2(clicon_handle h, yang_spec *yspec; cxobj *xret = NULL; cxobj *xerr; - char *media_accept; - int use_xml = 0; /* By default use JSON */ cxobj **xvec = NULL; size_t xlen; - int pretty; int i; cxobj *x; clicon_debug(1, "%s", __FUNCTION__); - pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); - media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp); - if (strcmp(media_accept, "application/yang-data+xml")==0) - use_xml++; yspec = clicon_dbspec_yang(h); if ((cbpath = cbuf_new()) == NULL) goto done; @@ -349,9 +346,12 @@ api_data_get2(clicon_handle h, * @param[in] pi Offset, where path starts * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] username Authenticated user - The HEAD method is sent by the client to retrieve just the header fields - that would be returned for the comparable GET method, without the - response message-body. + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML + * + * The HEAD method is sent by the client to retrieve just the header fields + * that would be returned for the comparable GET method, without the + * response message-body. * Relation to netconf: none */ int @@ -360,9 +360,11 @@ api_data_head(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, - char *username) + char *username, + int pretty, + int use_xml) { - return api_data_get2(h, r, pcvec, pi, qvec, username, 1); + return api_data_get2(h, r, pcvec, pi, qvec, username, pretty, use_xml, 1); } /*! REST GET method @@ -373,6 +375,8 @@ api_data_head(clicon_handle h, * @param[in] pi Offset, where path starts * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML * @code * curl -G http://localhost/restconf/data/interfaces/interface=eth0 * @endcode @@ -395,9 +399,11 @@ api_data_get(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, - char *username) + char *username, + int pretty, + int use_xml) { - return api_data_get2(h, r, pcvec, pi, qvec, username, 0); + return api_data_get2(h, r, pcvec, pi, qvec, username, pretty, use_xml, 0); } /*! Generic REST POST method @@ -409,6 +415,9 @@ api_data_get(clicon_handle h, * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] data Stream input data * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML for output data + * @param[in] parse_xml Set to 0 for JSON and 1 for XML for input data * @note restconf POST is mapped to edit-config create. POST: @@ -436,11 +445,13 @@ api_data_post(clicon_handle h, int pi, cvec *qvec, char *data, - char *username) + char *username, + int pretty, + int use_xml, + int parse_xml) { int retval = -1; enum operation_type op = OP_CREATE; - int pretty; int i; cxobj *xdata = NULL; cbuf *cbx = NULL; @@ -451,24 +462,13 @@ api_data_post(clicon_handle h, yang_spec *yspec; cxobj *xa; cxobj *xu; - char *media_content_type; - int parse_xml = 0; /* By default expect and parse JSON */ cxobj *xret = NULL; + cxobj *xretcom = NULL; cxobj *xerr; - char *media_accept; - int use_xml = 0; /* By default use JSON */ clicon_debug(1, "%s api_path:\"%s\" json:\"%s\"", __FUNCTION__, api_path, data); - pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); - media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp); - if (strcmp(media_accept, "application/yang-data+xml")==0) - use_xml++; - media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp); - if (media_content_type && - strcmp(media_content_type, "application/yang-data+xml")==0) - parse_xml++; if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_FATAL, 0, "No DB_SPEC"); goto done; @@ -527,7 +527,6 @@ api_data_post(clicon_handle h, cprintf(cbx, "none"); if (clicon_xml2cbuf(cbx, xtop, 0, 0) < 0) goto done; - cprintf(cbx, ""); clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path); if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) @@ -535,14 +534,17 @@ api_data_post(clicon_handle h, if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ if (api_return_err(h, r, xerr, pretty, use_xml) < 0) goto done; - goto done; + goto ok; } /* Assume this is validation failed since commit includes validate */ - if (clicon_rpc_commit(h) < 0){ + if (clicon_rpc_netconf(h, "", &xretcom, NULL) < 0) + goto done; + if ((xerr = xpath_first(xretcom, "//rpc-error")) != NULL){ if (clicon_rpc_discard_changes(h) < 0) goto done; - badrequest(r); - goto done; + if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + goto done; + goto ok; } FCGX_SetExitStatus(201, r->out); /* Created */ FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n"); @@ -553,6 +555,8 @@ api_data_post(clicon_handle h, clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); if (xret) xml_free(xret); + if (xretcom) + xml_free(xretcom); if (xtop) xml_free(xtop); if (xdata) @@ -623,6 +627,10 @@ match_list_keys(yang_stmt *y, * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] data Stream input data * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML for output data + * @param[in] parse_xml Set to 0 for JSON and 1 for XML for input data + * @note restconf PUT is mapped to edit-config replace. * @example curl -X PUT -d '{"enabled":"false"}' http://127.0.0.1/restconf/data/interfaces/interface=eth1 @@ -642,7 +650,10 @@ api_data_put(clicon_handle h, int pi, cvec *qvec, char *data, - char *username) + char *username, + int pretty, + int use_xml, + int parse_xml) { int retval = -1; enum operation_type op = OP_REPLACE; @@ -657,16 +668,13 @@ api_data_put(clicon_handle h, yang_spec *yspec; cxobj *xa; cxobj *xu; - char *media_content_type; - int parse_xml = 0; /* By default expect and parse JSON */ char *api_path; + cxobj *xret = NULL; + cxobj *xretcom = NULL; + cxobj *xerr; clicon_debug(1, "%s api_path:\"%s\" json:\"%s\"", __FUNCTION__, api_path0, data); - media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp); - if (media_content_type && - strcmp(media_content_type, "application/yang-data+xml")==0) - parse_xml++; if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_FATAL, 0, "No DB_SPEC"); goto done; @@ -746,21 +754,27 @@ api_data_put(clicon_handle h, /* Create text buffer for transfer to backend */ if ((cbx = cbuf_new()) == NULL) goto done; + cprintf(cbx, ""); + cprintf(cbx, "none"); if (clicon_xml2cbuf(cbx, xtop, 0, 0) < 0) goto done; + cprintf(cbx, ""); clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path); - if (clicon_rpc_edit_config(h, "candidate", - OP_NONE, - cbuf_get(cbx)) < 0){ - notfound(r); + if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) + goto done; + if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + goto done; goto ok; } - /* Assume this is validation failed since commit includes validate */ - if (clicon_rpc_commit(h) < 0){ - if (clicon_rpc_discard_changes(h) < 0) - goto done; - badrequest(r); + if (clicon_rpc_netconf(h, "", &xretcom, NULL) < 0) goto done; + if ((xerr = xpath_first(xretcom, "//rpc-error")) != NULL){ + if (clicon_rpc_discard_changes(h) < 0) + goto done; + if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + goto done; + goto ok; } FCGX_SetExitStatus(201, r->out); /* Created */ FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n"); @@ -769,6 +783,10 @@ api_data_put(clicon_handle h, retval = 0; done: clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); + if (xret) + xml_free(xret); + if (xretcom) + xml_free(xretcom); if (xtop) xml_free(xtop); if (xdata) @@ -807,8 +825,10 @@ api_data_patch(clicon_handle h, * @param[in] h CLIXON handle * @param[in] r Fastcgi request handle * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) - * @param[in] username Authenticated user * @param[in] pi Offset, where path starts + * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML * Example: * curl -X DELETE http://127.0.0.1/restconf/data/interfaces/interface=eth0 * Netconf: (nc:operation="delete") @@ -818,7 +838,9 @@ api_data_delete(clicon_handle h, FCGX_Request *r, char *api_path, int pi, - char *username) + char *username, + int pretty, + int use_xml) { int retval = -1; int i; @@ -830,6 +852,9 @@ api_data_delete(clicon_handle h, yang_node *y = NULL; yang_spec *yspec; enum operation_type op = OP_DELETE; + cxobj *xret = NULL; + cxobj *xretcom = NULL; + cxobj *xerr; clicon_debug(1, "%s api_path:%s", __FUNCTION__, api_path); if ((yspec = clicon_dbspec_yang(h)) == NULL){ @@ -860,21 +885,27 @@ api_data_delete(clicon_handle h, goto done; if ((cbx = cbuf_new()) == NULL) goto done; - + cprintf(cbx, ""); + cprintf(cbx, "none"); if (clicon_xml2cbuf(cbx, xtop, 0, 0) < 0) goto done; - if (clicon_rpc_edit_config(h, "candidate", - OP_NONE, - cbuf_get(cbx)) < 0){ - notfound(r); + cprintf(cbx, ""); + if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) + goto done; + if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + goto done; goto ok; } /* Assume this is validation failed since commit includes validate */ - if (clicon_rpc_commit(h) < 0){ - if (clicon_rpc_discard_changes(h) < 0) - goto done; - badrequest(r); + if (clicon_rpc_netconf(h, "", &xretcom, NULL) < 0) goto done; + if ((xerr = xpath_first(xretcom, "//rpc-error")) != NULL){ + if (clicon_rpc_discard_changes(h) < 0) + goto done; + if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + goto done; + goto ok; } FCGX_SetExitStatus(201, r->out); FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n"); @@ -884,6 +915,10 @@ api_data_delete(clicon_handle h, done: if (cbx) cbuf_free(cbx); + if (xret) + xml_free(xret); + if (xretcom) + xml_free(xretcom); if (xtop) xml_free(xtop); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); @@ -899,6 +934,8 @@ api_data_delete(clicon_handle h, * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] data Stream input data * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML * * @code * curl -G http://localhost/restconf/operations @@ -911,18 +948,17 @@ api_data_delete(clicon_handle h, */ int api_operations_get(clicon_handle h, - FCGX_Request *r, - char *path, - cvec *pcvec, - int pi, - cvec *qvec, - char *data, - char *username) + FCGX_Request *r, + char *path, + cvec *pcvec, + int pi, + cvec *qvec, + char *data, + char *username, + int pretty, + int use_xml) { int retval = -1; - int pretty; - char *media_accept; - int use_xml = 0; /* By default use JSON */ yang_spec *yspec; yang_stmt *ym; yang_stmt *yc; @@ -932,10 +968,6 @@ api_operations_get(clicon_handle h, cxobj *xt = NULL; clicon_debug(1, "%s", __FUNCTION__); - pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); - media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp); - if (strcmp(media_accept, "application/yang-data+xml")==0) - use_xml++; yspec = clicon_dbspec_yang(h); if ((cbx = cbuf_new()) == NULL) goto done; @@ -994,19 +1026,25 @@ api_operations_get(clicon_handle h, * @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] data Stream input data * @param[in] username Authenticated user + * @param[in] pretty Set to 1 for pretty-printed xml/json output + * @param[in] use_xml Set to 0 for JSON and 1 for XML for output data + * @param[in] parse_xml Set to 0 for JSON and 1 for XML for input data * @note We map post to edit-config create. POST {+restconf}/operations/ */ int api_operations_post(clicon_handle h, - FCGX_Request *r, - char *path, - cvec *pcvec, - int pi, - cvec *qvec, - char *data, - char *username) + FCGX_Request *r, + char *path, + cvec *pcvec, + int pi, + cvec *qvec, + char *data, + char *username, + int pretty, + int use_xml, + int parse_xml) { int retval = -1; int i; @@ -1024,24 +1062,9 @@ api_operations_post(clicon_handle h, cxobj *xinput; cxobj *xoutput; cxobj *x; - char *media_content_type; - int parse_xml = 0; /* By default expect and parse JSON */ - char *media_accept; - int use_xml = 0; /* By default return JSON */ - int pretty; cxobj *xa; clicon_debug(1, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, path); - pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY"); - if ((media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp)) && - strcmp(media_accept, "application/yang-data+xml")==0) - use_xml++; - media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp); - if (media_content_type && - strcmp(media_content_type, "application/yang-data+xml")==0) - parse_xml++; - clicon_debug(1, "%s accept:\"%s\" content-type:\"%s\"", - __FUNCTION__, media_accept, media_content_type); if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_FATAL, 0, "No DB_SPEC"); goto done; @@ -1128,8 +1151,7 @@ api_operations_post(clicon_handle h, xml_name_set(xoutput, "output"); if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL && xoutput){ - - clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx)); + // clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx)); cbuf_reset(cbx); xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */ if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, youtput) < 0) diff --git a/apps/restconf/restconf_methods.h b/apps/restconf/restconf_methods.h index 246552b2..b482d9ce 100644 --- a/apps/restconf/restconf_methods.h +++ b/apps/restconf/restconf_methods.h @@ -46,28 +46,31 @@ */ int api_data_options(clicon_handle h, FCGX_Request *r); int api_data_head(clicon_handle h, FCGX_Request *r, cvec *pcvec, int pi, - cvec *qvec, char *username); + cvec *qvec, char *username, int pretty, int use_xml); int api_data_get(clicon_handle h, FCGX_Request *r, cvec *pcvec, int pi, - cvec *qvec, char *username); + cvec *qvec, char *username, int pretty, int use_xml); int api_data_post(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, - cvec *qvec, char *data, char *username); + cvec *qvec, char *data, char *username, + int pretty, int use_xml, int parse_xml); int api_data_put(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, - cvec *qvec, char *data, char *username); + cvec *qvec, char *data, char *username, + int pretty, int use_xml, int parse_xml); int api_data_patch(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, cvec *qvec, char *data, char *username); int api_data_delete(clicon_handle h, FCGX_Request *r, char *api_path, int pi, - char *username); + char *username, int pretty, int use_xml); int api_operations_get(clicon_handle h, FCGX_Request *r, char *path, - cvec *pcvec, int pi, cvec *qvec, char *data, char *username); + cvec *pcvec, int pi, cvec *qvec, char *data, char *username, + int pretty, int use_xml); int api_operations_post(clicon_handle h, FCGX_Request *r, char *path, cvec *pcvec, int pi, cvec *qvec, char *data, - char *username); + char *username, int pretty, int use_xml, int parse_xml); #endif /* _RESTCONF_METHODS_H_ */ diff --git a/test/test_restconf.sh b/test/test_restconf.sh index d09c7812..d0515410 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -211,7 +211,7 @@ new "Check deleted eth/0/0" expectfn 'curl -s -G http://localhost/restconf/data' $state new "restconf Re-Delete eth/0/0 using none should generate error" -expectfn 'curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' "Not Found" +expectfn 'curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' '"error-message": "Object to delete does not exist"' new "restconf Add subtree eth/0/0 using PUT" expectfn 'curl -s -X PUT -d {"interface":{"name":"eth/0/0","type":"eth","enabled":true}} http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' "" diff --git a/test/test_restconf2.sh b/test/test_restconf2.sh index 55a23308..db275dc1 100755 --- a/test/test_restconf2.sh +++ b/test/test_restconf2.sh @@ -77,6 +77,9 @@ expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" new "restconf GET if-type" expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0/type" '{"type": "regular"}' +new "restconf POST interface without mandatory type" +expectfn 'curl -s -X POST -d {"interface":{"name":"TEST"}} http://localhost/restconf/data/cont1' '"error-message": "Missing mandatory variable: type"' + new "restconf POST interface" expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1' "" @@ -133,9 +136,6 @@ expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://l new "restconf PUT change key error" expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' "Bad request" -new "restconf POST invalid no type" -expectfn 'curl -s -X POST -d {"interface":{"name":"ALPHA"}} http://localhost/restconf/data/cont1' "Bad request" - new "Kill restconf daemon" sudo pkill -u www-data clixon_restconf