]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: make option http_proxy automatically rewrite the URL
authorWilly Tarreau <w@1wt.eu>
Mon, 16 Dec 2013 13:30:55 +0000 (14:30 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 16 Dec 2013 13:30:55 +0000 (14:30 +0100)
There are very few users of http_proxy, and all of them complain about
the same thing : the request is passed unmodified to the server (in its
proxy form), and it is not possible to fix it using reqrep rules because
http_proxy happens after.

So let's have http_proxy fix the URL it has analysed to get rid of the
scheme and the host part. This will do what users of this feature expect.

src/proto_http.c

index 721bc36beff5c1e8da82cf6b7003b63d7f38130b..bd663ef3382463f686f93de68522d0eba85d7cb3 100644 (file)
@@ -3747,6 +3747,7 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
         */
        if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
                struct connection *conn;
+               char *path;
 
                /* Note that for now we don't reuse existing proxy connections */
                if (unlikely((conn = si_alloc_conn(req->cons, 0)) == NULL)) {
@@ -3762,7 +3763,39 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
 
                        return 0;
                }
-               url2sa(req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l, &conn->addr.to);
+
+               path = http_get_path(txn);
+               url2sa(req->buf->p + msg->sl.rq.u,
+                      path ? path - (req->buf->p + msg->sl.rq.u) : msg->sl.rq.u_l,
+                      &conn->addr.to);
+               /* if the path was found, we have to remove everything between
+                * req->buf->p + msg->sl.rq.u and path (excluded). If it was not
+                * found, we need to replace from req->buf->p + msg->sl.rq.u for
+                * u_l characters by a single "/".
+                */
+               if (path) {
+                       char *cur_ptr = req->buf->p;
+                       char *cur_end = cur_ptr + txn->req.sl.rq.l;
+                       int delta;
+
+                       delta = buffer_replace2(req->buf, req->buf->p + msg->sl.rq.u, path, NULL, 0);
+                       http_msg_move_end(&txn->req, delta);
+                       cur_end += delta;
+                       if (http_parse_reqline(&txn->req, HTTP_MSG_RQMETH,  cur_ptr, cur_end + 1, NULL, NULL) == NULL)
+                               goto return_bad_req;
+               }
+               else {
+                       char *cur_ptr = req->buf->p;
+                       char *cur_end = cur_ptr + txn->req.sl.rq.l;
+                       int delta;
+
+                       delta = buffer_replace2(req->buf, req->buf->p + msg->sl.rq.u,
+                                               req->buf->p + msg->sl.rq.u + msg->sl.rq.u_l, "/", 1);
+                       http_msg_move_end(&txn->req, delta);
+                       cur_end += delta;
+                       if (http_parse_reqline(&txn->req, HTTP_MSG_RQMETH,  cur_ptr, cur_end + 1, NULL, NULL) == NULL)
+                               goto return_bad_req;
+               }
        }
 
        /*