#include <proto/acl.h>
#include <proto/arg.h>
#include <proto/backend.h>
+#include <proto/buffers.h>
#include <proto/frontend.h>
#include <proto/lb_chash.h>
#include <proto/lb_fas.h>
struct proxy *px = s->be;
unsigned int plen = px->url_param_len;
unsigned long len = msg->body_len;
- const char *params = req->p + msg->sov;
+ const char *params = b_ptr(req, (int)(msg->sov - req->o));
const char *p = params;
- if (len > req->i - (msg->sov - msg->som))
- len = req->i - (msg->sov - msg->som);
+ if (len > buffer_len(req) - (msg->sov - msg->som))
+ len = buffer_len(req) - (msg->sov - msg->som);
if (len == 0)
return NULL;
ctx.idx = 0;
/* if the message is chunked, we skip the chunk size, but use the value as len */
- http_find_header2(px->hh_name, plen, s->req->p + msg->sol, &txn->hdr_idx, &ctx);
+ http_find_header2(px->hh_name, plen, b_ptr(s->req, (int)(msg->sol - s->req->o)), &txn->hdr_idx, &ctx);
/* if the header is not found or empty, let's fallback to round robin */
if (!ctx.idx || !ctx.vlen)
int ret;
struct sample smp;
struct arg args[2];
+ int rewind;
/* tot_weight appears to mean srv_count */
if (px->lbprm.tot_weight == 0)
args[0].data.str.len = px->hh_len;
args[1].type = ARGT_STOP;
+ b_rew(s->req, rewind = s->req->o);
+
ret = smp_fetch_rdp_cookie(px, s, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, args, &smp);
len = smp.data.str.len;
+ b_adv(s->req, rewind);
+
if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0)
return NULL;
if (s->txn.req.msg_state < HTTP_MSG_BODY)
break;
srv = get_server_uh(s->be,
- s->req->p + s->txn.req.sol + s->txn.req.sl.rq.u,
+ b_ptr(s->req, (int)(s->txn.req.sol + s->txn.req.sl.rq.u - s->req->o)),
s->txn.req.sl.rq.u_l);
break;
break;
srv = get_server_ph(s->be,
- s->req->p + s->txn.req.sol + s->txn.req.sl.rq.u,
+ b_ptr(s->req, (int)(s->txn.req.sol + s->txn.req.sl.rq.u - s->req->o)),
s->txn.req.sl.rq.u_l);
if (!srv && s->txn.meth == HTTP_METH_POST)
if (srv->bind_hdr_occ) {
char *vptr;
int vlen;
+ int rewind;
/* bind to the IP in a header */
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+ b_rew(s->req, rewind = s->req->o);
if (http_get_hdr(&s->txn.req, srv->bind_hdr_name, srv->bind_hdr_len,
&s->txn.hdr_idx, srv->bind_hdr_occ, NULL, &vptr, &vlen)) {
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
htonl(inetaddr_host_lim(vptr, vptr + vlen));
}
+ b_adv(s->req, rewind);
}
break;
default:
if (s->be->bind_hdr_occ) {
char *vptr;
int vlen;
+ int rewind;
/* bind to the IP in a header */
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+ b_rew(s->req, rewind = s->req->o);
if (http_get_hdr(&s->txn.req, s->be->bind_hdr_name, s->be->bind_hdr_len,
&s->txn.hdr_idx, s->be->bind_hdr_occ, NULL, &vptr, &vlen)) {
((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
htonl(inetaddr_host_lim(vptr, vptr + vlen));
}
+ b_adv(s->req, rewind);
}
break;
default:
return 0;
}
-/* send a server's name with an outgoing request over an established connection */
+/* send a server's name with an outgoing request over an established connection.
+ * Note: this function is designed to be called once the request has been scheduled
+ * for being forwarded. This is the reason why it rewinds the buffer before
+ * proceeding.
+ */
int http_send_name_header(struct http_txn *txn, struct proxy* be, const char* srv_name) {
struct hdr_ctx ctx;
char *hdr_name = be->server_id_hdr_name;
int hdr_name_len = be->server_id_hdr_len;
-
+ struct buffer *req = txn->req.buf;
char *hdr_val;
+ unsigned int old_o, old_i;
ctx.idx = 0;
+ old_o = req->o;
+ if (old_o) {
+ /* The request was already skipped, let's restore it */
+ b_rew(req, old_o);
+ }
+
+ old_i = req->i;
while (http_find_header2(hdr_name, hdr_name_len, txn->req.buf->p + txn->req.sol, &txn->hdr_idx, &ctx)) {
/* remove any existing values from the header */
http_remove_header2(&txn->req, &txn->hdr_idx, &ctx);
hdr_val += strlcpy2(hdr_val, srv_name, trash + trashlen - hdr_val);
http_header_add_tail2(&txn->req, &txn->hdr_idx, trash, hdr_val - trash);
+ if (old_o) {
+ /* If this was a forwarded request, we must readjust the amount of
+ * data to be forwarded in order to take into account the size
+ * variations.
+ */
+ b_adv(req, old_o + req->i - old_i);
+ }
+
return 0;
}