}
}
+/* This function returns HTTP_ERR_<num> (enum) matching http status code.
+ * Returned value should match codes from http_err_codes.
+ */
+static const int http_get_status_idx(unsigned int status)
+{
+ switch (status) {
+ case 200: return HTTP_ERR_200;
+ case 400: return HTTP_ERR_400;
+ case 403: return HTTP_ERR_403;
+ case 405: return HTTP_ERR_405;
+ case 408: return HTTP_ERR_408;
+ case 429: return HTTP_ERR_429;
+ case 500: return HTTP_ERR_500;
+ case 502: return HTTP_ERR_502;
+ case 503: return HTTP_ERR_503;
+ case 504: return HTTP_ERR_504;
+ default: return HTTP_ERR_500;
+ }
+}
+
void init_proto_http()
{
int i;
channel_erase(si_oc(si));
channel_auto_close(si_ic(si));
channel_auto_read(si_ic(si));
- if (status > 0 && msg) {
+ if (status > 0)
s->txn->status = status;
+ if (msg)
bo_inject(si_ic(si), msg->str, msg->len);
- }
if (!(s->flags & SF_ERR_MASK))
s->flags |= err;
if (!(s->flags & SF_FINST_MASK))
* and message.
*/
-struct chunk *http_error_message(struct stream *s, int msgnum)
+struct chunk *http_error_message(struct stream *s)
{
+ const int msgnum = http_get_status_idx(s->txn->status);
+
if (s->be->errmsg[msgnum].str)
return &s->be->errmsg[msgnum];
else if (strm_fe(s)->errmsg[msgnum].str)
{
int err_type = si->err_type;
+ /* set s->txn->status for http_error_message(s) */
+ s->txn->status = 503;
+
if (err_type & SI_ET_QUEUE_ABRT)
http_server_error(s, si, SF_ERR_CLICL, SF_FINST_Q,
- 503, http_error_message(s, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
+ 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, HTTP_ERR_503));
- else /* SI_ET_CONN_OTHER and others */
+ http_error_message(s));
+ else { /* SI_ET_CONN_OTHER and others */
+ s->txn->status = 500;
http_server_error(s, si, SF_ERR_INTERNAL, SF_FINST_C,
- 500, http_error_message(s, HTTP_ERR_500));
+ 500, http_error_message(s));
+ }
}
extern const char sess_term_cond[8];
txn->status = 408;
msg->err_state = msg->msg_state;
msg->msg_state = HTTP_MSG_ERROR;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_408));
+ http_reply_and_close(s, txn->status, http_error_message(s));
req->analysers &= AN_REQ_FLT_END;
stream_inc_http_req_ctr(s);
txn->status = 400;
msg->err_state = msg->msg_state;
msg->msg_state = HTTP_MSG_ERROR;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
req->analysers &= AN_REQ_FLT_END;
stream_inc_http_err_ctr(s);
stream_inc_http_req_ctr(s);
if (ret) {
/* we fail this request, let's return 503 service unavail */
txn->status = 503;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_503));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_LOCAL; /* we don't want a real error here */
goto return_prx_cond;
/* nothing to fail, let's reply normaly */
txn->status = 200;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_200));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_LOCAL; /* we don't want a real error here */
goto return_prx_cond;
txn->req.err_state = txn->req.msg_state;
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
sess->fe->fe_counters.failed_req++;
if (sess->listener->counters)
if (unlikely(!stream_int_register_handler(&s->si[1], objt_applet(s->target)))) {
txn->status = 500;
s->logs.tv_request = now;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_500));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_RESOURCE;
txn->flags |= TX_CLDENY;
txn->status = http_err_codes[deny_status];
s->logs.tv_request = now;
- http_reply_and_close(s, txn->status, http_error_message(s, deny_status));
+ http_reply_and_close(s, txn->status, http_error_message(s));
stream_inc_http_err_ctr(s);
sess->fe->fe_counters.denied_req++;
if (sess->fe != s->be)
txn->req.err_state = txn->req.msg_state;
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
sess->fe->fe_counters.failed_req++;
if (sess->listener->counters)
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 500;
req->analysers &= AN_REQ_FLT_END;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_500));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_RESOURCE;
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400;
req->analysers &= AN_REQ_FLT_END;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
sess->fe->fe_counters.failed_req++;
if (sess->listener->counters)
txn->status = 500;
if (!(req->flags & CF_READ_ERROR))
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_500));
+ http_reply_and_close(s, txn->status, http_error_message(s));
req->analysers &= AN_REQ_FLT_END;
req->analyse_exp = TICK_ETERNITY;
if ((req->flags & CF_READ_TIMEOUT) || tick_is_expired(req->analyse_exp, now_ms)) {
txn->status = 408;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_408));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_CLITO;
txn->req.err_state = txn->req.msg_state;
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_PRXCOND;
http_reply_and_close(s, txn->status, NULL);
} else {
txn->status = 400;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
}
req->analysers &= AN_REQ_FLT_END;
s->res.analysers &= AN_RES_FLT_END; /* we're in data phase, we want to abort both directions */
http_reply_and_close(s, txn->status, NULL);
} else {
txn->status = 502;
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
+ http_reply_and_close(s, txn->status, http_error_message(s));
}
req->analysers &= AN_REQ_FLT_END;
s->res.analysers &= AN_RES_FLT_END; /* we're in data phase, we want to abort both directions */
txn->status = 502;
s->si[1].flags |= SI_FL_NOLINGER;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_PRXCOND;
txn->status = 502;
s->si[1].flags |= SI_FL_NOLINGER;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_SRVCL;
txn->status = 504;
s->si[1].flags |= SI_FL_NOLINGER;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_504));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_SRVTO;
txn->status = 400;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_CLICL;
txn->status = 502;
s->si[1].flags |= SI_FL_NOLINGER;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_SRVCL;
s->logs.t_data = -1; /* was not a valid response */
s->si[1].flags |= SI_FL_NOLINGER;
channel_truncate(rep);
- http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
+ http_reply_and_close(s, txn->status, http_error_message(s));
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))