4

Using libevent to do HTTP request. I would like to print all the HTTP headers in the server response, but not sure how.

static void http_request_done(struct evhttp_request *req, void *ctx) {
    //how do I print out all the http headers in the server response 
}

evhttp_request_new(http_request_done,NULL);

I know I can get an individual header like the following, but how do I get all the headers?

static void http_request_done(struct evhttp_request *req, void *ctx) {
    struct evkeyvalq * kv = evhttp_request_get_input_headers(req);
    printf("%s\n", evhttp_find_header(kv, "SetCookie"));
}

Thanks.

packetie
  • 4,839
  • 8
  • 37
  • 72

2 Answers2

4

Though I don't have any previous experience with libevent library, it's rather clear for me that API doesn't provide such functionality (see its API for reference). However what you can do is to write your own method using TAILQ_FOREACH internal macro, which is defined in event-internal.h. Definition of evhttp_find_header is rather straightforward:

const char *
evhttp_find_header(const struct evkeyvalq *headers, const char *key)
{
    struct evkeyval *header;

    TAILQ_FOREACH(header, headers, next) {
        if (evutil_ascii_strcasecmp(header->key, key) == 0)
            return (header->value);
    }

    return (NULL);
}

Instead of doing evutil_ascii_strcasecmp you can just simply obtain header->key or header->value entries from evkeyval struct (defined in include/event2/keyvalq_struct.h):

/*
 * Key-Value pairs.  Can be used for HTTP headers but also for
 * query argument parsing.
 */
struct evkeyval {
    TAILQ_ENTRY(evkeyval) next;

    char *key;
    char *value;
};
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • thanks @Grzegorz Szpetkowski for the quick response, I don't have "event-internal.h" in the /usr/local/include/event2. I can copy event-internal.h to the directory but hesitated because that's more like a kludge. – packetie Jul 19 '14 at 17:11
  • @codingFun: This is "hard-way" method, so it reqires to download libevent source, thus requires manual compilation. As I checked definition should be put in `http.c` and appriopriate declaration (prototype) in `include/event2/http.h` (you probably using it in your program). – Grzegorz Szpetkowski Jul 19 '14 at 17:16
  • it's a little strange that my program can compile as long as I don't use the macro TAILQ_FOREACH. Seems that the macro is ONLY in the internal header files. What do you think? – packetie Jul 19 '14 at 17:27
  • @codingFun: It's internal function-like macro, not intended to be exposed to public API (so your program doesn't compile), essentially is just a `for` loop with another `TAILQ_FIRST`, `TAILQ_END`, `TAILQ_NEXT` f-l macros. – Grzegorz Szpetkowski Jul 19 '14 at 17:36
4

Thanks to helpful tips from @Grzegorz Szpetkowski, I created the following routine which works fine. The reason that "kv = kv->next.tqe_next" was used was because of "TAILQ_ENTRY(evkeyval) next" in the definition of struct evkeyval.

static void http_request_done(struct evhttp_request *req, void *ctx) {
    struct evkeyvalq *header = evhttp_request_get_input_headers(req);
    struct evkeyval* kv = header->tqh_first;
    while (kv) {
        printf("%s: %s\n", kv->key, kv->value);
        kv = kv->next.tqe_next;
    }
}
packetie
  • 4,839
  • 8
  • 37
  • 72