]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Implemented http_client_request_url_str() function that accepts...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 17 Mar 2017 22:39:33 +0000 (23:39 +0100)
committerGitLab <gitlab@git.dovecot.net>
Wed, 22 Mar 2017 18:41:09 +0000 (20:41 +0200)
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.

src/lib-http/http-client-request.c
src/lib-http/http-client.h
src/lib-http/test-http-client-errors.c

index c3af89b431d634fd302f1d60223edd694d09936e..4ee7ad582e574ad45b1af8e91e8fd84f85447314 100644 (file)
@@ -131,6 +131,39 @@ http_client_request_url(struct http_client *client,
        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 @@ static void http_client_request_do_submit(struct http_client_request *req)
                (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);
index 19428805755270e8a4334a568ec8be9765bfbe55..7a9c9e79a3dc2d8de57c3b49a44824d3b921b973 100644 (file)
@@ -130,6 +130,8 @@ struct http_client_settings {
 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
@@ -204,6 +206,15 @@ http_client_request_url(struct http_client *client,
                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
index 1d09255b647c688dfe6c983501402c7af6a33bf6..b1651244925daa2d0295878abeeb70e872674f88 100644 (file)
@@ -151,6 +151,72 @@ static void test_unconfigured_ssl(void)
        test_end();
 }
 
+/*
+ * 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_reconnect_failure(void)
 
 static void (*const test_functions[])(void) = {
        test_unconfigured_ssl,
+       test_invalid_url,
        test_host_lookup_failed,
        test_connection_refused,
        test_connection_lost_prematurely,