diff options
| author | Konstantin Pavlov <thresh@nginx.com> | 2022-06-02 16:51:49 +0400 |
|---|---|---|
| committer | Konstantin Pavlov <thresh@nginx.com> | 2022-06-02 16:51:49 +0400 |
| commit | d9fddee1dbfc1f5d49c8f40386289d7188030952 (patch) | |
| tree | 842a62b343ac33eba10e7a426a10b55bb1c46aed /src/nxt_http_return.c | |
| parent | 420395ee2e7cd464e157c49bea3d74f15bf25f30 (diff) | |
| parent | 0d48fe73c4450901622373e35f6ff3a944ec13d6 (diff) | |
| download | unit-1.27.0-1.tar.gz unit-1.27.0-1.tar.bz2 | |
Merged with the default branch.1.27.0-1
Diffstat (limited to 'src/nxt_http_return.c')
| -rw-r--r-- | src/nxt_http_return.c | 177 |
1 files changed, 143 insertions, 34 deletions
diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 18fd490d..82c91568 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -8,13 +8,24 @@ typedef struct { - nxt_http_status_t status; - nxt_str_t location; + nxt_http_status_t status; + nxt_var_t *location; + nxt_str_t encoded; } nxt_http_return_conf_t; +typedef struct { + nxt_str_t location; + nxt_str_t encoded; +} nxt_http_return_ctx_t; + + static nxt_http_action_t *nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); +static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, + const nxt_str_t *location); +static void nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data); +static void nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data); static const nxt_http_request_state_t nxt_http_return_send_state; @@ -24,8 +35,7 @@ nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, nxt_http_action_conf_t *acf) { - nxt_str_t *loc; - nxt_uint_t encode; + nxt_str_t str; nxt_http_return_conf_t *conf; conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); @@ -38,30 +48,20 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, conf->status = nxt_conf_get_number(acf->ret); - if (acf->location.length > 0) { - if (nxt_is_complex_uri_encoded(acf->location.start, - acf->location.length)) - { - loc = nxt_str_dup(mp, &conf->location, &acf->location); - if (nxt_slow_path(loc == NULL)) { - return NXT_ERROR; - } - - } else { - loc = &conf->location; + if (acf->location == NULL) { + return NXT_OK; + } - encode = nxt_encode_complex_uri(NULL, acf->location.start, - acf->location.length); - loc->length = acf->location.length + encode * 2; + nxt_conf_get_string(acf->location, &str); - loc->start = nxt_mp_nget(mp, loc->length); - if (nxt_slow_path(loc->start == NULL)) { - return NXT_ERROR; - } + conf->location = nxt_var_compile(&str, mp, 0); + if (nxt_slow_path(conf->location == NULL)) { + return NXT_ERROR; + } - nxt_encode_complex_uri(loc->start, acf->location.start, - acf->location.length); - } + if (nxt_var_is_const(conf->location)) { + nxt_var_raw(conf->location, &str); + return nxt_http_return_encode(mp, &conf->encoded, &str); } return NXT_OK; @@ -72,13 +72,24 @@ nxt_http_action_t * nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_http_field_t *field; + nxt_int_t ret; + nxt_http_return_ctx_t *ctx; nxt_http_return_conf_t *conf; conf = action->u.conf; - nxt_debug(task, "http return: %d (loc: \"%V\")", - conf->status, &conf->location); +#if (NXT_DEBUG) + nxt_str_t loc; + + if (conf->location == NULL) { + nxt_str_set(&loc, ""); + + } else { + nxt_var_raw(conf->location, &loc); + } + + nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); +#endif if (conf->status >= NXT_HTTP_BAD_REQUEST && conf->status <= NXT_HTTP_SERVER_ERROR_MAX) @@ -87,27 +98,125 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, return NULL; } + if (conf->location == NULL) { + ctx = NULL; + + } else { + ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_return_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + goto fail; + } + } + r->status = conf->status; r->resp.content_length_n = 0; - if (conf->location.length > 0) { + if (ctx == NULL || nxt_var_is_const(conf->location)) { + if (ctx != NULL) { + ctx->encoded = conf->encoded; + } + + nxt_http_return_send_ready(task, r, ctx); + + } else { + ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + nxt_var_query(task, r->var_query, conf->location, &ctx->location); + + nxt_var_query_resolve(task, r->var_query, ctx, + nxt_http_return_send_ready, + nxt_http_return_var_error); + } + + return NULL; + +fail: + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; +} + + +static nxt_int_t +nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, + const nxt_str_t *location) +{ + nxt_uint_t encode; + + if (nxt_is_complex_uri_encoded(location->start, location->length)) { + *encoded = *location; + + return NXT_OK; + } + + encode = nxt_encode_complex_uri(NULL, location->start, location->length); + encoded->length = location->length + encode * 2; + + encoded->start = nxt_mp_nget(mp, encoded->length); + if (nxt_slow_path(encoded->start == NULL)) { + return NXT_ERROR; + } + + nxt_encode_complex_uri(encoded->start, location->start, location->length); + + return NXT_OK; +} + + +static void +nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data) +{ + nxt_int_t ret; + nxt_http_field_t *field; + nxt_http_request_t *r; + nxt_http_return_ctx_t *ctx; + + r = obj; + ctx = data; + + if (ctx != NULL) { + if (ctx->location.length > 0) { + ret = nxt_http_return_encode(r->mem_pool, &ctx->encoded, + &ctx->location); + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } + } + field = nxt_list_zero_add(r->resp.fields); if (nxt_slow_path(field == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + goto fail; } nxt_http_field_name_set(field, "Location"); - field->value = conf->location.start; - field->value_length = conf->location.length; + field->value = ctx->encoded.start; + field->value_length = ctx->encoded.length; } r->state = &nxt_http_return_send_state; nxt_http_request_header_send(task, r, NULL, NULL); - return NULL; + return; + +fail: + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); +} + + +static void +nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data) +{ + nxt_http_request_t *r; + + r = obj; + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } |
