Mercurial > dovecot > core-2.2
changeset 21793:e3b32123b0c2
lib-http: client: Implemented http_client_request_url_str() function that accepts an URL string rather than a pre-parsed URL object.
If the provided HTTP URL is invalid, the callback with the error is called some time later from the ioloop.
This change also amends the test-http-client-errors test suite with a new test for this new feature.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Fri, 17 Mar 2017 23:39:33 +0100 |
parents | 40393fbf9954 |
children | cc18acb777cb |
files | src/lib-http/http-client-request.c src/lib-http/http-client.h src/lib-http/test-http-client-errors.c |
diffstat | 3 files changed, 113 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-request.c Fri Mar 17 23:51:19 2017 +0100 +++ b/src/lib-http/http-client-request.c Fri Mar 17 23:39:33 2017 +0100 @@ -131,6 +131,39 @@ return req; } +#undef http_client_request_url_str +struct http_client_request * +http_client_request_url_str(struct http_client *client, + const char *method, const char *url_str, + http_client_request_callback_t *callback, void *context) +{ + struct http_client_request *req, *tmpreq; + struct http_url *target_url; + const char *error; + + req = tmpreq = http_client_request_new + (client, method, callback, context); + + if (http_url_parse(url_str, NULL, HTTP_URL_ALLOW_USERINFO_PART, + req->pool, &target_url, &error) < 0) { + req->label = p_strdup_printf(req->pool, + "[Req%u: %s %s]", req->id, req->method, url_str); + http_client_request_error(&tmpreq, + HTTP_CLIENT_REQUEST_ERROR_INVALID_URL, + t_strdup_printf("Invalid HTTP URL: %s", error)); + return req; + } + + req->origin_url = *target_url; + req->target = p_strdup(req->pool, http_url_create_target(target_url)); + if (target_url->user != NULL && *target_url->user != '\0' && + target_url->password != NULL) { + req->username = p_strdup(req->pool, target_url->user); + req->password = p_strdup(req->pool, target_url->password); + } + return req; +} + #undef http_client_request_connect struct http_client_request * http_client_request_connect(struct http_client *client, @@ -580,6 +613,8 @@ (req->host_socket != NULL) || (req->host_url != NULL); const char *authority, *target; + if (req->state == HTTP_REQUEST_STATE_ABORTED) + return; i_assert(req->state == HTTP_REQUEST_STATE_NEW); authority = http_url_create_authority(&req->origin_url);
--- a/src/lib-http/http-client.h Fri Mar 17 23:51:19 2017 +0100 +++ b/src/lib-http/http-client.h Fri Mar 17 23:39:33 2017 +0100 @@ -133,6 +133,8 @@ enum http_client_request_error { /* The request was aborted */ HTTP_CLIENT_REQUEST_ERROR_ABORTED = HTTP_RESPONSE_STATUS_INTERNAL, + /* Failed to parse HTTP target url */ + HTTP_CLIENT_REQUEST_ERROR_INVALID_URL, /* Failed to perform DNS lookup for the host */ HTTP_CLIENT_REQUEST_ERROR_HOST_LOOKUP_FAILED, /* Failed to setup any connection for the host and client settings allowed @@ -207,6 +209,15 @@ CALLBACK_TYPECHECK(callback, void (*)( \ const struct http_response *response, typeof(context))), \ (http_client_request_callback_t *)callback, context) +struct http_client_request * +http_client_request_url_str(struct http_client *client, + const char *method, const char *url_str, + http_client_request_callback_t *callback, void *context); +#define http_client_request_url_str(client, method, url_str, callback, context) \ + http_client_request_url_str(client, method, url_str + \ + CALLBACK_TYPECHECK(callback, void (*)( \ + const struct http_response *response, typeof(context))), \ + (http_client_request_callback_t *)callback, context) /* create new HTTP CONNECT request. If this HTTP is configured to use a proxy, a CONNECT request will be submitted at that proxy, otherwise the connection
--- a/src/lib-http/test-http-client-errors.c Fri Mar 17 23:51:19 2017 +0100 +++ b/src/lib-http/test-http-client-errors.c Fri Mar 17 23:39:33 2017 +0100 @@ -152,6 +152,72 @@ } /* + * Invalid URL + */ + +/* client */ + +struct _invalid_url { + unsigned int count; +}; + +static void +test_client_invalid_url_response( + const struct http_response *resp, + struct _invalid_url *ctx) +{ + if (debug) + i_debug("RESPONSE: %u %s", resp->status, resp->reason); + + test_assert(resp->status == HTTP_CLIENT_REQUEST_ERROR_INVALID_URL); + test_assert(resp->reason != NULL && *resp->reason != '\0'); + + if (--ctx->count == 0) { + i_free(ctx); + io_loop_stop(ioloop); + } +} + +static bool +test_client_invalid_url(const struct http_client_settings *client_set) +{ + struct http_client_request *hreq; + struct _invalid_url *ctx; + + ctx = i_new(struct _invalid_url, 1); + ctx->count = 2; + + http_client = http_client_init(client_set); + + hreq = http_client_request_url_str(http_client, + "GET", "imap://example.com/INBOX", + test_client_invalid_url_response, ctx); + http_client_request_submit(hreq); + + hreq = http_client_request_url_str(http_client, + "GET", "http:/www.example.com", + test_client_invalid_url_response, ctx); + http_client_request_submit(hreq); + + return TRUE; +} + +/* test */ + +static void test_invalid_url(void) +{ + struct http_client_settings http_client_set; + + test_client_defaults(&http_client_set); + + test_begin("invalid url"); + test_run_client_server(&http_client_set, + test_client_invalid_url, + NULL, 0, NULL); + test_end(); +} + +/* * Host lookup failed */ @@ -2679,6 +2745,7 @@ static void (*test_functions[])(void) = { test_unconfigured_ssl, + test_invalid_url, test_host_lookup_failed, test_connection_refused, test_connection_lost_prematurely,