Added a "fallback" option to be used with the "share" action.
It allows proceeding to another action if a file isn't available.
An example:
{
"share": "/data/www/",
"fallback": {
"pass": "applications/php"
}
}
In the example above, an attempt is made first to serve a request with
a file from the "/data/www/" directory. If there's no such file, the
request is passed to the "php" application.
Fallback actions may be nested:
{
"share": "/data/www/",
"fallback": {
"share": "/data/cache/",
"fallback": {
"proxy": "http://127.0.0.1:9000"
}
}
}
This commit is contained in:
@@ -339,6 +339,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ nxt_string("fallback"),
|
||||||
|
NXT_CONF_VLDT_OBJECT,
|
||||||
|
&nxt_conf_vldt_action,
|
||||||
|
NULL },
|
||||||
|
|
||||||
NXT_CONF_VLDT_END
|
NXT_CONF_VLDT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ struct nxt_http_action_s {
|
|||||||
nxt_http_route_t *route;
|
nxt_http_route_t *route;
|
||||||
nxt_http_upstream_t *upstream;
|
nxt_http_upstream_t *upstream;
|
||||||
nxt_app_t *application;
|
nxt_app_t *application;
|
||||||
|
nxt_http_action_t *fallback;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
nxt_str_t name;
|
nxt_str_t name;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ typedef struct {
|
|||||||
nxt_conf_value_t *pass;
|
nxt_conf_value_t *pass;
|
||||||
nxt_conf_value_t *share;
|
nxt_conf_value_t *share;
|
||||||
nxt_conf_value_t *proxy;
|
nxt_conf_value_t *proxy;
|
||||||
|
nxt_conf_value_t *fallback;
|
||||||
} nxt_http_route_action_conf_t;
|
} nxt_http_route_action_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task,
|
|||||||
static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task,
|
static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task,
|
||||||
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
|
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
|
||||||
static nxt_int_t nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf,
|
static nxt_int_t nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf,
|
||||||
nxt_conf_value_t *cv, nxt_http_route_match_t *match);
|
nxt_conf_value_t *cv, nxt_http_action_t *action);
|
||||||
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
|
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
|
||||||
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
||||||
nxt_bool_t case_sensitive);
|
nxt_bool_t case_sensitive);
|
||||||
@@ -407,7 +408,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
uint32_t n;
|
uint32_t n;
|
||||||
nxt_mp_t *mp;
|
nxt_mp_t *mp;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_conf_value_t *match_conf;
|
nxt_conf_value_t *match_conf, *action_conf;
|
||||||
nxt_http_route_test_t *test;
|
nxt_http_route_test_t *test;
|
||||||
nxt_http_route_rule_t *rule;
|
nxt_http_route_rule_t *rule;
|
||||||
nxt_http_route_table_t *table;
|
nxt_http_route_table_t *table;
|
||||||
@@ -416,6 +417,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
nxt_http_route_match_conf_t mtcf;
|
nxt_http_route_match_conf_t mtcf;
|
||||||
|
|
||||||
static nxt_str_t match_path = nxt_string("/match");
|
static nxt_str_t match_path = nxt_string("/match");
|
||||||
|
static nxt_str_t action_path = nxt_string("/action");
|
||||||
|
|
||||||
match_conf = nxt_conf_get_path(cv, &match_path);
|
match_conf = nxt_conf_get_path(cv, &match_path);
|
||||||
|
|
||||||
@@ -433,7 +435,12 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
match->action.handler = NULL;
|
match->action.handler = NULL;
|
||||||
match->items = n;
|
match->items = n;
|
||||||
|
|
||||||
ret = nxt_http_route_action_create(tmcf, cv, match);
|
action_conf = nxt_conf_get_path(cv, &action_path);
|
||||||
|
if (nxt_slow_path(action_conf == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_http_route_action_create(tmcf, action_conf, &match->action);
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -579,30 +586,27 @@ static nxt_conf_map_t nxt_http_route_action_conf[] = {
|
|||||||
NXT_CONF_MAP_PTR,
|
NXT_CONF_MAP_PTR,
|
||||||
offsetof(nxt_http_route_action_conf_t, proxy)
|
offsetof(nxt_http_route_action_conf_t, proxy)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
nxt_string("fallback"),
|
||||||
|
NXT_CONF_MAP_PTR,
|
||||||
|
offsetof(nxt_http_route_action_conf_t, fallback)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv,
|
nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv,
|
||||||
nxt_http_route_match_t *match)
|
nxt_http_action_t *action)
|
||||||
{
|
{
|
||||||
nxt_mp_t *mp;
|
nxt_mp_t *mp;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_str_t name, *string;
|
nxt_str_t name, *string;
|
||||||
nxt_conf_value_t *conf, *action_conf;
|
nxt_conf_value_t *conf;
|
||||||
nxt_http_route_action_conf_t accf;
|
nxt_http_route_action_conf_t accf;
|
||||||
|
|
||||||
static nxt_str_t action_path = nxt_string("/action");
|
|
||||||
|
|
||||||
action_conf = nxt_conf_get_path(cv, &action_path);
|
|
||||||
if (action_conf == NULL) {
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nxt_memzero(&accf, sizeof(accf));
|
nxt_memzero(&accf, sizeof(accf));
|
||||||
|
|
||||||
ret = nxt_conf_map_object(tmcf->mem_pool,
|
ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf,
|
||||||
action_conf, nxt_http_route_action_conf,
|
|
||||||
nxt_nitems(nxt_http_route_action_conf), &accf);
|
nxt_nitems(nxt_http_route_action_conf), &accf);
|
||||||
if (ret != NXT_OK) {
|
if (ret != NXT_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -612,7 +616,7 @@ nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv,
|
|||||||
|
|
||||||
if (accf.share != NULL) {
|
if (accf.share != NULL) {
|
||||||
conf = accf.share;
|
conf = accf.share;
|
||||||
match->action.handler = nxt_http_static_handler;
|
action->handler = nxt_http_static_handler;
|
||||||
|
|
||||||
} else if (accf.proxy != NULL) {
|
} else if (accf.proxy != NULL) {
|
||||||
conf = accf.proxy;
|
conf = accf.proxy;
|
||||||
@@ -622,13 +626,23 @@ nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv,
|
|||||||
|
|
||||||
mp = tmcf->router_conf->mem_pool;
|
mp = tmcf->router_conf->mem_pool;
|
||||||
|
|
||||||
string = nxt_str_dup(mp, &match->action.name, &name);
|
string = nxt_str_dup(mp, &action->name, &name);
|
||||||
if (nxt_slow_path(string == NULL)) {
|
if (nxt_slow_path(string == NULL)) {
|
||||||
return NXT_ERROR;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (accf.fallback != NULL) {
|
||||||
|
action->u.fallback = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t));
|
||||||
|
if (nxt_slow_path(action->u.fallback == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nxt_http_route_action_create(tmcf, accf.fallback,
|
||||||
|
action->u.fallback);
|
||||||
|
}
|
||||||
|
|
||||||
if (accf.proxy != NULL) {
|
if (accf.proxy != NULL) {
|
||||||
return nxt_http_proxy_create(mp, &match->action);
|
return nxt_http_proxy_create(mp, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
@@ -1043,18 +1057,13 @@ static void
|
|||||||
nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||||
nxt_http_route_t *route)
|
nxt_http_route_t *route)
|
||||||
{
|
{
|
||||||
nxt_http_action_t *action;
|
|
||||||
nxt_http_route_match_t **match, **end;
|
nxt_http_route_match_t **match, **end;
|
||||||
|
|
||||||
match = &route->match[0];
|
match = &route->match[0];
|
||||||
end = match + route->items;
|
end = match + route->items;
|
||||||
|
|
||||||
while (match < end) {
|
while (match < end) {
|
||||||
action = &(*match)->action;
|
nxt_http_action_resolve(task, tmcf, &(*match)->action);
|
||||||
|
|
||||||
if (action->handler == NULL) {
|
|
||||||
nxt_http_action_resolve(task, tmcf, &(*match)->action);
|
|
||||||
}
|
|
||||||
|
|
||||||
match++;
|
match++;
|
||||||
}
|
}
|
||||||
@@ -1067,6 +1076,16 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
{
|
{
|
||||||
nxt_str_t name;
|
nxt_str_t name;
|
||||||
|
|
||||||
|
if (action->handler != NULL) {
|
||||||
|
if (action->handler == nxt_http_static_handler
|
||||||
|
&& action->u.fallback != NULL)
|
||||||
|
{
|
||||||
|
nxt_http_action_resolve(task, tmcf, action->u.fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
name = action->name;
|
name = action->name;
|
||||||
|
|
||||||
if (nxt_str_start(&name, "applications/", 13)) {
|
if (nxt_str_start(&name, "applications/", 13)) {
|
||||||
@@ -1201,6 +1220,13 @@ nxt_http_action_cleanup(nxt_task_t *task, nxt_http_action_t *action)
|
|||||||
{
|
{
|
||||||
if (action->handler == nxt_http_application_handler) {
|
if (action->handler == nxt_http_application_handler) {
|
||||||
nxt_router_app_use(task, action->u.application, -1);
|
nxt_router_app_use(task, action->u.application, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action->handler == nxt_http_static_handler
|
||||||
|
&& action->u.fallback != NULL)
|
||||||
|
{
|
||||||
|
nxt_http_action_cleanup(task, action->u.fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
|
|||||||
if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) {
|
if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) {
|
||||||
|
|
||||||
if (!nxt_str_eq(r->method, "HEAD", 4)) {
|
if (!nxt_str_eq(r->method, "HEAD", 4)) {
|
||||||
|
if (action->u.fallback != NULL) {
|
||||||
|
return action->u.fallback;
|
||||||
|
}
|
||||||
|
|
||||||
nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED);
|
nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -123,6 +127,10 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (level == NXT_LOG_ERR && action->u.fallback != NULL) {
|
||||||
|
return action->u.fallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (status != NXT_HTTP_NOT_FOUND) {
|
if (status != NXT_HTTP_NOT_FOUND) {
|
||||||
nxt_log(task, level, "open(\"%FN\") failed %E", f->name, f->error);
|
nxt_log(task, level, "open(\"%FN\") failed %E", f->name, f->error);
|
||||||
}
|
}
|
||||||
@@ -222,8 +230,13 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
|
|||||||
nxt_file_close(task, f);
|
nxt_file_close(task, f);
|
||||||
|
|
||||||
if (nxt_slow_path(!nxt_is_dir(&fi))) {
|
if (nxt_slow_path(!nxt_is_dir(&fi))) {
|
||||||
|
if (action->u.fallback != NULL) {
|
||||||
|
return action->u.fallback;
|
||||||
|
}
|
||||||
|
|
||||||
nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file",
|
nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file",
|
||||||
f->name);
|
f->name);
|
||||||
|
|
||||||
nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND);
|
nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user