mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-21 05:00:42 +00:00
[MEDIUM] rename process_request to http_process_request
Now the function only does HTTP request and nothing else. Also pass the request buffer to it.
This commit is contained in:
parent
d34af78a34
commit
59234e91c2
@ -62,7 +62,7 @@ void process_session(struct task *t, int *next);
|
|||||||
int process_cli(struct session *t);
|
int process_cli(struct session *t);
|
||||||
int process_srv_data(struct session *t);
|
int process_srv_data(struct session *t);
|
||||||
int process_srv_conn(struct session *t);
|
int process_srv_conn(struct session *t);
|
||||||
int process_request(struct session *t);
|
int http_process_request(struct session *t, struct buffer *req);
|
||||||
int http_process_tarpit(struct session *s, struct buffer *req);
|
int http_process_tarpit(struct session *s, struct buffer *req);
|
||||||
int http_process_request_body(struct session *s, struct buffer *req);
|
int http_process_request_body(struct session *s, struct buffer *req);
|
||||||
int process_response(struct session *t);
|
int process_response(struct session *t);
|
||||||
|
287
src/proto_http.c
287
src/proto_http.c
@ -1563,22 +1563,20 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
|
|||||||
* called after XXX bytes have been received (or transfered), and the min of
|
* called after XXX bytes have been received (or transfered), and the min of
|
||||||
* all's wishes will be used to ring back (unless a special condition occurs).
|
* all's wishes will be used to ring back (unless a special condition occurs).
|
||||||
*/
|
*/
|
||||||
int process_request(struct session *t)
|
int http_process_request(struct session *s, struct buffer *req)
|
||||||
{
|
{
|
||||||
struct buffer *req = t->req;
|
|
||||||
|
|
||||||
DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
|
DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
|
||||||
now_ms, __FUNCTION__,
|
now_ms, __FUNCTION__,
|
||||||
t,
|
s,
|
||||||
req,
|
req,
|
||||||
req->rex, req->wex,
|
req->rex, req->wex,
|
||||||
req->flags,
|
req->flags,
|
||||||
req->l,
|
req->l,
|
||||||
req->analysers);
|
req->analysers);
|
||||||
|
|
||||||
if (req->analysers & AN_REQ_HTTP_HDR) {
|
|
||||||
/*
|
/*
|
||||||
* Now parse the partial (or complete) lines.
|
* We will parse the partial (or complete) lines.
|
||||||
* We will check the request syntax, and also join multi-line
|
* We will check the request syntax, and also join multi-line
|
||||||
* headers. An index of all the lines will be elaborated while
|
* headers. An index of all the lines will be elaborated while
|
||||||
* parsing.
|
* parsing.
|
||||||
@ -1594,7 +1592,7 @@ int process_request(struct session *t)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int cur_idx;
|
int cur_idx;
|
||||||
struct http_txn *txn = &t->txn;
|
struct http_txn *txn = &s->txn;
|
||||||
struct http_msg *msg = &txn->req;
|
struct http_msg *msg = &txn->req;
|
||||||
struct proxy *cur_proxy;
|
struct proxy *cur_proxy;
|
||||||
|
|
||||||
@ -1609,14 +1607,14 @@ int process_request(struct session *t)
|
|||||||
|
|
||||||
sol = req->data + msg->som;
|
sol = req->data + msg->som;
|
||||||
eol = sol + msg->sl.rq.l;
|
eol = sol + msg->sl.rq.l;
|
||||||
debug_hdr("clireq", t, sol, eol);
|
debug_hdr("clireq", s, sol, eol);
|
||||||
|
|
||||||
sol += hdr_idx_first_pos(&txn->hdr_idx);
|
sol += hdr_idx_first_pos(&txn->hdr_idx);
|
||||||
cur_idx = hdr_idx_first_idx(&txn->hdr_idx);
|
cur_idx = hdr_idx_first_idx(&txn->hdr_idx);
|
||||||
|
|
||||||
while (cur_idx) {
|
while (cur_idx) {
|
||||||
eol = sol + txn->hdr_idx.v[cur_idx].len;
|
eol = sol + txn->hdr_idx.v[cur_idx].len;
|
||||||
debug_hdr("clihdr", t, sol, eol);
|
debug_hdr("clihdr", s, sol, eol);
|
||||||
sol = eol + txn->hdr_idx.v[cur_idx].cr + 1;
|
sol = eol + txn->hdr_idx.v[cur_idx].cr + 1;
|
||||||
cur_idx = txn->hdr_idx.v[cur_idx].next;
|
cur_idx = txn->hdr_idx.v[cur_idx].next;
|
||||||
}
|
}
|
||||||
@ -1656,11 +1654,11 @@ int process_request(struct session *t)
|
|||||||
/* we cannot return any message on error */
|
/* we cannot return any message on error */
|
||||||
msg->msg_state = HTTP_MSG_ERROR;
|
msg->msg_state = HTTP_MSG_ERROR;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
//t->fe->failed_req++;
|
s->fe->failed_req++;
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
s->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
t->flags |= SN_FINST_R;
|
s->flags |= SN_FINST_R;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1668,36 +1666,36 @@ int process_request(struct session *t)
|
|||||||
else if (req->flags & BF_READ_TIMEOUT || tick_is_expired(req->analyse_exp, now_ms)) {
|
else if (req->flags & BF_READ_TIMEOUT || tick_is_expired(req->analyse_exp, now_ms)) {
|
||||||
/* read timeout : give up with an error message. */
|
/* read timeout : give up with an error message. */
|
||||||
txn->status = 408;
|
txn->status = 408;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_408));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_408));
|
||||||
msg->msg_state = HTTP_MSG_ERROR;
|
msg->msg_state = HTTP_MSG_ERROR;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
t->fe->failed_req++;
|
s->fe->failed_req++;
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLITO;
|
s->flags |= SN_ERR_CLITO;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
t->flags |= SN_FINST_R;
|
s->flags |= SN_FINST_R;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4: have we encountered a close ? */
|
/* 4: have we encountered a close ? */
|
||||||
else if (req->flags & BF_SHUTR) {
|
else if (req->flags & BF_SHUTR) {
|
||||||
txn->status = 400;
|
txn->status = 400;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_400));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
|
||||||
msg->msg_state = HTTP_MSG_ERROR;
|
msg->msg_state = HTTP_MSG_ERROR;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
t->fe->failed_req++;
|
s->fe->failed_req++;
|
||||||
|
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
s->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
t->flags |= SN_FINST_R;
|
s->flags |= SN_FINST_R;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_write_dis(req);
|
buffer_write_dis(req);
|
||||||
/* just set the request timeout once at the beginning of the request */
|
/* just set the request timeout once at the beginning of the request */
|
||||||
if (!tick_isset(req->analyse_exp))
|
if (!tick_isset(req->analyse_exp))
|
||||||
req->analyse_exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq);
|
req->analyse_exp = tick_add_ifset(now_ms, s->fe->timeout.httpreq);
|
||||||
|
|
||||||
/* we're not ready yet */
|
/* we're not ready yet */
|
||||||
return 0;
|
return 0;
|
||||||
@ -1723,29 +1721,29 @@ int process_request(struct session *t)
|
|||||||
|
|
||||||
/* we can make use of server redirect on GET and HEAD */
|
/* we can make use of server redirect on GET and HEAD */
|
||||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||||
t->flags |= SN_REDIRECTABLE;
|
s->flags |= SN_REDIRECTABLE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2: check if the URI matches the monitor_uri.
|
* 2: check if the URI matches the monitor_uri.
|
||||||
* We have to do this for every request which gets in, because
|
* We have to do this for every request which gets in, because
|
||||||
* the monitor-uri is defined by the frontend.
|
* the monitor-uri is defined by the frontend.
|
||||||
*/
|
*/
|
||||||
if (unlikely((t->fe->monitor_uri_len != 0) &&
|
if (unlikely((s->fe->monitor_uri_len != 0) &&
|
||||||
(t->fe->monitor_uri_len == msg->sl.rq.u_l) &&
|
(s->fe->monitor_uri_len == msg->sl.rq.u_l) &&
|
||||||
!memcmp(&req->data[msg->sl.rq.u],
|
!memcmp(&req->data[msg->sl.rq.u],
|
||||||
t->fe->monitor_uri,
|
s->fe->monitor_uri,
|
||||||
t->fe->monitor_uri_len))) {
|
s->fe->monitor_uri_len))) {
|
||||||
/*
|
/*
|
||||||
* We have found the monitor URI
|
* We have found the monitor URI
|
||||||
*/
|
*/
|
||||||
struct acl_cond *cond;
|
struct acl_cond *cond;
|
||||||
cur_proxy = t->fe;
|
cur_proxy = s->fe;
|
||||||
|
|
||||||
t->flags |= SN_MONITOR;
|
s->flags |= SN_MONITOR;
|
||||||
|
|
||||||
/* Check if we want to fail this monitor request or not */
|
/* Check if we want to fail this monitor request or not */
|
||||||
list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
|
list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
|
||||||
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ);
|
int ret = acl_exec_cond(cond, cur_proxy, s, txn, ACL_DIR_REQ);
|
||||||
|
|
||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (cond->pol == ACL_COND_UNLESS)
|
if (cond->pol == ACL_COND_UNLESS)
|
||||||
@ -1754,7 +1752,7 @@ int process_request(struct session *t)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
/* we fail this request, let's return 503 service unavail */
|
/* we fail this request, let's return 503 service unavail */
|
||||||
txn->status = 503;
|
txn->status = 503;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_503));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_503));
|
||||||
goto return_prx_cond;
|
goto return_prx_cond;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1770,7 +1768,7 @@ int process_request(struct session *t)
|
|||||||
* Note: we cannot log anymore if the request has been
|
* Note: we cannot log anymore if the request has been
|
||||||
* classified as invalid.
|
* classified as invalid.
|
||||||
*/
|
*/
|
||||||
if (unlikely(t->logs.logwait & LW_REQ)) {
|
if (unlikely(s->logs.logwait & LW_REQ)) {
|
||||||
/* we have a complete HTTP request that we must log */
|
/* we have a complete HTTP request that we must log */
|
||||||
if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) {
|
if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) {
|
||||||
int urilen = msg->sl.rq.l;
|
int urilen = msg->sl.rq.l;
|
||||||
@ -1780,14 +1778,13 @@ int process_request(struct session *t)
|
|||||||
memcpy(txn->uri, &req->data[msg->som], urilen);
|
memcpy(txn->uri, &req->data[msg->som], urilen);
|
||||||
txn->uri[urilen] = 0;
|
txn->uri[urilen] = 0;
|
||||||
|
|
||||||
if (!(t->logs.logwait &= ~LW_REQ))
|
if (!(s->logs.logwait &= ~LW_REQ))
|
||||||
t->do_log(t);
|
s->do_log(s);
|
||||||
} else {
|
} else {
|
||||||
Alert("HTTP logging : out of memory.\n");
|
Alert("HTTP logging : out of memory.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 4. We may have to convert HTTP/0.9 requests to HTTP/1.0 */
|
/* 4. We may have to convert HTTP/0.9 requests to HTTP/1.0 */
|
||||||
if (unlikely(msg->sl.rq.v_l == 0)) {
|
if (unlikely(msg->sl.rq.v_l == 0)) {
|
||||||
int delta;
|
int delta;
|
||||||
@ -1821,9 +1818,9 @@ int process_request(struct session *t)
|
|||||||
|
|
||||||
|
|
||||||
/* 5: we may need to capture headers */
|
/* 5: we may need to capture headers */
|
||||||
if (unlikely((t->logs.logwait & LW_REQHDR) && t->fe->req_cap))
|
if (unlikely((s->logs.logwait & LW_REQHDR) && s->fe->req_cap))
|
||||||
capture_headers(req->data + msg->som, &txn->hdr_idx,
|
capture_headers(req->data + msg->som, &txn->hdr_idx,
|
||||||
txn->req.cap, t->fe->req_cap);
|
txn->req.cap, s->fe->req_cap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 6: we will have to evaluate the filters.
|
* 6: we will have to evaluate the filters.
|
||||||
@ -1852,12 +1849,12 @@ int process_request(struct session *t)
|
|||||||
do {
|
do {
|
||||||
struct acl_cond *cond;
|
struct acl_cond *cond;
|
||||||
struct redirect_rule *rule;
|
struct redirect_rule *rule;
|
||||||
struct proxy *rule_set = t->be;
|
struct proxy *rule_set = s->be;
|
||||||
cur_proxy = t->be;
|
cur_proxy = s->be;
|
||||||
|
|
||||||
/* first check whether we have some ACLs set to redirect this request */
|
/* first check whether we have some ACLs set to redirect this request */
|
||||||
list_for_each_entry(rule, &cur_proxy->redirect_rules, list) {
|
list_for_each_entry(rule, &cur_proxy->redirect_rules, list) {
|
||||||
int ret = acl_exec_cond(rule->cond, cur_proxy, t, txn, ACL_DIR_REQ);
|
int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
|
||||||
|
|
||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||||
@ -1931,7 +1928,7 @@ int process_request(struct session *t)
|
|||||||
|
|
||||||
txn->status = rule->code;
|
txn->status = rule->code;
|
||||||
/* let's log the request time */
|
/* let's log the request time */
|
||||||
t->logs.tv_request = now;
|
s->logs.tv_request = now;
|
||||||
stream_int_retnclose(req->prod, &rdr);
|
stream_int_retnclose(req->prod, &rdr);
|
||||||
goto return_prx_cond;
|
goto return_prx_cond;
|
||||||
}
|
}
|
||||||
@ -1939,7 +1936,7 @@ int process_request(struct session *t)
|
|||||||
|
|
||||||
/* first check whether we have some ACLs set to block this request */
|
/* first check whether we have some ACLs set to block this request */
|
||||||
list_for_each_entry(cond, &cur_proxy->block_cond, list) {
|
list_for_each_entry(cond, &cur_proxy->block_cond, list) {
|
||||||
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ);
|
int ret = acl_exec_cond(cond, cur_proxy, s, txn, ACL_DIR_REQ);
|
||||||
|
|
||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (cond->pol == ACL_COND_UNLESS)
|
if (cond->pol == ACL_COND_UNLESS)
|
||||||
@ -1948,28 +1945,28 @@ int process_request(struct session *t)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
txn->status = 403;
|
txn->status = 403;
|
||||||
/* let's log the request time */
|
/* let's log the request time */
|
||||||
t->logs.tv_request = now;
|
s->logs.tv_request = now;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_403));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
|
||||||
goto return_prx_cond;
|
goto return_prx_cond;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try headers filters */
|
/* try headers filters */
|
||||||
if (rule_set->req_exp != NULL) {
|
if (rule_set->req_exp != NULL) {
|
||||||
if (apply_filters_to_request(t, req, rule_set->req_exp) < 0)
|
if (apply_filters_to_request(s, req, rule_set->req_exp) < 0)
|
||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(t->flags & SN_BE_ASSIGNED) && (t->be != cur_proxy)) {
|
if (!(s->flags & SN_BE_ASSIGNED) && (s->be != cur_proxy)) {
|
||||||
/* to ensure correct connection accounting on
|
/* to ensure correct connection accounting on
|
||||||
* the backend, we count the connection for the
|
* the backend, we count the connection for the
|
||||||
* one managing the queue.
|
* one managing the queue.
|
||||||
*/
|
*/
|
||||||
t->be->beconn++;
|
s->be->beconn++;
|
||||||
if (t->be->beconn > t->be->beconn_max)
|
if (s->be->beconn > s->be->beconn_max)
|
||||||
t->be->beconn_max = t->be->beconn;
|
s->be->beconn_max = s->be->beconn;
|
||||||
t->be->cum_beconn++;
|
s->be->cum_beconn++;
|
||||||
t->flags |= SN_BE_ASSIGNED;
|
s->flags |= SN_BE_ASSIGNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* has the request been denied ? */
|
/* has the request been denied ? */
|
||||||
@ -1977,14 +1974,14 @@ int process_request(struct session *t)
|
|||||||
/* no need to go further */
|
/* no need to go further */
|
||||||
txn->status = 403;
|
txn->status = 403;
|
||||||
/* let's log the request time */
|
/* let's log the request time */
|
||||||
t->logs.tv_request = now;
|
s->logs.tv_request = now;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_403));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
|
||||||
goto return_prx_cond;
|
goto return_prx_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We might have to check for "Connection:" */
|
/* We might have to check for "Connection:" */
|
||||||
if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) &&
|
if (((s->fe->options | s->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) &&
|
||||||
!(t->flags & SN_CONN_CLOSED)) {
|
!(s->flags & SN_CONN_CLOSED)) {
|
||||||
char *cur_ptr, *cur_end, *cur_next;
|
char *cur_ptr, *cur_end, *cur_next;
|
||||||
int cur_idx, old_idx, delta, val;
|
int cur_idx, old_idx, delta, val;
|
||||||
struct hdr_idx_elem *cur_hdr;
|
struct hdr_idx_elem *cur_hdr;
|
||||||
@ -2010,7 +2007,7 @@ int process_request(struct session *t)
|
|||||||
* and this line indicates non-close. We
|
* and this line indicates non-close. We
|
||||||
* replace it.
|
* replace it.
|
||||||
*/
|
*/
|
||||||
if (t->flags & SN_CONN_CLOSED) {
|
if (s->flags & SN_CONN_CLOSED) {
|
||||||
delta = buffer_replace2(req, cur_ptr, cur_next, NULL, 0);
|
delta = buffer_replace2(req, cur_ptr, cur_next, NULL, 0);
|
||||||
txn->req.eoh += delta;
|
txn->req.eoh += delta;
|
||||||
cur_next += delta;
|
cur_next += delta;
|
||||||
@ -2025,7 +2022,7 @@ int process_request(struct session *t)
|
|||||||
cur_hdr->len += delta;
|
cur_hdr->len += delta;
|
||||||
txn->req.eoh += delta;
|
txn->req.eoh += delta;
|
||||||
}
|
}
|
||||||
t->flags |= SN_CONN_CLOSED;
|
s->flags |= SN_CONN_CLOSED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
old_idx = cur_idx;
|
old_idx = cur_idx;
|
||||||
@ -2047,71 +2044,71 @@ int process_request(struct session *t)
|
|||||||
* FIXME!!! that one is rather dangerous, we want to
|
* FIXME!!! that one is rather dangerous, we want to
|
||||||
* make it follow standard rules (eg: clear req->analysers).
|
* make it follow standard rules (eg: clear req->analysers).
|
||||||
*/
|
*/
|
||||||
if (stats_check_uri_auth(t, rule_set)) {
|
if (stats_check_uri_auth(s, rule_set)) {
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now check whether we have some switching rules for this request */
|
/* now check whether we have some switching rules for this request */
|
||||||
if (!(t->flags & SN_BE_ASSIGNED)) {
|
if (!(s->flags & SN_BE_ASSIGNED)) {
|
||||||
struct switching_rule *rule;
|
struct switching_rule *rule;
|
||||||
|
|
||||||
list_for_each_entry(rule, &cur_proxy->switching_rules, list) {
|
list_for_each_entry(rule, &cur_proxy->switching_rules, list) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = acl_exec_cond(rule->cond, cur_proxy, t, txn, ACL_DIR_REQ);
|
ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
|
||||||
|
|
||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||||
ret = !ret;
|
ret = !ret;
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
t->be = rule->be.backend;
|
s->be = rule->be.backend;
|
||||||
t->be->beconn++;
|
s->be->beconn++;
|
||||||
if (t->be->beconn > t->be->beconn_max)
|
if (s->be->beconn > s->be->beconn_max)
|
||||||
t->be->beconn_max = t->be->beconn;
|
s->be->beconn_max = s->be->beconn;
|
||||||
t->be->cum_beconn++;
|
s->be->cum_beconn++;
|
||||||
|
|
||||||
/* assign new parameters to the session from the new backend */
|
/* assign new parameters to the session from the new backend */
|
||||||
t->rep->rto = t->req->wto = t->be->timeout.server;
|
s->rep->rto = s->req->wto = s->be->timeout.server;
|
||||||
t->req->cto = t->be->timeout.connect;
|
s->req->cto = s->be->timeout.connect;
|
||||||
t->conn_retries = t->be->conn_retries;
|
s->conn_retries = s->be->conn_retries;
|
||||||
t->flags |= SN_BE_ASSIGNED;
|
s->flags |= SN_BE_ASSIGNED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(t->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) {
|
if (!(s->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) {
|
||||||
/* No backend was set, but there was a default
|
/* No backend was set, but there was a default
|
||||||
* backend set in the frontend, so we use it and
|
* backend set in the frontend, so we use it and
|
||||||
* loop again.
|
* loop again.
|
||||||
*/
|
*/
|
||||||
t->be = cur_proxy->defbe.be;
|
s->be = cur_proxy->defbe.be;
|
||||||
t->be->beconn++;
|
s->be->beconn++;
|
||||||
if (t->be->beconn > t->be->beconn_max)
|
if (s->be->beconn > s->be->beconn_max)
|
||||||
t->be->beconn_max = t->be->beconn;
|
s->be->beconn_max = s->be->beconn;
|
||||||
t->be->cum_beconn++;
|
s->be->cum_beconn++;
|
||||||
|
|
||||||
/* assign new parameters to the session from the new backend */
|
/* assign new parameters to the session from the new backend */
|
||||||
t->rep->rto = t->req->wto = t->be->timeout.server;
|
s->rep->rto = s->req->wto = s->be->timeout.server;
|
||||||
t->req->cto = t->be->timeout.connect;
|
s->req->cto = s->be->timeout.connect;
|
||||||
t->conn_retries = t->be->conn_retries;
|
s->conn_retries = s->be->conn_retries;
|
||||||
t->flags |= SN_BE_ASSIGNED;
|
s->flags |= SN_BE_ASSIGNED;
|
||||||
}
|
}
|
||||||
} while (t->be != cur_proxy); /* we loop only if t->be has changed */
|
} while (s->be != cur_proxy); /* we loop only if s->be has changed */
|
||||||
|
|
||||||
if (!(t->flags & SN_BE_ASSIGNED)) {
|
if (!(s->flags & SN_BE_ASSIGNED)) {
|
||||||
/* To ensure correct connection accounting on
|
/* To ensure correct connection accounting on
|
||||||
* the backend, we count the connection for the
|
* the backend, we count the connection for the
|
||||||
* one managing the queue.
|
* one managing the queue.
|
||||||
*/
|
*/
|
||||||
t->be->beconn++;
|
s->be->beconn++;
|
||||||
if (t->be->beconn > t->be->beconn_max)
|
if (s->be->beconn > s->be->beconn_max)
|
||||||
t->be->beconn_max = t->be->beconn;
|
s->be->beconn_max = s->be->beconn;
|
||||||
t->be->cum_beconn++;
|
s->be->cum_beconn++;
|
||||||
t->flags |= SN_BE_ASSIGNED;
|
s->flags |= SN_BE_ASSIGNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2125,8 +2122,8 @@ int process_request(struct session *t)
|
|||||||
* If HTTP PROXY is set we simply get remote server address
|
* If HTTP PROXY is set we simply get remote server address
|
||||||
* parsing incoming request.
|
* parsing incoming request.
|
||||||
*/
|
*/
|
||||||
if ((t->be->options & PR_O_HTTP_PROXY) && !(t->flags & SN_ADDR_SET)) {
|
if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
|
||||||
url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &t->srv_addr);
|
url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &s->srv_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2135,52 +2132,50 @@ int process_request(struct session *t)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* It needs to look into the URI */
|
/* It needs to look into the URI */
|
||||||
if (t->be->appsession_name) {
|
if (s->be->appsession_name) {
|
||||||
get_srv_from_appsession(t, &req->data[msg->som], msg->sl.rq.l);
|
get_srv_from_appsession(s, &req->data[msg->som], msg->sl.rq.l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 8: Now we can work with the cookies.
|
* 8: Now we can work with the cookies.
|
||||||
* Note that doing so might move headers in the request, but
|
* Note that doing so might move headers in the request, but
|
||||||
* the fields will stay coherent and the URI will not move.
|
* the fields will stay coherent and the URI will not move.
|
||||||
* This should only be performed in the backend.
|
* This should only be performed in the backend.
|
||||||
*/
|
*/
|
||||||
if ((t->be->cookie_name || t->be->appsession_name || t->be->capture_name)
|
if ((s->be->cookie_name || s->be->appsession_name || s->be->capture_name)
|
||||||
&& !(txn->flags & (TX_CLDENY|TX_CLTARPIT)))
|
&& !(txn->flags & (TX_CLDENY|TX_CLTARPIT)))
|
||||||
manage_client_side_cookies(t, req);
|
manage_client_side_cookies(s, req);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 9: add X-Forwarded-For if either the frontend or the backend
|
* 9: add X-Forwarded-For if either the frontend or the backend
|
||||||
* asks for it.
|
* asks for it.
|
||||||
*/
|
*/
|
||||||
if ((t->fe->options | t->be->options) & PR_O_FWDFOR) {
|
if ((s->fe->options | s->be->options) & PR_O_FWDFOR) {
|
||||||
if (t->cli_addr.ss_family == AF_INET) {
|
if (s->cli_addr.ss_family == AF_INET) {
|
||||||
/* Add an X-Forwarded-For header unless the source IP is
|
/* Add an X-Forwarded-For header unless the source IP is
|
||||||
* in the 'except' network range.
|
* in the 'except' network range.
|
||||||
*/
|
*/
|
||||||
if ((!t->fe->except_mask.s_addr ||
|
if ((!s->fe->except_mask.s_addr ||
|
||||||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->fe->except_mask.s_addr)
|
(((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->fe->except_mask.s_addr)
|
||||||
!= t->fe->except_net.s_addr) &&
|
!= s->fe->except_net.s_addr) &&
|
||||||
(!t->be->except_mask.s_addr ||
|
(!s->be->except_mask.s_addr ||
|
||||||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->be->except_mask.s_addr)
|
(((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->be->except_mask.s_addr)
|
||||||
!= t->be->except_net.s_addr)) {
|
!= s->be->except_net.s_addr)) {
|
||||||
int len;
|
int len;
|
||||||
unsigned char *pn;
|
unsigned char *pn;
|
||||||
pn = (unsigned char *)&((struct sockaddr_in *)&t->cli_addr)->sin_addr;
|
pn = (unsigned char *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr;
|
||||||
|
|
||||||
/* Note: we rely on the backend to get the header name to be used for
|
/* Note: we rely on the backend to get the header name to be used for
|
||||||
* x-forwarded-for, because the header is really meant for the backends.
|
* x-forwarded-for, because the header is really meant for the backends.
|
||||||
* However, if the backend did not specify any option, we have to rely
|
* However, if the backend did not specify any option, we have to rely
|
||||||
* on the frontend's header name.
|
* on the frontend's header name.
|
||||||
*/
|
*/
|
||||||
if (t->be->fwdfor_hdr_len) {
|
if (s->be->fwdfor_hdr_len) {
|
||||||
len = t->be->fwdfor_hdr_len;
|
len = s->be->fwdfor_hdr_len;
|
||||||
memcpy(trash, t->be->fwdfor_hdr_name, len);
|
memcpy(trash, s->be->fwdfor_hdr_name, len);
|
||||||
} else {
|
} else {
|
||||||
len = t->fe->fwdfor_hdr_len;
|
len = s->fe->fwdfor_hdr_len;
|
||||||
memcpy(trash, t->fe->fwdfor_hdr_name, len);
|
memcpy(trash, s->fe->fwdfor_hdr_name, len);
|
||||||
}
|
}
|
||||||
len += sprintf(trash + len, ": %d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
|
len += sprintf(trash + len, ": %d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
|
||||||
|
|
||||||
@ -2189,14 +2184,14 @@ int process_request(struct session *t)
|
|||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t->cli_addr.ss_family == AF_INET6) {
|
else if (s->cli_addr.ss_family == AF_INET6) {
|
||||||
/* FIXME: for the sake of completeness, we should also support
|
/* FIXME: for the sake of completeness, we should also support
|
||||||
* 'except' here, although it is mostly useless in this case.
|
* 'except' here, although it is mostly useless in this case.
|
||||||
*/
|
*/
|
||||||
int len;
|
int len;
|
||||||
char pn[INET6_ADDRSTRLEN];
|
char pn[INET6_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET6,
|
inet_ntop(AF_INET6,
|
||||||
(const void *)&((struct sockaddr_in6 *)(&t->cli_addr))->sin6_addr,
|
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
|
||||||
pn, sizeof(pn));
|
pn, sizeof(pn));
|
||||||
|
|
||||||
/* Note: we rely on the backend to get the header name to be used for
|
/* Note: we rely on the backend to get the header name to be used for
|
||||||
@ -2204,12 +2199,12 @@ int process_request(struct session *t)
|
|||||||
* However, if the backend did not specify any option, we have to rely
|
* However, if the backend did not specify any option, we have to rely
|
||||||
* on the frontend's header name.
|
* on the frontend's header name.
|
||||||
*/
|
*/
|
||||||
if (t->be->fwdfor_hdr_len) {
|
if (s->be->fwdfor_hdr_len) {
|
||||||
len = t->be->fwdfor_hdr_len;
|
len = s->be->fwdfor_hdr_len;
|
||||||
memcpy(trash, t->be->fwdfor_hdr_name, len);
|
memcpy(trash, s->be->fwdfor_hdr_name, len);
|
||||||
} else {
|
} else {
|
||||||
len = t->fe->fwdfor_hdr_len;
|
len = s->fe->fwdfor_hdr_len;
|
||||||
memcpy(trash, t->fe->fwdfor_hdr_name, len);
|
memcpy(trash, s->fe->fwdfor_hdr_name, len);
|
||||||
}
|
}
|
||||||
len += sprintf(trash + len, ": %s", pn);
|
len += sprintf(trash + len, ": %s", pn);
|
||||||
|
|
||||||
@ -2223,23 +2218,23 @@ int process_request(struct session *t)
|
|||||||
* 10: add "Connection: close" if needed and not yet set.
|
* 10: add "Connection: close" if needed and not yet set.
|
||||||
* Note that we do not need to add it in case of HTTP/1.0.
|
* Note that we do not need to add it in case of HTTP/1.0.
|
||||||
*/
|
*/
|
||||||
if (!(t->flags & SN_CONN_CLOSED) &&
|
if (!(s->flags & SN_CONN_CLOSED) &&
|
||||||
((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) {
|
((s->fe->options | s->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) {
|
||||||
if ((unlikely(msg->sl.rq.v_l != 8) ||
|
if ((unlikely(msg->sl.rq.v_l != 8) ||
|
||||||
unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) &&
|
unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) &&
|
||||||
unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx,
|
unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx,
|
||||||
"Connection: close", 17)) < 0)
|
"Connection: close", 17)) < 0)
|
||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
t->flags |= SN_CONN_CLOSED;
|
s->flags |= SN_CONN_CLOSED;
|
||||||
}
|
}
|
||||||
/* Before we switch to data, was assignment set in manage_client_side_cookie?
|
/* Before we switch to data, was assignment set in manage_client_side_cookie?
|
||||||
* If not assigned, perhaps we are balancing on url_param, but this is a
|
* If not assigned, perhaps we are balancing on url_param, but this is a
|
||||||
* POST; and the parameters are in the body, maybe scan there to find our server.
|
* POST; and the parameters are in the body, maybe scan there to find our server.
|
||||||
* (unless headers overflowed the buffer?)
|
* (unless headers overflowed the buffer?)
|
||||||
*/
|
*/
|
||||||
if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) &&
|
if (!(s->flags & (SN_ASSIGNED|SN_DIRECT)) &&
|
||||||
t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL &&
|
s->txn.meth == HTTP_METH_POST && s->be->url_param_name != NULL &&
|
||||||
t->be->url_param_post_limit != 0 && !(req->flags & BF_FULL) &&
|
s->be->url_param_post_limit != 0 && !(req->flags & BF_FULL) &&
|
||||||
memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) {
|
memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) {
|
||||||
/* are there enough bytes here? total == l || r || rlim ?
|
/* are there enough bytes here? total == l || r || rlim ?
|
||||||
* len is unsigned, but eoh is int,
|
* len is unsigned, but eoh is int,
|
||||||
@ -2272,7 +2267,7 @@ int process_request(struct session *t)
|
|||||||
goto end_check_maybe_wait_for_body;
|
goto end_check_maybe_wait_for_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(len > t->be->url_param_post_limit)) {
|
if (likely(len > s->be->url_param_post_limit)) {
|
||||||
/* nothing to do, we got enough */
|
/* nothing to do, we got enough */
|
||||||
} else {
|
} else {
|
||||||
/* limit implies we are supposed to need this many bytes
|
/* limit implies we are supposed to need this many bytes
|
||||||
@ -2302,8 +2297,8 @@ int process_request(struct session *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* but limited to what we care about, maybe we don't expect any entity data (hint == 0) */
|
/* but limited to what we care about, maybe we don't expect any entity data (hint == 0) */
|
||||||
if (t->be->url_param_post_limit < hint)
|
if (s->be->url_param_post_limit < hint)
|
||||||
hint = t->be->url_param_post_limit;
|
hint = s->be->url_param_post_limit;
|
||||||
/* now do we really need to buffer more data? */
|
/* now do we really need to buffer more data? */
|
||||||
if (len < hint) {
|
if (len < hint) {
|
||||||
buffer_write_dis(req);
|
buffer_write_dis(req);
|
||||||
@ -2321,7 +2316,7 @@ int process_request(struct session *t)
|
|||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
buffer_set_rlim(req, BUFSIZE); /* no more rewrite needed */
|
buffer_set_rlim(req, BUFSIZE); /* no more rewrite needed */
|
||||||
t->logs.tv_request = now;
|
s->logs.tv_request = now;
|
||||||
|
|
||||||
/* When a connection is tarpitted, we use the tarpit timeout,
|
/* When a connection is tarpitted, we use the tarpit timeout,
|
||||||
* which may be the same as the connect timeout if unspecified.
|
* which may be the same as the connect timeout if unspecified.
|
||||||
@ -2329,46 +2324,32 @@ int process_request(struct session *t)
|
|||||||
* eventually expire. We build the tarpit as an analyser.
|
* eventually expire. We build the tarpit as an analyser.
|
||||||
*/
|
*/
|
||||||
if (txn->flags & TX_CLTARPIT) {
|
if (txn->flags & TX_CLTARPIT) {
|
||||||
buffer_flush(t->req);
|
buffer_flush(s->req);
|
||||||
/* flush the request so that we can drop the connection early
|
/* flush the request so that we can drop the connection early
|
||||||
* if the client closes first.
|
* if the client closes first.
|
||||||
*/
|
*/
|
||||||
buffer_write_dis(req);
|
buffer_write_dis(req);
|
||||||
req->analysers |= AN_REQ_HTTP_TARPIT;
|
req->analysers |= AN_REQ_HTTP_TARPIT;
|
||||||
req->analyse_exp = tick_add_ifset(now_ms, t->be->timeout.tarpit);
|
req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.tarpit);
|
||||||
if (!req->analyse_exp)
|
if (!req->analyse_exp)
|
||||||
req->analyse_exp = now_ms;
|
req->analyse_exp = now_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK let's go on with the BODY now */
|
/* OK let's go on with the BODY now */
|
||||||
goto end_of_headers;
|
return 1;
|
||||||
|
|
||||||
return_bad_req: /* let's centralize all bad requests */
|
return_bad_req: /* let's centralize all bad requests */
|
||||||
txn->req.msg_state = HTTP_MSG_ERROR;
|
txn->req.msg_state = HTTP_MSG_ERROR;
|
||||||
txn->status = 400;
|
txn->status = 400;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_400));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
|
||||||
t->fe->failed_req++;
|
s->fe->failed_req++;
|
||||||
return_prx_cond:
|
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
|
||||||
t->flags |= SN_ERR_PRXCOND;
|
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
|
||||||
t->flags |= SN_FINST_R;
|
|
||||||
return 0;
|
|
||||||
end_of_headers:
|
|
||||||
; // to keep gcc happy
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: eventhough nobody should set an unknown flag, clearing them right now will
|
return_prx_cond:
|
||||||
* probably reduce one day's debugging session.
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
*/
|
s->flags |= SN_ERR_PRXCOND;
|
||||||
#ifdef DEBUG_DEV
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
if (req->analysers & ~(AN_REQ_INSPECT | AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY)) {
|
s->flags |= SN_FINST_R;
|
||||||
fprintf(stderr, "FIXME !!!! unknown analysers flags %s:%d = 0x%08X\n",
|
|
||||||
__FILE__, __LINE__, req->analysers);
|
|
||||||
ABORT_NOW();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,8 +705,8 @@ resync_stream_interface:
|
|||||||
if (!tcp_inspect_request(s, s->req))
|
if (!tcp_inspect_request(s, s->req))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (s->req->analysers)
|
if (s->req->analysers & AN_REQ_HTTP_HDR)
|
||||||
if (!process_request(s))
|
if (!http_process_request(s, s->req))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (s->req->analysers & AN_REQ_HTTP_TARPIT)
|
if (s->req->analysers & AN_REQ_HTTP_TARPIT)
|
||||||
|
Loading…
Reference in New Issue
Block a user