* RESTCONF in Clixon used empty key as "wildchar". But according to RFC 8040 it should mean the "empty string".
* Example: `GET restconf/data/x:a=` * Previous meaning (wrong): Return all `a` elements. * New meaning (correct): Return the `a` instance with empty key string: "". * [RESTCONF GET request of single-key list with empty string returns all elements #213](https://github.com/clicon/clixon/issues/213) * [RESTCONF GETof lists with empty string keys does not work #214](https://github.com/clicon/clixon/issues/214)
This commit is contained in:
parent
af04ec9e9d
commit
17e7b25537
8 changed files with 77 additions and 22 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -37,6 +37,15 @@ Expected: June 2021
|
||||||
* Yang deviation [deviation statement not yet support #211](https://github.com/clicon/clixon/issues/211)
|
* Yang deviation [deviation statement not yet support #211](https://github.com/clicon/clixon/issues/211)
|
||||||
* See RFC7950 Sec 5.6.3
|
* See RFC7950 Sec 5.6.3
|
||||||
|
|
||||||
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* RESTCONF in Clixon used empty key as "wildchar". But according to RFC 8040 it should mean the "empty string".
|
||||||
|
* Example: `GET restconf/data/x:a=`
|
||||||
|
* Previous meaning (wrong): Return all `a` elements.
|
||||||
|
* New meaning (correct): Return the `a` instance with empty key string: "".
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
* Add default network namespace constant: `RESTCONF_NETNS_DEFAULT` with default value "default".
|
* Add default network namespace constant: `RESTCONF_NETNS_DEFAULT` with default value "default".
|
||||||
|
|
@ -46,6 +55,8 @@ Expected: June 2021
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
||||||
|
* [RESTCONF GET request of single-key list with empty string returns all elements #213](https://github.com/clicon/clixon/issues/213)
|
||||||
|
* [RESTCONF GETof lists with empty string keys does not work #214](https://github.com/clicon/clixon/issues/214)
|
||||||
* Fixed: [Multiple http requests in native restconf yields same reply #212](https://github.com/clicon/clixon/issues/212)
|
* Fixed: [Multiple http requests in native restconf yields same reply #212](https://github.com/clicon/clixon/issues/212)
|
||||||
|
|
||||||
## 5.1.0
|
## 5.1.0
|
||||||
|
|
@ -77,6 +88,8 @@ The 5.1 release contains more RESTCONF native mode restructuring, new multi-yang
|
||||||
|
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
|
Users may have to change how they access the system
|
||||||
|
|
||||||
* Native RESTCONF mode
|
* Native RESTCONF mode
|
||||||
* Configure native mode changed to: `configure --with-restconf=native`, NOT `evhtp`
|
* Configure native mode changed to: `configure --with-restconf=native`, NOT `evhtp`
|
||||||
* Use libevhtp from https://github.com/clixon/clixon-libevhtp.git, NOT from criticalstack
|
* Use libevhtp from https://github.com/clixon/clixon-libevhtp.git, NOT from criticalstack
|
||||||
|
|
|
||||||
|
|
@ -713,7 +713,7 @@ api_path2xpath_cvv(cvec *api_path,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Check if has value, means '=' */
|
/* Check if has value, means '=' */
|
||||||
if (cv2str(cv, NULL, 0) > 0){
|
if (cv_type_get(cv) == CGV_STRING){
|
||||||
/* val is uri percent encoded, eg x%2Cy,z */
|
/* val is uri percent encoded, eg x%2Cy,z */
|
||||||
if ((val = cv2str_dup(cv)) == NULL)
|
if ((val = cv2str_dup(cv)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -560,8 +560,9 @@ xml_chardata_cbuf_append(cbuf *cb,
|
||||||
* err;
|
* err;
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* a=b&c=d -> [[a,"b"][c="d"]
|
* a=b&c=d -> [[a,"b"][c,"d"]
|
||||||
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
|
* a&b= -> [[a,null][b,""]]
|
||||||
|
* Note difference between empty (CGV_EMPTY) and empty string (CGV_STRING)
|
||||||
* XXX differentiate between error and null cvec.
|
* XXX differentiate between error and null cvec.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -622,12 +623,11 @@ uri_str2cvec(char *string,
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (strlen(s)){
|
if (strlen(s)){
|
||||||
if ((cv = cvec_add(cvv, CGV_STRING)) == NULL){
|
if ((cv = cvec_add(cvv, CGV_EMPTY)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cvec_add");
|
clicon_err(OE_UNIX, errno, "cvec_add");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
cv_name_set(cv, s);
|
cv_name_set(cv, s);
|
||||||
cv_string_set(cv, "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s = snext;
|
s = snext;
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ xpath_tree2cbuf(xpath_tree *xs,
|
||||||
cprintf(xcb, "/");
|
cprintf(xcb, "/");
|
||||||
break;
|
break;
|
||||||
case XP_PRIME_STR:
|
case XP_PRIME_STR:
|
||||||
cprintf(xcb, "'%s'", xs->xs_s0);
|
cprintf(xcb, "'%s'", xs->xs_s0?xs->xs_s0:"");
|
||||||
break;
|
break;
|
||||||
case XP_PRIME_NR:
|
case XP_PRIME_NR:
|
||||||
cprintf(xcb, "%s", xs->xs_strnr?xs->xs_strnr:"0");
|
cprintf(xcb, "%s", xs->xs_strnr?xs->xs_strnr:"0");
|
||||||
|
|
|
||||||
|
|
@ -824,8 +824,12 @@ xp_relop(xp_ctx *xc1,
|
||||||
s1 = xml_body(x);
|
s1 = xml_body(x);
|
||||||
switch(op){
|
switch(op){
|
||||||
case XO_EQ:
|
case XO_EQ:
|
||||||
if (s1 == NULL || s2 == NULL)
|
if (s1 == NULL && s2 == NULL)
|
||||||
xr->xc_bool = (s1==NULL && s2 == NULL);
|
xr->xc_bool = 1;
|
||||||
|
else if (s1 == NULL && strlen(s2) == 0)
|
||||||
|
xr->xc_bool = 1;
|
||||||
|
else if (strlen(s1) == 0 && s2 == NULL)
|
||||||
|
xr->xc_bool = 1;
|
||||||
else
|
else
|
||||||
xr->xc_bool = (strcmp(s1, s2)==0);
|
xr->xc_bool = (strcmp(s1, s2)==0);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -441,9 +441,9 @@ predicates : predicates '[' expr ']' { $$=xp_new(XP_PRED,A_NAN,NULL, NULL, NULL
|
||||||
primaryexpr : '(' expr ')' { $$=xp_new(XP_PRI0,A_NAN,NULL, NULL, NULL, $2, NULL); clicon_debug(3,"primaryexpr-> ( expr )"); }
|
primaryexpr : '(' expr ')' { $$=xp_new(XP_PRI0,A_NAN,NULL, NULL, NULL, $2, NULL); clicon_debug(3,"primaryexpr-> ( expr )"); }
|
||||||
| NUMBER { $$=xp_new(XP_PRIME_NR,A_NAN, $1, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> NUMBER(%s)", $1); /*XXX*/}
|
| NUMBER { $$=xp_new(XP_PRIME_NR,A_NAN, $1, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> NUMBER(%s)", $1); /*XXX*/}
|
||||||
| QUOTE string QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" string \""); }
|
| QUOTE string QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" string \""); }
|
||||||
| QUOTE QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" \""); }
|
| QUOTE QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, strdup(""), NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" \""); }
|
||||||
| APOST string APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' string '"); }
|
| APOST string APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' string '"); }
|
||||||
| APOST APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' '"); }
|
| APOST APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, strdup(""), NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' '"); }
|
||||||
| FUNCTIONNAME ')' { if (($$ = xp_primary_function(_XPY, $1, NULL)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname ()"); }
|
| FUNCTIONNAME ')' { if (($$ = xp_primary_function(_XPY, $1, NULL)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname ()"); }
|
||||||
| FUNCTIONNAME args ')' { if (($$ = xp_primary_function(_XPY, $1, $2)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname (arguments)"); }
|
| FUNCTIONNAME args ')' { if (($$ = xp_primary_function(_XPY, $1, $2)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname (arguments)"); }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Testcases for Restconf list and leaf-list keys, check matching keys for RFC8040 4.5:
|
# Testcases for Restconf list and leaf-list keys, check matching keys for RFC8040 4.5:
|
||||||
# the key values must match in URL and data
|
# the key values must match in URL and data
|
||||||
|
# Empty keys vs comma as a key
|
||||||
|
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
@ -82,7 +83,7 @@ if [ $BE -ne 0 ]; then
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "waiting"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
|
|
@ -91,11 +92,11 @@ if [ $RC -ne 0 ]; then
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
start_restconf -f $cfg
|
start_restconf -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
|
||||||
wait_restconf
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
new "restconf PUT add whole list entry"
|
new "restconf PUT add whole list entry"
|
||||||
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y -d '{"list:a":{"b":"x","c":"y","nonkey":"0"}}')" 0 "HTTP/1.1 201 Created"
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y -d '{"list:a":{"b":"x","c":"y","nonkey":"0"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
|
@ -112,6 +113,7 @@ expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCP
|
||||||
new "restconf PUT add whole list entry XML"
|
new "restconf PUT add whole list entry XML"
|
||||||
expectpart "$(curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d '<a xmlns="urn:example:clixon"><b>xx</b><c>xy</c><nonkey>0</nonkey></a>' $RCPROTO://localhost/restconf/data/list:c/a=xx,xy)" 0 "HTTP/1.1 201 Created"
|
expectpart "$(curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d '<a xmlns="urn:example:clixon"><b>xx</b><c>xy</c><nonkey>0</nonkey></a>' $RCPROTO://localhost/restconf/data/list:c/a=xx,xy)" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET sub key"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/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":"malformed key =a, expected '
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/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":"malformed key =a, expected '
|
||||||
|
|
||||||
new "restconf PUT change whole list entry (same keys)"
|
new "restconf PUT change whole list entry (same keys)"
|
||||||
|
|
@ -147,6 +149,15 @@ expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json
|
||||||
new "restconf PUT list-list"
|
new "restconf PUT list-list"
|
||||||
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=z -d '{"list:e":{"f":"z","nonkey":"0"}}')" 0 "HTTP/1.1 201 Created"
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=z -d '{"list:e":{"f":"z","nonkey":"0"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET e element with empty string key expect empty"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=)" 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 PUT list-list empty string"
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e= -d '{"list:e":{"f":"","nonkey":"42"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET e element with empty string key"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=)" 0 "HTTP/1.1 200 OK" '<e xmlns="urn:example:clixon"><f/><nonkey>42</nonkey></e>'
|
||||||
|
|
||||||
new "restconf PUT change list-lst entry (wrong keys)(expect fail)"
|
new "restconf PUT change list-lst entry (wrong keys)(expect fail)"
|
||||||
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=z -d '{"list:e":{"f":"wrong","nonkey":"0"}}')" 0 "HTTP/1.1 412 Precondition Failed" '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"api-path keys do not match data keys"}}}'
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,y/e=z -d '{"list:e":{"f":"wrong","nonkey":"0"}}')" 0 "HTTP/1.1 412 Precondition Failed" '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"api-path keys do not match data keys"}}}'
|
||||||
|
|
||||||
|
|
@ -174,6 +185,33 @@ expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json
|
||||||
new "restconf GET check percent-encoded"
|
new "restconf GET check percent-encoded"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x%2Cy,z)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"x,y","c":"z","nonkey":"foo"}\]}'
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x%2Cy,z)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"x,y","c":"z","nonkey":"foo"}\]}'
|
||||||
|
|
||||||
|
new "restconf PUT ,z empty string as first key"
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=,z -d '{"list:a":{"b":"","c":"z", "nonkey":"42"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET ,z empty"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=,z)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"","c":"z","nonkey":"42"}\]}'
|
||||||
|
|
||||||
|
new "restconf PUT x, empty string as second key"
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x, -d '{"list:a":{"b":"x","c":"", "nonkey":"43"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET x, empty"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=x,)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"x","c":"","nonkey":"43"}\]}'
|
||||||
|
|
||||||
|
new "restconf PUT , empty string as second key"
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=, -d '{"list:a":{"b":"","c":"", "nonkey":"44"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET , empty"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=,)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":"","c":"","nonkey":"44"}\]}'
|
||||||
|
|
||||||
|
new "restconf PUT two commas as keys"
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=%2C,%2C -d '{"list:a":{"b":",","c":",", "nonkey":"45"}}')" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
|
new "restconf GET two commas"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c/a=%2C,%2C)" 0 "HTTP/1.1 200 OK" '{"list:a":\[{"b":",","c":",","nonkey":"45"}\]}'
|
||||||
|
|
||||||
|
new "restconf GET all empty strings"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf/data/list:c)" 0 "HTTP/1.1 200 OK" '{"list:c":{"a":\[{"b":"","c":"","nonkey":"44"},{"b":"","c":"z","nonkey":"42"},{"b":",","c":",","nonkey":"45"},{"b":"x","c":"","nonkey":"43"}'
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
stop_restconf
|
stop_restconf
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ if [ $BE -ne 0 ]; then
|
||||||
start_backend -s startup -f $cfg
|
start_backend -s startup -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "waiting"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
|
|
@ -120,11 +120,11 @@ if [ $RC -ne 0 ]; then
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
start_restconf -f $cfg
|
start_restconf -f $cfg
|
||||||
|
|
||||||
new "waiting restconf"
|
|
||||||
wait_restconf
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
# also in test_restconf.sh
|
# also in test_restconf.sh
|
||||||
new "MUST support the PATCH method for a plain patch"
|
new "MUST support the PATCH method for a plain patch"
|
||||||
expectpart "$(curl -u andy:bar $CURLOPTS -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 $CURLOPTS -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"
|
||||||
|
|
@ -174,7 +174,7 @@ if [ $BE -ne 0 ]; then
|
||||||
start_backend -s startup -f $cfg
|
start_backend -s startup -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "waiting"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
|
|
@ -183,11 +183,11 @@ if [ $RC -ne 0 ]; then
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
start_restconf -f $cfg
|
start_restconf -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
|
||||||
wait_restconf
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
# 4.6.1. Plain Patch
|
# 4.6.1. Plain Patch
|
||||||
new "Create album London Calling with PUT"
|
new "Create album London Calling with PUT"
|
||||||
expectpart "$(curl -u andy:bar $CURLOPTS -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 $CURLOPTS -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"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue