The attached experimental patch tries to send a 504 back to the sender
whenever ((rpf_last & CF_SHUTW) && (rpf_last & CF_AUTO_CLOSE)). This
is the condition that we were seeing in the rep flags that resulted in
no http responses being sent to the clients.
I am pretty new to haproxy. Is this on the right track?
From 7b862d66c760c8e4cb2cfdde373190cd306e042d Mon Sep 17 00:00:00 2001
From: Shayan Pooya <[email protected]>
Date: Tue, 18 Nov 2014 22:20:32 -0500
Subject: [PATCH] MINOR: send a 504 back to the client if there has been a read
timeout
---
include/proto/proto_http.h | 1 +
src/proto_http.c | 19 +++++++++++++++++++
src/session.c | 4 ++++
3 files changed, 24 insertions(+)
diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
index 945d49c..ef5212c 100644
--- a/include/proto/proto_http.h
+++ b/include/proto/proto_http.h
@@ -76,6 +76,7 @@ int http_wait_for_response(struct session *s, struct channel *rep, int an_bit);
int http_process_res_common(struct session *s, struct channel *rep, int an_bit, struct proxy *px);
int http_request_forward_body(struct session *s, struct channel *req, int an_bit);
int http_response_forward_body(struct session *s, struct channel *res, int an_bit);
+int http_notify_timeout(struct session *s, struct channel *rep);
void debug_hdr(const char *dir, struct session *s, const char *start, const char *end);
void get_srv_from_appsession(struct session *s, const char *begin, int len);
diff --git a/src/proto_http.c b/src/proto_http.c
index 3a3aa80..99081fc 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5625,6 +5625,25 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
return 0;
}
+int http_notify_timeout(struct session *s, struct channel *rep)
+{
+ struct http_txn *txn = &s->txn;
+
+ channel_auto_close(rep);
+ rep->analysers = 0;
+ txn->status = 504;
+ rep->prod->flags |= SI_FL_NOLINGER;
+ bi_erase(rep);
+ stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_504));
+
+ if (!(s->flags & SN_ERR_MASK))
+ s->flags |= SN_ERR_SRVTO;
+ if (!(s->flags & SN_FINST_MASK))
+ s->flags |= SN_FINST_H;
+
+ return 0;
+}
+
/* This stream analyser waits for a complete HTTP response. It returns 1 if the
* processing can continue on next analysers, or zero if it either needs more
* data or wants to immediately abort the response (eg: timeout, error, ...). It
diff --git a/src/session.c b/src/session.c
index aeaa7e1..1a582cc 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2386,6 +2386,10 @@ struct task *process_session(struct task *t)
* FIXME: this is probably where we should produce error responses.
*/
+ if ((rpf_last & CF_SHUTW) && (rpf_last & CF_AUTO_CLOSE)) {
+ http_notify_timeout(s, s->rep);
+ }
+
/* first, let's check if the response buffer needs to shutdown(write) */
if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CLOSE|CF_SHUTR)) ==
(CF_AUTO_CLOSE|CF_SHUTR))) {
--
1.9.3