]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] store a complete dump of request and response errors in proxies
authorWilly Tarreau <w@1wt.eu>
Sun, 1 Mar 2009 22:21:47 +0000 (23:21 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 Mar 2009 09:26:38 +0000 (10:26 +0100)
Each proxy instance, either frontend or backend, now has some room
dedicated to storing a complete dated request or response in case
of parsing error. This will make it possible to consult errors in
order to find the exact cause, which is particularly important for
troubleshooting faulty applications.

include/types/proxy.h
src/proto_http.c

index 2f6779150887f056f94034c50a1b2e5b26c6219e..9adf5cde2398cd2dfad1c5557d6d878a29cbc60d 100644 (file)
@@ -123,6 +123,17 @@ struct fwrr_group {
        int next_weight;        /* total weight of the next time range */
 }; 
 
+struct error_snapshot {
+       struct timeval when;            /* date of this event, (tv_sec == 0) means "never" */
+       unsigned int len;               /* original length of the last invalid request/response */
+       unsigned int pos;               /* position of the first invalid character */
+       unsigned int sid;               /* ID of the faulty session */
+       struct server *srv;             /* server associated with the error (or NULL) */
+       struct proxy *oe;               /* other end = frontend or backend involved */
+       struct sockaddr_storage src;    /* client's address */
+       char buf[BUFSIZE];              /* copy of the beginning of the message */
+};
+
 struct proxy {
        struct listener *listen;                /* the listen addresses and sockets */
        struct in_addr mon_net, mon_mask;       /* don't forward connections from this net (network order) FIXME: should support IPv6 */
@@ -259,6 +270,7 @@ struct proxy {
        int next_svid;                          /* next server-id, used for SNMP */
        unsigned int backlog;                   /* force the frontend's listen backlog */
        unsigned int bind_proc;                 /* bitmask of processes using this proxy. 0 = all. */
+       struct error_snapshot invalid_req, invalid_rep; /* captures of last errors */
 };
 
 struct switching_rule {
index 86b411ea81ed4211870c75e37dc4a648784880bd..c88a93c726d4e15219a877f6a6864c9dbfbe92ce 100644 (file)
@@ -1538,7 +1538,7 @@ int http_process_request(struct session *s, struct buffer *req)
         * For the parsing, we use a 28 states FSM.
         *
         * Here is the information we currently have :
-        *   req->data + req->som  = beginning of request
+        *   req->data + msg->som  = beginning of request
         *   req->data + req->eoh  = end of processed headers / start of current one
         *   req->data + req->eol  = end of current header or line (LF or CRLF)
         *   req->lr = first non-visited byte
@@ -2317,6 +2317,21 @@ int http_process_request(struct session *s, struct buffer *req)
        return 1;
 
  return_bad_req: /* let's centralize all bad requests */
+       if (unlikely(msg->msg_state == HTTP_MSG_ERROR)) {
+               /* we detected a parsing error. We want to archive this request
+                * in the dedicated proxy area for later troubleshooting.
+                */
+               struct error_snapshot *es = &s->fe->invalid_req;
+               int maxlen = MIN(req->r - req->data + msg->som, sizeof(es->buf));
+               memcpy(es->buf, req->data + msg->som, maxlen);
+               es->pos  = req->lr - req->data + msg->som;
+               es->len  = req->r - req->data + msg->som;
+               es->when = now;
+               es->sid  = s->uniq_id;
+               es->srv  = s->srv;
+               es->oe   = s->be;
+               es->src  = s->cli_addr;
+       }
        txn->req.msg_state = HTTP_MSG_ERROR;
        txn->status = 400;
        req->analysers = 0;
@@ -2539,6 +2554,20 @@ int process_response(struct session *t)
                if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
                        /* Invalid response */
                        if (unlikely(msg->msg_state == HTTP_MSG_ERROR)) {
+                               /* we detected a parsing error. We want to archive this response
+                                * in the dedicated proxy area for later troubleshooting.
+                                */
+                               struct error_snapshot *es = &t->be->invalid_rep;
+                               int maxlen = MIN(rep->r - rep->data + msg->som, sizeof(es->buf));
+                               memcpy(es->buf, rep->data + msg->som, maxlen);
+                               es->pos = rep->lr - rep->data + msg->som;
+                               es->len = rep->r - rep->data + msg->som;
+                               es->when = now;
+                               es->sid = t->uniq_id;
+                               es->srv = t->srv;
+                               es->oe = t->fe;
+                               es->src = t->cli_addr;
+
                        hdr_response_bad:
                                //buffer_shutr(rep);
                                //buffer_shutw(req);