MEDIUM: http: add a prefetch function for ACL pattern fetch
This function will be called by all ACL fetch functions. Right now all ACL fetch functions have to perform the exact same tests to check whether data are available. Also, only one of them is able to actually parse an HTTP request. Using the prefetch function, it will be possible to try to parse a request on the fly and to avoid the fetch if some data are missing. This will significantly reduce the amount of tests in all ACL fetch functions.
This commit is contained in:
parent
9dab5fc4d4
commit
14174bc4c0
|
@ -7528,6 +7528,87 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
|||
/************************************************************************/
|
||||
|
||||
|
||||
/* This function ensures that the prerequisites for an L7 fetch are ready,
|
||||
* which means that a request or response is ready. If some data is missing,
|
||||
* a parsing attempt is made. This is useful in TCP-based ACLs which are able
|
||||
* to extract data from L7.
|
||||
*
|
||||
* The function returns :
|
||||
* 0 if some data is missing or if the requested data cannot be fetched
|
||||
* -1 if it is certain that we'll never have any HTTP message there
|
||||
* 1 if an HTTP message is ready
|
||||
*/
|
||||
static int
|
||||
acl_prefetch_http(struct proxy *px, struct session *s, void *l7, int dir,
|
||||
struct acl_expr *expr, struct acl_test *test)
|
||||
{
|
||||
struct http_txn *txn = l7;
|
||||
struct http_msg *msg = &txn->req;
|
||||
|
||||
/* Note: hdr_idx.v cannot be NULL in this ACL because the ACL is tagged
|
||||
* as a layer7 ACL, which involves automatic allocation of hdr_idx.
|
||||
*/
|
||||
|
||||
if (unlikely(!s || !txn))
|
||||
return 0;
|
||||
|
||||
/* Check for a dependency on a request */
|
||||
|
||||
if (expr->kw->requires & ACL_USE_L7REQ_ANY) {
|
||||
if (unlikely(!s->req))
|
||||
return 0;
|
||||
|
||||
if (unlikely(txn->req.msg_state < HTTP_MSG_BODY)) {
|
||||
if ((msg->msg_state == HTTP_MSG_ERROR) || (s->req->flags & BF_FULL)) {
|
||||
test->flags |= ACL_TEST_F_SET_RES_FAIL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to decode HTTP request */
|
||||
if (likely(msg->next < s->req->i))
|
||||
http_msg_analyzer(msg, &txn->hdr_idx);
|
||||
|
||||
/* Still no valid request ? */
|
||||
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
|
||||
if ((msg->msg_state == HTTP_MSG_ERROR) || (s->req->flags & BF_FULL)) {
|
||||
test->flags |= ACL_TEST_F_SET_RES_FAIL;
|
||||
return -1;
|
||||
}
|
||||
/* wait for final state */
|
||||
test->flags |= ACL_TEST_F_MAY_CHANGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OK we just got a valid HTTP request. We have some minor
|
||||
* preparation to perform so that further checks can rely
|
||||
* on HTTP tests.
|
||||
*/
|
||||
txn->meth = find_http_meth(msg->buf->p + msg->sol, msg->sl.rq.m_l);
|
||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||
s->flags |= SN_REDIRECTABLE;
|
||||
|
||||
if (unlikely(msg->sl.rq.v_l == 0) && !http_upgrade_v09_to_v10(txn)) {
|
||||
test->flags |= ACL_TEST_F_SET_RES_FAIL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((expr->kw->requires & ACL_USE_L7REQ_VOLATILE) &&
|
||||
txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
|
||||
return 0; /* data might have moved and indexes changed */
|
||||
|
||||
/* otherwise everything's ready for the request */
|
||||
}
|
||||
|
||||
/* Check for a dependency on a response */
|
||||
if (expr->kw->requires & ACL_USE_L7RTR_ANY) {
|
||||
if (txn->rsp.msg_state < HTTP_MSG_BODY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* everything's OK */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* 1. Check on METHOD
|
||||
|
|
Loading…
Reference in New Issue