mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
[master] stats improvements
3700. [func] Allow access to subgroups of XML statistics via special URLs http://<server>:<port>/xml/v3/server, /zones, /net, /tasks, /mem, and /status. [RT #35115] 3699. [bug] Improvements to statistics channel XSL stylesheet: the stylesheet can now be cached by the browser; section headers are omitted from the stats display when there is no data in those sections to be displayed; counters are now right-justified for easier readability. [RT #35117]
This commit is contained in:
120
lib/isc/httpd.c
120
lib/isc/httpd.c
@@ -26,6 +26,7 @@
|
||||
#include <isc/socket.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <string.h>
|
||||
@@ -58,20 +59,6 @@
|
||||
#define HTTP_SENDGROW 1024
|
||||
#define HTTP_SEND_MAXLEN 10240
|
||||
|
||||
/*%
|
||||
* HTTP urls. These are the URLs we manage, and the function to call to
|
||||
* provide the data for it. We pass in the base url (so the same function
|
||||
* can handle multiple requests), and a structure to fill in to return a
|
||||
* result to the client. We also pass in a pointer to be filled in for
|
||||
* the data cleanup function.
|
||||
*/
|
||||
struct isc_httpdurl {
|
||||
char *url;
|
||||
isc_httpdaction_t *action;
|
||||
void *action_arg;
|
||||
ISC_LINK(isc_httpdurl_t) link;
|
||||
};
|
||||
|
||||
#define HTTPD_CLOSE 0x0001 /* Got a Connection: close header */
|
||||
#define HTTPD_FOUNDHOST 0x0002 /* Got a Host: header */
|
||||
|
||||
@@ -87,6 +74,7 @@ struct isc_httpd {
|
||||
*/
|
||||
char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
|
||||
isc_uint32_t recvlen; /*%< length recv'd */
|
||||
char *headers; /*%< set in process_request() */
|
||||
unsigned int method;
|
||||
char *url;
|
||||
char *querystring;
|
||||
@@ -217,20 +205,12 @@ static isc_result_t process_request(isc_httpd_t *, int);
|
||||
static void httpdmgr_destroy(isc_httpdmgr_t *);
|
||||
static isc_result_t grow_headerspace(isc_httpd_t *);
|
||||
static void reset_client(isc_httpd_t *httpd);
|
||||
static isc_result_t render_404(const char *, const char *,
|
||||
void *,
|
||||
unsigned int *, const char **,
|
||||
const char **, isc_buffer_t *,
|
||||
isc_httpdfree_t **, void **);
|
||||
static isc_result_t render_500(const char *, const char *,
|
||||
void *,
|
||||
unsigned int *, const char **,
|
||||
const char **, isc_buffer_t *,
|
||||
isc_httpdfree_t **, void **);
|
||||
|
||||
static isc_httpdaction_t render_404;
|
||||
static isc_httpdaction_t render_500;
|
||||
|
||||
static void
|
||||
destroy_client(isc_httpd_t **httpdp)
|
||||
{
|
||||
destroy_client(isc_httpd_t **httpdp) {
|
||||
isc_httpd_t *httpd = *httpdp;
|
||||
isc_httpdmgr_t *httpdmgr = httpd->mgr;
|
||||
|
||||
@@ -321,8 +301,7 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
}
|
||||
|
||||
static void
|
||||
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
|
||||
{
|
||||
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) {
|
||||
isc_mem_t *mctx;
|
||||
isc_httpdurl_t *url;
|
||||
|
||||
@@ -379,8 +358,7 @@ httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
|
||||
#define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN)
|
||||
|
||||
static isc_result_t
|
||||
process_request(isc_httpd_t *httpd, int length)
|
||||
{
|
||||
process_request(isc_httpd_t *httpd, int length) {
|
||||
char *s;
|
||||
char *p;
|
||||
int delim;
|
||||
@@ -390,6 +368,7 @@ process_request(isc_httpd_t *httpd, int length)
|
||||
httpd->recvlen += length;
|
||||
|
||||
httpd->recvbuf[httpd->recvlen] = 0;
|
||||
httpd->headers = NULL;
|
||||
|
||||
/*
|
||||
* If we don't find a blank line in our buffer, return that we need
|
||||
@@ -494,6 +473,8 @@ process_request(isc_httpd_t *httpd, int length)
|
||||
p = s + 1;
|
||||
s = p;
|
||||
|
||||
httpd->headers = s;
|
||||
|
||||
if (strstr(s, "Connection: close") != NULL)
|
||||
httpd->flags |= HTTPD_CLOSE;
|
||||
|
||||
@@ -513,8 +494,7 @@ process_request(isc_httpd_t *httpd, int length)
|
||||
}
|
||||
|
||||
static void
|
||||
isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
|
||||
{
|
||||
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
|
||||
isc_result_t result;
|
||||
isc_httpdmgr_t *httpdmgr = ev->ev_arg;
|
||||
isc_httpd_t *httpd;
|
||||
@@ -609,8 +589,8 @@ isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_404(const char *url, const char *querystring,
|
||||
void *arg,
|
||||
render_404(const char *url, isc_httpdurl_t *urlinfo,
|
||||
const char *querystring, const char *headers, void *arg,
|
||||
unsigned int *retcode, const char **retmsg,
|
||||
const char **mimetype, isc_buffer_t *b,
|
||||
isc_httpdfree_t **freecb, void **freecb_args)
|
||||
@@ -618,7 +598,9 @@ render_404(const char *url, const char *querystring,
|
||||
static char msg[] = "No such URL.";
|
||||
|
||||
UNUSED(url);
|
||||
UNUSED(urlinfo);
|
||||
UNUSED(querystring);
|
||||
UNUSED(headers);
|
||||
UNUSED(arg);
|
||||
|
||||
*retcode = 404;
|
||||
@@ -633,8 +615,8 @@ render_404(const char *url, const char *querystring,
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_500(const char *url, const char *querystring,
|
||||
void *arg,
|
||||
render_500(const char *url, isc_httpdurl_t *urlinfo,
|
||||
const char *querystring, const char *headers, void *arg,
|
||||
unsigned int *retcode, const char **retmsg,
|
||||
const char **mimetype, isc_buffer_t *b,
|
||||
isc_httpdfree_t **freecb, void **freecb_args)
|
||||
@@ -642,7 +624,9 @@ render_500(const char *url, const char *querystring,
|
||||
static char msg[] = "Internal server failure.";
|
||||
|
||||
UNUSED(url);
|
||||
UNUSED(urlinfo);
|
||||
UNUSED(querystring);
|
||||
UNUSED(headers);
|
||||
UNUSED(arg);
|
||||
|
||||
*retcode = 500;
|
||||
@@ -657,8 +641,7 @@ render_500(const char *url, const char *querystring,
|
||||
}
|
||||
|
||||
static void
|
||||
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
|
||||
{
|
||||
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
isc_httpd_t *httpd = ev->ev_arg;
|
||||
@@ -710,8 +693,9 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
|
||||
url = ISC_LIST_NEXT(url, link);
|
||||
}
|
||||
if (url == NULL)
|
||||
result = httpd->mgr->render_404(httpd->url, httpd->querystring,
|
||||
NULL,
|
||||
result = httpd->mgr->render_404(httpd->url, NULL,
|
||||
httpd->querystring,
|
||||
NULL, NULL,
|
||||
&httpd->retcode,
|
||||
&httpd->retmsg,
|
||||
&httpd->mimetype,
|
||||
@@ -719,14 +703,18 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
|
||||
&httpd->freecb,
|
||||
&httpd->freecb_arg);
|
||||
else
|
||||
result = url->action(httpd->url, httpd->querystring,
|
||||
result = url->action(httpd->url, url,
|
||||
httpd->querystring,
|
||||
httpd->headers,
|
||||
url->action_arg,
|
||||
&httpd->retcode, &httpd->retmsg,
|
||||
&httpd->mimetype, &httpd->bodybuffer,
|
||||
&httpd->freecb, &httpd->freecb_arg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
result = httpd->mgr->render_500(httpd->url, httpd->querystring,
|
||||
NULL, &httpd->retcode,
|
||||
result = httpd->mgr->render_500(httpd->url, url,
|
||||
httpd->querystring,
|
||||
NULL, NULL,
|
||||
&httpd->retcode,
|
||||
&httpd->retmsg,
|
||||
&httpd->mimetype,
|
||||
&httpd->bodybuffer,
|
||||
@@ -739,9 +727,19 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
|
||||
isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
|
||||
isc_httpd_addheader(httpd, "Date", datebuf);
|
||||
isc_httpd_addheader(httpd, "Expires", datebuf);
|
||||
isc_httpd_addheader(httpd, "Last-Modified", datebuf);
|
||||
isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
|
||||
isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
|
||||
|
||||
if (url != NULL && url->isstatic) {
|
||||
char loadbuf[32];
|
||||
isc_time_formathttptimestamp(&url->loadtime,
|
||||
loadbuf, sizeof(loadbuf));
|
||||
isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
|
||||
isc_httpd_addheader(httpd, "Cache-Control: public", NULL);
|
||||
} else {
|
||||
isc_httpd_addheader(httpd, "Last-Modified", datebuf);
|
||||
isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
|
||||
isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
|
||||
}
|
||||
|
||||
isc_httpd_addheader(httpd, "Server: libisc", NULL);
|
||||
isc_httpd_addheaderuint(httpd, "Content-Length",
|
||||
isc_buffer_usedlength(&httpd->bodybuffer));
|
||||
@@ -766,8 +764,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
|
||||
}
|
||||
|
||||
void
|
||||
isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
|
||||
{
|
||||
isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
|
||||
isc_httpdmgr_t *httpdmgr;
|
||||
isc_httpd_t *httpd;
|
||||
httpdmgr = *httpdmgrp;
|
||||
@@ -794,8 +791,7 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
grow_headerspace(isc_httpd_t *httpd)
|
||||
{
|
||||
grow_headerspace(isc_httpd_t *httpd) {
|
||||
char *newspace;
|
||||
unsigned int newlen;
|
||||
isc_region_t r;
|
||||
@@ -816,8 +812,7 @@ grow_headerspace(isc_httpd_t *httpd)
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_httpd_response(isc_httpd_t *httpd)
|
||||
{
|
||||
isc_httpd_response(isc_httpd_t *httpd) {
|
||||
isc_result_t result;
|
||||
unsigned int needlen;
|
||||
|
||||
@@ -869,8 +864,7 @@ isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_httpd_endheaders(isc_httpd_t *httpd)
|
||||
{
|
||||
isc_httpd_endheaders(isc_httpd_t *httpd) {
|
||||
isc_result_t result;
|
||||
|
||||
while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
|
||||
@@ -912,8 +906,7 @@ isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
|
||||
}
|
||||
|
||||
static void
|
||||
isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
|
||||
{
|
||||
isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
|
||||
isc_httpd_t *httpd = ev->ev_arg;
|
||||
isc_region_t r;
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *)ev;
|
||||
@@ -977,8 +970,7 @@ out:
|
||||
}
|
||||
|
||||
static void
|
||||
reset_client(isc_httpd_t *httpd)
|
||||
{
|
||||
reset_client(isc_httpd_t *httpd) {
|
||||
/*
|
||||
* Catch errors here. We MUST be in RECV mode, and we MUST NOT have
|
||||
* any outstanding buffers. If we have buffers, we have a leak.
|
||||
@@ -989,6 +981,7 @@ reset_client(isc_httpd_t *httpd)
|
||||
|
||||
httpd->recvbuf[0] = 0;
|
||||
httpd->recvlen = 0;
|
||||
httpd->headers = NULL;
|
||||
httpd->method = ISC_HTTPD_METHODUNKNOWN;
|
||||
httpd->url = NULL;
|
||||
httpd->querystring = NULL;
|
||||
@@ -1002,6 +995,14 @@ reset_client(isc_httpd_t *httpd)
|
||||
isc_result_t
|
||||
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
|
||||
isc_httpdaction_t *func, void *arg)
|
||||
{
|
||||
return (isc_httpdmgr_addurl2(httpdmgr, url, ISC_FALSE, func, arg));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
|
||||
isc_boolean_t isstatic,
|
||||
isc_httpdaction_t *func, void *arg)
|
||||
{
|
||||
isc_httpdurl_t *item;
|
||||
|
||||
@@ -1022,6 +1023,9 @@ isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
|
||||
|
||||
item->action = func;
|
||||
item->action_arg = arg;
|
||||
item->isstatic = isstatic;
|
||||
isc_time_now(&item->loadtime);
|
||||
|
||||
ISC_LINK_INIT(item, link);
|
||||
ISC_LIST_APPEND(httpdmgr->urls, item, link);
|
||||
|
||||
|
@@ -26,6 +26,23 @@
|
||||
#include <isc/types.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/time.h>
|
||||
|
||||
/*%
|
||||
* HTTP urls. These are the URLs we manage, and the function to call to
|
||||
* provide the data for it. We pass in the base url (so the same function
|
||||
* can handle multiple requests), and a structure to fill in to return a
|
||||
* result to the client. We also pass in a pointer to be filled in for
|
||||
* the data cleanup function.
|
||||
*/
|
||||
struct isc_httpdurl {
|
||||
char *url;
|
||||
isc_httpdaction_t *action;
|
||||
void *action_arg;
|
||||
isc_boolean_t isstatic;
|
||||
isc_time_t loadtime;
|
||||
ISC_LINK(isc_httpdurl_t) link;
|
||||
};
|
||||
|
||||
#define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
|
||||
#define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001)
|
||||
@@ -49,6 +66,11 @@ isc_result_t
|
||||
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
|
||||
isc_httpdaction_t *func, void *arg);
|
||||
|
||||
isc_result_t
|
||||
isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
|
||||
isc_boolean_t isstatic,
|
||||
isc_httpdaction_t *func, void *arg);
|
||||
|
||||
isc_result_t
|
||||
isc_httpd_response(isc_httpd_t *httpd);
|
||||
|
||||
|
@@ -103,7 +103,9 @@ typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
|
||||
|
||||
/* The following cannot be listed alphabetically due to forward reference */
|
||||
typedef isc_result_t (isc_httpdaction_t)(const char *url,
|
||||
isc_httpdurl_t *urlinfo,
|
||||
const char *querystring,
|
||||
const char *headers,
|
||||
void *arg,
|
||||
unsigned int *retcode,
|
||||
const char **retmsg,
|
||||
|
@@ -315,6 +315,16 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_time_parsehttptimestamp(char *input, isc_time_t *t);
|
||||
/*%<
|
||||
* Parse the time in 'input' into the isc_time_t pointed to by 't',
|
||||
* expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
|
||||
*
|
||||
* Requires:
|
||||
*\li 'buf' and 't' are not NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
|
||||
/*%<
|
||||
|
@@ -407,6 +407,24 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
|
||||
INSIST(flen < len);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
|
||||
struct tm t_tm;
|
||||
time_t when;
|
||||
char *p;
|
||||
|
||||
REQUIRE(buf != NULL);
|
||||
REQUIRE(t != NULL);
|
||||
p = strptime(buf, "%a, %d %b %Y %H:%M:%S %Z", &t_tm);
|
||||
if (p == NULL)
|
||||
return (ISC_R_UNEXPECTED);
|
||||
when = timegm(&t_tm);
|
||||
if (when == -1)
|
||||
return (ISC_R_UNEXPECTED);
|
||||
isc_time_set(t, when, 0);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
|
||||
time_t now;
|
||||
|
Reference in New Issue
Block a user