[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] [PATCH] Add Host header in HTTP/1.1 requests if it's missing.



Hello,

Here is patch to add "host" header to outgoing HTTP/1.1 requests.
Please, review.

Without the patch libevent-based evhttp-client.c can't get reply from
any sane server because the request is rejected with "400 Bad request"
and workaround - adding the header manually - is required.

--
WBRBW, Leonid Evdokimov
xmpp:leon@xxxxxxxxxxxx && http://darkk.net.ru
tel:+79816800702 && tel:+79050965222
#include <event2/event.h>
#include <event2/dns.h>
#include <event2/http.h>
#include <sys/queue.h>
#include <event2/keyvalq_struct.h> /* ugly :( */
#include <stdlib.h>
#include <stdio.h>

void httpcb(struct evhttp_request *req, void *arg)
{
    struct evkeyvalq *ihead = evhttp_request_get_input_headers(req);
    struct evkeyvalq *ohead = evhttp_request_get_output_headers(req);
    struct evkeyval *h;

    printf("%s %s HTTP/x.x\n", 
            evhttp_request_get_command(req) == EVHTTP_REQ_GET ? "GET" : "...",
            evhttp_request_get_uri(req));
    TAILQ_FOREACH(h, ohead, next) {
        printf("%s: %s\n", h->key, h->value);
    }
    printf("\n");

    printf("HTTP/x.x %d ...\n", evhttp_request_get_response_code(req));
    TAILQ_FOREACH(h, ihead, next) {
        printf("%s: %s\n", h->key, h->value);
    }
    printf("\n");

    event_base_loopbreak(arg);
}


int main(int argc, char* argv[])
{
    if (argc != 4) {
        printf("Usage: %s <host> <port> <path>\n", argv[0]);
        return 1;
    }

    struct event_base* evbase = event_base_new();

    struct evdns_base *evdns = evdns_base_new(evbase, 1);

    struct evhttp_connection *conn = evhttp_connection_base_new
                        (evbase, evdns, argv[1], atoi(argv[2]));
    evhttp_connection_set_timeout(conn, 10);

    struct evhttp_request* req = evhttp_request_new(httpcb, evbase);

    /* @see 0006-Add-Host-header-in-HTTP-1.1-requests-if-it-s-missing.patch
     * struct evkeyvalq *hout = evhttp_request_get_output_headers(req);
     * evhttp_add_header, (hout, "Host", "example.org:8080");
     */

    evhttp_make_request(conn, req, EVHTTP_REQ_GET, argv[3]);

    event_base_loop(evbase, 0);

    /* NB: it's not cleaned up during event_base_free */
    evhttp_connection_free(conn);

    /* evdns_base_free is called during event_base_free, but noone should rely
     * on that */
    const int send_err_shutdown = 0;
    evdns_base_free(evdns, send_err_shutdown);

    event_base_free(evbase);
    return 0;
}
From a87fc928f7a61ca691861154ffd9ba3e6aec0397 Mon Sep 17 00:00:00 2001
From: Leonid Evdokimov <darkk@xxxxxxxxxxxxxx>
Date: Fri, 19 Aug 2011 14:47:20 +0400
Subject: [PATCH 6/6] Add Host header in HTTP/1.1 requests if it's missing.

---
 http.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/http.c b/http.c
index 58fef16..823bf19 100644
--- a/http.c
+++ b/http.c
@@ -456,6 +456,18 @@ evhttp_make_header_request(struct evhttp_connection *evcon,
 	    "%s %s HTTP/%d.%d\r\n",
 	    method, req->uri, req->major, req->minor);
 
+	if (req->major == 1 && req->minor >= 1 &&
+	    evhttp_find_header(req->output_headers, "Host") == NULL) {
+		if (evcon->port == 80) {
+			evhttp_add_header(req->output_headers, "Host", evcon->address);
+		}
+		else {
+			char host[255 + 1 + 5 + 1];
+			evutil_snprintf(host, sizeof(host), "%s:%u", evcon->address, evcon->port);
+			evhttp_add_header(req->output_headers, "Host", host);
+		}
+	}
+
 	/* Add the content length on a post or put request if missing */
 	if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
 	    evhttp_find_header(req->output_headers, "Content-Length") == NULL){
-- 
1.7.4.1