diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index e7181ec97..417d5e6fd 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -91,7 +91,7 @@ void perform_http_redirect(struct session *s, struct stream_interface *si); void http_return_srv_error(struct session *s, struct stream_interface *si); void http_capture_bad_message(struct error_snapshot *es, struct session *s, struct buffer *buf, struct http_msg *msg, - struct proxy *other_end); + int state, struct proxy *other_end); unsigned int get_ip_from_hdr2(struct http_msg *msg, const char *hname, int hlen, struct hdr_idx *idx, int occ); diff --git a/include/types/proxy.h b/include/types/proxy.h index 9704783e2..89cb09b77 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -161,6 +161,8 @@ struct error_snapshot { 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 */ + unsigned int state; /* message state before the error (when saved) */ + unsigned int flags; /* buffer flags */ 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 */ diff --git a/src/dumpstats.c b/src/dumpstats.c index 269518456..da2980970 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -3477,23 +3477,27 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) chunk_printf(&msg, " frontend %s (#%d): invalid request\n" " src %s, session #%d, backend %s (#%d), server %s (#%d)\n" + " HTTP internal state %d, buffer flags 0x%08x\n" " request length %d bytes, error at position %d:\n \n", s->data_ctx.errors.px->id, s->data_ctx.errors.px->uuid, pn, es->sid, (es->oe->cap & PR_CAP_BE) ? es->oe->id : "", (es->oe->cap & PR_CAP_BE) ? es->oe->uuid : -1, es->srv ? es->srv->id : "", es->srv ? es->srv->puid : -1, + es->state, es->flags, es->len, es->pos); break; case 1: chunk_printf(&msg, " backend %s (#%d) : invalid response\n" " src %s, session #%d, frontend %s (#%d), server %s (#%d)\n" + " HTTP internal state %d, buffer flags 0x%08x\n" " response length %d bytes, error at position %d:\n \n", s->data_ctx.errors.px->id, s->data_ctx.errors.px->uuid, pn, es->sid, es->oe->id, es->oe->uuid, es->srv ? es->srv->id : "", es->srv ? es->srv->puid : -1, + es->state, es->flags, es->len, es->pos); break; } diff --git a/src/proto_http.c b/src/proto_http.c index 4dcefca2d..893f8da29 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2487,7 +2487,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) /* we cannot return any message on error */ if (msg->err_pos >= 0) { - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); session_inc_http_err_ctr(s); } @@ -2515,7 +2515,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) /* read timeout : give up with an error message. */ if (msg->err_pos >= 0) { - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); session_inc_http_err_ctr(s); } txn->status = 408; @@ -2543,7 +2543,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) goto failed_keep_alive; if (msg->err_pos >= 0) - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); txn->status = 400; stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400)); msg->msg_state = HTTP_MSG_ERROR; @@ -2625,7 +2625,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * to block on that, so we have to capture it now. */ if (unlikely(msg->err_pos >= 0)) - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); /* * 1: identify the method @@ -2821,7 +2821,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) /* we detected a parsing error. We want to archive this request * in the dedicated proxy area for later troubleshooting. */ - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); } txn->req.msg_state = HTTP_MSG_ERROR; @@ -3375,7 +3375,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s /* we detected a parsing error. We want to archive this request * in the dedicated proxy area for later troubleshooting. */ - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); } txn->req.msg_state = HTTP_MSG_ERROR; @@ -3626,7 +3626,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit) /* we detected a parsing error. We want to archive this request * in the dedicated proxy area for later troubleshooting. */ - http_capture_bad_message(&s->fe->invalid_req, s, req, msg, s->fe); + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe); } txn->req.msg_state = HTTP_MSG_ERROR; @@ -4591,7 +4591,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) */ hdr_response_bad: if (msg->msg_state == HTTP_MSG_ERROR || msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); s->be->counters.failed_resp++; if (s->srv) { @@ -4622,7 +4622,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) /* read error */ else if (rep->flags & BF_READ_ERROR) { if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); s->be->counters.failed_resp++; if (s->srv) { @@ -4647,7 +4647,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) /* read timeout : return a 504 to the client. */ else if (rep->flags & BF_READ_TIMEOUT) { if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); s->be->counters.failed_resp++; if (s->srv) { @@ -4672,7 +4672,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) /* close from server */ else if (rep->flags & BF_SHUTR) { if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); s->be->counters.failed_resp++; if (s->srv) { @@ -4697,7 +4697,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) /* write error to client (we don't send any message then) */ else if (rep->flags & BF_WRITE_ERROR) { if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); s->be->counters.failed_resp++; rep->analysers = 0; @@ -4722,7 +4722,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) */ if (unlikely(msg->err_pos >= 0)) - http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, s->fe); + http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe); /* * 1: get the status code @@ -7200,7 +7200,7 @@ int stats_check_uri(struct session *t, struct proxy *backend) */ void http_capture_bad_message(struct error_snapshot *es, struct session *s, struct buffer *buf, struct http_msg *msg, - struct proxy *other_end) + int state, struct proxy *other_end) { es->len = buf->r - (buf->data + msg->som); memcpy(es->buf, buf->data + msg->som, MIN(es->len, sizeof(es->buf))); @@ -7213,6 +7213,8 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s, es->srv = s->srv; es->oe = other_end; es->src = s->cli_addr; + es->state = state; + es->flags = buf->flags; } /* return the IP address pointed to by occurrence of header in