diff options
author | Valentin Bartenev <vbart@nginx.com> | 2020-03-03 20:37:47 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2020-03-03 20:37:47 +0300 |
commit | a98de7f705f3b182fb405cced7ce85805bd6ffd3 (patch) | |
tree | 5fcca52bbcd8b80f5b539fb772061fea964c4cc4 /src | |
parent | a60f856ce2bc2eccbce0b0dfaa6ec98a30f74f67 (diff) | |
download | unit-a98de7f705f3b182fb405cced7ce85805bd6ffd3.tar.gz unit-a98de7f705f3b182fb405cced7ce85805bd6ffd3.tar.bz2 |
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"
}
}
}
Diffstat (limited to 'src')
-rw-r--r-- | src/nxt_conf_validation.c | 5 | ||||
-rw-r--r-- | src/nxt_http.h | 1 | ||||
-rw-r--r-- | src/nxt_http_route.c | 72 | ||||
-rw-r--r-- | src/nxt_http_static.c | 13 |
4 files changed, 68 insertions, 23 deletions
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 4282f46b..8189cd44 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -339,6 +339,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { NULL, NULL }, + { nxt_string("fallback"), + NXT_CONF_VLDT_OBJECT, + &nxt_conf_vldt_action, + NULL }, + NXT_CONF_VLDT_END }; diff --git a/src/nxt_http.h b/src/nxt_http.h index 030d77a7..67c7645b 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -189,6 +189,7 @@ struct nxt_http_action_s { nxt_http_route_t *route; nxt_http_upstream_t *upstream; nxt_app_t *application; + nxt_http_action_t *fallback; } u; nxt_str_t name; diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index ef9593b7..6fce895e 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -43,6 +43,7 @@ typedef struct { nxt_conf_value_t *pass; nxt_conf_value_t *share; nxt_conf_value_t *proxy; + nxt_conf_value_t *fallback; } 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, 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, - 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, nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 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; nxt_mp_t *mp; 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_rule_t *rule; 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; 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); @@ -433,7 +435,12 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, match->action.handler = NULL; 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)) { return NULL; } @@ -579,30 +586,27 @@ static nxt_conf_map_t nxt_http_route_action_conf[] = { NXT_CONF_MAP_PTR, 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 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_int_t ret; nxt_str_t name, *string; - nxt_conf_value_t *conf, *action_conf; + nxt_conf_value_t *conf; 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)); - ret = nxt_conf_map_object(tmcf->mem_pool, - action_conf, nxt_http_route_action_conf, + ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf, nxt_nitems(nxt_http_route_action_conf), &accf); if (ret != NXT_OK) { 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) { conf = accf.share; - match->action.handler = nxt_http_static_handler; + action->handler = nxt_http_static_handler; } else if (accf.proxy != NULL) { 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; - string = nxt_str_dup(mp, &match->action.name, &name); + string = nxt_str_dup(mp, &action->name, &name); if (nxt_slow_path(string == NULL)) { 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) { - return nxt_http_proxy_create(mp, &match->action); + return nxt_http_proxy_create(mp, action); } 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_t *route) { - nxt_http_action_t *action; nxt_http_route_match_t **match, **end; match = &route->match[0]; end = match + route->items; while (match < end) { - action = &(*match)->action; - - if (action->handler == NULL) { - nxt_http_action_resolve(task, tmcf, &(*match)->action); - } + nxt_http_action_resolve(task, tmcf, &(*match)->action); match++; } @@ -1067,6 +1076,16 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, { 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; 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) { 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); } } diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 44132859..46ae57a7 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -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_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); return NULL; } @@ -123,6 +127,10 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r, break; } + if (level == NXT_LOG_ERR && action->u.fallback != NULL) { + return action->u.fallback; + } + if (status != NXT_HTTP_NOT_FOUND) { 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); 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", f->name); + nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); return NULL; } |