diff --git a/http.c b/http.c index 533915d2..d2ba8130 100644 --- a/http.c +++ b/http.c @@ -417,6 +417,7 @@ evhttp_response_needs_body(struct evhttp_request *req) return (req->response_code != HTTP_NOCONTENT && req->response_code != HTTP_NOTMODIFIED && (req->response_code < 100 || req->response_code >= 200) && + req->type != EVHTTP_REQ_CONNECT && req->type != EVHTTP_REQ_HEAD); } @@ -541,6 +542,9 @@ evhttp_is_connection_close(int flags, struct evkeyvalq* headers) static int evhttp_is_request_connection_close(struct evhttp_request *req) { + if (req->type == EVHTTP_REQ_CONNECT) + return 0; + return evhttp_is_connection_close(req->flags, req->input_headers) || evhttp_is_connection_close(req->flags, req->output_headers); diff --git a/sample/http-connect.c b/sample/http-connect.c index af2c86a8..53f816d3 100644 --- a/sample/http-connect.c +++ b/sample/http-connect.c @@ -23,15 +23,44 @@ struct connect_base struct evhttp_uri *location; }; +static struct evhttp_uri* uri_parse(const char *str) +{ + struct evhttp_uri *uri; + VERIFY(uri = evhttp_uri_parse(str)); + VERIFY(evhttp_uri_get_host(uri)); + VERIFY(evhttp_uri_get_port(uri) > 0); + return uri; +} +static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX]) +{ + struct evhttp_uri *path; + + VERIFY(evhttp_uri_join(uri, buffer, URL_MAX)); + + path = evhttp_uri_parse(buffer); + evhttp_uri_set_scheme(path, NULL); + evhttp_uri_set_userinfo(path, 0); + evhttp_uri_set_host(path, NULL); + evhttp_uri_set_port(path, -1); + VERIFY(evhttp_uri_join(path, buffer, URL_MAX)); + return buffer; +} +static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX]) +{ + VERIFY(evhttp_uri_join(uri, buffer, URL_MAX)); + VERIFY(evhttp_uri_get_host(uri)); + VERIFY(evhttp_uri_get_port(uri) > 0); + evutil_snprintf(buffer, URL_MAX, "%s:%d", + evhttp_uri_get_host(uri), evhttp_uri_get_port(uri)); + return buffer; +} + static void get_cb(struct evhttp_request *req, void *arg) { ev_ssize_t len; struct evbuffer *evbuf; - struct evhttp_connection *evcon; VERIFY(req); - evcon = evhttp_request_get_connection(req); - VERIFY(evcon); evbuf = evhttp_request_get_input_buffer(req); len = evbuffer_get_length(evbuf); @@ -41,26 +70,26 @@ static void get_cb(struct evhttp_request *req, void *arg) static void connect_cb(struct evhttp_request *proxy_req, void *arg) { - char buffer[URL_MAX]; - struct connect_base *base = arg; struct evhttp_connection *evcon = base->evcon; struct evhttp_uri *location = base->location; + struct evhttp_request *req; + char buffer[URL_MAX]; VERIFY(proxy_req); - if (evcon) { - struct evhttp_request *req = evhttp_request_new(get_cb, NULL); - evhttp_add_header(req->output_headers, "Connection", "close"); - VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET, - evhttp_uri_join(location, buffer, URL_MAX))); - } + VERIFY(evcon); + + req = evhttp_request_new(get_cb, NULL); + evhttp_add_header(req->output_headers, "Connection", "close"); + evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location)); + VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + uri_path(location, buffer))); } int main(int argc, const char **argv) { - char buffer[URL_MAX]; + char hostport[URL_MAX]; - struct evhttp_uri *host_port; struct evhttp_uri *location; struct evhttp_uri *proxy; @@ -75,28 +104,8 @@ int main(int argc, const char **argv) return 1; } - { - VERIFY(proxy = evhttp_uri_parse(argv[1])); - VERIFY(evhttp_uri_get_host(proxy)); - VERIFY(evhttp_uri_get_port(proxy) > 0); - } - { - host_port = evhttp_uri_parse(argv[2]); - evhttp_uri_set_scheme(host_port, NULL); - evhttp_uri_set_userinfo(host_port, NULL); - evhttp_uri_set_path(host_port, NULL); - evhttp_uri_set_query(host_port, NULL); - evhttp_uri_set_fragment(host_port, NULL); - VERIFY(evhttp_uri_get_host(host_port)); - VERIFY(evhttp_uri_get_port(host_port) > 0); - } - { - location = evhttp_uri_parse(argv[2]); - evhttp_uri_set_scheme(location, NULL); - evhttp_uri_set_userinfo(location, 0); - evhttp_uri_set_host(location, NULL); - evhttp_uri_set_port(location, -1); - } + proxy = uri_parse(argv[1]); + location = uri_parse(argv[2]); VERIFY(base = event_base_new()); VERIFY(evcon = evhttp_connection_base_new(base, NULL, @@ -105,17 +114,18 @@ int main(int argc, const char **argv) connect_base.location = location; VERIFY(req = evhttp_request_new(connect_cb, &connect_base)); + uri_hostport(location, hostport); evhttp_add_header(req->output_headers, "Connection", "keep-alive"); evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive"); - evutil_snprintf(buffer, URL_MAX, "%s:%d", - evhttp_uri_get_host(host_port), evhttp_uri_get_port(host_port)); - evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, buffer); + evhttp_add_header(req->output_headers, "Host", hostport); + evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport); event_base_dispatch(base); + evhttp_connection_free(evcon); event_base_free(base); evhttp_uri_free(proxy); - evhttp_uri_free(host_port); evhttp_uri_free(location); + return 0; }