MINOR: http: custom status reason.
The older 'rsprep' directive allows modification of the status reason. Extend 'http-response set-status' to take an optional string of the new status reason. http-response set-status 418 reason "I'm a coffeepot" Matching updates in Lua code: - AppletHTTP.set_status - HTTP.res_set_status Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
This commit is contained in:
parent
2afff9c2d6
commit
52f5db2a44
@ -4122,7 +4122,7 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
|||||||
set-header <name> <fmt> | del-header <name> |
|
set-header <name> <fmt> | del-header <name> |
|
||||||
replace-header <name> <regex-match> <replace-fmt> |
|
replace-header <name> <regex-match> <replace-fmt> |
|
||||||
replace-value <name> <regex-match> <replace-fmt> |
|
replace-value <name> <regex-match> <replace-fmt> |
|
||||||
set-status <status> |
|
set-status <status> [reason <str>] |
|
||||||
set-log-level <level> | set-mark <mark> | set-tos <tos> |
|
set-log-level <level> | set-mark <mark> | set-tos <tos> |
|
||||||
add-acl(<file name>) <key fmt> |
|
add-acl(<file name>) <key fmt> |
|
||||||
del-acl(<file name>) <key fmt> |
|
del-acl(<file name>) <key fmt> |
|
||||||
@ -4215,13 +4215,16 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
|||||||
Cache-Control: max-age=3600, private
|
Cache-Control: max-age=3600, private
|
||||||
|
|
||||||
- "set-status" replaces the response status code with <status> which must
|
- "set-status" replaces the response status code with <status> which must
|
||||||
be an integer between 100 and 999. Note that the reason is automatically
|
be an integer between 100 and 999. Optionally, a custom reason text can be
|
||||||
adapted to the new code.
|
provided defined by <str>, or the default reason for the specified code
|
||||||
|
will be used as a fallback.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
# return "431 Request Header Fields Too Large"
|
# return "431 Request Header Fields Too Large"
|
||||||
http-response set-status 431
|
http-response set-status 431
|
||||||
|
# return "503 Slow Down", custom reason
|
||||||
|
http-response set-status 503 reason "Slow Down".
|
||||||
|
|
||||||
- "set-nice" sets the "nice" factor of the current request being processed.
|
- "set-nice" sets the "nice" factor of the current request being processed.
|
||||||
It only has effect against the other requests being processed at the same
|
It only has effect against the other requests being processed at the same
|
||||||
|
@ -1443,13 +1443,15 @@ HTTP class
|
|||||||
:param class_http http: The related http object.
|
:param class_http http: The related http object.
|
||||||
:param string uri: The new uri.
|
:param string uri: The new uri.
|
||||||
|
|
||||||
.. js:function:: HTTP.res_set_status(http, status)
|
.. js:function:: HTTP.res_set_status(http, status [, reason])
|
||||||
|
|
||||||
Rewrites the response status code with the parameter "code". Note that the
|
Rewrites the response status code with the parameter "code".
|
||||||
reason is automatically adapted to the new code.
|
|
||||||
|
If no custom reason is provided, it will be generated from the status.
|
||||||
|
|
||||||
:param class_http http: The related http object.
|
:param class_http http: The related http object.
|
||||||
:param integer status: The new response status code.
|
:param integer status: The new response status code.
|
||||||
|
:param string reason: The new response reason (optional).
|
||||||
|
|
||||||
.. _txn_class:
|
.. _txn_class:
|
||||||
|
|
||||||
@ -2080,13 +2082,14 @@ AppletHTTP class
|
|||||||
AppletHTTP.headers["accept"][2] = "*/*, q=0.1"
|
AppletHTTP.headers["accept"][2] = "*/*, q=0.1"
|
||||||
..
|
..
|
||||||
|
|
||||||
.. js:function:: AppletHTTP.set_status(applet, code)
|
.. js:function:: AppletHTTP.set_status(applet, code [, reason])
|
||||||
|
|
||||||
This function sets the HTTP status code for the response. The allowed code are
|
This function sets the HTTP status code for the response. The allowed code are
|
||||||
from 100 to 599.
|
from 100 to 599.
|
||||||
|
|
||||||
:param class_AppletHTTP applet: An :ref:`applethttp_class`
|
:param class_AppletHTTP applet: An :ref:`applethttp_class`
|
||||||
:param integer code: the status code returned to the client.
|
:param integer code: the status code returned to the client.
|
||||||
|
:param string reason: the status reason returned to the client (optional).
|
||||||
|
|
||||||
.. js:function:: AppletHTTP.add_header(applet, name, value)
|
.. js:function:: AppletHTTP.add_header(applet, name, value)
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ int http_header_match2(const char *hdr, const char *end, const char *name, int l
|
|||||||
int http_remove_header2(struct http_msg *msg, struct hdr_idx *idx, struct hdr_ctx *ctx);
|
int http_remove_header2(struct http_msg *msg, struct hdr_idx *idx, struct hdr_ctx *ctx);
|
||||||
int http_header_add_tail2(struct http_msg *msg, struct hdr_idx *hdr_idx, const char *text, int len);
|
int http_header_add_tail2(struct http_msg *msg, struct hdr_idx *hdr_idx, const char *text, int len);
|
||||||
int http_replace_req_line(int action, const char *replace, int len, struct proxy *px, struct stream *s);
|
int http_replace_req_line(int action, const char *replace, int len, struct proxy *px, struct stream *s);
|
||||||
void http_set_status(unsigned int status, struct stream *s);
|
void http_set_status(unsigned int status, const char *reason, struct stream *s);
|
||||||
int http_transform_header_str(struct stream* s, struct http_msg *msg, const char* name,
|
int http_transform_header_str(struct stream* s, struct http_msg *msg, const char* name,
|
||||||
unsigned int name_len, const char *str, struct my_regex *re,
|
unsigned int name_len, const char *str, struct my_regex *re,
|
||||||
int action);
|
int action);
|
||||||
|
@ -135,6 +135,7 @@ struct act_rule {
|
|||||||
} cap;
|
} cap;
|
||||||
struct {
|
struct {
|
||||||
unsigned int code; /* HTTP status code */
|
unsigned int code; /* HTTP status code */
|
||||||
|
const char *reason; /* HTTP status reason */
|
||||||
} status;
|
} status;
|
||||||
struct {
|
struct {
|
||||||
struct sample_expr *expr;
|
struct sample_expr *expr;
|
||||||
|
@ -80,6 +80,7 @@ struct appctx {
|
|||||||
int left_bytes; /* The max amount of bytes that we can read. */
|
int left_bytes; /* The max amount of bytes that we can read. */
|
||||||
int flags;
|
int flags;
|
||||||
int status;
|
int status;
|
||||||
|
const char *reason;
|
||||||
struct task *task;
|
struct task *task;
|
||||||
} hlua_apphttp; /* used by the Lua HTTP services */
|
} hlua_apphttp; /* used by the Lua HTTP services */
|
||||||
struct {
|
struct {
|
||||||
|
14
src/hlua.c
14
src/hlua.c
@ -3591,6 +3591,7 @@ static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
|
|||||||
lua_rawseti(L, -2, 0);
|
lua_rawseti(L, -2, 0);
|
||||||
appctx->appctx = ctx;
|
appctx->appctx = ctx;
|
||||||
appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
|
appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
|
||||||
|
appctx->appctx->ctx.hlua_apphttp.reason = NULL; /* Use default reason based on status */
|
||||||
appctx->htxn.s = s;
|
appctx->htxn.s = s;
|
||||||
appctx->htxn.p = px;
|
appctx->htxn.p = px;
|
||||||
|
|
||||||
@ -4119,6 +4120,7 @@ __LJMP static int hlua_applet_http_status(lua_State *L)
|
|||||||
{
|
{
|
||||||
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
|
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
|
||||||
int status = MAY_LJMP(luaL_checkinteger(L, 2));
|
int status = MAY_LJMP(luaL_checkinteger(L, 2));
|
||||||
|
const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
|
||||||
|
|
||||||
if (status < 100 || status > 599) {
|
if (status < 100 || status > 599) {
|
||||||
lua_pushboolean(L, 0);
|
lua_pushboolean(L, 0);
|
||||||
@ -4126,6 +4128,7 @@ __LJMP static int hlua_applet_http_status(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
appctx->appctx->ctx.hlua_apphttp.status = status;
|
appctx->appctx->ctx.hlua_apphttp.status = status;
|
||||||
|
appctx->appctx->ctx.hlua_apphttp.reason = reason;
|
||||||
lua_pushboolean(L, 1);
|
lua_pushboolean(L, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -4178,12 +4181,16 @@ __LJMP static int hlua_applet_http_start_response(lua_State *L)
|
|||||||
int hdr_connection = 0;
|
int hdr_connection = 0;
|
||||||
int hdr_contentlength = -1;
|
int hdr_contentlength = -1;
|
||||||
int hdr_chunked = 0;
|
int hdr_chunked = 0;
|
||||||
|
const char *reason = appctx->appctx->ctx.hlua_apphttp.reason;
|
||||||
|
|
||||||
|
if (reason == NULL)
|
||||||
|
reason = get_reason(appctx->appctx->ctx.hlua_apphttp.status);
|
||||||
|
|
||||||
/* Use the same http version than the request. */
|
/* Use the same http version than the request. */
|
||||||
chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
|
chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
|
||||||
appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
|
appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
|
||||||
appctx->appctx->ctx.hlua_apphttp.status,
|
appctx->appctx->ctx.hlua_apphttp.status,
|
||||||
get_reason(appctx->appctx->ctx.hlua_apphttp.status));
|
reason);
|
||||||
|
|
||||||
/* Get the array associated to the field "response" in the object AppletHTTP. */
|
/* Get the array associated to the field "response" in the object AppletHTTP. */
|
||||||
lua_pushvalue(L, 0);
|
lua_pushvalue(L, 0);
|
||||||
@ -4737,17 +4744,18 @@ static int hlua_http_req_set_uri(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function set the response code. */
|
/* This function set the response code & optionally reason. */
|
||||||
static int hlua_http_res_set_status(lua_State *L)
|
static int hlua_http_res_set_status(lua_State *L)
|
||||||
{
|
{
|
||||||
struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
|
struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
|
||||||
unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
|
unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
|
||||||
|
const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
|
||||||
|
|
||||||
/* Check if a valid response is parsed */
|
/* Check if a valid response is parsed */
|
||||||
if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
|
if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
http_set_status(code, htxn->s);
|
http_set_status(code, reason, htxn->s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12454,14 +12454,14 @@ int http_replace_req_line(int action, const char *replace, int len,
|
|||||||
/* This function replace the HTTP status code and the associated message. The
|
/* This function replace the HTTP status code and the associated message. The
|
||||||
* variable <status> contains the new status code. This function never fails.
|
* variable <status> contains the new status code. This function never fails.
|
||||||
*/
|
*/
|
||||||
void http_set_status(unsigned int status, struct stream *s)
|
void http_set_status(unsigned int status, const char *reason, struct stream *s)
|
||||||
{
|
{
|
||||||
struct http_txn *txn = s->txn;
|
struct http_txn *txn = s->txn;
|
||||||
char *cur_ptr, *cur_end;
|
char *cur_ptr, *cur_end;
|
||||||
int delta;
|
int delta;
|
||||||
char *res;
|
char *res;
|
||||||
int c_l;
|
int c_l;
|
||||||
const char *msg;
|
const char *msg = reason;
|
||||||
int msg_len;
|
int msg_len;
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash);
|
||||||
@ -12472,9 +12472,10 @@ void http_set_status(unsigned int status, struct stream *s)
|
|||||||
trash.str[c_l] = ' ';
|
trash.str[c_l] = ' ';
|
||||||
trash.len = c_l + 1;
|
trash.len = c_l + 1;
|
||||||
|
|
||||||
|
/* Do we have a custom reason format string? */
|
||||||
|
if (msg == NULL)
|
||||||
msg = get_reason(status);
|
msg = get_reason(status);
|
||||||
msg_len = strlen(msg);
|
msg_len = strlen(msg);
|
||||||
|
|
||||||
strncpy(&trash.str[trash.len], msg, trash.size - trash.len);
|
strncpy(&trash.str[trash.len], msg, trash.size - trash.len);
|
||||||
trash.len += msg_len;
|
trash.len += msg_len;
|
||||||
|
|
||||||
@ -12520,7 +12521,7 @@ enum act_return http_action_set_req_line(struct act_rule *rule, struct proxy *px
|
|||||||
enum act_return action_http_set_status(struct act_rule *rule, struct proxy *px,
|
enum act_return action_http_set_status(struct act_rule *rule, struct proxy *px,
|
||||||
struct session *sess, struct stream *s, int flags)
|
struct session *sess, struct stream *s, int flags)
|
||||||
{
|
{
|
||||||
http_set_status(rule->arg.status.code, s);
|
http_set_status(rule->arg.status.code, rule->arg.status.reason, s);
|
||||||
return ACT_RET_CONT;
|
return ACT_RET_CONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12596,7 +12597,7 @@ enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg, struc
|
|||||||
|
|
||||||
/* Check if an argument is available */
|
/* Check if an argument is available */
|
||||||
if (!*args[*orig_arg]) {
|
if (!*args[*orig_arg]) {
|
||||||
memprintf(err, "expects exactly 1 argument <status>");
|
memprintf(err, "expects 1 argument: <status>; or 3 arguments: <status> reason <fmt>");
|
||||||
return ACT_RET_PRS_ERR;
|
return ACT_RET_PRS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12608,6 +12609,16 @@ enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg, struc
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*orig_arg)++;
|
(*orig_arg)++;
|
||||||
|
|
||||||
|
/* set custom reason string */
|
||||||
|
rule->arg.status.reason = NULL; // If null, we use the default reason for the status code.
|
||||||
|
if (*args[*orig_arg] && strcmp(args[*orig_arg], "reason") == 0 &&
|
||||||
|
(*args[*orig_arg + 1] && strcmp(args[*orig_arg + 1], "if") != 0 && strcmp(args[*orig_arg + 1], "unless") != 0)) {
|
||||||
|
(*orig_arg)++;
|
||||||
|
rule->arg.status.reason = strdup(args[*orig_arg]);
|
||||||
|
(*orig_arg)++;
|
||||||
|
}
|
||||||
|
|
||||||
return ACT_RET_PRS_OK;
|
return ACT_RET_PRS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user