Handle HTTP/1.1 pipelined requests
Check to see whether there are outstanding requests in the httpd receive buffer after sending the response, and if so, process them. Test that pipelined requests are handled by sending multiple minimal HTTP/1.1 using netcat (nc) and checking that we get back the same number of responses.
This commit is contained in:
@@ -112,6 +112,9 @@ SHELL=@SHELL@
|
||||
# CURL will be empty if no program was found by configure
|
||||
CURL=@CURL@
|
||||
|
||||
# NC will be empty if no program was found by configure
|
||||
NC=@NC@
|
||||
|
||||
# XMLLINT will be empty if no program was found by configure
|
||||
XMLLINT=@XMLLINT@
|
||||
|
||||
|
||||
@@ -175,8 +175,12 @@ echo_i "checking bind9.xsl vs xml ($n)"
|
||||
if $FEATURETEST --have-libxml2 && [ -x "${CURL}" ] && [ -x "${XSLTPROC}" ] ; then
|
||||
$DIGCMD +notcp +recurse @10.53.0.3 soa . > dig.out.test$n.1 2>&1
|
||||
$DIGCMD +notcp +recurse @10.53.0.3 soa example > dig.out.test$n.2 2>&1
|
||||
${CURL} http://10.53.0.3:${EXTRAPORT1}/xml/v3 > curl.out.${n}.xml 2>/dev/null || ret=1
|
||||
${CURL} http://10.53.0.3:${EXTRAPORT1}/bind9.xsl > curl.out.${n}.xsl 2>/dev/null || ret=1
|
||||
# check multiple requests over the same socket
|
||||
time1=$($PERL -e 'print time(), "\n";')
|
||||
${CURL} --http1.1 -o curl.out.${n}.xml http://10.53.0.3:${EXTRAPORT1}/xml/v3 \
|
||||
-o curl.out.${n}.xsl http://10.53.0.3:${EXTRAPORT1}/bind9.xsl 2>/dev/null || ret=1
|
||||
time2=$($PERL -e 'print time(), "\n";')
|
||||
test $((time2 - time1)) -lt 5 || ret=1
|
||||
${DIFF} ${TOP_SRCDIR}/bin/named/bind9.xsl curl.out.${n}.xsl || ret=1
|
||||
${XSLTPROC} curl.out.${n}.xsl - < curl.out.${n}.xml > xsltproc.out.${n} 2>/dev/null || ret=1
|
||||
cp curl.out.${n}.xml stats.xml.out || ret=1
|
||||
|
||||
@@ -28,3 +28,4 @@ rm -f xml.*mem json.*mem
|
||||
rm -f xml.*stats json.*stats
|
||||
rm -f zones zones.out.* zones.json.* zones.xml.* zones.expect.*
|
||||
rm -rf ./__pycache__
|
||||
rm -f nc.out*
|
||||
|
||||
@@ -374,5 +374,26 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
n=`expr $n + 1`
|
||||
|
||||
if [ -x "${NC}" ] ; then
|
||||
echo_i "Check HTTP/1.1 pipelined requests are handled ($n)"
|
||||
ret=0
|
||||
${NC} 10.53.0.3 ${EXTRAPORT1} << EOF > nc.out$n || ret=1
|
||||
GET /xml/v3/status HTTP/1.1
|
||||
Host: 10.53.0.3:${EXTRAPORT1}
|
||||
|
||||
GET /xml/v3/status HTTP/1.1
|
||||
Host: 10.53.0.3:${EXTRAPORT1}
|
||||
Connection: close
|
||||
|
||||
EOF
|
||||
lines=$(grep "^HTTP/1.1" nc.out$n | wc -l)
|
||||
test $lines = 2 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
n=`expr $n + 1`
|
||||
else
|
||||
echo_i "skipping test as nc not found"
|
||||
fi
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
||||
@@ -1256,6 +1256,13 @@ AC_CONFIG_FILES([doc/doxygen/doxygen-input-filter],
|
||||
AC_PATH_PROG(CURL, curl, curl)
|
||||
AC_SUBST(CURL)
|
||||
|
||||
#
|
||||
# Look for nc
|
||||
#
|
||||
|
||||
AC_PATH_PROGS(NC, nc, nc)
|
||||
AC_SUBST(NC)
|
||||
|
||||
#
|
||||
# IDN support using libidn2
|
||||
#
|
||||
|
||||
@@ -403,11 +403,14 @@ process_request(isc_httpd_t *httpd, isc_region_t *region, size_t *buflen) {
|
||||
len = limit;
|
||||
}
|
||||
|
||||
memmove(httpd->recvbuf + httpd->recvlen, region->base, len);
|
||||
httpd->recvlen += len;
|
||||
httpd->recvbuf[httpd->recvlen] = 0;
|
||||
*buflen = httpd->recvlen;
|
||||
if (len > 0U) {
|
||||
memmove(httpd->recvbuf + httpd->recvlen, region->base, len);
|
||||
httpd->recvlen += len;
|
||||
httpd->recvbuf[httpd->recvlen] = 0;
|
||||
isc_region_consume(region, len);
|
||||
}
|
||||
httpd->headers = NULL;
|
||||
*buflen = httpd->recvlen;
|
||||
|
||||
/*
|
||||
* If we don't find a blank line in our buffer, return that we need
|
||||
@@ -858,10 +861,22 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
goto cleanup_readhandle;
|
||||
}
|
||||
|
||||
result = process_request(httpd, region, &buflen);
|
||||
result = process_request(
|
||||
httpd, region == NULL ? &(isc_region_t){ NULL, 0 } : region,
|
||||
&buflen);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
if (buflen < HTTP_RECVLEN - 1) {
|
||||
/* don't unref, keep reading */
|
||||
if (region != NULL) {
|
||||
/* don't unref, keep reading */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* We have been called from httpd_senddone
|
||||
* and we need to resume reading. Detach
|
||||
* readhandle before resuming.
|
||||
*/
|
||||
isc_nmhandle_detach(&httpd->readhandle);
|
||||
isc_nm_resumeread(handle);
|
||||
return;
|
||||
}
|
||||
goto cleanup_readhandle;
|
||||
@@ -950,6 +965,7 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
* the response headers and store the result in httpd->sendbuffer.
|
||||
*/
|
||||
isc_buffer_dup(mgr->mctx, &httpd->sendbuffer, &httpd->headerbuffer);
|
||||
isc_buffer_clear(&httpd->headerbuffer);
|
||||
isc_buffer_setautorealloc(httpd->sendbuffer, true);
|
||||
databuffer = (is_compressed ? &httpd->compbuffer : &httpd->bodybuffer);
|
||||
isc_buffer_usedregion(databuffer, &r);
|
||||
@@ -965,6 +981,7 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
}
|
||||
httpd->recvlen -= httpd->consume;
|
||||
httpd->consume = 0;
|
||||
httpd->recvbuf[httpd->recvlen] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1150,7 +1167,16 @@ httpd_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
}
|
||||
|
||||
httpd->state = RECV;
|
||||
isc_nm_resumeread(handle);
|
||||
if (httpd->recvlen != 0) {
|
||||
/*
|
||||
* Outstanding requests still exist, start processing
|
||||
* them.
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &httpd->readhandle);
|
||||
httpd_request(handle, ISC_R_SUCCESS, NULL, httpd->mgr);
|
||||
} else {
|
||||
isc_nm_resumeread(handle);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
||||
Reference in New Issue
Block a user