http_client_connection_ssl_handshaked(const char **error_r, void *context)
{
struct http_client_connection *conn = context;
- const char *error, *host = conn->peer->addr.https_name;
+ const char *error, *host = conn->peer->addr.a.tcp.https_name;
if (ssl_iostream_check_cert_validity(conn->ssl_iostream, host, &error) == 0)
http_client_connection_debug(conn, "SSL handshake successful");
http_client_connection_debug(conn, "Starting SSL handshake");
if (io_stream_create_ssl_client(conn->client->ssl_ctx,
- conn->peer->addr.https_name, &ssl_set,
+ conn->peer->addr.a.tcp.https_name, &ssl_set,
&conn->conn.input, &conn->conn.output,
&conn->ssl_iostream, &error) < 0) {
*error_r = t_strdup_printf(
} else {
conn->connected_timestamp = ioloop_timeval;
http_client_connection_debug(conn, "Connected");
- if (conn->peer->addr.https_name != NULL) {
+ if (http_client_peer_addr_is_https(&conn->peer->addr)) {
if (http_client_connection_ssl_init(conn, &error) < 0) {
http_client_peer_connection_failure(conn->peer, error);
http_client_connection_debug(conn, "%s", error);
static const struct connection_settings http_client_connection_set = {
.input_max_size = (size_t)-1,
.output_max_size = (size_t)-1,
- .client = TRUE
+ .client = TRUE,
+ .delayed_unix_client_connected_callback = TRUE
};
static const struct connection_vfuncs http_client_connection_vfuncs = {
case HTTP_CLIENT_PEER_ADDR_RAW:
conn_type = "Raw";
break;
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ conn_type = "Unix";
+ break;
}
conn = i_new(struct http_client_connection, 1);
if (peer->addr.type != HTTP_CLIENT_PEER_ADDR_RAW)
i_array_init(&conn->request_wait_list, 16);
- if (peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL) {
- http_client_connection_connect_tunnel(conn, &addr->ip, addr->port);
- } else {
- connection_init_client_ip
- (peer->client->conn_list, &conn->conn, &addr->ip, addr->port);
+ switch (peer->addr.type) {
+ case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+ http_client_connection_connect_tunnel
+ (conn, &addr->a.tcp.ip, addr->a.tcp.port);
+ break;
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ connection_init_client_unix(peer->client->conn_list, &conn->conn,
+ addr->a.un.path);
+ conn->connect_initialized = TRUE;
+ http_client_connection_connect(conn);
+ break;
+ default:
+ connection_init_client_ip(peer->client->conn_list, &conn->conn,
+ &addr->a.tcp.ip, addr->a.tcp.port);
conn->connect_initialized = TRUE;
http_client_connection_connect(conn);
}
}
}
+static struct http_client_host *http_client_host_create
+(struct http_client *client)
+{
+ struct http_client_host *host;
+
+ // FIXME: limit the maximum number of inactive cached hosts
+ host = i_new(struct http_client_host, 1);
+ host->client = client;
+ i_array_init(&host->queues, 4);
+ DLLIST_PREPEND(&client->hosts_list, host);
+
+ return host;
+}
+
struct http_client_host *http_client_host_get
(struct http_client *client, const struct http_url *host_url)
{
struct http_client_host *host;
- const char *hostname = host_url->host_name;
-
- host = hash_table_lookup(client->hosts, hostname);
- if (host == NULL) {
- // FIXME: limit the maximum number of inactive cached hosts
- host = i_new(struct http_client_host, 1);
- host->client = client;
- host->name = i_strdup(hostname);
- i_array_init(&host->queues, 4);
-
- hostname = host->name;
- hash_table_insert(client->hosts, hostname, host);
- DLLIST_PREPEND(&client->hosts_list, host);
-
- if (host_url->have_host_ip) {
- host->ips_count = 1;
- host->ips = i_new(struct ip_addr, host->ips_count);
- host->ips[0] = host_url->host_ip;
+
+ if (host_url == NULL) {
+ host = client->unix_host;
+ if (host == NULL) {
+ host = http_client_host_create(client);
+ host->name = i_strdup("[unix]");
+ host->unix_local = TRUE;
+
+ client->unix_host = host;
+
+ http_client_host_debug(host, "Unix host created");
}
- http_client_host_debug(host, "Host created");
+ } else {
+ const char *hostname = host_url->host_name;
+
+ host = hash_table_lookup(client->hosts, hostname);
+ if (host == NULL) {
+ host = http_client_host_create(client);
+ host->name = i_strdup(hostname);
+ hostname = host->name;
+ hash_table_insert(client->hosts, hostname, host);
+
+ if (host_url->have_host_ip) {
+ host->ips_count = 1;
+ host->ips = i_new(struct ip_addr, host->ips_count);
+ host->ips[0] = host_url->host_ip;
+ }
+
+ http_client_host_debug(host, "Host created");
+ }
}
return host;
}
struct http_client_request *req)
{
struct http_client_queue *queue;
- const struct http_url *host_url = req->host_url;
struct http_client_peer_addr addr;
const char *error;
req->host = host;
- if (host_url->have_ssl && host->client->ssl_ctx == NULL) {
+ http_client_request_get_peer_addr(req, &addr);
+ if (http_client_peer_addr_is_https(&addr) &&
+ host->client->ssl_ctx == NULL) {
if (http_client_init_ssl_ctx(host->client, &error) < 0) {
http_client_request_error(req,
HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, error);
}
}
- http_client_request_get_peer_addr(req, &addr);
-
/* add request to queue (grouped by tcp port) */
queue = http_client_queue_create(host, &addr);
http_client_queue_submit_request(queue, req);
+ if (host->unix_local) {
+ http_client_queue_connection_setup(queue);
+ return;
+ }
+
/* start DNS lookup if necessary */
if (host->ips_count == 0 && host->dns_lookup == NULL)
http_client_host_lookup(host);
http_client_host_debug(host, "Host destroy");
DLLIST_REMOVE(&host->client->hosts_list, host);
- hash_table_remove(host->client->hosts, hostname);
+ if (host != host->client->unix_host)
+ hash_table_remove(host->client->hosts, hostname);
if (host->dns_lookup != NULL)
dns_lookup_abort(&host->dns_lookup);
{
switch (peer->type) {
case HTTP_CLIENT_PEER_ADDR_RAW:
- return net_ip_hash(&peer->ip) + peer->port + 1;
+ return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port + 1;
case HTTP_CLIENT_PEER_ADDR_HTTP:
- return net_ip_hash(&peer->ip) + peer->port;
+ return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port;
case HTTP_CLIENT_PEER_ADDR_HTTPS:
case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
- return net_ip_hash(&peer->ip) + peer->port +
- (peer->https_name == NULL ? 0 : str_hash(peer->https_name));
+ return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port +
+ (peer->a.tcp.https_name == NULL ?
+ 0 : str_hash(peer->a.tcp.https_name));
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ return str_hash(peer->a.un.path);
}
i_unreached();
return 0;
if (peer1->type != peer2->type)
return (peer1->type > peer2->type ? 1 : -1);
- if ((ret=net_ip_cmp(&peer1->ip, &peer2->ip)) != 0)
- return ret;
- if (peer1->port != peer2->port)
- return (peer1->port > peer2->port ? 1 : -1);
- if (peer1->type != HTTP_CLIENT_PEER_ADDR_HTTPS)
- return 0;
- return null_strcmp(peer1->https_name, peer2->https_name);
+ switch (peer1->type) {
+ case HTTP_CLIENT_PEER_ADDR_RAW:
+ case HTTP_CLIENT_PEER_ADDR_HTTP:
+ case HTTP_CLIENT_PEER_ADDR_HTTPS:
+ case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+ if ((ret=net_ip_cmp(&peer1->a.tcp.ip, &peer2->a.tcp.ip)) != 0)
+ return ret;
+ if (peer1->a.tcp.port != peer2->a.tcp.port)
+ return (peer1->a.tcp.port > peer2->a.tcp.port ? 1 : -1);
+ if (peer1->type != HTTP_CLIENT_PEER_ADDR_HTTPS)
+ return 0;
+ return null_strcmp
+ (peer1->a.tcp.https_name, peer2->a.tcp.https_name);
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ return null_strcmp(peer1->a.un.path, peer2->a.un.path);
+ }
+ i_unreached();
+ return 0;
}
/*
{
struct http_client_peer *peer;
- i_assert(addr->https_name == NULL || client->ssl_ctx != NULL);
-
peer = i_new(struct http_client_peer, 1);
peer->client = client;
peer->addr = *addr;
- peer->https_name = i_strdup(addr->https_name);
- peer->addr.https_name = peer->https_name;
+
+ switch (addr->type) {
+ case HTTP_CLIENT_PEER_ADDR_HTTPS:
+ case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+ i_assert(client->ssl_ctx != NULL);
+ peer->addr_name = i_strdup(addr->a.tcp.https_name);
+ peer->addr.a.tcp.https_name = peer->addr_name;
+ break;
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ peer->addr_name = i_strdup(addr->a.un.path);
+ peer->addr.a.un.path = peer->addr_name;
+ break;
+ default:
+ break;
+ }
+
i_array_init(&peer->queues, 16);
i_array_init(&peer->conns, 16);
(peer->client->peers, (const struct http_client_peer_addr *)&peer->addr);
DLLIST_REMOVE(&peer->client->peers_list, peer);
- i_free(peer->https_name);
+ i_free(peer->addr_name);
i_free(peer);
*_peer = NULL;
}
HTTP_CLIENT_PEER_ADDR_HTTP = 0,
HTTP_CLIENT_PEER_ADDR_HTTPS,
HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL,
- HTTP_CLIENT_PEER_ADDR_RAW
+ HTTP_CLIENT_PEER_ADDR_RAW,
+ HTTP_CLIENT_PEER_ADDR_UNIX,
};
struct http_client_peer_addr {
enum http_client_peer_addr_type type;
- const char *https_name; /* TLS SNI */
- struct ip_addr ip;
- in_port_t port;
+ union {
+ struct {
+ const char *https_name; /* TLS SNI */
+ struct ip_addr ip;
+ in_port_t port;
+ } tcp;
+ struct {
+ const char *path;
+ } un;
+ } a;
};
struct http_client_request {
struct http_url origin_url;
const char *username, *password;
+ const char *host_socket;
const struct http_url *host_url;
const char *authority;
struct http_client_peer {
struct http_client_peer_addr addr;
- char *https_name;
+ char *addr_name;
struct http_client *client;
struct http_client_peer *prev, *next;
char *name;
struct http_client_peer_addr addr;
- char *https_name;
+ char *addr_name;
/* current index in host->ips */
unsigned int ips_connect_idx;
/* active DNS lookup */
struct dns_lookup *dns_lookup;
+
+ unsigned int unix_local:1;
};
struct http_client {
struct connection_list *conn_list;
HASH_TABLE_TYPE(http_client_host) hosts;
+ struct http_client_host *unix_host;
struct http_client_host *hosts_list;
HASH_TABLE_TYPE(http_client_peer) peers;
struct http_client_peer *peers_list;
void http_client_request_unref(struct http_client_request **_req);
int http_client_request_delay_from_response(struct http_client_request *req,
const struct http_response *response);
+void http_client_request_get_peer_addr(const struct http_client_request *req,
+ struct http_client_peer_addr *addr);
enum http_response_payload_type
http_client_request_get_payload_type(struct http_client_request *req);
int http_client_request_send(struct http_client_request *req,
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)
{
- if (addr->ip.family == AF_INET6)
- return t_strdup_printf("[%s]:%u", net_ip2addr(&addr->ip), addr->port);
- return t_strdup_printf("%s:%u", net_ip2addr(&addr->ip), addr->port);
+ 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 *
return req->label;
}
-static inline void
-http_client_request_get_peer_addr(const struct http_client_request *req,
- struct http_client_peer_addr *addr)
-{
- const struct http_url *host_url = req->host_url;
-
- memset(addr, 0, sizeof(*addr));
- if (req->connect_direct) {
- addr->type = HTTP_CLIENT_PEER_ADDR_RAW;
- addr->port = (host_url->have_port ? host_url->port : HTTPS_DEFAULT_PORT);
- } else if (host_url->have_ssl) {
- if (req->ssl_tunnel)
- addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL;
- else
- addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS;
- addr->https_name = host_url->host_name;
- addr->port = (host_url->have_port ? host_url->port : HTTPS_DEFAULT_PORT);
- } else {
- addr->type = HTTP_CLIENT_PEER_ADDR_HTTP;
- addr->port = (host_url->have_port ? host_url->port : HTTP_DEFAULT_PORT);
- }
-}
-
static inline bool
http_client_request_to_proxy(const struct http_client_request *req)
{
array_foreach_modifiable(&host->queues, queue_idx) {
struct http_client_queue *queue = *queue_idx;
- if (queue->addr.type == addr->type && queue->addr.port == addr->port &&
- null_strcmp(queue->addr.https_name, addr->https_name) == 0)
+ if (http_client_peer_addr_cmp(&queue->addr, addr) == 0)
return queue;
}
queue = http_client_queue_find(host, addr);
if (queue == NULL) {
- char *name;
+ queue = i_new(struct http_client_queue, 1);
+ queue->client = host->client;
+ queue->host = host;
+ queue->addr = *addr;
switch (addr->type) {
case HTTP_CLIENT_PEER_ADDR_RAW:
- name = i_strdup_printf("raw://%s:%u", host->name, addr->port);
+ queue->name =
+ i_strdup_printf("raw://%s:%u", host->name, addr->a.tcp.port);
+ queue->addr.a.tcp.https_name = NULL;
break;
case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
case HTTP_CLIENT_PEER_ADDR_HTTPS:
- name = i_strdup_printf("https://%s:%u", host->name, addr->port);
+ queue->name =
+ i_strdup_printf("https://%s:%u", host->name, addr->a.tcp.port);
+ queue->addr_name = i_strdup(addr->a.tcp.https_name);
+ queue->addr.a.tcp.https_name = queue->addr_name;
break;
case HTTP_CLIENT_PEER_ADDR_HTTP:
- name = i_strdup_printf("http://%s:%u", host->name, addr->port);
+ queue->name =
+ i_strdup_printf("http://%s:%u", host->name, addr->a.tcp.port);
+ queue->addr.a.tcp.https_name = NULL;
+ break;
+ case HTTP_CLIENT_PEER_ADDR_UNIX:
+ queue->name = i_strdup_printf("unix:%s", addr->a.un.path);
+ queue->addr_name = i_strdup(addr->a.un.path);
+ queue->addr.a.un.path = queue->addr_name;
break;
default:
i_unreached();
}
- queue = i_new(struct http_client_queue, 1);
- queue->client = host->client;
- queue->host = host;
- queue->addr = *addr;
- queue->https_name = i_strdup(addr->https_name);
- queue->addr.https_name = queue->https_name;
- queue->name = name;
queue->ips_connect_idx = 0;
i_array_init(&queue->requests, 16);
i_array_init(&queue->queued_requests, 16);
{
http_client_queue_fail
(queue, HTTP_CLIENT_REQUEST_ERROR_ABORTED, "Aborted");
- i_free(queue->https_name);
if (array_is_created(&queue->pending_peers))
array_free(&queue->pending_peers);
array_free(&queue->requests);
timeout_remove(&queue->to_connect);
if (queue->to_delayed != NULL)
timeout_remove(&queue->to_delayed);
+ i_free(queue->addr_name);
i_free(queue->name);
i_free(queue);
}
&queue->client->set;
struct http_client_host *host = queue->host;
+ i_assert(queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX);
i_assert(queue->ips_connect_idx < host->ips_count);
i_assert(queue->ips_connect_start_idx < host->ips_count);
{
struct http_client_host *host = queue->host;
const struct http_client_peer_addr *addr = &queue->addr;
+ const char *https_name;
+
+ i_assert(queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX);
if (queue->to_connect != NULL)
timeout_remove(&queue->to_connect);
/* if our our previous connection attempt takes longer than the
soft_connect_timeout, we start a connection attempt to the next IP in
parallel */
+ https_name = http_client_peer_addr_get_https_name(addr);
http_client_queue_debug(queue, "Connection to %s%s is taking a long time; "
"starting parallel connection attempt to next IP",
- http_client_peer_addr2str(addr), addr->https_name == NULL ? "" :
- t_strdup_printf(" (SSL=%s)", addr->https_name));
+ http_client_peer_addr2str(addr), (https_name == NULL ? "" :
+ t_strdup_printf(" (SSL=%s)", https_name)));
/* next IP */
queue->ips_connect_idx = (queue->ips_connect_idx + 1) % host->ips_count;
unsigned int num_requests =
array_count(&queue->queued_requests) +
array_count(&queue->queued_urgent_requests);
+ const char *ssl = "";
if (num_requests == 0)
return;
/* update our peer address */
- i_assert(queue->ips_connect_idx < host->ips_count);
- queue->addr.ip = host->ips[queue->ips_connect_idx];
+ if (queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX) {
+ i_assert(queue->ips_connect_idx < host->ips_count);
+ queue->addr.a.tcp.ip = host->ips[queue->ips_connect_idx];
+ ssl = http_client_peer_addr_get_https_name(addr);
+ ssl = (ssl == NULL ? "" : t_strdup_printf(" (SSL=%s)", ssl));
+ }
http_client_queue_debug(queue, "Setting up connection to %s%s "
- "(%u requests pending)", http_client_peer_addr2str(addr),
- (addr->https_name == NULL ? "" :
- t_strdup_printf(" (SSL=%s)", addr->https_name)), num_requests);
+ "(%u requests pending)", http_client_peer_addr2str(addr), ssl,
+ num_requests);
/* create/get peer */
}
if (new_peer) {
http_client_queue_debug(queue, "Started new connection to %s%s",
- http_client_peer_addr2str(addr), (addr->https_name == NULL ? "" :
- t_strdup_printf(" (SSL=%s)", addr->https_name)));
+ http_client_peer_addr2str(addr), ssl);
array_append(&queue->pending_peers, &peer, 1);
queue->connect_attempts++;
}
/* start soft connect time-out (but only if we have another IP left) */
- msecs = host->client->set.soft_connect_timeout_msecs;
- if (!http_client_queue_is_last_connect_ip(queue) && msecs > 0 &&
- queue->to_connect == NULL) {
- queue->to_connect =
- timeout_add(msecs, http_client_queue_soft_connect_timeout, queue);
+ if (queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX) {
+ msecs = host->client->set.soft_connect_timeout_msecs;
+ if (!http_client_queue_is_last_connect_ip(queue) && msecs > 0 &&
+ queue->to_connect == NULL) {
+ queue->to_connect =
+ timeout_add(msecs, http_client_queue_soft_connect_timeout, queue);
+ }
}
}
}
http_client_queue_connection_success(struct http_client_queue *queue,
const struct http_client_peer_addr *addr)
{
- /* we achieved at least one connection the the addr->ip */
- queue->ips_connect_start_idx =
- http_client_host_get_ip_idx(queue->host, &addr->ip);
+ if (queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX) {
+ /* we achieved at least one connection the the addr->ip */
+ queue->ips_connect_start_idx =
+ http_client_host_get_ip_idx(queue->host, &addr->a.tcp.ip);
+ }
/* reset attempt counter */
queue->connect_attempts = 0;
{
const struct http_client_settings *set =
&queue->client->set;
+ const char *https_name = http_client_peer_addr_get_https_name(addr);
struct http_client_host *host = queue->host;
- http_client_queue_debug(queue, "Failed to set up connection to %s%s: %s "
+ http_client_queue_debug(queue,
+ "Failed to set up connection to %s%s: %s "
"(%u peers pending, %u requests pending)",
http_client_peer_addr2str(addr),
- (addr->https_name == NULL ? "" :
- t_strdup_printf(" (SSL=%s)", addr->https_name)), reason,
- (array_is_created(&queue->pending_peers) ?
+ (https_name == NULL ? "" :
+ t_strdup_printf(" (SSL=%s)", https_name)),
+ reason, (array_is_created(&queue->pending_peers) ?
array_count(&queue->pending_peers): 0),
array_count(&queue->requests));
if (queue->to_connect != NULL)
timeout_remove(&queue->to_connect);
+ if (queue->addr.type == HTTP_CLIENT_PEER_ADDR_UNIX) {
+ http_client_queue_fail(queue,
+ HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, reason);
+ return;
+ }
+
if (http_client_queue_is_last_connect_ip(queue)) {
/* all IPs failed, but retry all of them again if we have more
connect attempts left or on the next request. */
{
struct http_client *client = req->client;
struct http_client_host *host;
+ const char *proxy_socket_path = client->set.proxy_socket_path;
const struct http_url *proxy_url = client->set.proxy_url;
+ bool have_proxy = (proxy_socket_path != NULL) || (proxy_url != NULL);
const char *authority, *target;
i_assert(req->state == HTTP_REQUEST_STATE_NEW);
}
/* determine what host to contact to submit this request */
- if (proxy_url != NULL) {
+ if (have_proxy) {
if (req->origin_url.have_ssl && !client->set.no_ssl_tunnel &&
!req->connect_tunnel) {
- req->host_url = &req->origin_url; /* tunnel to origin server */
+ req->host_url = &req->origin_url; /* tunnel to origin server */
req->ssl_tunnel = TRUE;
+ } else if (proxy_socket_path != NULL) {
+ req->host_socket = proxy_socket_path; /* proxy on unix socket */
+ req->host_url = NULL;
} else {
- req->host_url = proxy_url; /* proxy server */
+ req->host_url = proxy_url; /* normal proxy server */
+ req->host_socket = NULL;
}
} else {
- req->host_url = &req->origin_url; /* origin server */
+ req->host_url = &req->origin_url; /* origin server */
}
/* use submission date if no date is set explicitly */
req->label = p_strdup_printf(req->pool, "[%s %s]", req->method, target);
/* update request target */
- if (req->connect_tunnel || proxy_url != NULL)
+ if (req->connect_tunnel || have_proxy)
req->target = p_strdup(req->pool, target);
- if (proxy_url == NULL) {
+ if (!have_proxy) {
/* if we don't have a proxy, CONNECT requests are handled by creating
the requested connection directly */
req->connect_direct = req->connect_tunnel;
client->requests_count++;
}
+void
+http_client_request_get_peer_addr(const struct http_client_request *req,
+ struct http_client_peer_addr *addr)
+{
+ const char *host_socket = req->host_socket;
+ const struct http_url *host_url = req->host_url;
+
+ memset(addr, 0, sizeof(*addr));
+ if (host_socket != NULL) {
+ addr->type = HTTP_CLIENT_PEER_ADDR_UNIX;
+ addr->a.un.path = host_socket;
+ } else if (req->connect_direct) {
+ addr->type = HTTP_CLIENT_PEER_ADDR_RAW;
+ addr->a.tcp.port =
+ (host_url->have_port ? host_url->port : HTTPS_DEFAULT_PORT);
+ } else if (host_url->have_ssl) {
+ if (req->ssl_tunnel)
+ addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL;
+ else
+ addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS;
+ addr->a.tcp.https_name = host_url->host_name;
+ addr->a.tcp.port =
+ (host_url->have_port ? host_url->port : HTTPS_DEFAULT_PORT);
+ } else {
+ addr->type = HTTP_CLIENT_PEER_ADDR_HTTP;
+ addr->a.tcp.port =
+ (host_url->have_port ? host_url->port : HTTP_DEFAULT_PORT);
+ }
+}
+
static void
http_client_request_finish_payload_out(struct http_client_request *req)
{
/* User-Agent: header (default: none) */
const char *user_agent;
- /* configuration for using a proxy */
- const char *proxy_socket_path; /* FIXME: implement */
+ /* proxy on unix socket */
+ const char *proxy_socket_path;
+ /* URL for normal proxy (ignored if proxy_socket_path is set) */
const struct http_url *proxy_url;
+ /* credentials for proxy */
const char *proxy_username;
const char *proxy_password;