62
70
static apr_status_t ignore_all_cert_errors(void *data, int failures,
63
71
const serf_ssl_certificate_t *cert)
65
print_ssl_cert_errors(failures);
73
print_ssl_cert_errors(failures);
67
75
/* In a real application, you would normally would not want to do this */
68
76
return APR_SUCCESS;
80
convert_organisation_to_str(apr_hash_t *org, apr_pool_t *pool)
82
return apr_psprintf(pool, "%s, %s, %s, %s, %s (%s)",
83
(char*)apr_hash_get(org, "OU", APR_HASH_KEY_STRING),
84
(char*)apr_hash_get(org, "O", APR_HASH_KEY_STRING),
85
(char*)apr_hash_get(org, "L", APR_HASH_KEY_STRING),
86
(char*)apr_hash_get(org, "ST", APR_HASH_KEY_STRING),
87
(char*)apr_hash_get(org, "C", APR_HASH_KEY_STRING),
88
(char*)apr_hash_get(org, "E", APR_HASH_KEY_STRING));
71
91
static apr_status_t print_certs(void *data, int failures, int error_depth,
72
92
const serf_ssl_certificate_t * const * certs,
73
93
apr_size_t certs_len)
86
106
fprintf(stderr, "Chain provided with depth=%d\n", error_depth);
88
108
while ((current = *certs) != NULL)
110
apr_hash_t *issuer, *subject, *serf_cert;
111
apr_array_header_t *san;
113
subject = serf_ssl_cert_subject(current, pool);
114
issuer = serf_ssl_cert_issuer(current, pool);
115
serf_cert = serf_ssl_cert_certificate(current, pool);
90
117
fprintf(stderr, "\n-----BEGIN CERTIFICATE-----\n");
118
fprintf(stderr, "Hostname: %s\n",
119
(const char *)apr_hash_get(subject, "CN", APR_HASH_KEY_STRING));
120
fprintf(stderr, "Sha1: %s\n",
121
(const char *)apr_hash_get(serf_cert, "sha1", APR_HASH_KEY_STRING));
122
fprintf(stderr, "Valid from: %s\n",
123
(const char *)apr_hash_get(serf_cert, "notBefore", APR_HASH_KEY_STRING));
124
fprintf(stderr, "Valid until: %s\n",
125
(const char *)apr_hash_get(serf_cert, "notAfter", APR_HASH_KEY_STRING));
126
fprintf(stderr, "Issuer: %s\n", convert_organisation_to_str(issuer, pool));
128
san = apr_hash_get(serf_cert, "subjectAltName", APR_HASH_KEY_STRING);
131
for (i = 0; i < san->nelts; i++) {
132
char *s = APR_ARRAY_IDX(san, i, char*);
133
fprintf(stderr, "SubjectAltName: %s\n", s);
91
137
fprintf(stderr, "%s\n", serf_ssl_cert_export(current, pool));
92
138
fprintf(stderr, "-----END CERTIFICATE-----\n");
96
142
apr_pool_destroy(pool);
97
143
return APR_SUCCESS;
170
227
#define apr_atomic_read32 apr_atomic_read
173
static apr_status_t handle_response(serf_request_t *request,
174
serf_bucket_t *response,
231
static int append_request_headers(void *baton,
182
handler_baton_t *ctx = handler_baton;
185
/* A NULL response can come back if the request failed completely */
188
status = serf_bucket_response_status(response, &sl);
194
status = serf_bucket_read(response, 2048, &data, &len);
195
if (SERF_BUCKET_READ_ERROR(status))
198
/* got some data. print it out. */
199
fwrite(data, 1, len, stdout);
201
/* are we done yet? */
202
if (APR_STATUS_IS_EOF(status)) {
203
if (ctx->print_headers) {
205
hdrs = serf_bucket_response_get_headers(response);
207
status = serf_bucket_read(hdrs, 2048, &data, &len);
208
if (SERF_BUCKET_READ_ERROR(status))
211
fwrite(data, 1, len, stdout);
212
if (APR_STATUS_IS_EOF(status)) {
218
apr_atomic_inc32(&ctx->completed_requests);
222
/* have we drained the response so far? */
223
if (APR_STATUS_IS_EAGAIN(status))
226
/* loop to read some more. */
235
serf_bucket_t *hdrs_bkt = baton;
236
serf_bucket_headers_setc(hdrs_bkt, key, value);
231
240
static apr_status_t setup_request(serf_request_t *request,
270
279
"Serf/" SERF_VERSION_STRING);
271
280
/* Shouldn't serf do this for us? */
272
281
serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip");
282
#ifdef CONNECTION_CLOSE_HDR
283
serf_bucket_headers_setn(hdrs_bkt, "Connection", "close");
274
if (ctx->authn != NULL) {
275
serf_bucket_headers_setn(hdrs_bkt, "Authorization", ctx->authn);
286
/* Add the extra headers from the command line */
287
if (ctx->req_hdrs != NULL) {
288
serf_bucket_headers_do(ctx->req_hdrs, append_request_headers, hdrs_bkt);
278
291
*acceptor = ctx->acceptor;
279
292
*acceptor_baton = ctx->acceptor_baton;
280
293
*handler = ctx->handler;
281
294
*handler_baton = ctx;
283
296
return APR_SUCCESS;
299
static apr_status_t handle_response(serf_request_t *request,
300
serf_bucket_t *response,
306
handler_baton_t *ctx = handler_baton;
309
/* A NULL response probably means that the connection was closed while
310
this request was already written. Just requeue it. */
311
serf_connection_t *conn = serf_request_get_conn(request);
313
serf_connection_request_create(conn, setup_request, handler_baton);
317
status = serf_bucket_response_status(response, &sl);
323
struct iovec vecs[64];
325
apr_size_t bytes_written;
327
status = serf_bucket_read_iovec(response, 8000, 64, vecs, &vecs_read);
328
if (SERF_BUCKET_READ_ERROR(status))
331
/* got some data. print it out. */
333
apr_file_writev(ctx->output_file, vecs, vecs_read, &bytes_written);
336
/* are we done yet? */
337
if (APR_STATUS_IS_EOF(status)) {
338
if (ctx->print_headers) {
340
hdrs = serf_bucket_response_get_headers(response);
342
status = serf_bucket_read_iovec(hdrs, 8000, 64, vecs,
345
if (SERF_BUCKET_READ_ERROR(status))
349
apr_file_writev(ctx->output_file, vecs, vecs_read,
352
if (APR_STATUS_IS_EOF(status)) {
358
apr_atomic_inc32(&ctx->completed_requests);
362
/* have we drained the response so far? */
363
if (APR_STATUS_IS_EAGAIN(status))
366
/* loop to read some more. */
372
credentials_callback(char **username,
374
serf_request_t *request, void *baton,
375
int code, const char *authn_type,
379
handler_baton_t *ctx = baton;
381
if (ctx->auth_attempts > 0)
383
return SERF_ERROR_AUTHN_FAILED;
387
*username = (char*)ctx->username;
388
*password = (char*)ctx->password;
389
ctx->auth_attempts++;
286
395
static void print_usage(apr_pool_t *pool)
288
397
puts("serf_get [options] URL");
290
399
puts("-v\tDisplay version");
291
400
puts("-H\tPrint response headers");
292
401
puts("-n <count> Fetch URL <count> times");
293
puts("-a <user:password> Present Basic authentication credentials");
402
puts("-x <count> Number of maximum outstanding requests inflight");
403
puts("-U <user> Username for Basic/Digest authentication");
404
puts("-P <password> Password for Basic/Digest authentication");
294
405
puts("-m <method> Use the <method> HTTP Method");
295
406
puts("-f <file> Use the <file> as the request body");
296
407
puts("-p <hostname:port> Use the <host:port> as proxy server");
408
puts("-r <header:value> Use <header:value> as request header");
299
411
int main(int argc, const char **argv)
301
413
apr_status_t status;
302
414
apr_pool_t *pool;
415
serf_bucket_alloc_t *bkt_alloc;
303
416
serf_context_t *context;
304
417
serf_connection_t *connection;
305
418
serf_request_t *request;
306
419
app_baton_t app_ctx;
307
420
handler_baton_t handler_ctx;
421
serf_bucket_t *req_hdrs = NULL;
309
423
const char *proxy = NULL;
310
424
const char *raw_url, *method, *req_body_path = NULL;
313
427
int print_headers;
428
const char *username = NULL;
429
const char *password = "";
315
430
apr_getopt_t *opt;
317
432
const char *opt_arg;
332
449
apr_getopt_init(&opt, pool, argc, argv);
334
while ((status = apr_getopt(opt, "a:f:hHm:n:vp:", &opt_c, &opt_arg)) ==
451
while ((status = apr_getopt(opt, "U:P:f:hHm:n:vp:x:r:", &opt_c, &opt_arg)) ==
340
srclen = strlen(opt_arg);
341
enclen = apr_base64_encode_len(srclen);
342
authn = apr_palloc(pool, enclen + 6);
343
strcpy(authn, "Basic ");
344
(void) apr_base64_encode(&authn[6], opt_arg, srclen);
347
462
req_body_path = opt_arg;
485
inflight = apr_strtoi64(opt_arg, NULL, 10);
487
printf("Problem converting number of requests to have outstanding (%d)\n",
500
if (req_hdrs == NULL) {
501
/* first request header, allocate bucket */
502
req_hdrs = serf_bucket_headers_create(bkt_alloc);
504
sep = strchr(opt_arg, ':');
505
if ((sep == NULL) || (sep == opt_arg) || (strlen(sep) <= 1)) {
506
printf("Invalid request header string (%s)\n", opt_arg);
510
while (*hdr_val == ' ') {
513
serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1,
514
hdr_val, strlen(hdr_val), 1);
372
518
puts("Serf version: " SERF_VERSION_STRING);
444
597
serf_config_proxy(context, proxy_address);
602
serf_config_authn_types(context, SERF_AUTHN_ALL);
606
serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE);
609
serf_config_credentials_callback(context, credentials_callback);
447
611
/* ### Connection or Context should have an allocator? */
448
app_ctx.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
612
app_ctx.bkt_alloc = bkt_alloc;
449
613
app_ctx.ssl_ctx = NULL;
451
615
status = serf_connection_create2(&connection, context, url,
461
625
handler_ctx.completed_requests = 0;
462
626
handler_ctx.print_headers = print_headers;
627
apr_file_open_stdout(&handler_ctx.output_file, pool);
464
629
handler_ctx.host = url.hostinfo;
465
630
handler_ctx.method = method;
466
handler_ctx.path = url.path;
467
handler_ctx.authn = authn;
631
handler_ctx.path = apr_pstrcat(pool,
633
url.query ? "?" : "",
634
url.query ? url.query : "",
636
handler_ctx.username = username;
637
handler_ctx.password = password;
638
handler_ctx.auth_attempts = 0;
469
640
handler_ctx.req_body_path = req_body_path;
471
642
handler_ctx.acceptor = accept_response;
472
643
handler_ctx.acceptor_baton = &app_ctx;
473
644
handler_ctx.handler = handle_response;
645
handler_ctx.req_hdrs = req_hdrs;
647
serf_connection_set_max_outstanding_requests(connection, inflight);
475
649
for (i = 0; i < count; i++) {
476
650
request = serf_connection_request_create(connection, setup_request,
660
const char *err_string;
661
err_string = serf_error_string(status);
663
err_string = apr_strerror(status, buf, sizeof(buf));
487
printf("Error running context: (%d) %s\n", status,
488
apr_strerror(status, buf, sizeof(buf)));
666
printf("Error running context: (%d) %s\n", status, err_string);
489
667
apr_pool_destroy(pool);