dirkx 99/04/05 06:52:21
Modified: src/support ab.8 ab.c
Added: src/support README
Log:
Added Basic Auth, Cookies and arbitrary headers to ab.c/ab.8. Sorry
for the diff; ident seemed to have mangled some lines with the current
.indedent.pro. Sneaked in a write() to writev() replacement which
at least on FreeBSD makes a POST significantly 2-5% faster.
Added a README file. To make it even more obvious that there are
usefull things such as rotate_log, split_log and the likes.
Revision Changes Path
1.5 +47 -0 apache-1.3/src/support/ab.8
Index: ab.8
===================================================================
RCS file: /x3/home/cvs/apache-1.3/src/support/ab.8,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ab.8 1999/02/19 16:25:35 1.4
+++ ab.8 1999/04/05 13:52:20 1.5
@@ -1,4 +1,5 @@
.TH ab 1 "March 1998"
+.\" $Id: ab.8,v 1.5 1999/04/05 13:52:20 dirkx Exp $
.\" Copyright (c) 1998-1999 The Apache Group. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -66,6 +67,14 @@
] [
.BI \-p " POST file"
] [
+.BI \-A " Authenticate username:password"
+] [
+.BI \-P " Proxy Authenticate username:password"
+] [
+.BI \-H " Custom header"
+] [
+.BI \-C " Cookie name=value"
+] [
.BI \-T " content-type"
] [
.BI \-v " verbosity"
@@ -126,6 +135,31 @@
File containing data to POST.
.TP 12
+.BI \-A " Authorization username:password"
+Supply BASIC Authentification credentials to the server. The username
+and password are separated by a single ':' and send on the wire uuencoded.
+The string is send regardless of wether the server needs it; (i.e. has
+send an 401. Authentifcation needed).
+
+.TP 12
+.BI \-p " Proxy-Authorization username:password"
+Supply BASIC Authentification credentials to a proxy en-route. The username
+and password are separated by a single ':' and send on the wire uuencoded.
+The string is send regardless of wether the proxy needs it; (i.e. has
+send an 407 Proxy authentifcation needed).
+
+.TP 12
+.BI \-C " Cookie name=value"
+Add a 'Cookie:' line to the request. The argument is typically in the form
+of a 'name=value' pair. This field is repeatable.
+
+.TP 12
+.BI \-p " Header string"
+Postfix extra headers to the request. The argument is typically in the form
+of a valid header line; containing a colon separated field value pair. (i.e.
+'Accept-Encoding: zip/zop;8bit').
+
+.TP 12
.BI \-T " content-type"
Content-type header to use for POST data.
@@ -158,6 +192,19 @@
.B \-h
Display usage information.
.PD
+.SH BUGS
+There are various statically declared buffers of fixed length. Combined
+with the lazy parsing of the command line arguments, the response headers
+from the server and other external inputs this might bite you.
+.P
+It does not implment HTTP/1.x fully; only accepts some 'expected' forms
+of responses. The rather heavy use of
+.BR strstr(3)
+shows up top in profile,
+which might indicate a performance problem; i.e. you would measure the
+.BR ab
+performance rather than the server's.
+
.SH SEE ALSO
.BR httpd(8)
.
1.21 +130 -30 apache-1.3/src/support/ab.c
Index: ab.c
===================================================================
RCS file: /x3/home/cvs/apache-1.3/src/support/ab.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- ab.c 1999/02/19 16:25:35 1.20
+++ ab.c 1999/04/05 13:52:21 1.21
@@ -81,6 +81,7 @@
** - Cleaned up by Ralf S. Engelschall <[EMAIL PROTECTED]>, March 1998
** - POST and verbosity by Kurt Sussman <[EMAIL PROTECTED]>, August
1998
** - HTML table output added by David N. Welton <[EMAIL PROTECTED]>,
January 1999
+ ** - Added Cookie, Arbitrary header and auth support. <[EMAIL
PROTECTED]>, April 199
**
*/
@@ -120,11 +121,17 @@
#include <string.h>
#define ap_select select
-#else /* (!)NO_APACHE_INCLUDES */
+#else /* (!)NO_APACHE_INCLUDES */
#include "ap_config.h"
#include <fcntl.h>
#include <sys/time.h>
-#endif /* NO_APACHE_INCLUDES */
+
+#ifndef NO_WRITEV
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+
+#endif /* NO_APACHE_INCLUDES */
/* ------------------- DEFINITIONS -------------------------- */
/* maximum number of requests on a time limited test */
@@ -146,7 +153,8 @@
char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
int cbx; /* offset in cbuffer */
int keepalive; /* non-zero if a keep-alive request */
- int gotheader; /* non-zero if we have the entire header in
cbuff */
+ int gotheader; /* non-zero if we have the entire header in
+ * cbuff */
struct timeval start, connect, done;
};
@@ -174,6 +182,10 @@
char *postdata; /* *buffer containing data from
postfile */
int postlen = 0; /* length of data to be POSTed */
char content_type[1024]; /* content type to put in POST header */
+char cookie[1024], /* optional cookie line */
+ auth[1024], /* optional (basic/uuencoded)
+ * authentification */
+ hdrs[4096]; /* optional arbitrary headers */
int port = 80; /* port number */
int use_html = 0; /* use html in the report */
@@ -223,20 +235,63 @@
exit(errno);
}
+/* -- simple uuencode, lifted from main/util.c which
+ * needed the pool, so duplicated here with normal
+ * malloc.
+ */
+static const char basis_64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static char *uuencode(char *string)
+{
+ int i, len = strlen(string);
+ char *p;
+ char *encoded = (char *) malloc((len + 2) / 3 * 4 + 1);
+ p = encoded;
+ for (i = 0; i < len; i += 3) {
+ *p++ = basis_64[string[i] >> 2];
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
+ ((int) (string[i + 2] & 0xC0) >> 6)];
+ *p++ = basis_64[string[i + 2] & 0x3F];
+ };
+ *p-- = '\0';
+ *p-- = '=';
+ *p-- = '=';
+ return encoded;
+}
+
+
/* --------------------------------------------------------- */
/* write out request to a connection - assumes we can write
(small) request out in one go into our new socket buffer */
-static void write_request(struct connection *c)
+static void write_request(struct connection * c)
{
+#ifndef NO_WRITEV
+ struct iovec out[2]; int outcnt = 1;
+#endif
gettimeofday(&c->connect, 0);
- /* XXX: this could use writev for posting -- more efficient -djg */
- write(c->fd, request, reqlen);
+#ifndef NO_WRITEV
+ out[0].iov_base = request;
+ out[0].iov_len = reqlen;
+
if (posting) {
- write(c->fd, postdata, postlen);
+ out[1].iov_base = postdata;
+ out[1].iov_len = postlen;
+ outcnt = 2;
totalposted += (reqlen + postlen);
}
+ writev(c->fd,out, outcnt);
+#else
+ write(c->fd,request,reqlen);
+ if (posting) {
+ write(c->fd,postdata,postlen);
+ totalposted += (reqlen + postlen);
+ }
+#endif
c->state = STATE_READ;
FD_SET(c->fd, &readbits);
@@ -469,7 +524,7 @@
/* start asnchronous non-blocking connection */
-static void start_connect(struct connection *c)
+static void start_connect(struct connection * c)
{
c->read = 0;
c->bread = 0;
@@ -484,7 +539,7 @@
nonblock(c->fd);
gettimeofday(&c->start, 0);
- if (connect(c->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
+ if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
if (errno == EINPROGRESS) {
c->state = STATE_CONNECTING;
FD_SET(c->fd, &writebits);
@@ -508,7 +563,7 @@
/* close down connection and save stats */
-static void close_connection(struct connection *c)
+static void close_connection(struct connection * c)
{
if (c->read == 0 && c->keepalive) {
/* server has legitimately shut down an idle keep alive request */
@@ -548,7 +603,7 @@
/* read data from connection */
-static void read_connection(struct connection *c)
+static void read_connection(struct connection * c)
{
int r;
char *part;
@@ -570,13 +625,14 @@
if (!c->gotheader) {
char *s;
int l = 4;
- int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator
*/
+ int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0
+ * terminator */
int tocopy = (space < r) ? space : r;
#ifndef CHARSET_EBCDIC
memcpy(c->cbuff + c->cbx, buffer, space);
-#else /*CHARSET_EBCDIC */
+#else /* CHARSET_EBCDIC */
ascii2ebcdic(c->cbuff + c->cbx, buffer, space);
-#endif /*CHARSET_EBCDIC */
+#endif /* CHARSET_EBCDIC */
c->cbx += tocopy;
space -= tocopy;
c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
@@ -584,8 +640,10 @@
printf("LOG: header received:\n%s\n", c->cbuff);
}
s = strstr(c->cbuff, "\r\n\r\n");
- /* this next line is so that we talk to NCSA 1.5 which blatantly breaks
- the http specifaction */
+ /*
+ * this next line is so that we talk to NCSA 1.5 which blatantly
+ * breaks the http specifaction
+ */
if (!s) {
s = strstr(c->cbuff, "\n\n");
l = 2;
@@ -620,10 +678,12 @@
*q = 0;
}
- /* XXX: this parsing isn't even remotely HTTP compliant...
- * but in the interest of speed it doesn't totally have to be,
- * it just needs to be extended to handle whatever servers
- * folks want to test against. -djg */
+ /*
+ * XXX: this parsing isn't even remotely HTTP compliant... but in
+ * the interest of speed it doesn't totally have to be, it just
+ * needs to be extended to handle whatever servers folks want to
+ * test against. -djg
+ */
/* check response code */
part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
@@ -732,29 +792,31 @@
if (!posting) {
sprintf(request, "GET %s HTTP/1.0\r\n"
"User-Agent: ApacheBench/%s\r\n"
- "%s"
+ "%s" "%s" "%s"
"Host: %s\r\n"
"Accept: */*\r\n"
- "\r\n",
+ "\r\n" "%s",
path,
VERSION,
keepalive ? "Connection: Keep-Alive\r\n" : "",
- hostname);
+ cookie, auth, hostname, hdrs);
}
else {
sprintf(request, "POST %s HTTP/1.0\r\n"
"User-Agent: ApacheBench/%s\r\n"
- "%s"
+ "%s" "%s" "%s"
"Host: %s\r\n"
"Accept: */*\r\n"
"Content-length: %d\r\n"
"Content-type: %s\r\n"
+ "%s"
"\r\n",
path,
VERSION,
keepalive ? "Connection: Keep-Alive\r\n" : "",
+ cookie, auth,
hostname, postlen,
- (content_type[0]) ? content_type : "text/plain");
+ (content_type[0]) ? content_type : "text/plain", hdrs);
}
if (verbosity >= 2)
@@ -764,7 +826,7 @@
#ifdef CHARSET_EBCDIC
ebcdic2ascii(request, request, reqlen);
-#endif /*CHARSET_EBCDIC */
+#endif /* CHARSET_EBCDIC */
/* ok - lets start */
gettimeofday(&start, 0);
@@ -851,6 +913,13 @@
fprintf(stderr, " -x attributes String to insert as table
attributes\n");
fprintf(stderr, " -y attributes String to insert as tr
attributes\n");
fprintf(stderr, " -z attributes String to insert as td or th
attributes\n");
+ fprintf(stderr, " -C attribute Add cookie, eg. 'Apache=1234.
(repeatable)\n");
+ fprintf(stderr, " -H attribute Add Arbitrary header line, eg.
'Accept-Encoding: zop'\n");
+ fprintf(stderr, " Inserted after all normal header
lines. (repeatable)\n");
+ fprintf(stderr, " -A attribute Add Basic WWW Authentication, the
attributes\n");
+ fprintf(stderr, " are a colon separated username and
password.\n");
+ fprintf(stderr, " -p attribute Add Basic Proxy Authentication, the
attributes\n");
+ fprintf(stderr, " are a colon separated username and
password.\n");
fprintf(stderr, " -V Print version number and exit\n");
fprintf(stderr, " -k Use HTTP KeepAlive feature\n");
fprintf(stderr, " -h Display usage information (this
message)\n");
@@ -929,9 +998,11 @@
tablestring = "";
trstring = "";
tdstring = "bgcolor=white";
-
+ cookie[0] = '\0';
+ auth[0] = '\0';
+ hdrs[0] = '\0';
optind = 1;
- while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:")) > 0) {
+ while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:C:H:P:A:")) > 0) {
switch (c) {
case 'n':
requests = atoi(optarg);
@@ -958,11 +1029,37 @@
break;
case 't':
tlimit = atoi(optarg);
- requests = MAX_REQUESTS; /* need to size data array on something
*/
+ requests = MAX_REQUESTS; /* need to size data array on
+ * something */
break;
case 'T':
strcpy(content_type, optarg);
break;
+ case 'C':
+ strncat(cookie, "Cookie: ", sizeof(cookie));
+ strncat(cookie, optarg, sizeof(cookie));
+ strncat(cookie, "\r\n", sizeof(cookie));
+ break;
+ case 'A':
+ /*
+ * assume username passwd already to be in colon separated form.
+ */
+ strncat(auth, "Authorization: basic ", sizeof(auth));
+ strncat(auth, uuencode(optarg), sizeof(auth));
+ strncat(auth, "\r\n", sizeof(auth));
+ break;
+ case 'P':
+ /*
+ * assume username passwd already to be in colon separated form.
+ */
+ strncat(auth, "Proxy-Authorization: basic ", sizeof(auth));
+ strncat(auth, uuencode(optarg), sizeof(auth));
+ strncat(auth, "\r\n", sizeof(auth));
+ break;
+ case 'H':
+ strncat(hdrs, optarg, sizeof(hdrs));
+ strncat(hdrs, "\r\n", sizeof(hdrs));
+ break;
case 'V':
copyright();
exit(0);
@@ -970,7 +1067,10 @@
case 'w':
use_html = 1;
break;
- /* if any of the following three are used, turn on html output
automatically */
+ /*
+ * if any of the following three are used, turn on html output
+ * automatically
+ */
case 'x':
use_html = 1;
tablestring = optarg;
1.1 apache-1.3/src/support/README
Index: README
===================================================================
Support files:
ab
ABuse your server with this benchmarker. Rudimentary
command line testing tool.
apachectl
Apache run-time Control script. To facilitate the
administrator and/or your rc.d scripts to control the
functioning of the Apache httpd daemon.
apxs
APache eXtenSion tool. Eases building and installing
DSO style modules.
dbmmanage
Create and update user authentication files in the faster
DBM format used by mod_auth_db.
htdigest
Create and update user authentication files used in
DIGEST authentification. See mod_auth_digest.
htpasswd
Create and update user authentication files used in
BASIC authentification. I.e. the htpasswd files.
See mod_auth.
httpd.8
General apache man page.
log_server_status
This script is designed to be run at a frequent interval by something
like cron. It connects to the server and downloads the status
information. It reformats the information to a single line and logs
it to a file.
logresolve
resolve hostnames for IP-adresses in Apache logfiles
phf_abuse_log.cgi
This script can be used to detect people trying to abuse an ancient
and long plugged security hole which existed in a CGI script distributed
with Apache 1.0.3 and earlier versions.
rotatelogs
rotate Apache logs without having to kill the server.
split-logfile
This script will take a combined virtual hosts access
log file and break its contents into separate files.
suexec
Switch User For Exec. Used internally by apache,
see the document `Apache suEXEC Support'
under http://www.apache.org/docs/suexec.html .