blob: 44e15499c192d78e8892625f71a691dafb3fdcd9 [file] [log] [blame] [raw]
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_echo_foreach.h"
#include "ngx_http_echo_util.h"
#include <nginx.h>
ngx_int_t
ngx_http_echo_it_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_echo_ctx_t *ctx;
ngx_uint_t i;
ngx_array_t *choices;
ngx_str_t *choice_elts, *choice;
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
if (ctx && ctx->foreach != NULL) {
choices = ctx->foreach->choices;
i = ctx->foreach->next_choice;
if (i < choices->nelts) {
choice_elts = choices->elts;
choice = &choice_elts[i];
v->len = choice->len;
v->data = choice->data;
v->valid = 1;
v->no_cacheable = 1;
v->not_found = 0;
return NGX_OK;
}
}
v->not_found = 1;
return NGX_OK;
}
ngx_int_t
ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r,
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
{
ngx_http_echo_loc_conf_t *elcf;
ngx_str_t *delimiter, *compound;
u_char *pos, *last, *end;
ngx_str_t *choice;
ngx_str_t *computed_arg_elts;
ngx_array_t *cmds;
ngx_http_echo_cmd_t *cmd;
ngx_http_echo_cmd_t *cmd_elts;
if (ctx->foreach != NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Nested echo_foreach not supported yet.");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (computed_args->nelts < 2) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"echo_foreach should take at least two arguments. "
"(if your delimiter starts with \"-\", preceding it "
"with a \"--\".)");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
computed_arg_elts = computed_args->elts;
compound = &computed_arg_elts[1];
dd("HEY coumpound len: %u", (int) compound->len);
ctx->foreach = ngx_palloc(r->pool, sizeof(ngx_http_echo_foreach_ctx_t));
if (ctx->foreach == NULL) {
return NGX_ERROR;
}
ctx->foreach->cmd_index = ctx->next_handler_cmd;
ctx->foreach->next_choice = 0;
ctx->foreach->choices = ngx_array_create(r->pool, 10, sizeof(ngx_str_t));
if (ctx->foreach->choices == NULL) {
return NGX_ERROR;
}
delimiter = &computed_arg_elts[0];
pos = compound->data;
end = compound->data + compound->len;
while ((last = ngx_http_echo_strlstrn(pos, end, delimiter->data,
delimiter->len - 1)) != NULL)
{
dd("entered the loop");
if (last == pos) {
dd("!!! len == 0");
pos = last + delimiter->len;
continue;
}
choice = ngx_array_push(ctx->foreach->choices);
if (choice == NULL) {
return NGX_ERROR;
}
choice->data = pos;
choice->len = last - pos;
pos = last + delimiter->len;
}
if (pos < end) {
choice = ngx_array_push(ctx->foreach->choices);
if (choice == NULL) {
return NGX_ERROR;
}
choice->data = pos;
choice->len = end - pos;
}
if (ctx->foreach->choices->nelts == 0) {
/* skip the foreach body entirely */
elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
cmds = elcf->handler_cmds;
cmd_elts = cmds->elts;
for (/* void */; ctx->next_handler_cmd < cmds->nelts;
ctx->next_handler_cmd++)
{
cmd = &cmd_elts[ctx->next_handler_cmd + 1];
if (cmd->opcode == echo_opcode_echo_end) {
return NGX_OK;
}
}
}
return NGX_OK;
}
ngx_int_t
ngx_http_echo_exec_echo_end(ngx_http_request_t *r,
ngx_http_echo_ctx_t *ctx)
{
if (ctx->foreach == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Found a echo_end that has no corresponding echo_foreach "
"before it.");
return NGX_ERROR;
}
ctx->foreach->next_choice++;
if (ctx->foreach->next_choice >= ctx->foreach->choices->nelts) {
/* TODO We need to explicitly free the foreach ctx from
* the pool */
ctx->foreach = NULL;
return NGX_OK;
}
dd("echo_end: ++ next_choice (total: %u): %u",
(unsigned) ctx->foreach->choices->nelts,
(unsigned) ctx->foreach->next_choice);
/* the main handler dispatcher loop will increment
* ctx->next_handler_cmd for us anyway. */
ctx->next_handler_cmd = ctx->foreach->cmd_index;
return NGX_OK;
}