Hi,
On Fri, Feb 10, Willy Tarreau wrote:
> On Mon, Feb 06, 2017 at 04:33:01PM +0200, Jarno Huuskonen wrote:
> > Hi,
> >
> > On Mon, Jan 16, Willy Tarreau wrote:
> > > > The second patch updates http_process_req_common/http_process_tarpit to
> > > > use deny_status. http_process_tarpit has a switch statement for mapping
> > > > txn->status (200<->504) to HTTP_ERR_<num>(enum). Is this reasonable ?
> > >
> > > Yes it's reasonable however it would be a good idea to instead write a
> > > short function in charge of returning this index based on the status code
> > > and then to use it everywhere we need this index, including in your own
> > > code. When you look at http_error_message(), everywhere it's called,
> > > txn->status already contains the status code, except in one place :
> > > http_return_srv_error() where we set the status code. Thus I'd proceed
> > > like this :
> > >
> > > 1) change http_server_error() to set the status code separately from the
> > > message :
> > >
> > > if (status > 0)
> > > s->txn->status = status;
> > > if (msg)
> > > bo_inject(si_ic(si), msg->str, msg->len);
> > >
> > > 2) implement your switch/case as a function (eg: http_get_status_idx())
> > >
> > > 3) make http_error_message() pass s->txn->status to htpt_get_status_idx()
> > > to retrieve the message index, and drop its second argument ; modify
> > > http_return_srv_error() to pass NULL to all calls to
> > > http_server_error()
> > > instead of http_error_message(), and add a final call in this function
> > > to do this :
> > >
> > > bo_putchk(&s->res, http_error_message(s));
> >
> > Do you mean that bo_putchk should go to end of http_return_srv_error ?
>
> I don't remember, I have to reread the code :-/
>
> > I don't think &s->res is correct ? It produces a compiler warning:
> > struct buffer * vs struct channel *
> > and coredumps if backend server is down and haproxy should return 503.
> >
> > What seems to work (very minimal testing) is:
> > bo_putchk(s->res.buf, http_error_message(s));
>
> Ah you're right apparently this one takes a buffer.
>
> > Does the attached patch look otherwise ok ?
>
> I think there's a problem in http_error_message(), there were some
> conditions to detect certain error cases on reused connections for
> which we had to remain silent and these conditions have disappeared
> so we'll return an error instead of silently closing.
I think the problem is with http_return_srv_error, I removed too many
arguments (and s->txn->flags checks) to http_server_error.
So we need to silently close if s->txn->flags & TX_NOT_FIRST or
s->flags & SF_SRV_REUSED ?
So it might work with (end of http_return_srv_error):
if (! ((s->txn->flags & TX_NOT_FIRST) || (s->flags & SF_SRV_REUSED)))
bo_putchk(s->res.buf, http_error_message(s));
or (http_return_srv_error) just remove second argument from
http_error_message call (and no bo_putchk). So http_return_srv_error
would be something like:
void http_return_srv_error(struct stream *s, struct stream_interface *si)
{
int err_type = si->err_type;
if (err_type & SI_ET_QUEUE_ABRT)
http_server_error(s, si, SF_ERR_CLICL, SF_FINST_Q,
503, http_error_message(s));
else if (err_type & SI_ET_CONN_ABRT)
http_server_error(s, si, SF_ERR_CLICL, SF_FINST_C,
503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
http_error_message(s));
else if (err_type & SI_ET_QUEUE_TO)
http_server_error(s, si, SF_ERR_SRVTO, SF_FINST_Q,
503, http_error_message(s));
else if (err_type & SI_ET_QUEUE_ERR)
http_server_error(s, si, SF_ERR_SRVCL, SF_FINST_Q,
503, http_error_message(s));
else if (err_type & SI_ET_CONN_TO)
http_server_error(s, si, SF_ERR_SRVTO, SF_FINST_C,
503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
http_error_message(s));
else if (err_type & SI_ET_CONN_ERR)
http_server_error(s, si, SF_ERR_SRVCL, SF_FINST_C,
503, (s->flags & SF_SRV_REUSED) ? NULL :
http_error_message(s));
else if (err_type & SI_ET_CONN_RES)
http_server_error(s, si, SF_ERR_RESOURCE, SF_FINST_C,
503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
http_error_message(s));
else /* SI_ET_CONN_OTHER and others */
http_server_error(s, si, SF_ERR_INTERNAL, SF_FINST_C,
500, http_error_message(s));
}
Does it work with this version of http_return_srv_error ?
-Jarno
--
Jarno Huuskonen