]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Cleaned up headers and added some more documentation there.
authorStephan Bosch <stephan@dovecot.fi>
Sat, 16 Apr 2016 00:03:10 +0000 (02:03 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 9 Nov 2016 12:22:34 +0000 (14:22 +0200)
src/lib-http/http-client-private.h
src/lib-http/http-client.h

index 876be910a4a24a004ea3267e433dc5e07314e2ec..0926f630e25c742caef2574c7676e97448a0592f 100644 (file)
@@ -6,6 +6,10 @@
 #include "http-url.h"
 #include "http-client.h"
 
+/*
+ * Defaults
+ */
+
 #define HTTP_DEFAULT_PORT 80
 #define HTTPS_DEFAULT_PORT 443
 
 #define HTTP_CLIENT_DEFAULT_BACKOFF_TIME_MSECS (100)
 #define HTTP_CLIENT_DEFAULT_BACKOFF_MAX_TIME_MSECS (1000*60)
 
+/*
+ * Types
+ */
+
 enum http_response_payload_type;
 
 struct http_client_host;
@@ -55,6 +63,10 @@ struct http_client_peer_addr {
        } a;
 };
 
+/*
+ * Objects
+ */
+
 struct http_client_request {
        pool_t pool;
        unsigned int refcount;
@@ -278,7 +290,78 @@ struct http_client {
        unsigned int requests_count;
 };
 
-int http_client_init_ssl_ctx(struct http_client *client, const char **error_r);
+/*
+ * Peer address
+ */
+
+static inline bool
+http_client_peer_addr_is_https(const struct http_client_peer_addr *addr)
+{
+       switch (addr->type) {
+       case HTTP_CLIENT_PEER_ADDR_HTTPS:
+       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+               return TRUE;
+       default:
+               break;
+       }
+       return FALSE;
+}
+
+static inline const char *
+http_client_peer_addr_get_https_name(const struct http_client_peer_addr *addr)
+{
+       switch (addr->type) {
+       case HTTP_CLIENT_PEER_ADDR_HTTPS:
+       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+               return addr->a.tcp.https_name;
+       default:
+               break;
+       }
+       return NULL;
+}
+
+static inline const char *
+http_client_peer_addr2str(const struct http_client_peer_addr *addr)
+{
+       switch (addr->type) {
+       case HTTP_CLIENT_PEER_ADDR_HTTP:
+       case HTTP_CLIENT_PEER_ADDR_HTTPS:
+       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+       case HTTP_CLIENT_PEER_ADDR_RAW:
+               if (addr->a.tcp.ip.family == AF_INET6) {
+                       return t_strdup_printf("[%s]:%u",
+                               net_ip2addr(&addr->a.tcp.ip), addr->a.tcp.port);
+               }
+               return t_strdup_printf("%s:%u",
+                       net_ip2addr(&addr->a.tcp.ip), addr->a.tcp.port);
+       case HTTP_CLIENT_PEER_ADDR_UNIX:
+               return t_strdup_printf("unix:%s", addr->a.un.path);
+       default:
+               break;
+       }
+       i_unreached();
+       return "";
+}
+
+/*
+ * Request
+ */
+
+static inline const char *
+http_client_request_label(struct http_client_request *req)
+{
+       if (req->label == NULL) {
+               return t_strdup_printf("[Req%u: %s %s%s]", req->id,
+                       req->method, http_url_create(&req->origin_url), req->target);
+       }
+       return req->label;
+}
+
+static inline bool
+http_client_request_to_proxy(const struct http_client_request *req)
+{
+       return (req->host_url != &req->origin_url);
+}
 
 void http_client_request_ref(struct http_client_request *req);
 /* Returns FALSE if unrefing destroyed the request entirely */
@@ -310,6 +393,19 @@ void http_client_request_redirect(struct http_client_request *req,
        unsigned int status, const char *location);
 void http_client_request_finish(struct http_client_request *req);
 
+/*
+ * Connection
+ */
+
+static inline const char *
+http_client_connection_label(struct http_client_connection *conn)
+{
+       return t_strdup_printf("%s%s [%d]",
+               http_client_peer_addr2str(&conn->peer->addr),
+               (conn->peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL ?
+                       " (tunnel)" : ""), conn->id);
+}
+
 struct connection_list *http_client_connection_list_init(void);
 
 struct http_client_connection *
@@ -339,6 +435,19 @@ void http_client_connection_switch_ioloop(struct http_client_connection *conn);
 void http_client_connection_start_tunnel(struct http_client_connection **_conn,
        struct http_client_tunnel *tunnel);
 
+/*
+ * Peer
+ */
+
+static inline const char *
+http_client_peer_label(struct http_client_peer *peer)
+{
+       if (peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL) {
+               return t_strconcat
+                       (http_client_peer_addr2str(&peer->addr), " (tunnel)", NULL);
+       }
+       return http_client_peer_addr2str(&peer->addr);
+}
 
 unsigned int http_client_peer_addr_hash
        (const struct http_client_peer_addr *peer) ATTR_PURE;
@@ -376,6 +485,10 @@ unsigned int
 http_client_peer_pending_connections(struct http_client_peer *peer);
 void http_client_peer_switch_ioloop(struct http_client_peer *peer);
 
+/*
+ * Queue
+ */
+
 struct http_client_queue *
 http_client_queue_create(struct http_client_host *host,
        const struct http_client_peer_addr *addr);
@@ -403,103 +516,9 @@ void http_client_queue_peer_disconnected(struct http_client_queue *queue,
        struct http_client_peer *peer);
 void http_client_queue_switch_ioloop(struct http_client_queue *queue);
 
-struct http_client_host *
-http_client_host_get(struct http_client *client,
-       const struct http_url *host_url);
-void http_client_host_free(struct http_client_host **_host);
-void http_client_host_submit_request(struct http_client_host *host,
-       struct http_client_request *req);
-void http_client_host_switch_ioloop(struct http_client_host *host);
-
-void http_client_delay_request_error(struct http_client *client,
-       struct http_client_request *req);
-void http_client_remove_request_error(struct http_client *client,
-       struct http_client_request *req);
-
-
-static inline bool
-http_client_peer_addr_is_https(const struct http_client_peer_addr *addr)
-{
-       switch (addr->type) {
-       case HTTP_CLIENT_PEER_ADDR_HTTPS:
-       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
-               return TRUE;
-       default:
-               break;
-       }
-       return FALSE;
-}
-
-static inline const char *
-http_client_peer_addr_get_https_name(const struct http_client_peer_addr *addr)
-{
-       switch (addr->type) {
-       case HTTP_CLIENT_PEER_ADDR_HTTPS:
-       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
-               return addr->a.tcp.https_name;
-       default:
-               break;
-       }
-       return NULL;
-}
-
-static inline const char *
-http_client_peer_addr2str(const struct http_client_peer_addr *addr)
-{
-       switch (addr->type) {
-       case HTTP_CLIENT_PEER_ADDR_HTTP:
-       case HTTP_CLIENT_PEER_ADDR_HTTPS:
-       case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
-       case HTTP_CLIENT_PEER_ADDR_RAW:
-               if (addr->a.tcp.ip.family == AF_INET6) {
-                       return t_strdup_printf("[%s]:%u",
-                               net_ip2addr(&addr->a.tcp.ip), addr->a.tcp.port);
-               }
-               return t_strdup_printf("%s:%u",
-                       net_ip2addr(&addr->a.tcp.ip), addr->a.tcp.port);
-       case HTTP_CLIENT_PEER_ADDR_UNIX:
-               return t_strdup_printf("unix:%s", addr->a.un.path);
-       default:
-               break;
-       }
-       i_unreached();
-       return "";
-}
-
-static inline const char *
-http_client_request_label(struct http_client_request *req)
-{
-       if (req->label == NULL) {
-               return t_strdup_printf("[Req%u: %s %s%s]", req->id,
-                       req->method, http_url_create(&req->origin_url), req->target);
-       }
-       return req->label;
-}
-
-static inline bool
-http_client_request_to_proxy(const struct http_client_request *req)
-{
-       return (req->host_url != &req->origin_url);
-}
-
-static inline const char *
-http_client_connection_label(struct http_client_connection *conn)
-{
-       return t_strdup_printf("%s%s [%d]",
-               http_client_peer_addr2str(&conn->peer->addr),
-               (conn->peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL ?
-                       " (tunnel)" : ""), conn->id);
-}
-
-static inline const char *
-http_client_peer_label(struct http_client_peer *peer)
-{
-       if (peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL) {
-               return t_strconcat
-                       (http_client_peer_addr2str(&peer->addr), " (tunnel)", NULL);
-       }
-       return http_client_peer_addr2str(&peer->addr);
-}
+/*
+ * Host
+ */
 
 static inline unsigned int
 http_client_host_get_ip_idx(struct http_client_host *host,
@@ -514,5 +533,24 @@ http_client_host_get_ip_idx(struct http_client_host *host,
        i_unreached();
 }
 
+struct http_client_host *
+http_client_host_get(struct http_client *client,
+       const struct http_url *host_url);
+void http_client_host_free(struct http_client_host **_host);
+void http_client_host_submit_request(struct http_client_host *host,
+       struct http_client_request *req);
+void http_client_host_switch_ioloop(struct http_client_host *host);
+
+/*
+ * Client
+ */
+
+int http_client_init_ssl_ctx(struct http_client *client,
+       const char **error_r);
+
+void http_client_delay_request_error(struct http_client *client,
+       struct http_client_request *req);
+void http_client_remove_request_error(struct http_client *client,
+       struct http_client_request *req);
 
 #endif
index b8c7919c7cd7bf9fb96530b93db46a0c68848422..6d595737c1950094467a5c00960cc080ffae1cad 100644 (file)
@@ -11,28 +11,9 @@ struct http_response;
 struct http_client;
 struct http_client_request;
 
-enum http_client_request_error {
-       HTTP_CLIENT_REQUEST_ERROR_ABORTED = 9000,
-       HTTP_CLIENT_REQUEST_ERROR_HOST_LOOKUP_FAILED,
-       HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED,
-       HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
-       HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
-       HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD,
-       HTTP_CLIENT_REQUEST_ERROR_BAD_RESPONSE,
-       HTTP_CLIENT_REQUEST_ERROR_TIMED_OUT,
-};
-
-enum http_request_state {
-       HTTP_REQUEST_STATE_NEW = 0,
-       HTTP_REQUEST_STATE_QUEUED,
-       HTTP_REQUEST_STATE_PAYLOAD_OUT,
-       HTTP_REQUEST_STATE_WAITING,
-       HTTP_REQUEST_STATE_GOT_RESPONSE,
-       HTTP_REQUEST_STATE_PAYLOAD_IN,
-       HTTP_REQUEST_STATE_FINISHED,
-       HTTP_REQUEST_STATE_ABORTED
-};
-extern const char *http_request_state_names[];
+/*
+ * Client settings
+ */
 
 struct http_client_settings {
        /* a) If dns_client is set, all lookups are done via it.
@@ -42,6 +23,7 @@ struct http_client_settings {
        struct dns_client *dns_client;
        const char *dns_client_socket_path;
 
+       /* ssl configuration */
        const char *ssl_ca_dir, *ssl_ca_file, *ssl_ca;
        const char *ssl_crypto_device;
        bool ssl_allow_invalid_cert;
@@ -59,8 +41,12 @@ struct http_client_settings {
        const char *proxy_username;
        const char *proxy_password;
 
+       /* directory for writing raw log data for debugging purposes */
        const char *rawlog_dir;
 
+       /* maximum time a connection will idle. if parallel connections are idle,
+          the duplicates will end earlier based on how many idle connections exist
+          to that same service */
        unsigned int max_idle_time_msecs;
 
        /* maximum number of parallel connections per peer (default = 1) */
@@ -139,6 +125,55 @@ struct http_client_settings {
        bool debug;
 };
 
+/*
+ * Request
+ */
+
+enum http_client_request_error {
+       /* The request was aborted */
+       HTTP_CLIENT_REQUEST_ERROR_ABORTED = 9000,
+       /* 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
+          no more attempts */
+       HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED,
+       /* Service returned an invalid redirect response for this request */
+       HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
+       /* The connection was lost unexpectedly while handling the request and
+          client settings allowed no more attempts */
+       HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+       /* The input stream passed to the request using
+          http_client_request_set_payload() returned an error while sending the
+          request. */
+       HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD,
+       /* The service returned a bad response */
+       HTTP_CLIENT_REQUEST_ERROR_BAD_RESPONSE,
+       /* The request timed out (either this was the last attempt or the
+          absolute timeout was hit) */
+       HTTP_CLIENT_REQUEST_ERROR_TIMED_OUT,
+};
+
+enum http_request_state {
+       /* New request; not yet submitted */
+       HTTP_REQUEST_STATE_NEW = 0,
+       /* Request is queued; waiting for a connection */
+       HTTP_REQUEST_STATE_QUEUED,
+       /* Request header is sent; still sending request payload to server */
+       HTTP_REQUEST_STATE_PAYLOAD_OUT,
+       /* Request is fully sent; waiting for response */
+       HTTP_REQUEST_STATE_WAITING,
+       /* Response header is received for the request */
+       HTTP_REQUEST_STATE_GOT_RESPONSE,
+       /* Reading response payload; response handler still needs to read more
+          payload. */
+       HTTP_REQUEST_STATE_PAYLOAD_IN,
+       /* Request is finished; still lingering due to references */
+       HTTP_REQUEST_STATE_FINISHED,
+       /* Request is aborted; still lingering due to references */
+       HTTP_REQUEST_STATE_ABORTED
+};
+extern const char *http_request_state_names[];
+
 struct http_client_tunnel {
        int fd_in, fd_out;
        struct istream *input;
@@ -149,9 +184,6 @@ typedef void
 http_client_request_callback_t(const struct http_response *response,
                               void *context);
 
-struct http_client *http_client_init(const struct http_client_settings *set);
-void http_client_deinit(struct http_client **_client);
-
 /* create new HTTP request */
 struct http_client_request *
 http_client_request(struct http_client *client,
@@ -163,6 +195,8 @@ http_client_request(struct http_client *client,
                        const struct http_response *response, typeof(context))), \
                (http_client_request_callback_t *)callback, context)
 
+/* create net HTTP request using provided URL. This implicitly sets
+   port, ssl, and username:password if provided. */
 struct http_client_request *
 http_client_request_url(struct http_client *client,
                    const char *method, const struct http_url *target_url,
@@ -188,6 +222,9 @@ http_client_request_connect(struct http_client *client,
                CALLBACK_TYPECHECK(callback, void (*)( \
                        const struct http_response *response, typeof(context))), \
                (http_client_request_callback_t *)callback, context)
+
+/* same as http_client_request_connect, but uses an IP rather than a host
+   name. */
 struct http_client_request *
 http_client_request_connect_ip(struct http_client *client,
                    const struct ip_addr *ip, in_port_t port,
@@ -199,25 +236,53 @@ http_client_request_connect_ip(struct http_client *client,
                        const struct http_response *response, typeof(context))), \
                (http_client_request_callback_t *)callback, context)
 
+/* set the port for the service the request is directed at */
 void http_client_request_set_port(struct http_client_request *req,
        in_port_t port);
+/* indicate whether service the request is directed at uses ssl */
 void http_client_request_set_ssl(struct http_client_request *req,
        bool ssl);
+/* set the urgent flag: this means that this request will get priority over
+   non-urgent request. Also, if no idle connection is available, a new
+   connection is created. Urgent requests are never pipelined. */
 void http_client_request_set_urgent(struct http_client_request *req);
 void http_client_request_set_preserve_exact_reason(struct http_client_request *req);
 
+/* add a custom header to the request. This can override headers that are
+   otherwise created implicitly. */
 void http_client_request_add_header(struct http_client_request *req,
                                    const char *key, const char *value);
+/* remove a header added earlier. This has no influence on implicitly created
+   headers. */
 void http_client_request_remove_header(struct http_client_request *req,
                                       const char *key);
+
+/* set the value of the "Date" header for the request using a time_t value.
+   Use this instead of setting it directly using
+   http_client_request_add_header() */
 void http_client_request_set_date(struct http_client_request *req,
                                    time_t date);
 
+/* assign an input stream for the outgoing payload of this request. The input
+   stream is read asynchronously while the request is sent to the server.
+
+   when sync=TRUE a "100 Continue" response is requested from the service. The
+   client will then postpone sending the payload until a provisional response
+   with code 100 is received. This way, an error response can be sent by the
+   service before any potentially big payload is transmitted. Use this only for
+   payload that can be large. */
 void http_client_request_set_payload(struct http_client_request *req,
                                     struct istream *input, bool sync);
+/* assign payload data to the request. The data is copied to the request pool.
+   If your data is already durably allocated during the existence of the
+   request, you should consider using http_client_request_set_payload() with
+   a data input stream instead. This will avoid copying the data unnecessarily.
+ */
 void http_client_request_set_payload_data(struct http_client_request *req,
                                     const unsigned char *data, size_t size);
 
+/* set an absolute timeout for this request specifically, overriding the
+   default client-wide absolute request timeout */
 void http_client_request_set_timeout_msecs(struct http_client_request *req,
        unsigned int msecs);
 void http_client_request_set_timeout(struct http_client_request *req,
@@ -230,9 +295,17 @@ void http_client_request_set_attempt_timeout_msecs(struct http_client_request *r
 void http_client_request_set_max_attempts(struct http_client_request *req,
        unsigned int max_attempts);
 
+/* set the username:password credentials for this request for simple
+   authentication. This function is meant for simple schemes that use a
+   password. More complex schemes will need to be handled manually.
+
+   This currently only supports the "basic" authentication scheme. */
 void http_client_request_set_auth_simple(struct http_client_request *req,
        const char *username, const char *password);
 
+/* delay handling of this request to a later time. This way, a request can be
+   submitted that is held for some time until a certain time period has passed.
+ */
 void http_client_request_delay_until(struct http_client_request *req,
        time_t time);
 void http_client_request_delay(struct http_client_request *req,
@@ -240,39 +313,64 @@ void http_client_request_delay(struct http_client_request *req,
 void http_client_request_delay_msecs(struct http_client_request *req,
        unsigned int msecs);
 
-const char *http_client_request_get_method(struct http_client_request *req);
-const char *http_client_request_get_target(struct http_client_request *req);
+/* return the HTTP method for the request */
+const char *
+http_client_request_get_method(struct http_client_request *req);
+/* return the HTTP target for the request */
+const char *
+http_client_request_get_target(struct http_client_request *req);
+/* return the request state */
 enum http_request_state
 http_client_request_get_state(struct http_client_request *req);
+
+/* submit the request. It is queued for transmission to the service */
 void http_client_request_submit(struct http_client_request *req);
+
+/* attempt to retry the request. This function is called within the request
+   callback. It returns false if the request cannot be retried */
 bool http_client_request_try_retry(struct http_client_request *req);
 
+/* abort the request immediately. It may still linger for a while when it is
+   already sent to the service, but the callback will not be called anymore. */
 void http_client_request_abort(struct http_client_request **req);
 
-/* Call the specified callback when HTTP request is destroyed. */
+/* call the specified callback when HTTP request is destroyed. */
 void http_client_request_set_destroy_callback(struct http_client_request *req,
                                              void (*callback)(void *),
                                              void *context);
 
-/* submits request and blocks until provided payload is sent. Multiple calls
-   are allowed; payload transmission is ended with
+/* submits request and blocks until the provided payload is sent. Multiple
+   calls are allowed; payload transmission is ended with
    http_client_request_finish_payload(). If the sending fails, returns -1
    and sets req=NULL to indicate that the request was freed, otherwise
    returns 0 and req is unchanged. */
 int http_client_request_send_payload(struct http_client_request **req,
        const unsigned char *data, size_t size);
-/* Finish sending the payload. Always frees req and sets it to NULL.
+/* finish sending the payload. Always frees req and sets it to NULL.
    Returns 0 on success, -1 on error. */
 int http_client_request_finish_payload(struct http_client_request **req);
 
+/* take over the connection this request was sent over for use as a HTTP
+   CONNECT tunnel. This only applies to requests that were created using
+   http_client_request_connect() or http_client_request_connect_ip(). */
 void http_client_request_start_tunnel(struct http_client_request *req,
        struct http_client_tunnel *tunnel);
 
+/*
+ * Client
+ */
+
+struct http_client *http_client_init(const struct http_client_settings *set);
+void http_client_deinit(struct http_client **_client);
+
+/* switch this client to the current ioloop */
 void http_client_switch_ioloop(struct http_client *client);
 
 /* blocks until all currently submitted requests are handled */
 void http_client_wait(struct http_client *client);
-/* Returns number of pending HTTP requests. */
-unsigned int http_client_get_pending_request_count(struct http_client *client);
+
+/* Returns the total number of pending HTTP requests. */
+unsigned int
+http_client_get_pending_request_count(struct http_client *client);
 
 #endif