mirror of
https://github.com/haproxy/haproxy.git
synced 2026-02-18 18:19:39 -05:00
[MEDIUM] allow a TCP frontend to switch to an HTTP backend
This patch allows a TCP frontend to switch to an HTTP backend. During the switch, missing structures are automatically allocated. The HTTP parser is enabled so that the backend first waits for a full HTTP request.
This commit is contained in:
parent
a55b7dc528
commit
51aecc76f8
3 changed files with 48 additions and 1 deletions
|
|
@ -4276,6 +4276,12 @@ use_backend <backend> unless <condition>
|
|||
used (in case of a "listen" section) or, in case of a frontend, no server is
|
||||
used and a 503 service unavailable response is returned.
|
||||
|
||||
Note that it is possible to switch from a TCP frontend to an HTTP backend. In
|
||||
this case, etiher the frontend has already checked that the protocol is HTTP,
|
||||
and backend processing will immediately follow, or the backend will wait for
|
||||
a complete HTTP request to get in. This feature is useful when a frontend
|
||||
must decode several protocols on a unique port, one of them being HTTP.
|
||||
|
||||
See also: "default_backend", "tcp-request", and section 7 about ACLs.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1832,6 +1832,12 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
|||
struct redirect_rule *rule;
|
||||
int cur_idx;
|
||||
|
||||
if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
|
||||
/* we need more data */
|
||||
buffer_write_dis(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req->analysers &= ~an_bit;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
|
||||
|
|
@ -2092,6 +2098,12 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
|
|||
struct http_txn *txn = &s->txn;
|
||||
struct http_msg *msg = &txn->req;
|
||||
|
||||
if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
|
||||
/* we need more data */
|
||||
buffer_write_dis(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req->analysers &= ~an_bit;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
|
||||
|
|
@ -2450,6 +2462,12 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit)
|
|||
long long limit = s->be->url_param_post_limit;
|
||||
struct hdr_ctx ctx;
|
||||
|
||||
if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
|
||||
/* we need more data */
|
||||
buffer_write_dis(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have to parse the HTTP request body to find any required data.
|
||||
* "balance url_param check_post" should have been the only way to get
|
||||
* into this. We were brought here after HTTP header analysis, so all
|
||||
|
|
|
|||
25
src/proxy.c
25
src/proxy.c
|
|
@ -30,6 +30,7 @@
|
|||
#include <proto/client.h>
|
||||
#include <proto/backend.h>
|
||||
#include <proto/fd.h>
|
||||
#include <proto/hdr_idx.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/protocols.h>
|
||||
#include <proto/proto_tcp.h>
|
||||
|
|
@ -245,7 +246,8 @@ struct proxy *findproxy(const char *name, int mode, int cap) {
|
|||
if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name))
|
||||
continue;
|
||||
|
||||
if (curproxy->mode != mode) {
|
||||
if (curproxy->mode != mode &&
|
||||
!(curproxy->mode == PR_MODE_HTTP && mode == PR_MODE_TCP)) {
|
||||
Alert("Unable to use proxy '%s' with wrong mode, required: %s, has: %s.\n",
|
||||
name, proxy_mode_str(mode), proxy_mode_str(curproxy->mode));
|
||||
Alert("You may want to use 'mode %s'.\n", proxy_mode_str(mode));
|
||||
|
|
@ -654,6 +656,27 @@ int session_set_backend(struct session *s, struct proxy *be)
|
|||
if (be->options2 & PR_O2_RSPBUG_OK)
|
||||
s->txn.rsp.err_pos = -1; /* let buggy responses pass */
|
||||
s->flags |= SN_BE_ASSIGNED;
|
||||
|
||||
/* If the target backend requires HTTP processing, we have to allocate
|
||||
* a struct hdr_idx for it if we did not have one.
|
||||
*/
|
||||
if (unlikely(!s->txn.hdr_idx.v && (be->acl_requires & ACL_USE_L7_ANY))) {
|
||||
if ((s->txn.hdr_idx.v = pool_alloc2(s->fe->hdr_idx_pool)) == NULL)
|
||||
return 0; /* not enough memory */
|
||||
s->txn.hdr_idx.size = MAX_HTTP_HDR;
|
||||
hdr_idx_init(&s->txn.hdr_idx);
|
||||
}
|
||||
|
||||
/* If we're switching from TCP mode to HTTP mode, we need to
|
||||
* enable several analysers on the backend.
|
||||
*/
|
||||
if (unlikely(s->fe->mode != PR_MODE_HTTP && s->be->mode == PR_MODE_HTTP)) {
|
||||
/* We want to wait for a complete HTTP request and process the
|
||||
* backend parts.
|
||||
*/
|
||||
s->req->analysers |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_BE | AN_REQ_HTTP_INNER;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue