MEDIUM: httpclient: allow to use another proxy
httpclient_new_from_proxy() is a variant of httpclient_new() which allows to create the requests from a different proxy. The proxy and its 2 servers are now stored in the httpclient structure. The proxy must have been created with httpclient_create_proxy() to be used. The httpclient_postcheck() callback will finish the initialization of all proxies created with PR_CAP_HTTPCLIENT.
This commit is contained in:
parent
54aec5f678
commit
992ad62e3c
@ -32,6 +32,11 @@ struct httpclient {
|
|||||||
int timeout_server; /* server timeout in ms */
|
int timeout_server; /* server timeout in ms */
|
||||||
void *caller; /* ptr of the caller */
|
void *caller; /* ptr of the caller */
|
||||||
unsigned int flags; /* other flags */
|
unsigned int flags; /* other flags */
|
||||||
|
struct proxy *px; /* proxy for special cases */
|
||||||
|
struct server *srv_raw; /* server for clear connections */
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
struct server *srv_ssl; /* server for SSL connections */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Action (FA) to do */
|
/* Action (FA) to do */
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
void httpclient_destroy(struct httpclient *hc);
|
void httpclient_destroy(struct httpclient *hc);
|
||||||
void httpclient_stop_and_destroy(struct httpclient *hc);
|
void httpclient_stop_and_destroy(struct httpclient *hc);
|
||||||
struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url);
|
struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url);
|
||||||
|
struct httpclient *httpclient_new_from_proxy(struct proxy *px, void *caller, enum http_meth_t meth, struct ist url);
|
||||||
|
int httpclient_set_proxy(struct httpclient *hc, struct proxy *px);
|
||||||
|
|
||||||
struct appctx *httpclient_start(struct httpclient *hc);
|
struct appctx *httpclient_start(struct httpclient *hc);
|
||||||
int httpclient_set_dst(struct httpclient *hc, const char *dst);
|
int httpclient_set_dst(struct httpclient *hc, const char *dst);
|
||||||
|
@ -610,6 +610,8 @@ void httpclient_destroy(struct httpclient *hc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate an httpclient and its buffers
|
/* Allocate an httpclient and its buffers
|
||||||
|
* Use the default httpclient_proxy
|
||||||
|
*
|
||||||
* Return NULL on failure */
|
* Return NULL on failure */
|
||||||
struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url)
|
struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url)
|
||||||
{
|
{
|
||||||
@ -624,6 +626,7 @@ struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct is
|
|||||||
hc->caller = caller;
|
hc->caller = caller;
|
||||||
hc->req.url = istdup(url);
|
hc->req.url = istdup(url);
|
||||||
hc->req.meth = meth;
|
hc->req.meth = meth;
|
||||||
|
httpclient_set_proxy(hc, httpclient_proxy);
|
||||||
|
|
||||||
return hc;
|
return hc;
|
||||||
|
|
||||||
@ -632,6 +635,49 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate an httpclient and its buffers,
|
||||||
|
* Use the proxy <px>
|
||||||
|
*
|
||||||
|
* Return and httpclient or NULL.
|
||||||
|
*/
|
||||||
|
struct httpclient *httpclient_new_from_proxy(struct proxy *px, void *caller, enum http_meth_t meth, struct ist url)
|
||||||
|
{
|
||||||
|
struct httpclient *hc;
|
||||||
|
|
||||||
|
hc = httpclient_new(caller, meth, url);
|
||||||
|
if (!hc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
httpclient_set_proxy(hc, px);
|
||||||
|
|
||||||
|
return hc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure an httpclient with a specific proxy <px>
|
||||||
|
*
|
||||||
|
* The proxy <px> must contains 2 srv, one configured for clear connections, the other for SSL.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int httpclient_set_proxy(struct httpclient *hc, struct proxy *px)
|
||||||
|
{
|
||||||
|
struct server *srv;
|
||||||
|
|
||||||
|
hc->px = px;
|
||||||
|
|
||||||
|
for (srv = px->srv; srv != NULL; srv = srv->next) {
|
||||||
|
if (srv->xprt == xprt_get(XPRT_RAW)) {
|
||||||
|
hc->srv_raw = srv;
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
} else if (srv->xprt == xprt_get(XPRT_SSL)) {
|
||||||
|
hc->srv_ssl = srv;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void httpclient_applet_io_handler(struct appctx *appctx)
|
static void httpclient_applet_io_handler(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
struct httpclient *hc = appctx->svcctx;
|
struct httpclient *hc = appctx->svcctx;
|
||||||
@ -974,12 +1020,12 @@ static int httpclient_applet_init(struct appctx *appctx)
|
|||||||
/* choose the SSL server or not */
|
/* choose the SSL server or not */
|
||||||
switch (scheme) {
|
switch (scheme) {
|
||||||
case SCH_HTTP:
|
case SCH_HTTP:
|
||||||
target = &httpclient_srv_raw->obj_type;
|
target = &hc->srv_raw->obj_type;
|
||||||
break;
|
break;
|
||||||
case SCH_HTTPS:
|
case SCH_HTTPS:
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (httpclient_srv_ssl) {
|
if (hc->srv_ssl) {
|
||||||
target = &httpclient_srv_ssl->obj_type;
|
target = &hc->srv_ssl->obj_type;
|
||||||
} else {
|
} else {
|
||||||
ha_alert("httpclient: SSL was disabled (wrong verify/ca-file)!\n");
|
ha_alert("httpclient: SSL was disabled (wrong verify/ca-file)!\n");
|
||||||
goto out_free_addr;
|
goto out_free_addr;
|
||||||
@ -991,7 +1037,7 @@ static int httpclient_applet_init(struct appctx *appctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appctx_finalize_startup(appctx, httpclient_proxy, &hc->req.buf) == -1) {
|
if (appctx_finalize_startup(appctx, hc->px, &hc->req.buf) == -1) {
|
||||||
ha_alert("httpclient: Failed to initialize appctx %s:%d.\n", __FUNCTION__, __LINE__);
|
ha_alert("httpclient: Failed to initialize appctx %s:%d.\n", __FUNCTION__, __LINE__);
|
||||||
goto out_free_addr;
|
goto out_free_addr;
|
||||||
}
|
}
|
||||||
@ -1301,53 +1347,71 @@ static int httpclient_postcheck()
|
|||||||
{
|
{
|
||||||
int err_code = ERR_NONE;
|
int err_code = ERR_NONE;
|
||||||
struct logsrv *logsrv;
|
struct logsrv *logsrv;
|
||||||
struct proxy *curproxy = httpclient_proxy;
|
struct proxy *curproxy = NULL;
|
||||||
char *errmsg = NULL;
|
char *errmsg = NULL;
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
struct server *srv = NULL;
|
||||||
|
struct server *srv_ssl = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (global.mode & MODE_MWORKER_WAIT)
|
if (global.mode & MODE_MWORKER_WAIT)
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
|
|
||||||
/* copy logs from "global" log list */
|
/* Initialize the logs for every proxy dedicated to the httpclient */
|
||||||
list_for_each_entry(logsrv, &global.logsrvs, list) {
|
for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
|
||||||
struct logsrv *node = malloc(sizeof(*node));
|
|
||||||
|
|
||||||
if (!node) {
|
if (!(curproxy->cap & PR_CAP_HTTPCLIENT))
|
||||||
memprintf(&errmsg, "out of memory.");
|
continue;
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(node, logsrv, sizeof(*node));
|
/* copy logs from "global" log list */
|
||||||
LIST_INIT(&node->list);
|
list_for_each_entry(logsrv, &global.logsrvs, list) {
|
||||||
LIST_APPEND(&curproxy->logsrvs, &node->list);
|
struct logsrv *node = malloc(sizeof(*node));
|
||||||
node->ring_name = logsrv->ring_name ? strdup(logsrv->ring_name) : NULL;
|
|
||||||
node->conf.file = logsrv->conf.file ? strdup(logsrv->conf.file) : NULL;
|
if (!node) {
|
||||||
}
|
memprintf(&errmsg, "out of memory.");
|
||||||
if (curproxy->conf.logformat_string) {
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
curproxy->conf.args.ctx = ARGC_LOG;
|
goto err;
|
||||||
if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat,
|
}
|
||||||
LOG_OPT_MANDATORY|LOG_OPT_MERGE_SPACES,
|
|
||||||
SMP_VAL_FE_LOG_END, &errmsg)) {
|
memcpy(node, logsrv, sizeof(*node));
|
||||||
memprintf(&errmsg, "failed to parse log-format : %s.", errmsg);
|
LIST_INIT(&node->list);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
LIST_APPEND(&curproxy->logsrvs, &node->list);
|
||||||
goto err;
|
node->ring_name = logsrv->ring_name ? strdup(logsrv->ring_name) : NULL;
|
||||||
|
node->conf.file = logsrv->conf.file ? strdup(logsrv->conf.file) : NULL;
|
||||||
|
}
|
||||||
|
if (curproxy->conf.logformat_string) {
|
||||||
|
curproxy->conf.args.ctx = ARGC_LOG;
|
||||||
|
if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat,
|
||||||
|
LOG_OPT_MANDATORY|LOG_OPT_MERGE_SPACES,
|
||||||
|
SMP_VAL_FE_LOG_END, &errmsg)) {
|
||||||
|
memprintf(&errmsg, "failed to parse log-format : %s.", errmsg);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
curproxy->conf.args.file = NULL;
|
||||||
|
curproxy->conf.args.line = 0;
|
||||||
}
|
}
|
||||||
curproxy->conf.args.file = NULL;
|
|
||||||
curproxy->conf.args.line = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (httpclient_srv_ssl) {
|
/* initialize the SNI for the SSL servers */
|
||||||
/* init the SNI expression */
|
|
||||||
/* always use the host header as SNI, without the port */
|
for (srv = curproxy->srv; srv != NULL; srv = srv->next) {
|
||||||
httpclient_srv_ssl->sni_expr = strdup("req.hdr(host),field(1,:)");
|
if (srv->xprt == xprt_get(XPRT_SSL)) {
|
||||||
err_code |= server_parse_sni_expr(httpclient_srv_ssl, httpclient_proxy, &errmsg);
|
srv_ssl = srv;
|
||||||
if (err_code & ERR_CODE) {
|
}
|
||||||
memprintf(&errmsg, "failed to configure sni: %s.", errmsg);
|
}
|
||||||
goto err;
|
if (srv_ssl) {
|
||||||
|
/* init the SNI expression */
|
||||||
|
/* always use the host header as SNI, without the port */
|
||||||
|
srv_ssl->sni_expr = strdup("req.hdr(host),field(1,:)");
|
||||||
|
err_code |= server_parse_sni_expr(srv_ssl, curproxy, &errmsg);
|
||||||
|
if (err_code & ERR_CODE) {
|
||||||
|
memprintf(&errmsg, "failed to configure sni: %s.", errmsg);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (err_code & ERR_CODE) {
|
if (err_code & ERR_CODE) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user