diff --git a/apps/restconf/restconf_api_evhtp.c b/apps/restconf/restconf_api_evhtp.c
index 1f7b559d..2b833fe2 100644
--- a/apps/restconf/restconf_api_evhtp.c
+++ b/apps/restconf/restconf_api_evhtp.c
@@ -148,12 +148,18 @@ restconf_reply_send(void *req0,
htp_sslutil_add_xheaders(req->headers_out, conn->ssl, HTP_SSLUTILS_XHDR_ALL);
#endif
+ /* If body, add a content-length header */
+ if (cb != NULL && cbuf_len(cb))
+ if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
+ goto done;
+
/* create evbuffer* : bufferevent_write_buffer/ drain,
ie send everything , except body */
evhtp_send_reply_start(req, req->status);
/* Write a body if cbuf is nonzero */
if (cb != NULL && cbuf_len(cb)){
+
/* Suboptimal, copy from cbuf to evbuffer */
if ((eb = evbuffer_new()) == NULL){
clicon_err(OE_CFG, errno, "evbuffer_new");
diff --git a/apps/restconf/restconf_err.c b/apps/restconf/restconf_err.c
index 047d3be9..ff8c034c 100644
--- a/apps/restconf/restconf_err.c
+++ b/apps/restconf/restconf_err.c
@@ -102,8 +102,6 @@ restconf_badrequest(clicon_handle h,
if (restconf_reply_header(req, "Content-Type", "text/html") < 0)
goto done;
cprintf(cb, "The requested URL %s or data is in some way badly formed.\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 400, cb) < 0)
goto done;
retval = 0;
@@ -144,9 +142,6 @@ restconf_unauthorized(clicon_handle h,
goto done;
cprintf(cb, "access-denied\n");
cprintf(cb, "The requested URL %s was unauthorized.\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
-
if (restconf_reply_send(req, 400, cb) < 0)
goto done;
retval = 0;
@@ -184,8 +179,6 @@ restconf_forbidden(clicon_handle h,
if (restconf_reply_header(req, "Content-Type", "text/html") < 0)
goto done;
cprintf(cb, "The requested URL %s was forbidden.\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 403, cb) < 0)
goto done;
retval = 0;
@@ -224,8 +217,6 @@ restconf_notfound(clicon_handle h,
if (restconf_reply_header(req, "Content-Type", "text/html") < 0)
goto done;
cprintf(cb, "The requested URL %s was not found on this server.\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 404, cb) < 0)
goto done;
retval = 0;
@@ -283,8 +274,6 @@ restconf_notacceptable(clicon_handle h,
if (restconf_reply_header(req, "Content-Type", "text/html") < 0)
goto done;
cprintf(cb, "The target resource does not have a current representation that would be acceptable to the user agent.\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 406, cb) < 0)
goto done;
retval = 0;
@@ -353,8 +342,6 @@ restconf_internal_server_error(clicon_handle h,
if (restconf_reply_header(req, "Content-Type", "text/html") < 0)
goto done;
cprintf(cb, "Internal server error when accessing %s\n", path);
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)=
- goto done;
if (restconf_reply_send(req, 500, cb) < 0)
goto done;
retval = 0;
@@ -479,8 +466,6 @@ api_return_err(clicon_handle h,
goto done;
break;
} /* switch media */
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, code, cb) < 0)
goto done;
// ok:
diff --git a/apps/restconf/restconf_evhtp_main.c b/apps/restconf/restconf_evhtp_main.c
index 3ed9dcd0..dcc690ce 100644
--- a/apps/restconf/restconf_evhtp_main.c
+++ b/apps/restconf/restconf_evhtp_main.c
@@ -138,11 +138,41 @@ evhtp_method2str(enum htp_method m)
case htp_method_DELETE:
return "DELETE";
break;
+ case htp_method_MKCOL:
+ return "MKCOL";
+ break;
+ case htp_method_COPY:
+ return "COPY";
+ break;
+ case htp_method_MOVE:
+ return "MOVE";
+ break;
+ case htp_method_OPTIONS:
+ return "OPTIONS";
+ break;
+ case htp_method_PROPFIND:
+ return "PROPFIND";
+ break;
+ case htp_method_PROPPATCH:
+ return "PROPPATCH";
+ break;
+ case htp_method_LOCK:
+ return "LOCK";
+ break;
+ case htp_method_UNLOCK:
+ return "UNLOCK";
+ break;
+ case htp_method_TRACE:
+ return "TRACE";
+ break;
+ case htp_method_CONNECT:
+ return "CONNECT";
+ break;
case htp_method_PATCH:
return "PATCH";
break;
default:
- return "XXX";
+ return "UNKNOWN";
break;
}
}
@@ -221,7 +251,6 @@ evhtp_params_set(clicon_handle h,
clicon_err(OE_CFG, errno, "evhtp_kvs_for_each");
goto done;
}
-
if (clixon_restconf_param_set(h, "REQUEST_METHOD", evhtp_method2str(meth)) < 0)
goto done;
if (clixon_restconf_param_set(h, "REQUEST_URI", path->full) < 0)
@@ -327,6 +356,7 @@ cx_path_wellknown(evhtp_request_t *req,
{
clicon_handle h = arg;
+ clicon_debug(1, "------------");
/* input debug */
if (clicon_debug_get())
evhtp_headers_for_each(req->headers_in, print_header, h);
@@ -356,6 +386,7 @@ cx_path_restconf(evhtp_request_t *req,
clicon_handle h = arg;
cvec *qvec = NULL;
+ clicon_debug(1, "------------");
/* input debug */
if (clicon_debug_get())
evhtp_headers_for_each(req->headers_in, print_header, h);
diff --git a/apps/restconf/restconf_fcgi_main.c b/apps/restconf/restconf_fcgi_main.c
index 6552ee6c..ebd0b56f 100644
--- a/apps/restconf/restconf_fcgi_main.c
+++ b/apps/restconf/restconf_fcgi_main.c
@@ -107,7 +107,6 @@ fcgi_params_set(clicon_handle h,
for (i = 0; envp[i] != NULL; i++){ /* on the form = */
if (clixon_strsplit(envp[i], '=', ¶m, &val) < 0)
goto done;
- clicon_debug(1, "%s param:%s val:%s", __FUNCTION__, param, val);
if (clixon_restconf_param_set(h, param, val) < 0)
goto done;
if (param){
@@ -142,7 +141,6 @@ fcgi_params_clear(clicon_handle h,
for (i = 0; envp[i] != NULL; i++){ /* on the form = */
if (clixon_strsplit(envp[i], '=', ¶m, NULL) < 0)
goto done;
- clicon_debug(1, "%s param:%s", __FUNCTION__, param);
if (clixon_restconf_param_del(h, param) < 0)
goto done;
if (param){
@@ -152,371 +150,9 @@ fcgi_params_clear(clicon_handle h,
}
retval = 0;
done:
- clicon_debug(1, "%s %d", __FUNCTION__, retval);
return retval;
}
-/*! Print all FCGI headers
- * @param[in] req Fastcgi request handle
- * @see https://nginx.org/en/docs/http/ngx_http_core_module.html#var_https
- */
-static int
-fcgi_print_headers(FCGX_Request *req)
-{
- char **environ = req->envp;
- int i;
-
- clicon_debug(1, "All environment vars:");
- for (i = 0; environ[i] != NULL; i++)
- clicon_debug(1, "%s", environ[i]);
- clicon_debug(1, "End environment vars");
- return 0;
-}
-
-/*! Generic REST method, GET, PUT, DELETE, etc
- * @param[in] h CLIXON handle
- * @param[in] r Fastcgi request handle
- * @param[in] api_path According to restconf (Sec 3.5.1.1 in [draft])
- * @param[in] pcvec Vector of path ie DOCUMENT_URI element
- * @param[in] pi Offset, where to start pcvec
- * @param[in] qvec Vector of query string (QUERY_STRING)
- * @param[in] pretty Set to 1 for pretty-printed xml/json output
- * @param[in] media_in Input media
- * @param[in] media_out Output media
- */
-static int
-api_data(clicon_handle h,
- FCGX_Request *req,
- char *api_path,
- cvec *pcvec,
- int pi,
- cvec *qvec,
- char *data,
- int pretty,
- restconf_media media_out)
-{
- int retval = -1;
- char *request_method;
-
- clicon_debug(1, "%s", __FUNCTION__);
- request_method = clixon_restconf_param_get(h, "REQUEST_METHOD");
- clicon_debug(1, "%s method:%s", __FUNCTION__, request_method);
- if (strcmp(request_method, "OPTIONS")==0)
- retval = api_data_options(h, req);
- else if (strcmp(request_method, "HEAD")==0)
- retval = api_data_head(h, req, api_path, pcvec, pi, qvec, pretty, media_out);
- else if (strcmp(request_method, "GET")==0)
- retval = api_data_get(h, req, api_path, pcvec, pi, qvec, pretty, media_out);
- else if (strcmp(request_method, "POST")==0)
- retval = api_data_post(h, req, api_path, pi, qvec, data, pretty, media_out);
- else if (strcmp(request_method, "PUT")==0)
- retval = api_data_put(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out);
- else if (strcmp(request_method, "PATCH")==0)
- retval = api_data_patch(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out);
- else if (strcmp(request_method, "DELETE")==0)
- retval = api_data_delete(h, req, api_path, pi, pretty, media_out);
- else
- retval = restconf_notfound(h, req);
- clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
- return retval;
-}
-
-/*! Operations REST method, POST
- * @param[in] h CLIXON handle
- * @param[in] r Fastcgi request handle
- * @param[in] path According to restconf (Sec 3.5.1.1 in [draft])
- * @param[in] pcvec Vector of path ie DOCUMENT_URI element
- * @param[in] pi Offset, where to start pcvec
- * @param[in] qvec Vector of query string (QUERY_STRING)
- * @param[in] data Stream input data
- * @param[in] media_out Output media
- */
-static int
-api_operations(clicon_handle h,
- FCGX_Request *r,
- char *path,
- cvec *pcvec,
- int pi,
- cvec *qvec,
- char *data,
- int pretty,
- restconf_media media_out)
-{
- int retval = -1;
- char *request_method;
-
- clicon_debug(1, "%s", __FUNCTION__);
- request_method = clixon_restconf_param_get(h, "REQUEST_METHOD");
- clicon_debug(1, "%s method:%s", __FUNCTION__, request_method);
- if (strcmp(request_method, "GET")==0)
- retval = api_operations_get(h, r, path, pi, qvec, data, pretty, media_out);
- else if (strcmp(request_method, "POST")==0)
- retval = api_operations_post(h, r, path, pi, qvec, data,
- pretty, media_out);
- else
- retval = restconf_notfound(h, r);
- return retval;
-}
-
-/*! Retrieve the Top-Level API Resource
- * @param[in] h Clicon handle
- * @param[in] r Fastcgi request handle
- * @note Only returns null for operations and data,...
- * See RFC8040 3.3
- * XXX doesnt check method
- */
-static int
-api_fcgi_root(clicon_handle h,
- FCGX_Request *r,
- int pretty,
- restconf_media media_out)
-
-{
- int retval = -1;
- cxobj *xt = NULL;
- cbuf *cb = NULL;
- yang_stmt *yspec;
-
- clicon_debug(1, "%s", __FUNCTION__);
- if ((yspec = clicon_dbspec_yang(h)) == NULL){
- clicon_err(OE_FATAL, 0, "No DB_SPEC");
- goto done;
- }
- FCGX_SetExitStatus(200, r->out); /* OK */
- FCGX_FPrintF(r->out, "Status: 200 OK\r\n");
- FCGX_FPrintF(r->out, "Cache-Control: no-cache\r\n");
-
- FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
- FCGX_FPrintF(r->out, "\r\n");
-
- if (clixon_xml_parse_string(""
- "2016-06-21",
- YB_MODULE, yspec, &xt, NULL) < 0)
- goto done;
- if ((cb = cbuf_new()) == NULL){
- clicon_err(OE_XML, errno, "cbuf_new");
- goto done;
- }
- if (xml_rootchild(xt, 0, &xt) < 0)
- goto done;
- switch (media_out){
- case YANG_DATA_XML:
- if (clicon_xml2cbuf(cb, xt, 0, pretty, -1) < 0)
- goto done;
- break;
- case YANG_DATA_JSON:
- if (xml2json_cbuf(cb, xt, pretty) < 0)
- goto done;
- break;
- default:
- break;
- }
- FCGX_FPrintF(r->out, "%s", cb?cbuf_get(cb):"");
- FCGX_FPrintF(r->out, "\r\n\r\n");
- retval = 0;
- done:
- if (cb)
- cbuf_free(cb);
- if (xt)
- xml_free(xt);
- return retval;
-}
-
-/*!
- * See https://tools.ietf.org/html/rfc7895
- */
-static int
-api_yang_library_version(clicon_handle h,
- FCGX_Request *r,
- int pretty,
- restconf_media media_out)
-
-{
- int retval = -1;
- cxobj *xt = NULL;
- cbuf *cb = NULL;
- char *ietf_yang_library_revision = "2016-06-21"; /* XXX */
-
- clicon_debug(1, "%s", __FUNCTION__);
- FCGX_SetExitStatus(200, r->out); /* OK */
- FCGX_FPrintF(r->out, "Cache-Control: no-cache\r\n");
- FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
- FCGX_FPrintF(r->out, "\r\n");
- if (clixon_xml_parse_va(YB_NONE, NULL, &xt, NULL,
- "%s",
- ietf_yang_library_revision) < 0)
- goto done;
- if (xml_rootchild(xt, 0, &xt) < 0)
- goto done;
- if ((cb = cbuf_new()) == NULL){
- goto done;
- }
- switch (media_out){
- case YANG_DATA_XML:
- if (clicon_xml2cbuf(cb, xt, 0, pretty, -1) < 0)
- goto done;
- break;
- case YANG_DATA_JSON:
- if (xml2json_cbuf(cb, xt, pretty) < 0)
- goto done;
- break;
- default:
- break;
- }
- clicon_debug(1, "%s cb%s", __FUNCTION__, cbuf_get(cb));
- FCGX_FPrintF(r->out, "%s\n", cb?cbuf_get(cb):"");
- FCGX_FPrintF(r->out, "\n\n");
- retval = 0;
- done:
- if (cb)
- cbuf_free(cb);
- if (xt)
- xml_free(xt);
- return retval;
-}
-
-/*! Process a FastCGI request
- * @param[in] r Fastcgi request handle
- */
-static int
-api_fcgi_restconf(clicon_handle h,
- FCGX_Request *req)
-{
- int retval = -1;
- char *path;
- char *query = NULL;
- char *api_resource;
- char **pvec = NULL;
- int pn;
- cvec *qvec = NULL;
- cvec *pcvec = NULL; /* for rest api */
- cbuf *cb = NULL;
- char *indata = NULL;
- int authenticated = 0;
- char *media_str = NULL;
- restconf_media media_out = YANG_DATA_JSON;
- int pretty;
- cxobj *xret = NULL;
- cxobj *xerr;
-
- clicon_debug(1, "%s", __FUNCTION__);
- path = restconf_uripath(h);
- query = clixon_restconf_param_get(h, "QUERY_STRING");
- pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY");
-
- /* Get media for output (proactive negotiation) RFC7231 by using
- * Accept:. This is for methods that have output, such as GET,
- * operation POST, etc
- * If accept is * default is yang-json
- */
- if ((media_str = clixon_restconf_param_get(h, "HTTP_ACCEPT")) == NULL){
- // retval = restconf_unsupported_media(r);
- // goto done;
- }
- else if ((int)(media_out = restconf_media_str2int(media_str)) == -1){
- if (strcmp(media_str, "*/*") == 0) /* catch-all */
- media_out = YANG_DATA_JSON;
- else{
- retval = restconf_unsupported_media(req);
- goto done;
- }
- }
- clicon_debug(1, "%s ACCEPT: %s %s", __FUNCTION__, media_str, restconf_media_int2str(media_out));
-
- if ((pvec = clicon_strsep(path, "/", &pn)) == NULL)
- goto done;
- /* Sanity check of path. Should be /restconf/ */
- if (pn < 2){
- restconf_notfound(h, req);
- goto ok;
- }
- if (strlen(pvec[0]) != 0){
- retval = restconf_notfound(h, req);
- goto done;
- }
- if (strcmp(pvec[1], RESTCONF_API)){
- retval = restconf_notfound(h, req);
- goto done;
- }
- fcgi_print_headers(req);
-
- if (pn == 2){
- retval = api_fcgi_root(h, req, pretty, media_out);
- goto done;
- }
- if ((api_resource = pvec[2]) == NULL){
- retval = restconf_notfound(h, req);
- goto done;
- }
- clicon_debug(1, "%s: api_resource=%s", __FUNCTION__, api_resource);
- if (query != NULL && strlen(query))
- if (str2cvec(query, '&', '=', &qvec) < 0)
- goto done;
- if (str2cvec(path, '/', '=', &pcvec) < 0) /* rest url eg /album=ricky/foo */
- goto done;
- /* indata */
- if ((cb = restconf_get_indata(req)) == NULL)
- goto done;
- indata = cbuf_get(cb);
- clicon_debug(1, "%s DATA=%s", __FUNCTION__, indata);
-
- /* If present, check credentials. See "plugin_credentials" in plugin
- * See RFC 8040 section 2.5
- */
- if ((authenticated = clixon_plugin_auth_all(h, req)) < 0)
- goto done;
- clicon_debug(1, "%s auth:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
-
- /* If set but no user, set a dummy user */
- if (authenticated){
- if (clicon_username_get(h) == NULL)
- clicon_username_set(h, "none");
- }
- else{
- if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
- goto done;
- if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
- if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
- goto done;
- goto ok;
- }
- goto ok;
- }
- clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
- if (strcmp(api_resource, "yang-library-version")==0){
- if (api_yang_library_version(h, req, pretty, media_out) < 0)
- goto done;
- }
- else if (strcmp(api_resource, "data") == 0){ /* restconf, skip /api/data */
- if (api_data(h, req, path, pcvec, 2, qvec, indata,
- pretty, media_out) < 0)
- goto done;
- }
- else if (strcmp(api_resource, "operations") == 0){ /* rpc */
- if (api_operations(h, req, path, pcvec, 2, qvec, indata,
- pretty, media_out) < 0)
- goto done;
- }
- else
- restconf_notfound(h, req);
- ok:
- retval = 0;
- done:
- clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
- if (pvec)
- free(pvec);
- if (qvec)
- cvec_free(qvec);
- if (pcvec)
- cvec_free(pcvec);
- if (cb)
- cbuf_free(cb);
- if (xret)
- xml_free(xret);
- return retval;
-}
-
-
/* Need global variable to for signal handler XXX */
static clicon_handle _CLICON_HANDLE = NULL;
@@ -868,14 +504,21 @@ main(int argc,
*/
if (fcgi_params_set(h, req->envp) < 0)
goto done;
- /* Debug_ print headers */
- if (clicon_debug_get())
- fcgi_print_headers(req);
-
if ((path = clixon_restconf_param_get(h, "REQUEST_URI")) != NULL){
clicon_debug(1, "path: %s", path);
- if (strncmp(path, "/" RESTCONF_API, strlen("/" RESTCONF_API)) == 0)
- api_fcgi_restconf(h, req); /* This is the function */
+ if (strncmp(path, "/" RESTCONF_API, strlen("/" RESTCONF_API)) == 0){
+ char *query = NULL;
+ cvec *qvec = NULL;
+ query = clixon_restconf_param_get(h, "QUERY_STRING");
+ if (query != NULL && strlen(query))
+ if (str2cvec(query, '&', '=', &qvec) < 0)
+ goto done;
+ api_root_restconf(h, req, qvec); /* This is the function */
+ if (qvec){
+ cvec_free(qvec);
+ qvec = NULL;
+ }
+ }
else if (strncmp(path+1, stream_path, strlen(stream_path)) == 0) {
api_stream(h, req, stream_path, &finish);
}
diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c
index 4741b2d2..d325d11b 100644
--- a/apps/restconf/restconf_lib.c
+++ b/apps/restconf/restconf_lib.c
@@ -441,6 +441,7 @@ clixon_restconf_param_set(clicon_handle h,
char *param,
char *val)
{
+ clicon_debug(1, "%s=%s", param, val);
return clicon_data_set(h, param, val);
}
diff --git a/apps/restconf/restconf_root.c b/apps/restconf/restconf_root.c
index 9c9cb27b..d62f4797 100644
--- a/apps/restconf/restconf_root.c
+++ b/apps/restconf/restconf_root.c
@@ -65,9 +65,11 @@
#include "restconf_api.h"
#include "restconf_err.h"
#include "restconf_root.h"
+#include "restconf_methods.h"
+#include "restconf_methods_get.h"
+#include "restconf_methods_post.h"
-
-/*! Determine the root of the RESTCONF API
+/*! Determine the root of the RESTCONF API by accessing /.well-known
* @param[in] h Clicon handle
* @param[in] req Generic Www handle (can be part of clixon handle)
* @see RFC8040 3.1 and RFC7320
@@ -105,9 +107,6 @@ api_well_known(clicon_handle h,
cprintf(cb, " \n");
cprintf(cb, "\r\n");
- /* Must be after body */
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 200, cb) < 0)
goto done;
ok:
@@ -118,19 +117,19 @@ api_well_known(clicon_handle h,
return retval;
}
-/*! Retrieve the Top-Level API Resource
+/*! Retrieve the Top-Level API Resource /restconf/ (exact)
* @param[in] h Clicon handle
* @param[in] r Fastcgi request handle
* @note Only returns null for operations and data,...
* See RFC8040 3.3
- * XXX doesnt check method
+ * @see api_root_restconf for accessing /restconf/ *
*/
static int
-api_root(clicon_handle h,
- void *req,
- char *request_method,
- int pretty,
- restconf_media media_out)
+api_root_restconf_exact(clicon_handle h,
+ void *req,
+ char *request_method,
+ int pretty,
+ restconf_media media_out)
{
int retval = -1;
@@ -175,8 +174,6 @@ api_root(clicon_handle h,
default:
break;
}
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
if (restconf_reply_send(req, 200, cb) < 0)
goto done;
ok:
@@ -199,20 +196,16 @@ api_yang_library_version(clicon_handle h,
restconf_media media_out)
{
-#if 1
- clicon_debug(1, "%s", __FUNCTION__);
- return 0;
-#else
int retval = -1;
cxobj *xt = NULL;
cbuf *cb = NULL;
char *ietf_yang_library_revision = "2016-06-21"; /* XXX */
clicon_debug(1, "%s", __FUNCTION__);
- FCGX_SetExitStatus(200, r->out); /* OK */
- FCGX_FPrintF(r->out, "Cache-Control: no-cache\r\n");
- FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
- FCGX_FPrintF(r->out, "\r\n");
+ if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
+ goto done;
+ if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0)
+ goto done;
if (clixon_xml_parse_va(YB_NONE, NULL, &xt, NULL,
"%s",
ietf_yang_library_revision) < 0)
@@ -220,6 +213,7 @@ api_yang_library_version(clicon_handle h,
if (xml_rootchild(xt, 0, &xt) < 0)
goto done;
if ((cb = cbuf_new()) == NULL){
+ clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
switch (media_out){
@@ -234,9 +228,8 @@ api_yang_library_version(clicon_handle h,
default:
break;
}
- clicon_debug(1, "%s cb%s", __FUNCTION__, cbuf_get(cb));
- FCGX_FPrintF(r->out, "%s\n", cb?cbuf_get(cb):"");
- FCGX_FPrintF(r->out, "\n\n");
+ if (restconf_reply_send(req, 200, cb) < 0)
+ goto done;
retval = 0;
done:
if (cb)
@@ -244,7 +237,6 @@ api_yang_library_version(clicon_handle h,
if (xt)
xml_free(xt);
return retval;
-#endif
}
/*! Generic REST method, GET, PUT, DELETE, etc
@@ -269,10 +261,6 @@ api_data(clicon_handle h,
int pretty,
restconf_media media_out)
{
-#if 1
- clicon_debug(1, "%s", __FUNCTION__);
- return 0;
-#else
int retval = -1;
char *request_method;
@@ -297,104 +285,6 @@ api_data(clicon_handle h,
retval = restconf_notfound(h, req);
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
return retval;
-#endif
-}
-
-/*! Move back to restconf_methods_get
- */
-static int
-api_operations_get(clicon_handle h,
- void *req,
- char *path,
- int pi,
- cvec *qvec,
- char *data,
- int pretty,
- restconf_media media_out)
-{
- int retval = -1;
- yang_stmt *yspec;
- yang_stmt *ymod; /* yang module */
- yang_stmt *yc;
- char *namespace;
- cbuf *cb = NULL;
- cxobj *xt = NULL;
- int i;
-
- clicon_debug(1, "%s", __FUNCTION__);
- yspec = clicon_dbspec_yang(h);
- if ((cb = cbuf_new()) == NULL){
- clicon_err(OE_UNIX, errno, "cbuf_new");
- goto done;
- }
- switch (media_out){
- case YANG_DATA_XML:
- cprintf(cb, "");
- break;
- case YANG_DATA_JSON:
- if (pretty)
- cprintf(cb, "{\"operations\": {\n");
- else
- cprintf(cb, "{\"operations\":{");
- break;
- default:
- break;
- }
- ymod = NULL;
- i = 0;
- while ((ymod = yn_each(yspec, ymod)) != NULL) {
- namespace = yang_find_mynamespace(ymod);
- yc = NULL;
- while ((yc = yn_each(ymod, yc)) != NULL) {
- if (yang_keyword_get(yc) != Y_RPC)
- continue;
- switch (media_out){
- case YANG_DATA_XML:
- cprintf(cb, "<%s xmlns=\"%s\"/>", yang_argument_get(yc), namespace);
- break;
- case YANG_DATA_JSON:
- if (i++){
- cprintf(cb, ",");
- if (pretty)
- cprintf(cb, "\n\t");
- }
- if (pretty)
- cprintf(cb, "\"%s:%s\": [null]", yang_argument_get(ymod), yang_argument_get(yc));
- else
- cprintf(cb, "\"%s:%s\":[null]", yang_argument_get(ymod), yang_argument_get(yc));
- break;
- default:
- break;
- }
- }
- }
- switch (media_out){
- case YANG_DATA_XML:
- cprintf(cb, "");
- break;
- case YANG_DATA_JSON:
- if (pretty)
- cprintf(cb, "}\n}");
- else
- cprintf(cb, "}}");
- break;
- default:
- break;
- }
- if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
- goto done;
- if (restconf_reply_header(req, "Content-Length", "%d", cbuf_len(cb)) < 0)
- goto done;
- if (restconf_reply_send(req, 200, cb) < 0)
- goto done;
- retval = 0;
- done:
- clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
- if (cb)
- cbuf_free(cb);
- if (xt)
- xml_free(xt);
- return retval;
}
/*! Operations REST method, POST
@@ -425,11 +315,9 @@ api_operations(clicon_handle h,
clicon_debug(1, "%s", __FUNCTION__);
if (strcmp(request_method, "GET")==0)
retval = api_operations_get(h, req, path, pi, qvec, data, pretty, media_out);
-#ifdef NYI
else if (strcmp(request_method, "POST")==0)
retval = api_operations_post(h, req, path, pi, qvec, data,
pretty, media_out);
-#endif
else
retval = restconf_notfound(h, req);
return retval;
@@ -439,6 +327,7 @@ api_operations(clicon_handle h,
* @param[in] h Clicon handle
* @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] qvec Query parameters, ie the ?=&= stuff
+ * @see api_root_restconf_exact for accessing /restconf/ exact
*/
int
api_root_restconf(clicon_handle h,
@@ -506,7 +395,7 @@ api_root_restconf(clicon_handle h,
goto done;
}
if (pn == 2){
- retval = api_root(h, req, request_method, pretty, media_out);
+ retval = api_root_restconf_exact(h, req, request_method, pretty, media_out);
goto done;
}
if ((api_resource = pvec[2]) == NULL){
@@ -546,10 +435,10 @@ api_root_restconf(clicon_handle h,
}
clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
if (strcmp(api_resource, "yang-library-version")==0){
- if (api_yang_library_version(h, req, pretty, media_out) < 0) /* XXX NYI */
+ if (api_yang_library_version(h, req, pretty, media_out) < 0)
goto done;
}
- else if (strcmp(api_resource, "data") == 0){ /* restconf, skip /api/data */ /* XXX NYI */
+ else if (strcmp(api_resource, "data") == 0){ /* restconf, skip /api/data */
if (api_data(h, req, path, pcvec, 2, qvec, indata,
pretty, media_out) < 0)
goto done;
diff --git a/lib/src/clixon_xml_io.c b/lib/src/clixon_xml_io.c
index 59b8ca34..f84cc98e 100644
--- a/lib/src/clixon_xml_io.c
+++ b/lib/src/clixon_xml_io.c
@@ -459,7 +459,7 @@ _xml_parse(const char *str,
int failed = 0; /* yang assignment */
int i;
- clicon_debug(1, "%s %s", __FUNCTION__, str);
+ clicon_debug(1, "%s", __FUNCTION__);
if (strlen(str) == 0)
return 0; /* OK */
if (xt == NULL){
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index 90725307..d94f7336 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -98,7 +98,7 @@ new "restconf schema resource, RFC 8040 sec 3.7 according to RFC 7895 (explicit
expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state/module=ietf-interfaces,2018-02-20)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:module":\[{"name":"ietf-interfaces","revision":"2018-02-20","namespace":"urn:ietf:params:xml:ns:yang:ietf-interfaces","conformance-type":"implement"}\]}'
new "restconf options. RFC 8040 4.1"
-expectpart "$(curl -is -X OPTIONS $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
+expectpart "$(curl -sik -X OPTIONS $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
# -I means HEAD
new "restconf HEAD. RFC 8040 4.2"
@@ -169,7 +169,7 @@ expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/clixon-example
# Exact match
new "restconf Add subtree eth/0/0 to datastore using POST"
-expectpart "$(curl -sik -X POST -H "Accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created' 'Location: http://localhost/restconf/data/ietf-interfaces:interfaces'
+expectpart "$(curl -sik -X POST -H "Accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created' "Location: $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces"
new "restconf Re-add subtree eth/0/0 which should give error"
expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $RCPROTO://localhost/restconf/data)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-exists","error-severity":"error","error-message":"Data already exists; cannot create new resource"}}}'
@@ -205,7 +205,7 @@ new "Add leaf description using POST"
expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:description":"The-first-interface"}' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 "HTTP/1.1 201 Created"
new "Add nothing using POST (expect fail)"
-expectpart "$(curl -is -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"The message-body MUST contain exactly one instance of the expected data resource"}}}'
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"The message-body MUST contain exactly one instance of the expected data resource"}}}'
new "restconf Check description added"
expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/1.1 200 OK" '{"ietf-interfaces:interfaces":{"interface":\[{"name":"eth/0/0","description":"The-first-interface","type":"clixon-example:eth","enabled":true,"oper-status":"up","clixon-example:my-status":{"int":42,"str":"foo"}}\]}}'
@@ -214,7 +214,7 @@ new "restconf delete eth/0/0"
expectpart "$(curl -sik -X DELETE $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 "HTTP/1.1 204 No Content"
new "Check deleted eth/0/0"
-expectpart "$(curl -sik -X GET http://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "$state"
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "$state"
new "restconf Re-Delete eth/0/0 using none should generate error"
expectpart "$(curl -sik -X DELETE $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 "HTTP/1.1 409 Conflict" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-missing","error-severity":"error","error-message":"Data does not exist; cannot delete resource"}}}'
@@ -234,16 +234,16 @@ expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d
fi
new "restconf rpc non-existing rpc without namespace"
-expectpart "$(curl -is -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/kalle)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"kalle"},"error-severity":"error","error-message":"RPC not defined"}}'
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/kalle)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"kalle"},"error-severity":"error","error-message":"RPC not defined"}}'
new "restconf rpc non-existing rpc"
-expectpart "$(curl -is -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/clixon-example:kalle)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"kalle"},"error-severity":"error","error-message":"RPC not defined"}}'
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/clixon-example:kalle)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"kalle"},"error-severity":"error","error-message":"RPC not defined"}}'
new "restconf rpc missing name"
-expectpart "$(curl -is -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations)" 0 'HTTP/1.1 412 Precondition Failed' '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"Operation name expected"}}}'
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations)" 0 'HTTP/1.1 412 Precondition Failed' '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"Operation name expected"}}}'
new "restconf rpc missing input"
-expectpart "$(curl -is -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"restconf RPC does not have input statement"}}}'
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"restconf RPC does not have input statement"}}}'
new "restconf rpc using POST xml"
ret=$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -H "Accept: application/yang-data+xml" -d '{"clixon-example:input":{"x":42}}' $RCPROTO://localhost/restconf/operations/clixon-example:example)
@@ -265,7 +265,7 @@ if [ -z "$match" ]; then
fi
new "restconf Add subtree without key (expected error)"
-expectpart "$(curl -is -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key =interface, expected'
+expectpart "$(curl -sik -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key =interface, expected'
new "restconf Add subtree with too many keys (expected error)"
expectpart "$(curl -sik -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=a,b)" 0 "HTTP/1.1 400 Bad Request" '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"List key interface length mismatch"}}}'
diff --git a/test/test_restconf2.sh b/test/test_restconf2.sh
index 972d3246..101fe950 100755
--- a/test/test_restconf2.sh
+++ b/test/test_restconf2.sh
@@ -190,7 +190,7 @@ expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:cont1/
#--------------- json type tests
new "restconf POST type x3 POST"
-expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 201 Created" "Location: http://localhost/restconf/data/example:types"
+expectpart "$(curl -sik -X POST -H "Content-Type: application/yang-data+json" -d '{"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example:types"
new "restconf POST type x3 GET"
expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:types)" 0 "HTTP/1.1 200 OK" '{"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}}'
diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh
index dd585d7a..8e0e0aa8 100755
--- a/test/test_restconf_err.sh
+++ b/test/test_restconf_err.sh
@@ -169,54 +169,54 @@ if [ $RC -ne 0 ]; then
fi
new "restconf POST initial tree"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+xml' -d "$XML" $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+xml' -d "$XML" $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created'
new "restconf GET initial datastore"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:a=0)" 0 'HTTP/1.1 200 OK' "$XML"
-
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:a=0)" 0 'HTTP/1.1 200 OK' "$XML"
+exit
new "restconf GET non-qualified list"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example:a)" 0 'HTTP/1.1 400 Bad Request' "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"rpc\",\"error-tag\":\"malformed-message\",\"error-severity\":\"error\",\"error-message\":\"malformed key =example:a, expected '=restval'\"}}}"
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:a)" 0 'HTTP/1.1 400 Bad Request' "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"rpc\",\"error-tag\":\"malformed-message\",\"error-severity\":\"error\",\"error-message\":\"malformed key =example:a, expected '=restval'\"}}}"
new "restconf GET non-qualified list subelements"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example:a/k)" 0 'HTTP/1.1 400 Bad Request' "^{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"rpc\",\"error-tag\":\"malformed-message\",\"error-severity\":\"error\",\"error-message\":\"malformed key =example:a, expected '=restval'\"}}}"
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:a/k)" 0 'HTTP/1.1 400 Bad Request' "^{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"rpc\",\"error-tag\":\"malformed-message\",\"error-severity\":\"error\",\"error-message\":\"malformed key =example:a, expected '=restval'\"}}}"
new "restconf GET non-existent container body"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example:a=0/c)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"Instance does not exist"}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:a=0/c)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"Instance does not exist"}}}'
new "restconf GET invalid (no yang) container body"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example:a=0/xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:a=0/xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
new "restconf GET invalid (no yang) element"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example:xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example:xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
new "restconf POST non-existent (no yang) element"
# should be invalid element
-expectpart "$(curl -is -X POST -H 'Content-Type: application/yang-data+xml' -d "$XML" $RCPROTO://localhost/restconf/data/example:a=23/xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+xml' -d "$XML" $RCPROTO://localhost/restconf/data/example:a=23/xxx)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"xxx"},"error-severity":"error","error-message":"Unknown element"}}}'
# Test for multi-module path where an augment stretches across modules
new "restconf POST augment multi-namespace path"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+xml' -d '23' $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+xml' -d '23' $RCPROTO://localhost/restconf/data)" 0 'HTTP/1.1 201 Created'
new "restconf GET augment multi-namespace top"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/augment:route-config)" 0 'HTTP/1.1 200 OK' '{"augment:route-config":{"dynamic":{"example:ospf":{"reference-bandwidth":23}}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/augment:route-config)" 0 'HTTP/1.1 200 OK' '{"augment:route-config":{"dynamic":{"example:ospf":{"reference-bandwidth":23}}}}'
new "restconf GET augment multi-namespace level 1"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic)" 0 'HTTP/1.1 200 OK' '{"augment:dynamic":{"example:ospf":{"reference-bandwidth":23}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic)" 0 'HTTP/1.1 200 OK' '{"augment:dynamic":{"example:ospf":{"reference-bandwidth":23}}}'
new "restconf GET augment multi-namespace cross"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/example:ospf)" 0 'HTTP/1.1 200 OK' '{"example:ospf":{"reference-bandwidth":23}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/example:ospf)" 0 'HTTP/1.1 200 OK' '{"example:ospf":{"reference-bandwidth":23}}'
new "restconf GET augment multi-namespace cross level 2"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/example:ospf/reference-bandwidth)" 0 'HTTP/1.1 200 OK' '{"example:reference-bandwidth":23}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/example:ospf/reference-bandwidth)" 0 'HTTP/1.1 200 OK' '{"example:reference-bandwidth":23}'
# XXX actually no such element
new "restconf GET augment multi-namespace, no 2nd module in api-path, fail"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/ospf)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"Instance does not exist"}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/augment:route-config/dynamic/ospf)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"Instance does not exist"}}}'
#----------------------------------------------
# Also generate an invalid state XML. This should generate an "Internal" error and the name of the
new "restconf GET failed state"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 '412 Precondition Failed' 'applicationoperation-failedmystateerrorNo such yang module. Internal error, state callback returned invalid XML: example_backend'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 '412 Precondition Failed' 'applicationoperation-failedmystateerrorNo such yang module. Internal error, state callback returned invalid XML: example_backend'
if [ $RC -ne 0 ]; then
new "Kill restconf daemon"
diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh
index 6301d2aa..5e58574e 100755
--- a/test/test_restconf_jukebox.sh
+++ b/test/test_restconf_jukebox.sh
@@ -89,160 +89,157 @@ if [ $RC -ne 0 ]; then
fi
new "B.1.1. Retrieve the Top-Level API Resource root"
-expectpart "$(curl -si -X GET -H 'Accept: application/xrd+xml' $RCPROTO://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200 OK" "Content-Type: application/xrd+xml" "" "" ""
+expectpart "$(curl -sik -X GET -H 'Accept: application/xrd+xml' $RCPROTO://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200 OK" "Content-Type: application/xrd+xml" "" "" ""
d='{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2016-06-21"}}'
new "B.1.1. Retrieve the Top-Level API Resource /restconf json"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" "$d"
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" "$d"
new "B.1.1. Retrieve the Top-Level API Resource /restconf xml (not in RFC)"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+xml" '2016-06-21'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+xml" '2016-06-21'
# This just catches the header and the jukebox module, the RFC has foo and bar which
# seems wrong to recreate
new "B.1.2. Retrieve the Server Module Information"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},'
new "B.1.3. Retrieve the Server Capability Information"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' 'urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=expliciturn:ietf:params:restconf:capability:depth
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' 'urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=expliciturn:ietf:params:restconf:capability:depth
'
new "B.2.1. Create New Data Resources (artist+json)"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library -d '{"example-jukebox:artist":[{"name":"Foo Fighters"}]}')" 0 "HTTP/1.1 201 Created" "Location: http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters"
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library -d '{"example-jukebox:artist":[{"name":"Foo Fighters"}]}')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters"
new "B.2.1. Create New Data Resources (album+xml)"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters -d 'Wasting Light2011')" 0 "HTTP/1.1 201 Created" "Location: http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light"
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters -d 'Wasting Light2011')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light"
new "B.2.1. Add Data Resources again (conflict - not in RFC)"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters -d 'Wasting Light2011')" 0 "HTTP/1.1 409 Conflict"
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters -d 'Wasting Light2011')" 0 "HTTP/1.1 409 Conflict"
new "4.5. PUT replace content (xml encoding)"
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d 'Wasting Lightjbox:alternative2011')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d 'Wasting Lightjbox:alternative2011')" 0 "HTTP/1.1 204 No Content"
new "4.5. PUT create new identity"
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":[{"name":"London Calling","year":1979}]}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":[{"name":"London Calling","year":1979}]}')" 0 "HTTP/1.1 201 Created"
new "4.5. Check jukebox content: 1 Clash and 1 Foo fighters album"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Calling1979Foo FightersWasting Lightjbox:alternative2011'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Calling1979Foo FightersWasting Lightjbox:alternative2011'
new "B.2.2. Added genre (preamble to actual test)"
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d '{"example-jukebox:album":[{"name":"Wasting Light","genre":"example-jukebox:alternative","year":2011}]}')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d '{"example-jukebox:album":[{"name":"Wasting Light","genre":"example-jukebox:alternative","year":2011}]}')" 0 "HTTP/1.1 204 No Content"
# First use of PATCH
new "B.2.2. Detect Datastore Resource Entity-Tag Change (XXX if-unmodified)"
-expectpart "$(curl -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light/genre -d '{"example-jukebox:genre":"example-jukebox:alternative"}')" 0 'HTTP/1.1 204 No Content'
+expectpart "$(curl -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light/genre -d '{"example-jukebox:genre":"example-jukebox:alternative"}')" 0 'HTTP/1.1 204 No Content'
new "B.2.3. Edit a Datastore Resource (Add 1 Foo fighter and Nick cave album)"
-expectpart "$(curl -si -X PATCH -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data -d 'trueFoo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988')" 0 'HTTP/1.1 204 No Content'
+expectpart "$(curl -sik -X PATCH -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data -d 'trueFoo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988')" 0 'HTTP/1.1 204 No Content'
new "B.2.3. Check patch system"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-system:system -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'true'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-system:system -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'true'
new "B.2.3. Check jukebox: 1 Clash, 2 Foo Fighters, 1 Nick Cave"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Calling1979Foo FightersOne by One2012Wasting Lightalternative2011Nick Cave and the Bad SeedsTender Prey1988'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Calling1979Foo FightersOne by One2012Wasting Lightalternative2011Nick Cave and the Bad SeedsTender Prey1988'
new "B.2.4. Replace a Datastore Resource"
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data -d 'Foo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data -d 'Foo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988')" 0 "HTTP/1.1 204 No Content"
new "B.2.4. Check replace"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'Foo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'Foo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988'
new "B.2.5. Edit a Data Resource (add Nick cave album The good son)"
-expectpart "$(curl -si -X PATCH $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Nick%20Cave%20and%20the%20Bad%20Seeds -H 'Content-Type: application/yang-data+xml' -d 'Nick Cave and the Bad SeedsThe Good Son1990')" 0 'HTTP/1.1 204 No Content'
+expectpart "$(curl -sik -X PATCH $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Nick%20Cave%20and%20the%20Bad%20Seeds -H 'Content-Type: application/yang-data+xml' -d 'Nick Cave and the Bad SeedsThe Good Son1990')" 0 'HTTP/1.1 204 No Content'
new "B.2.5. Check edit"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Nick%20Cave%20and%20the%20Bad%20Seeds -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'Nick Cave and the Bad SeedsTender Prey1988The Good Son1990'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Nick%20Cave%20and%20the%20Bad%20Seeds -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'Nick Cave and the Bad SeedsTender Prey1988The Good Son1990'
# note reverse order of down/up as it is ordered by system and down is before up
new 'B.3.1. "content" Parameter (preamble, add content)'
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-events:events -d '{"example-events:events":{"event":[{"name":"interface-down","description":"Interface down notification count"},{"name":"interface-up","description":"Interface up notification count"}]}}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-events:events -d '{"example-events:events":{"event":[{"name":"interface-down","description":"Interface down notification count"},{"name":"interface-up","description":"Interface up notification count"}]}}')" 0 "HTTP/1.1 201 Created"
new 'B.3.1. "content" Parameter (wrong content)'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=kalle -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-attribute","error-info":{"bad-attribute":"content"},"error-severity":"error","error-message":"Unrecognized value of content attribute"}}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=kalle -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-attribute","error-info":{"bad-attribute":"content"},"error-severity":"error","error-message":"Unrecognized value of content attribute"}}}'
new 'B.3.1. "content" Parameter example 1: content=all'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=all -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","description":"Interface down notification count","event-count":90},{"name":"interface-up","description":"Interface up notification count","event-count":77}\]}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=all -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","description":"Interface down notification count","event-count":90},{"name":"interface-up","description":"Interface up notification count","event-count":77}\]}}'
new 'B.3.1. "content" Parameter example 2: content=config'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=config -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","description":"Interface down notification count"},{"name":"interface-up","description":"Interface up notification count"}\]}}'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=config -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","description":"Interface down notification count"},{"name":"interface-up","description":"Interface up notification count"}\]}}'
new 'B.3.1. "content" Parameter example 3: content=nonconfig'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=nonconfig -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","event-count":90},{"name":"interface-up","event-count":77}\]}}'
-
-#new "restconf DELETE whole datastore"
-#expectfn "curl -s -X DELETE $RCPROTO://localhost/restconf/data" 0 ""
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-events:events?content=nonconfig -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-events:events":{"event":\[{"name":"interface-down","event-count":90},{"name":"interface-up","event-count":77}\]}}'
new 'B.3.2. "depth" Parameter example 1 unbound'
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=unbounded)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"library":{"artist":\[{"name":"Foo Fighters","album":\[{"name":"One by One","year":2012}\]},{"name":"Nick Cave and the Bad Seeds","album":\[{"name":"Tender Prey","year":1988},{"name":"The Good Son","year":1990}\]}\]}}}'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=unbounded)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"library":{"artist":\[{"name":"Foo Fighters","album":\[{"name":"One by One","year":2012}\]},{"name":"Nick Cave and the Bad Seeds","album":\[{"name":"Tender Prey","year":1988},{"name":"The Good Son","year":1990}\]}\]}}}'
new 'B.3.2. "depth" Parameter example 2 depth=1'
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=1)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{}}'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=1)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{}}'
new 'B.3.2. "depth" Parameter depth=2'
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=2)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"library":{}}}'
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=2)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"library":{}}}'
# Maybe this is not correct w [null,null]but I have no good examples
new 'B.3.2. "depth" Parameter depth=3'
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=3)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"artist":\[null,null\]}}}
+expectpart "$(curl -sik -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox?depth=3)" 0 "HTTP/1.1 200 OK" '{"example-jukebox:jukebox":{"artist":\[null,null\]}}}
'
new "restconf DELETE whole datastore"
-expectfn "curl -s -X DELETE $RCPROTO://localhost/restconf/data" 0 ""
+expectpart "$(curl -sik -X DELETE $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 204 No Content"
#new 'B.3.3. "fields" Parameter'
new 'B.3.4. "insert" Parameter'
JSON="{\"example-jukebox:song\":[{\"index\":1,\"id\":\"/example-jukebox:jukebox/library/artist[name='Foo Fighters']/album[name='Wasting Light']/song[name='Rope']\"}]}"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first -d "$JSON")" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=1'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first -d "$JSON")" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=1"
new 'B.3.4. "insert" Parameter first (RFC example says after)'
JSON="{\"example-jukebox:song\":[{\"index\":0,\"id\":\"/example-jukebox:jukebox/library/artist[name='Foo Fighters']/album[name='Wasting Light']/song[name='Bridge Burning']\"}]}"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first -d "$JSON")" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=0'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first -d "$JSON")" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=0"
new 'B.3.4. "insert" Parameter check order'
RES="Foo-One0/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Bridge Burning'\]1/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Rope'\]"
-expectpart "$(curl -si -X GET http://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
+expectpart "$(curl -sik -X GET http://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
new 'B.3.5. "point" Parameter (before for more interesting order: 0,2,1)'
JSON="{\"example-jukebox:song\":[{\"index\":2,\"id\":\"/example-jukebox:jukebox/library/artist[name='Foo Fighters']/album[name='Wasting Light']/song[name='Bridge Burning']\"}]}"
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' -d "$JSON" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=before\&point=%2Fexample-jukebox%3Ajukebox%2Fplaylist%3DFoo-One%2Fsong%3D1 )" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=2'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' -d "$JSON" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=before\&point=%2Fexample-jukebox%3Ajukebox%2Fplaylist%3DFoo-One%2Fsong%3D1 )" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=2"
new 'B.3.5. "point" check order (0,2,1)'
RES="Foo-One0/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Bridge Burning'\]2/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Bridge Burning'\]1/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Rope'\]"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
new 'B.3.5. "point" Parameter 3 after 2 (using PUT)'
JSON="{\"example-jukebox:song\":[{\"index\":3,\"id\":\"/example-jukebox:jukebox/library/artist[name='Foo Fighters']/album[name='Wasting Light']/song[name='Something else']\"}]}"
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' -d "$JSON" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=3?insert=after\&point=%2Fexample-jukebox%3Ajukebox%2Fplaylist%3DFoo-One%2Fsong%3D2 )" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -sik -X PUT -H 'Content-Type: application/yang-data+json' -d "$JSON" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=3?insert=after\&point=%2Fexample-jukebox%3Ajukebox%2Fplaylist%3DFoo-One%2Fsong%3D2 )" 0 "HTTP/1.1 201 Created"
new 'B.3.5. "point" check order (0,2,3,1)'
RES="Foo-One0/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Bridge Burning'\]2/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Bridge Burning'\]3/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Something else'\]1/example-jukebox:jukebox/library/artist\[name='Foo Fighters'\]/album\[name='Wasting Light'\]/song\[name='Rope'\]"
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/playlist=Foo-One -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' "$RES"
new "restconf DELETE whole datastore"
-expectfn "curl -s -X DELETE $RCPROTO://localhost/restconf/data" 0 ""
+expectpart "$(curl -sik -X DELETE $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 204 No Content"
new 'B.3.4. "insert/point" leaf-list 3 (not in RFC)'
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"3"}')" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:extra=3'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"3"}')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:extra=3"
new 'B.3.4. "insert/point" leaf-list 2 first'
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=first -d '{"example-jukebox:extra":"2"}')" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:extra=2'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=first -d '{"example-jukebox:extra":"2"}')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:extra=2"
new 'B.3.4. "insert/point" leaf-list 1 last'
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"1"}')" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:extra=1'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"1"}')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:extra=1"
#new 'B.3.4. "insert/point" move leaf-list 1 last'
#- restconf cannot move a leaf-list(list?) item
-#expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"1"}')" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:extra=1'
+#expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data?insert=last -d '{"example-jukebox:extra":"1"}')" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:extra=1"
new 'B.3.5. "insert/point" leaf-list check order (2,3,1)'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' '231'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' '231'
new 'B.3.5. "point" Parameter leaf-list 4 before 3'
-expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+json' -d '{"example-jukebox:extra":"4"}' $RCPROTO://localhost/restconf/data?insert=before\&point=%2Fexample-jukebox%3Aextra%3D3 )" 0 "HTTP/1.1 201 Created" 'Location: http://localhost/restconf/data/example-jukebox:extra=4'
+expectpart "$(curl -sik -X POST -H 'Content-Type: application/yang-data+json' -d '{"example-jukebox:extra":"4"}' $RCPROTO://localhost/restconf/data?insert=before\&point=%2Fexample-jukebox%3Aextra%3D3 )" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example-jukebox:extra=4"
new 'B.3.5. "insert/point" leaf-list check order (2,4,3,1)'
-expectpart "$(curl -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' '2431'
+expectpart "$(curl -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' '2431'
new "B.2.2. Detect Datastore Resource Entity-Tag Change" # XXX done except entity-changed
new 'B.3.3. "fields" Parameter'
diff --git a/test/test_restconf_listkey.sh b/test/test_restconf_listkey.sh
index 2a73d544..a27ad2dd 100755
--- a/test/test_restconf_listkey.sh
+++ b/test/test_restconf_listkey.sh
@@ -99,7 +99,7 @@ new "restconf GET whole list entry"
expectpart "$(curl -sik -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/)" 0 "HTTP/1.1 200 OK" '{"list:c":{"a":\[{"b":"x","c":"y","nonkey":"0"}\]}}'
new "restconf GET list entry itself (should fail)"
-expectpart "$(curl -si -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a)" 0 'HTTP/1.1 400 Bad Request' '^{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key =a, expected '
+expectpart "$(curl -sik -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a)" 0 'HTTP/1.1 400 Bad Request' '^{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key =a, expected '
new "restconf GET list entry"
expectpart "$(curl -sik -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"x","c":"y","nonkey":"0"}\]}'
diff --git a/test/test_restconf_patch.sh b/test/test_restconf_patch.sh
index 2bf14e38..05df4bb9 100755
--- a/test/test_restconf_patch.sh
+++ b/test/test_restconf_patch.sh
@@ -119,80 +119,80 @@ wait_restconf
# also in test_restconf.sh
new "MUST support the PATCH method for a plain patch"
-expectpart "$(curl -u andy:bar -is -X OPTIONS $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE" "Accept-Patch: application/yang-data+xml,application/yang-data+json"
+expectpart "$(curl -u andy:bar -sik -X OPTIONS $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE" "Accept-Patch: application/yang-data+xml,application/yang-data+json"
new "If the target resource instance does not exist, the server MUST NOT create it."
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":null}')" 0 "HTTP/1.1 400 Bad Request"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":null}')" 0 "HTTP/1.1 400 Bad Request"
new "Create it with PUT instead"
-expectpart "$(curl -u andy:bar -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":null}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -u andy:bar -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":null}')" 0 "HTTP/1.1 201 Created"
new "THEN change it with PATCH"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":{"library":{"artist":{"name":"Clash"}}}}')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":{"library":{"artist":{"name":"Clash"}}}}')" 0 "HTTP/1.1 204 No Content"
new "Check content (json)"
-expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:jukebox":{"library":{"artist":\[{"name":"Clash"}\]}}}'
+expectpart "$(curl -u andy:bar -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:jukebox":{"library":{"artist":\[{"name":"Clash"}\]}}}'
new "Check content (xml)"
expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'Clash'
new 'If the user is not authorized, "403 Forbidden" SHOULD be returned.'
-expectpart "$(curl -u wilma:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash -d '{"example-jukebox:artist":{"name":"Clash","album":{"name":"London Calling"}}}')" 0 "HTTP/1.1 403 Forbidden" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}'
+expectpart "$(curl -u wilma:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash -d '{"example-jukebox:artist":{"name":"Clash","album":{"name":"London Calling"}}}')" 0 "HTTP/1.1 403 Forbidden" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}'
new 'user is authorized'
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash -d '{"example-jukebox:artist":{"name":"Clash","album":{"name":"London Calling"}}}')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash -d '{"example-jukebox:artist":{"name":"Clash","album":{"name":"London Calling"}}}')" 0 "HTTP/1.1 204 No Content"
# 4.6.1. Plain Patch
new "restconf DELETE whole datastore"
-expectpart "$(curl -u andy:bar -is -X DELETE $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -u andy:bar -sik -X DELETE $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 204 No Content"
new "Create album London Calling with PUT"
-expectpart "$(curl -u andy:bar -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling"}}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -u andy:bar -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling"}}')" 0 "HTTP/1.1 201 Created"
new "The message-body for a plain patch MUST be present"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Beatles -d '')" 0 "HTTP/1.1 400 Bad Request"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Beatles -d '')" 0 "HTTP/1.1 400 Bad Request"
# Plain patch can be used to create or update, but not delete, a child
# resource within the target resource.
new "Create a child resource (genre and year)"
-expectpart "$(curl -u andy:bar -si -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling","genre":"example-jukebox:rock","year":"2129"}}')" 0 'HTTP/1.1 204 No Content'
+expectpart "$(curl -u andy:bar -sik -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling","genre":"example-jukebox:rock","year":"2129"}}')" 0 'HTTP/1.1 204 No Content'
new "Update a child resource (year)"
-expectpart "$(curl -u andy:bar -si -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling","year":"1979"}}')" 0 'HTTP/1.1 204 No Content'
+expectpart "$(curl -u andy:bar -sik -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"London Calling","year":"1979"}}')" 0 'HTTP/1.1 204 No Content'
new "Check content xml"
-expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'London Callingrock1979'
+expectpart "$(curl -u andy:bar -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'London Callingrock1979'
new "Check content json"
-expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:album":\[{"name":"London Calling","genre":"rock","year":1979}\]}'
+expectpart "$(curl -u andy:bar -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:album":\[{"name":"London Calling","genre":"rock","year":1979}\]}'
new "The message-body MUST be represented by the media type application/yang-data+xml (or +json ^)"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 204 No Content"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 204 No Content"
new "Check content (xml)"
-expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Callingjazz1979'
+expectpart "$(curl -u andy:bar -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:jukebox -H 'Accept: application/yang-data+xml')" 0 'HTTP/1.1 200 OK' 'ClashLondon Callingjazz1979'
new "not implemented media type"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-patch+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 501 Not Implemented"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-patch+xml' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 501 Not Implemented"
new "wrong media type"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: text/html' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 415 Unsupported Media Type"
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: text/html' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d 'London Callingjazz')" 0 "HTTP/1.1 415 Unsupported Media Type"
# If the target resource represents a YANG leaf-list, then the PATCH
# method MUST NOT change the value of the leaf-list instance.
# leaf-list extra{
new "Create leaf-list a"
-expectpart "$(curl -u andy:bar -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=a -d '{"example-jukebox:extra":"a"}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -u andy:bar -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=a -d '{"example-jukebox:extra":"a"}')" 0 "HTTP/1.1 201 Created"
new "Create leaf-list b"
-expectpart "$(curl -u andy:bar -si -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=b -d '{"example-jukebox:extra":"b"}')" 0 "HTTP/1.1 201 Created"
+expectpart "$(curl -u andy:bar -sik -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=b -d '{"example-jukebox:extra":"b"}')" 0 "HTTP/1.1 201 Created"
new "Check content"
-expectpart "$(curl -u andy:bar -si -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:extra":\["a","b"\]}'
+expectpart "$(curl -u andy:bar -sik -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+json')" 0 'HTTP/1.1 200 OK' '{"example-jukebox:extra":\["a","b"\]}'
new "MUST NOT change the value of the leaf-list instance"
-expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=a -d '{"example-jukebox:extra":"b"}')" 0 'HTTP/1.1 412 Precondition Failed'
+expectpart "$(curl -u andy:bar -sik -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:extra=a -d '{"example-jukebox:extra":"b"}')" 0 'HTTP/1.1 412 Precondition Failed'
# If the target resource represents a YANG list instance, then the key
# leaf values, in message-body representation, MUST be the same as the
@@ -200,7 +200,7 @@ expectpart "$(curl -u andy:bar -si -X PATCH -H 'Content-Type: application/yang-d
# used to change the key leaf values for a data resource instance.
new "The key leaf values MUST be the same as the key leaf values in the request"
-expectpart "$(curl -u andy:bar -si -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"The Clash"}}')" 0 'HTTP/1.1 412 Precondition Failed'
+expectpart "$(curl -u andy:bar -sik -X PATCH -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":{"name":"The Clash"}}')" 0 'HTTP/1.1 412 Precondition Failed'
new "Kill restconf daemon"
stop_restconf
diff --git a/test/test_upgrade_interfaces.sh b/test/test_upgrade_interfaces.sh
index 169e5cab..564cbf60 100755
--- a/test/test_upgrade_interfaces.sh
+++ b/test/test_upgrade_interfaces.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Upgrade a module by registering a manually programmed callback
-# The usecase is insipred by the ietf-interfaces upgrade from
+# The usecase is inspired by the ietf-interfaces upgrade from
# 2014-05-08 to 2018-02-20.
# That includes moving parts from interfaces-state to interfaces and then
# deprecating the whole /interfaces-state tree.
diff --git a/test/vagrant/vagrant.sh b/test/vagrant/vagrant.sh
index e45ed093..c313c45f 100755
--- a/test/vagrant/vagrant.sh
+++ b/test/vagrant/vagrant.sh
@@ -36,6 +36,7 @@ Vagrant.configure("2") do |config|
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "$box"
+ config.vm.box_check_update = true
config.ssh.shell = "sh" # freebsd
config.vm.define "$host"
config.vm.hostname = "$host"