diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd54b4bc..e5dc0304 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,8 @@
### Major New features
* Restconf RFC 8040 increased feature compliance
- * RESTCONF PATCH (plain patch) is supported according to RFC 8040 4.6.1
+ * RESTCONF PATCH (plain patch) is being implemented according to RFC 8040 4.6.1
+ * Work-in-progress, expected done by 4.1.0
* RESTCONF "insert" and "point" query parameters supported
* Applies to ordered-by-user leaf and leaf-lists
* RESTCONF PUT/POST erroneously returned 200 OK. Instead restconf now returns:
diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c
index 200ea022..fd263954 100644
--- a/apps/restconf/restconf_methods.c
+++ b/apps/restconf/restconf_methods.c
@@ -134,6 +134,7 @@ Mapping netconf error-tag -> status code
* Minimal support:
* 200 OK
* Allow: HEAD,GET,PUT,DELETE,OPTIONS
+ * @see RFC5789 PATCH Method for HTTP Section 3.2
*/
int
api_data_options(clicon_handle h,
@@ -141,7 +142,8 @@ api_data_options(clicon_handle h,
{
clicon_debug(1, "%s", __FUNCTION__);
FCGX_SetExitStatus(200, r->out); /* OK */
- FCGX_FPrintF(r->out, "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE\r\n");
+ FCGX_FPrintF(r->out, "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE\r\n");
+ FCGX_FPrintF(r->out, "Accept-Patch: application/yang-data+xml,application/yang-data+json\r\n");
FCGX_FPrintF(r->out, "\r\n");
return 0;
}
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index 068c6f56..a50ab9c0 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -101,11 +101,11 @@ expecteq "$(curl -s -H 'Accept: application/yang-data+json' -G http://localhost/
'
new "restconf options. RFC 8040 4.1"
-expectfn "curl -i -s -X OPTIONS http://localhost/restconf/data" 0 "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE"
+expectpart "$(curl -is -X OPTIONS http://localhost/restconf/data)" 0 "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
-new "restconf head. RFC 8040 4.2"
-expectfn "curl -s -I http://localhost/restconf/data" 0 "HTTP/1.1 200 OK"
-#Content-Type: application/yang-data+json"
+# -I means HEAD
+new "restconf HEAD. RFC 8040 4.2"
+expectpart "$(curl -si -I -H "Accept: application/yang-data+json" http://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+json"
new "restconf empty rpc"
expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" -d {\"clixon-example:input\":null} http://localhost/restconf/operations/clixon-example:empty)" 0 "HTTP/1.1 204 No Content"
diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh
index e14e6442..411adf9c 100755
--- a/test/test_restconf_jukebox.sh
+++ b/test/test_restconf_jukebox.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# Restconf RFC8040 Appendix A and B "jukebox" example
-
+# Not supported: B.2.2 if-unmodified
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@@ -92,10 +92,6 @@ new "B.2.1. Add Data Resources again (conflict - not in RFC)"
expectpart "$(curl -si -X POST -H 'Content-Type: application/yang-data+xml' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters -d 'Wasting Light2011')" 0 "HTTP/1.1 409 Conflict"
-new "B.2.2. Added genre"
-# Here the jbox identity is added
-expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' http://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"
-
new "4.5. PUT replace content (xml encoding)"
expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+xml' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d 'Wasting Lightjbox:alternative2011')" 0 "HTTP/1.1 204 No Content"
@@ -105,6 +101,9 @@ expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+json' http
new "4.5. Check jukebox content: 1 Clash and 1 Foo fighters album"
expectpart "$(curl -si -X GET http://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' http://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' http://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'
@@ -116,7 +115,7 @@ new "B.2.3. Check patch system"
expectpart "$(curl -si -X GET http://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 http://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 -si -X GET http://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' http://localhost/restconf/data -d 'Foo FightersOne by One2012Nick Cave and the Bad SeedsTender Prey1988')" 0 "HTTP/1.1 204 No Content"
@@ -124,6 +123,12 @@ expectpart "$(curl -si -X PUT -H 'Content-Type: application/yang-data+xml' http:
new "B.2.4. Check replace"
expectpart "$(curl -si -X GET http://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 http://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 http://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'
+
new "restconf DELETE whole datastore"
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
@@ -182,9 +187,7 @@ expectpart "$(curl -si -X GET http://localhost/restconf/data/example-jukebox:ext
if false; then # NYI
-new "B.2.2. Detect Datastore Resource Entity-Tag Change"
-new "B.2.3. Edit a Datastore Resource"
-new "B.2.5. Edit a Data Resource"
+new "B.2.2. Detect Datastore Resource Entity-Tag Change" # XXX done except entity-changed
new 'B.3.1. "content" Parameter'
new 'B.3.2. "depth" Parameter'
new 'B.3.3. "fields" Parameter'
diff --git a/test/test_restconf_patch.sh b/test/test_restconf_patch.sh
index ec539163..932d8a58 100755
--- a/test/test_restconf_patch.sh
+++ b/test/test_restconf_patch.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Restconf RFC8040 plain patch
+# Restconf RFC8040 plain patch Sec 4.6 / 4.6.1
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@@ -49,6 +49,22 @@ new "waiting"
wait_backend
wait_restconf
+# also in test_restconf.sh
+new "MUST support the PATCH method for a plain patch"
+expectpart "$(curl -is -X OPTIONS http://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 -si -X PATCH -H 'Content-Type: application/yang-data+json' http://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 -si -X PUT -H 'Content-Type: application/yang-data+json' http://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 -si -X PATCH -H 'Content-Type: application/yang-data+json' http://localhost/restconf/data/example-jukebox:jukebox -d '{"example-jukebox:jukebox":{"library":{"artist":{"name":"Clash"}}}}')" 0 "HTTP/1.1 204 No Content"
+
+new "Check content"
+expectpart "$(curl -si -X GET http://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 "Kill restconf daemon"
stop_restconf