Added patch media types; restconf patch test-cases; nsc spelling

This commit is contained in:
Olof hagsand 2019-08-09 14:49:40 +02:00
parent f319c18374
commit e244f5c8f8
12 changed files with 212 additions and 37 deletions

View file

@ -42,8 +42,10 @@
* Types (also in restconf_lib.h)
*/
enum restconf_media{
YANG_DATA_JSON, /* "application/yang-data+json" (default for RESTCONF) */
YANG_DATA_XML /* "application/yang-data+xml" */
YANG_DATA_JSON, /* "application/yang-data+json" */
YANG_DATA_XML, /* "application/yang-data+xml" */
YANG_PATCH_JSON, /* "application/yang-patch+json" */
YANG_PATCH_XML /* "application/yang-patch+xml" */
};
typedef enum restconf_media restconf_media;

View file

@ -32,6 +32,9 @@
***** END LICENSE BLOCK *****
* @see https://nginx.org/en/docs/http/ngx_http_core_module.html#var_https
* @note The response payload for errors uses text_html. RFC7231 is vague
* on the response payload (and its media). Maybe it should be omitted
* altogether?
*/
#include <stdlib.h>
@ -76,8 +79,8 @@ static const map_str2int netconf_restconf_map[] = {
{"bad-element", 400},
{"unknown-element", 400},
{"unknown-namespace", 400},
{"access-denied", 401}, /* or 403 */
{"access-denied", 403},
{"access-denied", 401}, /* or 403 */
{"lock-denied", 409},
{"resource-denied", 409},
{"rollback-failed", 500},
@ -144,6 +147,8 @@ static const map_str2int http_reason_phrase_map[] = {
static const map_str2int http_media_map[] = {
{"application/yang-data+xml", YANG_DATA_XML},
{"application/yang-data+json", YANG_DATA_JSON},
{"application/yang-patch+xml", YANG_PATCH_XML},
{"application/yang-patch+json", YANG_PATCH_JSON},
{NULL, -1}
};
@ -172,6 +177,12 @@ restconf_media_int2str(restconf_media media)
}
/*! Return media_in from Content-Type, -1 if not found or unrecognized
* @note media-type syntax does not support parameters
* @see RFC7231 Sec 3.1.1.1 for media-type syntax type:
* media-type = type "/" subtype *( OWS ";" OWS parameter )
* type = token
* subtype = token
*
*/
restconf_media
restconf_content_type(FCGX_Request *r)
@ -514,6 +525,10 @@ api_return_err(clicon_handle h,
FCGX_FPrintF(r->out, "%s", cbuf_get(cb));
FCGX_FPrintF(r->out, "}\r\n");
}
default:
clicon_err(OE_YANG, EINVAL, "Invalid media type %d", media);
goto done;
break;
} /* switch media */
ok:
retval = 0;

View file

@ -47,10 +47,13 @@
/*! RESTCONF media types
* @see http_media_map
* (also in clixon_restconf.h)
*/
enum restconf_media{
YANG_DATA_JSON, /* "application/yang-data+json" (default for RESTCONF) */
YANG_DATA_XML /* "application/yang-data+xml" */
YANG_DATA_JSON, /* "application/yang-data+json" */
YANG_DATA_XML, /* "application/yang-data+xml" */
YANG_PATCH_JSON, /* "application/yang-patch+json" */
YANG_PATCH_XML /* "application/yang-patch+xml" */
};
typedef enum restconf_media restconf_media;

View file

@ -249,6 +249,8 @@ api_root(clicon_handle h,
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");
@ -297,6 +299,8 @@ api_yang_library_version(clicon_handle h,
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):"");

View file

@ -510,7 +510,7 @@ api_data_write(clicon_handle h,
/* There is an api-path that defines an element in the datastore tree.
* Not top-of-tree.
*/
clicon_debug(1, "%s x:%s xbot:%s",__FUNCTION__, dname, xml_name(xbot));
clicon_debug(1, "%s Comparing bottom-of api-path (%s) with top-of-data (%s)",__FUNCTION__, xml_name(xbot), dname);
/* Check same symbol in api-path as data */
if (strcmp(dname, xml_name(xbot))){
@ -683,7 +683,6 @@ api_data_write(clicon_handle h,
FCGX_SetExitStatus(204, r->out); /* Replaced */
FCGX_FPrintF(r->out, "Status: 204 No Content\r\n");
}
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
FCGX_FPrintF(r->out, "\r\n");
ok:
retval = 0;
@ -794,13 +793,19 @@ api_data_patch(clicon_handle h,
int ret;
media_in = restconf_content_type(r);
if (media_in == YANG_DATA_XML || media_in == YANG_DATA_JSON){
/* plain patch */
switch (media_in){
case YANG_DATA_XML:
case YANG_DATA_JSON: /* plain patch */
ret = api_data_write(h, r, api_path0, pcvec, pi, qvec, data, pretty,
media_in, media_out, 1);
}
else{ /* Other patches are NYI */
break;
case YANG_PATCH_XML:
case YANG_PATCH_JSON: /* RFC 8072 patch */
ret = restconf_notimplemented(r);
break;
default:
ret = restconf_unsupported_media(r);
break;
}
return ret;
}

View file

@ -193,6 +193,8 @@ api_data_get2(clicon_handle h,
if (xml2json_cbuf(cbx, xret, pretty) < 0)
goto done;
break;
default:
break;
}
}
else{
@ -244,6 +246,8 @@ api_data_get2(clicon_handle h,
if (xml2json_cbuf_vec(cbx, xvec, xlen, pretty) < 0)
goto done;
break;
default:
break;
}
}
clicon_debug(1, "%s cbuf:%s", __FUNCTION__, cbuf_get(cbx));
@ -391,6 +395,8 @@ api_operations_get(clicon_handle h,
case YANG_DATA_JSON:
cprintf(cbx, "{\"operations\": {");
break;
default:
break;
}
ymod = NULL;
i = 0;
@ -409,7 +415,10 @@ api_operations_get(clicon_handle h,
cprintf(cbx, ",");
cprintf(cbx, "\"%s:%s\": null", yang_argument_get(ymod), yang_argument_get(yc));
break;
default:
break;
}
}
}
switch (media_out){
@ -419,6 +428,8 @@ api_operations_get(clicon_handle h,
case YANG_DATA_JSON:
cprintf(cbx, "}}");
break;
default:
break;
}
FCGX_SetExitStatus(200, r->out); /* OK */
FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));

View file

@ -951,6 +951,8 @@ api_operations_post(clicon_handle h,
goto done;
/* xoutput should now look: {"example:output": {"x":0,"y":42}} */
break;
default:
break;
}
FCGX_FPrintF(r->out, "%s", cbuf_get(cbret));
FCGX_FPrintF(r->out, "\r\n\r\n");