diff --git a/apps/restconf/restconf_err.c b/apps/restconf/restconf_err.c index 9f32d020..e2841c3f 100644 --- a/apps/restconf/restconf_err.c +++ b/apps/restconf/restconf_err.c @@ -116,6 +116,94 @@ restconf_badrequest(clicon_handle h, return retval; } +/*! HTTP error 404 + * @param[in] h Clicon handle + * @param[in] req Generic Www handle + * XXX skip body? + */ +int +restconf_notfound(clicon_handle h, + void *req) +{ + int retval = -1; +#ifdef SKIP_BODY /* Remove the body - should it really be there? */ + if (restconf_reply_send(req, 404, NULL) < 0) + goto done; + retval = 0; + done: +#else + char *path; + cbuf *cb = NULL; + + /* Create body */ + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + path = restconf_param_get("REQUEST_URI", r->envp); + 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_send(req, 404, cb) < 0) + goto done; + retval = 0; + done: + if (cb) + cbuf_free(cb); +#endif + return retval; +} + +/*! HTTP error 405 + * @param[in] req Generic Www handle + * @param[in] allow Which methods are allowed + */ +int +restconf_method_notallowed(void *req, + char *allow) +{ + int retval = -1; + + if (restconf_reply_header(req, "Allow", "%s", allow) < 0) + goto done; + if (restconf_reply_send(req, 405, NULL) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! HTTP error 409 Unsupporte dmedia + * @param[in] req Generic Www handle + */ +int +restconf_unsupported_media(void *req) +{ + int retval = -1; + + if (restconf_reply_send(req, 415, NULL) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! HTTP error 501 Not implemented + * @param[in] req Generic Www handle + */ +int +restconf_notimplemented(void *req) +{ + int retval = -1; + + if (restconf_reply_send(req, 501, NULL) < 0) + goto done; + retval = 0; + done: + return retval; +} + +#ifdef NOTUSED /*! HTTP error 401 * @param[in] h Clicon handle * @param[in] req Generic Www handle @@ -193,63 +281,6 @@ restconf_forbidden(clicon_handle h, return retval; } -/*! HTTP error 404 - * @param[in] h Clicon handle - * @param[in] req Generic Www handle - * XXX skip body? - */ -int -restconf_notfound(clicon_handle h, - void *req) -{ - int retval = -1; -#ifdef SKIP_BODY /* Remove the body - should it really be there? */ - if (restconf_reply_send(req, 404, NULL) < 0) - goto done; - retval = 0; - done: -#else - char *path; - cbuf *cb = NULL; - - /* Create body */ - if ((cb = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); - goto done; - } - path = restconf_param_get("REQUEST_URI", r->envp); - 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_send(req, 404, cb) < 0) - goto done; - retval = 0; - done: - if (cb) - cbuf_free(cb); -#endif - return retval; -} - -/*! HTTP error 405 - * @param[in] req Generic Www handle - * @param[in] allow Which methods are allowed - */ -int -restconf_method_notallowed(void *req, - char *allow) -{ - int retval = -1; - - if (restconf_reply_header(req, "Allow", "%s", allow) < 0) - goto done; - if (restconf_reply_send(req, 405, NULL) < 0) - goto done; - retval = 0; - done: - return retval; -} - /*! HTTP error 406 Not acceptable * @param[in] h Clicon handle * @param[in] req Generic Www handle @@ -304,21 +335,6 @@ restconf_conflict(void *req) return retval; } -/*! HTTP error 409 Unsupporte dmedia - * @param[in] req Generic Www handle - */ -int -restconf_unsupported_media(void *req) -{ - int retval = -1; - - if (restconf_reply_send(req, 415, NULL) < 0) - goto done; - retval = 0; - done: - return retval; -} - /*! HTTP error 500 Internal server error * @param[in] h Clicon handle * @param[in] req Generic Www handle @@ -355,21 +371,7 @@ restconf_internal_server_error(clicon_handle h, #endif return retval; } - -/*! HTTP error 501 Not implemented - * @param[in] req Generic Www handle - */ -int -restconf_notimplemented(void *req) -{ - int retval = -1; - - if (restconf_reply_send(req, 501, NULL) < 0) - goto done; - retval = 0; - done: - return retval; -} +#endif /* NOTUSED */ /*! Generic restconf error function on get/head request * @param[in] h Clixon handle diff --git a/apps/restconf/restconf_err.h b/apps/restconf/restconf_err.h index b236ecd7..a78e53b7 100644 --- a/apps/restconf/restconf_err.h +++ b/apps/restconf/restconf_err.h @@ -44,15 +44,17 @@ */ int restconf_badrequest(clicon_handle h, void *req); +int restconf_notfound(clicon_handle h, void *req); +int restconf_method_notallowed(void *req, char *allow); +int restconf_unsupported_media(void *req); +int restconf_notimplemented(void *req); +#ifdef NOTUSED int restconf_unauthorized(clicon_handle h, void *req); int restconf_forbidden(clicon_handle h, void *req); -int restconf_notfound(clicon_handle h, void *req); -int restconf_method_notallowed(void *req, char *allow); int restconf_notacceptable(clicon_handle h, void *req); int restconf_conflict(void *req); -int restconf_unsupported_media(void *req); int restconf_internal_server_error(clicon_handle h, void *req); -int restconf_notimplemented(void *req); +#endif /* NOTUSED */ int api_return_err(clicon_handle h, void *req, cxobj *xerr, int pretty, restconf_media media, int code0); diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index bfcd81ea..ab68516e5 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -504,6 +504,7 @@ evhtp_params_set(clicon_handle h, if (restconf_param_set(h, "REQUEST_URI", path->full) < 0) goto done; clicon_debug(1, "%s proto:%d", __FUNCTION__, req->proto); + /* XXX: Any two http numbers seem accepted by evhtp, like 1.99, 99.3 as http/1.1*/ if (req->proto != EVHTP_PROTO_10 && req->proto != EVHTP_PROTO_11){ if (restconf_badrequest(h, req) < 0) diff --git a/apps/restconf/restconf_root.c b/apps/restconf/restconf_root.c index a8123d0c..6f67752a 100644 --- a/apps/restconf/restconf_root.c +++ b/apps/restconf/restconf_root.c @@ -461,6 +461,10 @@ api_root_restconf(clicon_handle h, clicon_debug(1, "%s DATA=%s", __FUNCTION__, indata); /* If present, check credentials. See "plugin_credentials" in plugin + * retvals: + * -1 Error + * 0 Not authenticated + * 1 Authenticated * See RFC 8040 section 2.5 */ if ((ret = restconf_authentication_cb(h, req, pretty, media_out)) < 0) diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh index 17700e4f..78466aaa 100755 --- a/test/test_restconf_err.sh +++ b/test/test_restconf_err.sh @@ -18,6 +18,7 @@ # # Also generate an invalid state XML. This should generate an "Internal" error and the name of the # plugin should be visible in the error message. +# XXX does not test rpc-error from backend in api_return_err? # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi @@ -29,6 +30,8 @@ fyang=$dir/example.yang fyang2=$dir/augment.yang fxml=$dir/initial.xml fstate=$dir/state.xml +RCPROTO=http # Force to http due to netcat + # Define default restconfig config: RESTCONFIG RESTCONFIG=$(restconf_config none false) @@ -187,8 +190,58 @@ new "restconf POST initial tree" expectpart "$(curl $CURLOPTS -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" +#echo "curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:a=0" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:a=0)" 0 'HTTP/1.1 200 OK' "$XML" +# XXX cannot get this to work for all combinations of nc/netcat fcgi/native +# But leave it here for debugging where netcat works properly +if false; then + # Look for netcat or nc for direct socket http calls + if [ -n "$(type netcat 2> /dev/null)" ]; then + netcat="netcat -w 1" # -N works on evhtp but not fcgi + elif [ -n "$(type nc 2> /dev/null)" ]; then + netcat=nc + else + err1 "netcat/nc not found" + fi + + new "restconf GET initial datastore netcat" + expectpart "$(${netcat} 127.0.0.1 80 <