Restconf: Fixed http accept/content-type logic
yang mem-leak
This commit is contained in:
parent
f1d9e26755
commit
158ea40b59
6 changed files with 63 additions and 58 deletions
|
|
@ -282,19 +282,20 @@ api_http_data_file(clixon_handle h,
|
||||||
char *pathname,
|
char *pathname,
|
||||||
int head)
|
int head)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cbuf *cbfile = NULL;
|
cbuf *cbfile = NULL;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
cbuf *cbdata = NULL;
|
cbuf *cbdata = NULL;
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
off_t fsz = 0;
|
off_t fsz = 0;
|
||||||
long fsize;
|
long fsize;
|
||||||
char *www_data_root = NULL;
|
char *www_data_root = NULL;
|
||||||
char *suffix;
|
char *suffix;
|
||||||
char *media;
|
char *media;
|
||||||
int ret;
|
char *buf = NULL;
|
||||||
char *buf = NULL;
|
size_t sz;
|
||||||
size_t sz;
|
char *media_list = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_RESTCONF, "");
|
clixon_debug(CLIXON_DBG_RESTCONF, "");
|
||||||
if ((cbfile = cbuf_new()) == NULL){
|
if ((cbfile = cbuf_new()) == NULL){
|
||||||
|
|
@ -305,7 +306,6 @@ api_http_data_file(clixon_handle h,
|
||||||
clixon_err(OE_RESTCONF, ENOENT, "CLICON_HTTP_DATA_ROOT missing");
|
clixon_err(OE_RESTCONF, ENOENT, "CLICON_HTTP_DATA_ROOT missing");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
cprintf(cbfile, "%s", www_data_root);
|
cprintf(cbfile, "%s", www_data_root);
|
||||||
if (pathname){
|
if (pathname){
|
||||||
if (strlen(pathname) && pathname[0] != '/'){
|
if (strlen(pathname) && pathname[0] != '/'){
|
||||||
|
|
@ -331,6 +331,19 @@ api_http_data_file(clixon_handle h,
|
||||||
if ((media = clicon_str2str(mime_map, suffix)) == NULL)
|
if ((media = clicon_str2str(mime_map, suffix)) == NULL)
|
||||||
media = "application/octet-stream";
|
media = "application/octet-stream";
|
||||||
}
|
}
|
||||||
|
/* 5. Accepted media_out: should check text/html, JavaScript, image, and css
|
||||||
|
*/
|
||||||
|
if ((media_list = restconf_param_get(h, "HTTP_ACCEPT")) != NULL){
|
||||||
|
if (restconf_media_in_list(media, media_list) != 1 &&
|
||||||
|
restconf_media_in_list("*/*", media_list) != 1) {
|
||||||
|
/* If the server does not support any of the requested
|
||||||
|
* output encodings for a request, then it MUST return an error response
|
||||||
|
* with a "406 Not Acceptable" status-line. */
|
||||||
|
if (restconf_not_acceptable(h, req, 1, HTTP_DATA_TEXT_HTML) < 0)
|
||||||
|
goto done;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Size could have been taken from stat() but this reduces the race condition interval
|
/* Size could have been taken from stat() but this reduces the race condition interval
|
||||||
* There is still one without flock
|
* There is still one without flock
|
||||||
*/
|
*/
|
||||||
|
|
@ -416,12 +429,11 @@ api_http_data(clixon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *request_method = NULL;
|
char *request_method = NULL;
|
||||||
char *media_list = NULL;
|
|
||||||
int head = 0;
|
int head = 0;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
int ret;
|
|
||||||
cbuf *indata = NULL;
|
cbuf *indata = NULL;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_RESTCONF, "");
|
clixon_debug(CLIXON_DBG_RESTCONF, "");
|
||||||
if (req == NULL){
|
if (req == NULL){
|
||||||
|
|
@ -467,20 +479,6 @@ api_http_data(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* 5. Accepted media_out: should check text/html, JavaScript, image, and css
|
|
||||||
*/
|
|
||||||
if ((media_list = restconf_param_get(h, "HTTP_ACCEPT")) != NULL){
|
|
||||||
if (restconf_media_in_list("text/html", media_list) != 1 &&
|
|
||||||
restconf_media_in_list("*/*", media_list) != 1
|
|
||||||
&& 0) { /* XXX: not yet */
|
|
||||||
/* If the server does not support any of the requested
|
|
||||||
* output encodings for a request, then it MUST return an error response
|
|
||||||
* with a "406 Not Acceptable" status-line. */
|
|
||||||
if (restconf_not_acceptable(h, req, 1, HTTP_DATA_TEXT_HTML) < 0)
|
|
||||||
goto done;
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 6. Authenticate
|
/* 6. Authenticate
|
||||||
* Note, error handling may need change since it is restconf based
|
* Note, error handling may need change since it is restconf based
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ openconfig:
|
||||||
./getopenconfig.sh
|
./getopenconfig.sh
|
||||||
|
|
||||||
docker: clixon yang openconfig $(DOCKERFILE)
|
docker: clixon yang openconfig $(DOCKERFILE)
|
||||||
sudo docker build -f $(DOCKERFILE) -t $(IMG) $(DOCKERFLAGS) .
|
sudo docker build --progress plain -f $(DOCKERFILE) -t $(IMG) $(DOCKERFLAGS) .
|
||||||
|
|
||||||
push:
|
push:
|
||||||
sudo docker push $(IMG)
|
sudo docker push $(IMG)
|
||||||
|
|
|
||||||
|
|
@ -912,11 +912,16 @@ ys_free1(yang_stmt *ys,
|
||||||
{
|
{
|
||||||
rpc_callback_t *rc;
|
rpc_callback_t *rc;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
cvec *cvv;
|
||||||
|
|
||||||
if ((cv = ys->ys_cv) != NULL){ // To not trigger asserts
|
if ((cv = ys->ys_cv) != NULL){
|
||||||
ys->ys_cv = NULL;
|
ys->ys_cv = NULL;
|
||||||
cv_free(cv);
|
cv_free(cv);
|
||||||
}
|
}
|
||||||
|
if ((cvv = ys->ys_cvec) != NULL){
|
||||||
|
ys->ys_cvec = NULL;
|
||||||
|
cvec_free(cvv);
|
||||||
|
}
|
||||||
if (ys->ys_argument){
|
if (ys->ys_argument){
|
||||||
free(ys->ys_argument);
|
free(ys->ys_argument);
|
||||||
ys->ys_argument = NULL;
|
ys->ys_argument = NULL;
|
||||||
|
|
|
||||||
39
test/mem.sh
39
test/mem.sh
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Run valgrind leak test for cli, restconf, netconf or background.
|
# Run valgrind leak test for backend, restconf, cli, netconf or snmp.
|
||||||
# Stop on first error
|
# Stop on first error
|
||||||
# Typical run: ./mem.sh 2>&1 | tee mylog
|
# Typical run: ./mem.sh 2>&1 | tee mylog
|
||||||
|
|
||||||
|
|
@ -7,32 +7,22 @@
|
||||||
: ${pattern:=test_*.sh}
|
: ${pattern:=test_*.sh}
|
||||||
|
|
||||||
# Run valgrindtest once, args:
|
# Run valgrindtest once, args:
|
||||||
# what: (cli|netconf|restconf|backend)* # no args means all
|
# what: (backend|restconf|cli|netconf|snmp)* # no args means all
|
||||||
function memonce(){
|
function memonce(){
|
||||||
what=$1
|
what=$1
|
||||||
|
|
||||||
valgrindfile=$(mktemp)
|
valgrindfile=$(mktemp)
|
||||||
echo "valgrindfile:$valgrindfile"
|
echo "valgrindfile:$valgrindfile"
|
||||||
|
|
||||||
clixon_cli=
|
|
||||||
clixon_netconf=
|
|
||||||
clixon_backend=
|
clixon_backend=
|
||||||
clixon_restconf=
|
clixon_restconf=
|
||||||
|
clixon_cli=
|
||||||
|
clixon_netconf=
|
||||||
clixon_snmp=
|
clixon_snmp=
|
||||||
case "$what" in
|
case "$what" in
|
||||||
'cli')
|
|
||||||
valgrindtest=1
|
|
||||||
: ${DEMWAIT:=5} # valgrind backend needs some time to get up
|
|
||||||
clixon_cli="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_cli"
|
|
||||||
;;
|
|
||||||
'netconf')
|
|
||||||
valgrindtest=1
|
|
||||||
: ${DEMWAIT:=5} # valgrind backend needs some time to get up
|
|
||||||
clixon_netconf="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_netconf"
|
|
||||||
;;
|
|
||||||
'backend')
|
'backend')
|
||||||
valgrindtest=2 # This means backend valgrind test
|
valgrindtest=2 # This means backend valgrind test
|
||||||
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
|
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
|
||||||
# trace-children=no for test_restconf_rpc.sh
|
# trace-children=no for test_restconf_rpc.sh
|
||||||
sudo chown root $valgrindfile
|
sudo chown root $valgrindfile
|
||||||
sudo chmod 777 $valgrindfile
|
sudo chmod 777 $valgrindfile
|
||||||
|
|
@ -40,9 +30,19 @@ function memonce(){
|
||||||
;;
|
;;
|
||||||
'restconf')
|
'restconf')
|
||||||
valgrindtest=3 # This means restconf valgrind test
|
valgrindtest=3 # This means restconf valgrind test
|
||||||
: ${DEMWAIT:=15} # valgrind backend needs some time to get up
|
: ${DEMWAIT:=15} # valgrind backend needs some time to get up
|
||||||
clixon_restconf="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_restconf"
|
clixon_restconf="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_restconf"
|
||||||
|
|
||||||
|
;;
|
||||||
|
'cli')
|
||||||
|
valgrindtest=1
|
||||||
|
: ${DEMWAIT:=5} # valgrind backend needs some time to get up
|
||||||
|
clixon_cli="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_cli"
|
||||||
|
;;
|
||||||
|
'netconf')
|
||||||
|
valgrindtest=1
|
||||||
|
: ${DEMWAIT:=5} # valgrind backend needs some time to get up
|
||||||
|
clixon_netconf="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_netconf"
|
||||||
;;
|
;;
|
||||||
'snmp')
|
'snmp')
|
||||||
valgrindtest=4 # This means snmp valgrind test
|
valgrindtest=4 # This means snmp valgrind test
|
||||||
|
|
@ -50,9 +50,8 @@ function memonce(){
|
||||||
: ${DEMWAIT:=15} # valgrind snmp needs some time to get up
|
: ${DEMWAIT:=15} # valgrind snmp needs some time to get up
|
||||||
clixon_snmp="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_snmp"
|
clixon_snmp="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile clixon_snmp"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "usage: $0 cli|netconf|restconf|backend|snmp" # valgrind memleak checks
|
echo "usage: $0 backend|restconf|cli|netconf|snmp" # valgrind memleak checks
|
||||||
rm -f $valgrindfile
|
rm -f $valgrindfile
|
||||||
exit -1
|
exit -1
|
||||||
;;
|
;;
|
||||||
|
|
@ -108,9 +107,9 @@ fi
|
||||||
|
|
||||||
# First run sanity
|
# First run sanity
|
||||||
for c in $cmds; do
|
for c in $cmds; do
|
||||||
if [ $c != cli -a $c != netconf -a $c != restconf -a $c != backend -a $c != snmp ]; then
|
if [ $c != backend -a $c != restconf -a $c != cli -a $c != netconf -a $c != snmp ]; then
|
||||||
echo "c:$c"
|
echo "c:$c"
|
||||||
echo "usage: $0 [cli|netconf|restconf|backend|snmp]+"
|
echo "usage: $0 [backend||restconf|cli|netconf|snmp]+"
|
||||||
echo " with no args run all"
|
echo " with no args run all"
|
||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -213,10 +213,8 @@ EOF
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: wrong/media,*/*' $proto://localhost/data/index.html)" 0 "HT
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: wrong/media,*/*' $proto://localhost/data/index.html)" 0 "HT
|
||||||
TP/$HVER 200" "Content-Type: text/html" "<title>Welcome to Clixon!</title>"
|
TP/$HVER 200" "Content-Type: text/html" "<title>Welcome to Clixon!</title>"
|
||||||
|
|
||||||
if false; then # XXX Se step 5 in api_http_data, unclear which media should be accepted
|
|
||||||
new "Server does not support list of medias Expect 406"
|
new "Server does not support list of medias Expect 406"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: wrong/media' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 406" "content-type: text/html" "<error-message>Unacceptable output encoding</error-message>"
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: wrong/media' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 406" "content-type: text/html" "<error-message>Unacceptable output encoding</error-message>"
|
||||||
fi
|
|
||||||
|
|
||||||
new "WWW get dir -> expect index.html"
|
new "WWW get dir -> expect index.html"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data)" 0 "HTTP/$HVER 200" "Content-Type: text/html" "<title>Welcome to Clixon!</title>"
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data)" 0 "HTTP/$HVER 200" "Content-Type: text/html" "<title>Welcome to Clixon!</title>"
|
||||||
|
|
@ -231,7 +229,13 @@ fi
|
||||||
mv $dir/www/data/tmp.index.html $dir/www/data/index.html
|
mv $dir/www/data/tmp.index.html $dir/www/data/index.html
|
||||||
|
|
||||||
new "WWW get css"
|
new "WWW get css"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 200" "Content-Type: text/css" "display: inline;" --not-- "Content-Type: text/html"
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/css' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 200" "Content-Type: text/css" "display: inline;" --not-- "Content-Type: text/html"
|
||||||
|
|
||||||
|
new "WWW get css accept *"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html,*/*' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 200" "Content-Type: text/css" "display: inline;" --not-- "Content-Type: text/html"
|
||||||
|
|
||||||
|
new "WWW get css, operation-not-supported"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 406" "operation-not-supported"
|
||||||
|
|
||||||
new "WWW head"
|
new "WWW head"
|
||||||
expectpart "$(curl $CURLOPTS --head -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "Content-Type: text/html" --not-- "<title>Welcome to Clixon!</title>"
|
expectpart "$(curl $CURLOPTS --head -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "Content-Type: text/html" --not-- "<title>Welcome to Clixon!</title>"
|
||||||
|
|
|
||||||
|
|
@ -197,9 +197,8 @@ wait_restconf
|
||||||
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/$HVER 201"
|
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/$HVER 201"
|
||||||
|
|
||||||
#new "The message-body for a plain patch MUST be present"
|
new "The message-body for a plain patch MUST be present"
|
||||||
# XXX Hangs in SSL 3.3.2
|
expectpart "$(curl -u andy:bar $CURLOPTS -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Beatles -d '')" 0 "HTTP/$HVER 400" "The message-body MUST contain exactly one instance of the expected data resource"
|
||||||
#expectpart "$(curl -u andy:bar $CURLOPTS -X PATCH -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/example-jukebox:jukebox/library/artist=Beatles -d '')" 0 "HTTP/$HVER 400" kalle
|
|
||||||
|
|
||||||
# Plain patch can be used to create or update, but not delete, a child
|
# Plain patch can be used to create or update, but not delete, a child
|
||||||
# resource within the target resource.
|
# resource within the target resource.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue