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>
diff --git a/src/hlua.c b/src/hlua.c
index c343a7b..48fcf1a 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -3591,6 +3591,7 @@
lua_rawseti(L, -2, 0);
appctx->appctx = ctx;
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.p = px;
@@ -4119,6 +4120,7 @@
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
int status = MAY_LJMP(luaL_checkinteger(L, 2));
+ const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
if (status < 100 || status > 599) {
lua_pushboolean(L, 0);
@@ -4126,6 +4128,7 @@
}
appctx->appctx->ctx.hlua_apphttp.status = status;
+ appctx->appctx->ctx.hlua_apphttp.reason = reason;
lua_pushboolean(L, 1);
return 1;
}
@@ -4178,12 +4181,16 @@
int hdr_connection = 0;
int hdr_contentlength = -1;
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. */
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.status,
- get_reason(appctx->appctx->ctx.hlua_apphttp.status));
+ reason);
/* Get the array associated to the field "response" in the object AppletHTTP. */
lua_pushvalue(L, 0);
@@ -4737,17 +4744,18 @@
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)
{
struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
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 */
if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
return 0;
- http_set_status(code, htxn->s);
+ http_set_status(code, reason, htxn->s);
return 0;
}
diff --git a/src/proto_http.c b/src/proto_http.c
index 1507001..f7f7545 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -12454,14 +12454,14 @@
/* This function replace the HTTP status code and the associated message. The
* 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;
char *cur_ptr, *cur_end;
int delta;
char *res;
int c_l;
- const char *msg;
+ const char *msg = reason;
int msg_len;
chunk_reset(&trash);
@@ -12472,9 +12472,10 @@
trash.str[c_l] = ' ';
trash.len = c_l + 1;
- msg = get_reason(status);
+ /* Do we have a custom reason format string? */
+ if (msg == NULL)
+ msg = get_reason(status);
msg_len = strlen(msg);
-
strncpy(&trash.str[trash.len], msg, trash.size - trash.len);
trash.len += msg_len;
@@ -12520,7 +12521,7 @@
enum act_return action_http_set_status(struct act_rule *rule, struct proxy *px,
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;
}
@@ -12596,7 +12597,7 @@
/* Check if an argument is available */
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;
}
@@ -12608,6 +12609,16 @@
}
(*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;
}