[httperf] reading request body and headers from a file
Steffen Kiefer
steffen.kiefer at webde.de
Wed Jan 23 07:27:36 PST 2008
Ted Bullock schrieb:
> Can you please send this patch against the most recent CVS version.
Sure, i'm sorry.
Attached you will find the patch against the most recent CVS version.
Steffen
-------------- next part --------------
--- httperf-cvs-head/httperf/src/gen/misc.c 2007-07-16 02:59:57.000000000 +0200
+++ httperf-cvs-head_patched/httperf/src/gen/misc.c 2008-01-23 15:56:54.404135467 +0100
@@ -56,11 +56,23 @@
#include <call.h>
#include <localevent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
static const char *extra;
static size_t extra_len;
static size_t method_len;
+static size_t body_len;
+static const char *body;
+
+static const char *request_file_header;
+static size_t request_file_header_len;
+
/* A simple module that collects cookies from the server responses and
includes them in future calls to the server. */
@@ -124,16 +136,87 @@
if (method_len > 0)
call_set_method (c, param.method, method_len);
+ if (body_len > 0)
+ {
+ call_set_contents (c, body, body_len);
+ char content_length_header[50];
+ snprintf(content_length_header, 50, "Content-length: %d\r\n", body_len);
+ call_append_request_header (c, strdup(content_length_header), strlen(content_length_header));
+ }
+
if (extra_len > 0)
call_append_request_header (c, extra, extra_len);
+
+ if (request_file_header_len > 0)
+ call_append_request_header (c, request_file_header, request_file_header_len);
}
+static void
+parse_request_header_and_body(const char* request_file)
+{
+ // read headers & body from request_file
+ int fd = open(request_file, O_RDONLY);
+ if (fd < 0)
+ panic ("%s: can't open given request file '%s'.\n", prog_name, request_file);
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) < 0)
+ panic ("%s: can't determine filesize of file %s.\n", prog_name, request_file);
+
+ off_t filesize = statbuf.st_size;
+ body = (char*) malloc(filesize);
+ if (filesize > 0)
+ body = mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
+
+ // parse & set request headers
+ int headerlen = 0;
+ int newblankline = 1;
+ char* headersbuf = malloc(filesize);
+ for (;;)
+ {
+ headerlen++;
+ if (*body == 0)
+ {
+ // no headers given
+ body = headersbuf;
+ request_file_header_len = 0;
+ body_len = filesize;
+ break;
+ }
+ else if (*body == '\n')
+ {
+ if (newblankline == 1)
+ {
+ // finished parsing headers
+ body++;
+ headersbuf[headerlen] = '\0';
+ request_file_header_len = headerlen;
+ request_file_header = unescape (headersbuf, &request_file_header_len);
+ body_len = filesize - headerlen;
+ break;
+ }
+ else
+ {
+ newblankline = 1;
+ }
+ }
+ else if (isspace(*body) == 0)
+ {
+ newblankline = 0;
+ }
+ headersbuf[headerlen - 1] = *body;
+ body++;
+ }
+}
static void
init (void)
{
Any_Type arg;
+ if (param.request_file)
+ parse_request_header_and_body(param.request_file);
+
if (param.additional_header)
extra = unescape (param.additional_header, &extra_len);
@@ -144,10 +227,18 @@
event_register_handler (EV_CALL_NEW, call_created, arg);
}
+static void
+stop (void)
+{
+ if (body_len > 0 && body != 0)
+ munmap(body, body_len);
+}
+
+
Load_Generator misc =
{
"Miscellaneous command line options",
init,
no_op,
- no_op
+ stop
};
--- httperf-cvs-head/httperf/src/gen/wsesslog.c 2007-09-12 06:47:27.000000000 +0200
+++ httperf-cvs-head_patched/httperf/src/gen/wsesslog.c 2008-01-23 16:04:18.346220578 +0100
@@ -81,6 +81,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include <generic_types.h>
#include <object.h>
@@ -93,6 +97,7 @@
#include <rate.h>
#include <session.h>
+
/* Maximum number of sessions that can be defined in the configuration
file. */
#define MAX_SESSION_TEMPLATES 1000
@@ -116,7 +121,9 @@
int uri_len;
char *contents;
int contents_len;
- char extra_hdrs[50]; /* plenty for "Content-length: 1234567890" */
+ char *request_file;
+ int request_filelen;
+ char extra_hdrs[50000];
int extra_hdrs_len;
};
@@ -393,6 +400,7 @@
char method_str[1000];
char this_arg[10000];
char contents[10000];
+ char request_file[10000];
double think_time;
int bytes_read;
REQ *reqptr;
@@ -566,6 +574,160 @@
strlen (sptr->current_req->extra_hdrs);
}
}
+ else if (sscanf (this_arg, "request-file=%s", request_file) == 1)
+ {
+ /* this is tricky since request-file might be a quoted
+ string with embedded spaces or escaped quotes. We
+ should parse this carefully from parsed_so_far */
+ from = strchr (parsed_so_far, '=') + 1;
+ to = request_file;
+ single_quoted = FALSE;
+ double_quoted = FALSE;
+ escaped = FALSE;
+ done = FALSE;
+ while ((ch = *from++) != '\0' && !done)
+ {
+ if (escaped == TRUE)
+ {
+ switch (ch)
+ {
+ case 'n':
+ *to++ = '\n';
+ break;
+ case 'r':
+ *to++ = '\r';
+ break;
+ case 't':
+ *to++ = '\t';
+ break;
+ case '\n':
+ *to++ = '\n';
+ /* this allows an escaped newline to
+ continue the parsing to the next line. */
+ if (fgets(line,sizeof(line),fp) == NULL)
+ {
+ lineno++;
+ panic ("%s: premature EOF seen in '%s'\n",
+ prog_name, param.wsesslog.file);
+ }
+ parsed_so_far = from = line;
+ break;
+ default:
+ *to++ = ch;
+ break;
+ }
+ escaped = FALSE;
+ }
+ else if (ch == '"' && double_quoted)
+ {
+ double_quoted = FALSE;
+ }
+ else if (ch == '\'' && single_quoted)
+ {
+ single_quoted = FALSE;
+ }
+ else
+ {
+ switch (ch)
+ {
+ case '\t':
+ case '\n':
+ case ' ':
+ if (single_quoted == FALSE &&
+ double_quoted == FALSE)
+ done = TRUE; /* we are done */
+ else
+ *to++ = ch;
+ break;
+ case '\\': /* backslash */
+ escaped = TRUE;
+ break;
+ case '"': /* double quote */
+ if (single_quoted)
+ *to++ = ch;
+ else
+ double_quoted = TRUE;
+ break;
+ case '\'': /* single quote */
+ if (double_quoted)
+ *to++ = ch;
+ else
+ single_quoted = TRUE;
+ break;
+ default:
+ *to++ = ch;
+ break;
+ }
+ }
+ }
+ *to = '\0';
+ from--; /* back up 'from' to '\0' or white-space */
+ bytes_read = from - parsed_so_far;
+ if (strlen (request_file) > 0)
+ {
+ sptr->current_req->request_file = strdup (request_file);
+
+ // read headers & body from request_file
+ int fd = open(sptr->current_req->request_file, O_RDONLY);
+ if (fd < 0)
+ panic ("%s: can't open given request file '%s' from wsesslog.\n", prog_name, sptr->current_req->request_file);
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) < 0)
+ panic ("%s: can't determine filesize of file %s.\n", prog_name, sptr->current_req->request_file);
+
+ off_t filesize = statbuf.st_size;
+ sptr->current_req->request_filelen = filesize;
+ sptr->current_req->contents = (char*) malloc(filesize);
+ if (filesize > 0)
+ sptr->current_req->contents = mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
+
+ // parse & set request headers
+ int headerlen = 0;
+ int newblankline = 1;
+ char* headersbuf = malloc(filesize);
+ for (;;)
+ {
+ headerlen++;
+ if (*sptr->current_req->contents == 0)
+ // no headers given
+ sptr->current_req->contents = headersbuf;
+ sptr->current_req->contents_len = filesize;
+ break;
+ }
+ else if (*sptr->current_req->contents == '\n')
+ {
+ if (newblankline == 1)
+ {
+ // finished parsing headers
+ sptr->current_req->contents++;
+ headersbuf[headerlen] = '\0';
+ strncat(sptr->current_req->extra_hdrs, strdup(headersbuf), strlen(headersbuf));
+ sptr->current_req->extra_hdrs_len = strlen(sptr->current_req->extra_hdrs);
+ sptr->current_req->contents_len = filesize - headerlen;
+ break;
+ }
+ else
+ {
+ newblankline = 1;
+ }
+ }
+ else if (isspace(*sptr->current_req->contents) == 0)
+ {
+ newblankline = 0;
+ }
+ headersbuf[headerlen - 1] = *sptr->current_req->contents;
+ sptr->current_req->contents++;
+ }
+
+ char content_length_header[50];
+ snprintf(content_length_header, 50, "Content-length: %d\r\n", sptr->current_req->contents_len);
+ strncat(sptr->current_req->extra_hdrs,
+ content_length_header, strlen(content_length_header));
+ sptr->current_req->extra_hdrs_len =
+ strlen (sptr->current_req->extra_hdrs);
+ }
+ }
else
{
/* do not recognize this arg */
@@ -644,10 +806,36 @@
rate_generator_start (&rg_sess, EV_SESS_DESTROYED);
}
+static void
+stop (void)
+{
+ Sess_Private_Data *priv;
+ int i = 0;
+ for ( ; i < num_templates; i++)
+ {
+ priv = &session_templates[i];
+ if (priv != 0)
+ {
+ BURST* firstb = priv->current_burst;
+ BURST* currb;
+ for (currb = firstb; currb != 0; currb = currb->next)
+ {
+ REQ* firstreq = currb->req_list;
+ REQ* curreq;
+ for (curreq = firstreq; curreq != 0; curreq = curreq->next )
+ {
+ if (curreq->request_file != 0)
+ munmap(curreq->contents, curreq->request_filelen);
+ }
+ }
+ }
+ }
+}
+
Load_Generator wsesslog =
{
"creates log-based session workload",
init,
start,
- no_op
+ stop
};
--- httperf-cvs-head/httperf/src/httperf.c 2007-11-17 01:50:56.000000000 +0100
+++ httperf-cvs-head_patched/httperf/src/httperf.c 2008-01-23 16:07:15.017150968 +0100
@@ -129,6 +129,7 @@
{"print-request", optional_argument, ¶m.print_request, 0},
{"rate", required_argument, (int *) ¶m.rate, 0},
{"recv-buffer", required_argument, (int *) ¶m.recv_buffer_size, 0},
+ {"request-file", required_argument, (int *) ¶m.request_file, 0},
{"retry-on-failure", no_argument, ¶m.retry_on_failure, 1},
{"send-buffer", required_argument, (int *) ¶m.send_buffer_size, 0},
{"server", required_argument, (int *) ¶m.server, 0},
@@ -164,7 +165,7 @@
"\t[--num-calls N] [--num-conns N] [--period [d|u|e]T1[,T2]]\n"
"\t[--port N] "
"[--print-reply [header|body]] [--print-request [header|body]]\n"
- "\t[--rate X] [--recv-buffer N] [--retry-on-failure] "
+ "\t[--rate X] [--recv-buffer N] [--request-file file] [--retry-on-failure] "
"[--send-buffer N]\n"
"\t[--server S] [--server-name S] [--session-cookies]\n"
#ifdef HAVE_SSL
@@ -633,6 +634,8 @@
#endif
else if (flag == ¶m.uri)
param.uri = optarg;
+ else if (flag == ¶m.request_file)
+ param.request_file = optarg;
else if (flag == ¶m.think_timeout) {
errno = 0;
param.think_timeout = strtod(optarg, &end);
@@ -957,7 +960,7 @@
gen[num_gen++] = &sess_cookie;
}
- if (param.additional_header || param.method)
+ if (param.additional_header || param.method || param.request_file)
gen[num_gen++] = &misc;
/*
--- httperf-cvs-head/httperf/src/httperf.h 2007-07-15 23:14:20.000000000 +0200
+++ httperf-cvs-head_patched/httperf/src/httperf.h 2008-01-23 16:07:57.903008020 +0100
@@ -122,6 +122,7 @@
int use_timer_cache;
const char *additional_header; /* additional request header(s) */
const char *method; /* default call method */
+ const char *request_file; /* name of the file where entries are */
struct
{
u_int id;
More information about the httperf
mailing list