Permalink
Browse files

Initial round of API changes. Use "USE_API=1" during make to enable A…

…PI functionality. Right now, only version reporting works.
  • Loading branch information...
1 parent 5fc0d9c commit 241304ab2dd946a63c8aad720dc91c533662df88 @jbuchbinder committed Aug 4, 2011
Showing with 78 additions and 1 deletion.
  1. +5 −0 Makefile
  2. +8 −0 include/proto/dumpstats.h
  3. +3 −1 include/types/stream_interface.h
  4. +31 −0 src/dumpstats.c
  5. +31 −0 src/proto_http.c
View
@@ -24,6 +24,7 @@
# USE_CRYPT_H : set it if your system requires including crypt.h
# USE_VSYSCALL : enable vsyscall on Linux x86, bypassing libc
# USE_GETADDRINFO : use getaddrinfo() to resolve IPv6 host names.
+# USE_API : enable API specific code
#
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using
# "USE_xxx=" (empty string).
@@ -336,6 +337,10 @@ OPTIONS_OBJS += src/cttproxy.o
BUILD_OPTIONS += $(call ignore_implicit,USE_CTTPROXY)
endif
+ifneq ($(USE_API),)
+OPTIONS_CFLAGS += -DUSE_API
+endif
+
ifneq ($(USE_TPROXY),)
OPTIONS_CFLAGS += -DTPROXY
BUILD_OPTIONS += $(call ignore_implicit,USE_TPROXY)
@@ -35,6 +35,10 @@
#define STAT_NO_REFRESH 0x00000010 /* do not automatically refresh the stats page */
#define STAT_ADMIN 0x00000020 /* indicate a stats admin level */
#define STAT_BOUND 0x00800000 /* bound statistics to selected proxies/types/services */
+#ifdef USE_API
+#define STAT_API 0x10000000 /* stats call */
+#define API_VERSION "0.0.1"
+#endif /* USE_API */
#define STATS_TYPE_FE 0
#define STATS_TYPE_BE 1
@@ -62,6 +66,10 @@
#define STAT_STATUS_EXCD "EXCD" /* an error occured becayse the buffer couldn't store all data */
#define STAT_STATUS_DENY "DENY" /* action denied */
+#ifdef USE_API
+#define STAT_API_CMD_VERSION "version" /* request version */
+#endif /* USE_API */
+
extern struct si_applet http_stats_applet;
void stats_io_handler(struct stream_interface *si);
@@ -149,8 +149,10 @@ struct stream_interface {
unsigned int flags; /* STAT_* */
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
const char *st_code; /* pointer to the status code returned by an action */
- const char *api_action;
+#ifdef USE_API
+ const char *api_action; /* pointer to the API method being called */
const char *api_data;
+#endif /* USE_API */
} stats;
struct {
struct bref bref; /* back-reference from the session being dumped */
View
@@ -316,6 +316,16 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
return 0;
}
+#ifdef USE_API
+static int api_call(struct stream_interface *si, struct chunk *msg)
+{
+ if (memcmp(si->applet.ctx.stats.api_action, STAT_API_CMD_VERSION, strlen(STAT_API_CMD_VERSION)) == 0) {
+ return chunk_printf(msg, API_VERSION);
+ }
+ return chunk_printf(msg, "NOOP");
+}
+#endif /* USE_API */
+
static int print_csv_header(struct chunk *msg)
{
return chunk_printf(msg,
@@ -1571,7 +1581,11 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
"Cache-Control: no-cache\r\n"
"Connection: close\r\n"
"Content-Type: %s\r\n",
+#ifdef USE_API
+ (si->applet.ctx.stats.flags & STAT_FMT_CSV || si->applet.ctx.stats.flags & STAT_API) ? "text/plain" : "text/html");
+#else
(si->applet.ctx.stats.flags & STAT_FMT_CSV) ? "text/plain" : "text/html");
+#endif /* USE_API */
if (uri->refresh > 0 && !(si->applet.ctx.stats.flags & STAT_NO_REFRESH))
chunk_printf(&msg, "Refresh: %d\r\n",
@@ -1598,7 +1612,11 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
/* fall through */
case STAT_ST_HEAD:
+#if USE_API
+ if (!(si->applet.ctx.stats.flags & STAT_FMT_CSV) && !(si->applet.ctx.stats.flags & STAT_API)) {
+#else
if (!(si->applet.ctx.stats.flags & STAT_FMT_CSV)) {
+#endif /* USE_API */
/* WARNING! This must fit in the first buffer !!! */
chunk_printf(&msg,
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n"
@@ -1693,7 +1711,20 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
(uri->flags&ST_SHNODE) ? (uri->node ? uri->node : global.node) : ""
);
} else {
+#ifdef USE_API
+ if (si->applet.ctx.stats.flags & STAT_FMT_CSV) {
+ print_csv_header(&msg);
+
+ } else if (si->applet.ctx.stats.flags & STAT_API) {
+ api_call(si, &msg);
+ if (buffer_feed_chunk(rep, &msg) >= 0)
+ return 0;
+ si->applet.state = STAT_ST_FIN;
+ return 1;
+ }
+#else
print_csv_header(&msg);
+#endif /* USE_API */
}
if (buffer_feed_chunk(rep, &msg) >= 0)
return 0;
View
@@ -7351,6 +7351,37 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
return 0;
h += uri_auth->uri_len;
+
+#ifdef USE_API
+ /*
+ * Check to see if there are any calls to /api/ namespace, and
+ * route accordingly.
+ */
+ if (memcmp(h, "api/", 4) == 0) {
+ si->applet.ctx.stats.flags |= STAT_API;
+
+ /*
+ * Parsing rules here:
+ * 1) Break off everything after /api/
+ * 2) Look for another '/'. If there isn't one, treat the
+ * entire remainder as a command.
+ * 3) If there was a '/', split there and pass the remainder
+ * as the argument. If not, parse POST data.
+ */
+ h += 4;
+ if (*h == ' ') {
+ /* No command given */
+ si->applet.ctx.stats.api_action = STAT_API_CMD_VERSION;
+ return 1;
+ }
+ if (memcmp(h, STAT_API_CMD_VERSION, 7) == 0) {
+ si->applet.ctx.stats.api_action = STAT_API_CMD_VERSION;
+ return 1;
+ }
+ return 1;
+ }
+#endif /* USE_API */
+
while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 3) {
if (memcmp(h, ";up", 3) == 0) {
si->applet.ctx.stats.flags |= STAT_HIDE_DOWN;

0 comments on commit 241304a

Please sign in to comment.