~ubuntu-branches/ubuntu/trusty/serf/trusty-proposed

« back to all changes in this revision

Viewing changes to test/serf_get.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2013-12-31 13:17:16 UTC
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20131231131716-z7lpavv1il3sxb7g
Tags: upstream-1.3.3
ImportĀ upstreamĀ versionĀ 1.3.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
#include "serf.h"
27
27
 
 
28
/* Add Connection: close header to each request. */
 
29
/* #define CONNECTION_CLOSE_HDR */
 
30
 
28
31
typedef struct {
29
32
    const char *hostinfo;
30
33
    int using_ssl;
 
34
    int head_request;
31
35
    serf_ssl_context_t *ssl_ctx;
32
36
    serf_bucket_alloc_t *bkt_alloc;
33
37
} app_baton_t;
37
41
                              apr_status_t why,
38
42
                              apr_pool_t *pool)
39
43
{
 
44
    app_baton_t *ctx = closed_baton;
 
45
 
 
46
    ctx->ssl_ctx = NULL;
 
47
 
40
48
    if (why) {
41
49
        abort();
42
50
    }
62
70
static apr_status_t ignore_all_cert_errors(void *data, int failures,
63
71
                                           const serf_ssl_certificate_t *cert)
64
72
{
65
 
    print_ssl_cert_errors(failures);   
 
73
    print_ssl_cert_errors(failures);
66
74
 
67
75
     /* In a real application, you would normally would not want to do this */
68
76
    return APR_SUCCESS;
69
77
}
70
78
 
 
79
static char *
 
80
convert_organisation_to_str(apr_hash_t *org, apr_pool_t *pool)
 
81
{
 
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));
 
89
}
 
90
 
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);
87
107
 
88
108
    while ((current = *certs) != NULL)
89
 
    {   
 
109
    {
 
110
        apr_hash_t *issuer, *subject, *serf_cert;
 
111
        apr_array_header_t *san;
 
112
 
 
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);
 
116
 
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));
 
127
 
 
128
        san = apr_hash_get(serf_cert, "subjectAltName", APR_HASH_KEY_STRING);
 
129
        if (san) {
 
130
            int i;
 
131
            for (i = 0; i < san->nelts; i++) {
 
132
                char *s = APR_ARRAY_IDX(san, i, char*);
 
133
                fprintf(stderr, "SubjectAltName: %s\n", s);
 
134
            }
 
135
        }
 
136
 
91
137
        fprintf(stderr, "%s\n", serf_ssl_cert_export(current, pool));
92
138
        fprintf(stderr, "-----END CERTIFICATE-----\n");
93
139
        ++certs;
94
 
    }    
 
140
    }
95
141
 
96
142
    apr_pool_destroy(pool);
97
143
    return APR_SUCCESS;
132
178
                                      apr_pool_t *pool)
133
179
{
134
180
    serf_bucket_t *c;
 
181
    serf_bucket_t *response;
135
182
    serf_bucket_alloc_t *bkt_alloc;
 
183
    app_baton_t *app_ctx = acceptor_baton;
136
184
 
137
185
    /* get the per-request bucket allocator */
138
186
    bkt_alloc = serf_request_get_alloc(request);
140
188
    /* Create a barrier so the response doesn't eat us! */
141
189
    c = serf_bucket_barrier_create(stream, bkt_alloc);
142
190
 
143
 
    return serf_bucket_response_create(c, bkt_alloc);
 
191
    response = serf_bucket_response_create(c, bkt_alloc);
 
192
 
 
193
    if (app_ctx->head_request)
 
194
      serf_bucket_response_set_head(response);
 
195
 
 
196
    return response;
144
197
}
145
198
 
146
199
typedef struct {
150
203
    apr_atomic_t completed_requests;
151
204
#endif
152
205
    int print_headers;
 
206
    apr_file_t *output_file;
153
207
 
154
208
    serf_response_acceptor_t acceptor;
155
209
    app_baton_t *acceptor_baton;
160
214
    const char *method;
161
215
    const char *path;
162
216
    const char *req_body_path;
163
 
    const char *authn;
 
217
    const char *username;
 
218
    const char *password;
 
219
    int auth_attempts;
 
220
    serf_bucket_t *req_hdrs;
164
221
} handler_baton_t;
165
222
 
166
223
/* Kludges for APR 0.9 support. */
170
227
#define apr_atomic_read32 apr_atomic_read
171
228
#endif
172
229
 
173
 
static apr_status_t handle_response(serf_request_t *request,
174
 
                                    serf_bucket_t *response,
175
 
                                    void *handler_baton,
176
 
                                    apr_pool_t *pool)
 
230
 
 
231
static int append_request_headers(void *baton,
 
232
                                  const char *key,
 
233
                                  const char *value)
177
234
{
178
 
    const char *data;
179
 
    apr_size_t len;
180
 
    serf_status_line sl;
181
 
    apr_status_t status;
182
 
    handler_baton_t *ctx = handler_baton;
183
 
 
184
 
    if (!response) {
185
 
        /* A NULL response can come back if the request failed completely */
186
 
        return APR_EGENERAL;
187
 
    }
188
 
    status = serf_bucket_response_status(response, &sl);
189
 
    if (status) {
190
 
        return status;
191
 
    }
192
 
 
193
 
    while (1) {
194
 
        status = serf_bucket_read(response, 2048, &data, &len);
195
 
        if (SERF_BUCKET_READ_ERROR(status))
196
 
            return status;
197
 
 
198
 
        /* got some data. print it out. */
199
 
        fwrite(data, 1, len, stdout);
200
 
 
201
 
        /* are we done yet? */
202
 
        if (APR_STATUS_IS_EOF(status)) {
203
 
            if (ctx->print_headers) {
204
 
                serf_bucket_t *hdrs;
205
 
                hdrs = serf_bucket_response_get_headers(response);
206
 
                while (1) {
207
 
                    status = serf_bucket_read(hdrs, 2048, &data, &len);
208
 
                    if (SERF_BUCKET_READ_ERROR(status))
209
 
                        return status;
210
 
 
211
 
                    fwrite(data, 1, len, stdout);
212
 
                    if (APR_STATUS_IS_EOF(status)) {
213
 
                        break;
214
 
                    }
215
 
                }
216
 
            }
217
 
 
218
 
            apr_atomic_inc32(&ctx->completed_requests);
219
 
            return APR_EOF;
220
 
        }
221
 
 
222
 
        /* have we drained the response so far? */
223
 
        if (APR_STATUS_IS_EAGAIN(status))
224
 
            return status;
225
 
 
226
 
        /* loop to read some more. */
227
 
    }
228
 
    /* NOTREACHED */
 
235
    serf_bucket_t *hdrs_bkt = baton;
 
236
    serf_bucket_headers_setc(hdrs_bkt, key, value);
 
237
    return 0;
229
238
}
230
239
 
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");
 
284
#endif
273
285
 
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);
276
289
    }
277
290
 
278
291
    *acceptor = ctx->acceptor;
279
292
    *acceptor_baton = ctx->acceptor_baton;
280
293
    *handler = ctx->handler;
281
294
    *handler_baton = ctx;
282
 
 
 
295
    
283
296
    return APR_SUCCESS;
284
297
}
285
298
 
 
299
static apr_status_t handle_response(serf_request_t *request,
 
300
                                    serf_bucket_t *response,
 
301
                                    void *handler_baton,
 
302
                                    apr_pool_t *pool)
 
303
{
 
304
    serf_status_line sl;
 
305
    apr_status_t status;
 
306
    handler_baton_t *ctx = handler_baton;
 
307
 
 
308
    if (!response) {
 
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);
 
312
 
 
313
        serf_connection_request_create(conn, setup_request, handler_baton);
 
314
        return APR_SUCCESS;
 
315
    }
 
316
 
 
317
    status = serf_bucket_response_status(response, &sl);
 
318
    if (status) {
 
319
        return status;
 
320
    }
 
321
 
 
322
    while (1) {
 
323
        struct iovec vecs[64];
 
324
        int vecs_read;
 
325
        apr_size_t bytes_written;
 
326
 
 
327
        status = serf_bucket_read_iovec(response, 8000, 64, vecs, &vecs_read);
 
328
        if (SERF_BUCKET_READ_ERROR(status))
 
329
            return status;
 
330
 
 
331
        /* got some data. print it out. */
 
332
        if (vecs_read) {
 
333
            apr_file_writev(ctx->output_file, vecs, vecs_read, &bytes_written);
 
334
        }
 
335
 
 
336
        /* are we done yet? */
 
337
        if (APR_STATUS_IS_EOF(status)) {
 
338
            if (ctx->print_headers) {
 
339
                serf_bucket_t *hdrs;
 
340
                hdrs = serf_bucket_response_get_headers(response);
 
341
                while (1) {
 
342
                    status = serf_bucket_read_iovec(hdrs, 8000, 64, vecs,
 
343
                                                    &vecs_read);
 
344
 
 
345
                    if (SERF_BUCKET_READ_ERROR(status))
 
346
                        return status;
 
347
 
 
348
                    if (vecs_read) {
 
349
                        apr_file_writev(ctx->output_file, vecs, vecs_read,
 
350
                                        &bytes_written);
 
351
                    }
 
352
                    if (APR_STATUS_IS_EOF(status)) {
 
353
                        break;
 
354
                    }
 
355
                }
 
356
            }
 
357
 
 
358
            apr_atomic_inc32(&ctx->completed_requests);
 
359
            return APR_EOF;
 
360
        }
 
361
 
 
362
        /* have we drained the response so far? */
 
363
        if (APR_STATUS_IS_EAGAIN(status))
 
364
            return status;
 
365
 
 
366
        /* loop to read some more. */
 
367
    }
 
368
    /* NOTREACHED */
 
369
}
 
370
 
 
371
static apr_status_t
 
372
credentials_callback(char **username,
 
373
                     char **password,
 
374
                     serf_request_t *request, void *baton,
 
375
                     int code, const char *authn_type,
 
376
                     const char *realm,
 
377
                     apr_pool_t *pool)
 
378
{
 
379
    handler_baton_t *ctx = baton;
 
380
 
 
381
    if (ctx->auth_attempts > 0)
 
382
    {
 
383
        return SERF_ERROR_AUTHN_FAILED;
 
384
    }
 
385
    else
 
386
    {
 
387
        *username = (char*)ctx->username;
 
388
        *password = (char*)ctx->password;
 
389
        ctx->auth_attempts++;
 
390
 
 
391
        return APR_SUCCESS;
 
392
    }
 
393
}
 
394
 
286
395
static void print_usage(apr_pool_t *pool)
287
396
{
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");
297
409
}
298
410
 
299
411
int main(int argc, const char **argv)
300
412
{
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;
308
422
    apr_uri_t url;
309
423
    const char *proxy = NULL;
310
424
    const char *raw_url, *method, *req_body_path = NULL;
311
 
    int count;
 
425
    int count, inflight;
312
426
    int i;
313
427
    int print_headers;
314
 
    char *authn = NULL;
 
428
    const char *username = NULL;
 
429
    const char *password = "";
315
430
    apr_getopt_t *opt;
316
431
    char opt_c;
317
432
    const char *opt_arg;
321
436
 
322
437
    apr_pool_create(&pool, NULL);
323
438
    /* serf_initialize(); */
 
439
    bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
324
440
 
325
 
    /* Default to one round of fetching. */
 
441
    /* Default to one round of fetching with no limit to max inflight reqs. */
326
442
    count = 1;
 
443
    inflight = 0;
327
444
    /* Default to GET. */
328
445
    method = "GET";
329
446
    /* Do not print headers by default. */
331
448
 
332
449
    apr_getopt_init(&opt, pool, argc, argv);
333
450
 
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)) ==
335
452
           APR_SUCCESS) {
336
 
        int srclen, enclen;
337
453
 
338
454
        switch (opt_c) {
339
 
        case 'a':
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);
 
455
        case 'U':
 
456
            username = opt_arg;
 
457
            break;
 
458
        case 'P':
 
459
            password = opt_arg;
345
460
            break;
346
461
        case 'f':
347
462
            req_body_path = opt_arg;
365
480
                return errno;
366
481
            }
367
482
            break;
 
483
        case 'x':
 
484
            errno = 0;
 
485
            inflight = apr_strtoi64(opt_arg, NULL, 10);
 
486
            if (errno) {
 
487
                printf("Problem converting number of requests to have outstanding (%d)\n",
 
488
                       errno);
 
489
                return errno;
 
490
            }
 
491
            break;
368
492
        case 'p':
369
493
            proxy = opt_arg;
370
494
            break;
 
495
        case 'r':
 
496
            {
 
497
                char *sep;
 
498
                char *hdr_val;
 
499
 
 
500
                if (req_hdrs == NULL) {
 
501
                    /* first request header, allocate bucket */
 
502
                    req_hdrs = serf_bucket_headers_create(bkt_alloc);
 
503
                }
 
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);
 
507
                    return EINVAL;
 
508
                }
 
509
                hdr_val = sep + 1;
 
510
                while (*hdr_val == ' ') {
 
511
                    hdr_val++;
 
512
                }
 
513
                serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1,
 
514
                                         hdr_val, strlen(hdr_val), 1);
 
515
            }
 
516
            break;
371
517
        case 'v':
372
518
            puts("Serf version: " SERF_VERSION_STRING);
373
519
            exit(0);
398
544
        app_ctx.using_ssl = 0;
399
545
    }
400
546
 
 
547
    if (strcasecmp(method, "HEAD") == 0) {
 
548
        app_ctx.head_request = 1;
 
549
    }
 
550
    else {
 
551
        app_ctx.head_request = 0;
 
552
    }
 
553
 
401
554
    app_ctx.hostinfo = url.hostinfo;
402
555
 
403
556
    context = serf_context_create(pool);
444
597
        serf_config_proxy(context, proxy_address);
445
598
    }
446
599
 
 
600
    if (username)
 
601
    {
 
602
        serf_config_authn_types(context, SERF_AUTHN_ALL);
 
603
    }
 
604
    else
 
605
    {
 
606
        serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE);
 
607
    }
 
608
 
 
609
    serf_config_credentials_callback(context, credentials_callback);
 
610
 
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;
450
614
 
451
615
    status = serf_connection_create2(&connection, context, url,
460
624
 
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);
463
628
 
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,
 
632
                                   url.path,
 
633
                                   url.query ? "?" : "",
 
634
                                   url.query ? url.query : "",
 
635
                                   NULL);
 
636
    handler_ctx.username = username;
 
637
    handler_ctx.password = password;
 
638
    handler_ctx.auth_attempts = 0;
468
639
 
469
640
    handler_ctx.req_body_path = req_body_path;
470
641
 
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;
 
646
 
 
647
    serf_connection_set_max_outstanding_requests(connection, inflight);
474
648
 
475
649
    for (i = 0; i < count; i++) {
476
650
        request = serf_connection_request_create(connection, setup_request,
483
657
            continue;
484
658
        if (status) {
485
659
            char buf[200];
 
660
            const char *err_string;
 
661
            err_string = serf_error_string(status);
 
662
            if (!err_string) {
 
663
                err_string = apr_strerror(status, buf, sizeof(buf));
 
664
            }
486
665
 
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);
490
668
            exit(1);
491
669
        }