[mod_ssi] produce content in subrequest hook

(prerequisite for future mod_ssi enhancements)

This commit also addresses the concern that mod_geoip would
(previously) need to be listed in modules prior to mod_ssi.
x-ref:
  https://github.com/lighttpd/lighttpd1.4/pull/73
This commit is contained in:
Glenn Strauss 2016-12-06 00:25:56 -05:00
parent ac9822f468
commit 83ec97a054
3 changed files with 69 additions and 17 deletions

View File

@ -40,6 +40,21 @@
#include "etag.h"
static handler_ctx * handler_ctx_init(plugin_data *p) {
handler_ctx *hctx = calloc(1, sizeof(*hctx));
force_assert(hctx);
hctx->timefmt = p->timefmt;
hctx->stat_fn = p->stat_fn;
hctx->ssi_vars = p->ssi_vars;
hctx->ssi_cgi_env = p->ssi_cgi_env;
memcpy(&hctx->conf, &p->conf, sizeof(plugin_config));
return hctx;
}
static void handler_ctx_free(handler_ctx *hctx) {
free(hctx);
}
/* The newest modified time of included files for include statement */
static volatile time_t include_file_last_mtime = 0;
@ -150,7 +165,7 @@ static int ssi_env_add(void *venv, const char *key, size_t klen, const char *val
return 0;
}
static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
static int build_ssi_cgi_vars(server *srv, connection *con, handler_ctx *p) {
http_cgi_opts opts = { 0, 0, NULL, NULL };
/* temporarily remove Authorization from request headers
* so that Authorization does not end up in SSI environment */
@ -175,7 +190,7 @@ static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
return 0;
}
static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, const char **l, size_t n, struct stat *st) {
static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const char **l, size_t n, struct stat *st) {
/**
* <!--#element attribute=value attribute=value ... -->
@ -1008,7 +1023,7 @@ static int mod_ssi_parse_ssi_stmt_offlen(int o[10], const char * const s, const
return -1;
}
static void mod_ssi_parse_ssi_stmt(server *srv, connection *con, plugin_data *p, char *s, int len, struct stat *st) {
static void mod_ssi_parse_ssi_stmt(server *srv, connection *con, handler_ctx *p, char *s, int len, struct stat *st) {
/**
* <!--#element attribute=value attribute=value ... -->
@ -1079,7 +1094,7 @@ static int mod_ssi_stmt_len(const char *s, const int len) {
return 0; /* incomplete directive "<!--#...-->" */
}
static void mod_ssi_read_fd(server *srv, connection *con, plugin_data *p, int fd, struct stat *st) {
static void mod_ssi_read_fd(server *srv, connection *con, handler_ctx *p, int fd, struct stat *st) {
ssize_t rd;
size_t offset, pretag;
char buf[8192];
@ -1164,7 +1179,7 @@ static void mod_ssi_read_fd(server *srv, connection *con, plugin_data *p, int fd
# define FIFO_NONBLOCK 0
#endif
static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
static int mod_ssi_handle_request(server *srv, connection *con, handler_ctx *p) {
int fd;
struct stat st;
@ -1173,9 +1188,7 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p)
array_reset(p->ssi_vars);
array_reset(p->ssi_cgi_env);
buffer_copy_string_len(p->timefmt, CONST_STR_LEN("%a, %d %b %Y %H:%M:%S %Z"));
p->sizefmt = 0;
build_ssi_cgi_vars(srv, con, p);
p->if_is_false = 0;
/* Reset the modified time of included files */
include_file_last_mtime = 0;
@ -1197,7 +1210,6 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p)
close(fd);
con->file_started = 1;
con->file_finished = 1;
con->mode = p->id;
if (buffer_string_is_empty(p->conf.content_type)) {
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
@ -1291,19 +1303,46 @@ URIHANDLER_FUNC(mod_ssi_physical_path) {
if (buffer_is_empty(ds->value)) continue;
if (buffer_is_equal_right_len(con->physical.path, ds->value, buffer_string_length(ds->value))) {
con->plugin_ctx[p->id] = handler_ctx_init(p);
con->mode = p->id;
break;
}
}
return HANDLER_GO_ON;
}
SUBREQUEST_FUNC(mod_ssi_handle_subrequest) {
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
if (con->mode != p->id) return HANDLER_GO_ON; /* not my job */
/*
* NOTE: if mod_ssi modified to use fdevents, HANDLER_WAIT_FOR_EVENT,
* instead of blocking to completion, then hctx->timefmt, hctx->ssi_vars,
* and hctx->ssi_cgi_env should be allocated and cleaned up per request.
*/
/* handle ssi-request */
if (mod_ssi_handle_request(srv, con, p)) {
if (mod_ssi_handle_request(srv, con, hctx)) {
/* on error */
con->http_status = 500;
con->mode = DIRECT;
}
return HANDLER_FINISHED;
}
}
static handler_t mod_ssi_connection_reset(server *srv, connection *con, void *p_d) {
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (hctx) {
handler_ctx_free(hctx);
con->plugin_ctx[p->id] = NULL;
}
/* not found */
UNUSED(srv);
return HANDLER_GO_ON;
}
@ -1316,6 +1355,8 @@ int mod_ssi_plugin_init(plugin *p) {
p->init = mod_ssi_init;
p->handle_subrequest_start = mod_ssi_physical_path;
p->handle_subrequest = mod_ssi_handle_subrequest;
p->connection_reset = mod_ssi_connection_reset;
p->set_defaults = mod_ssi_set_defaults;
p->cleanup = mod_ssi_free;

View File

@ -20,6 +20,19 @@ typedef struct {
typedef struct {
PLUGIN_DATA;
buffer *timefmt;
buffer *stat_fn;
array *ssi_vars;
array *ssi_cgi_env;
plugin_config **config_storage;
plugin_config conf;
} plugin_data;
typedef struct {
buffer *timefmt;
int sizefmt;
@ -30,11 +43,9 @@ typedef struct {
int if_level, if_is_false_level, if_is_false, if_is_false_endif;
plugin_config **config_storage;
plugin_config conf;
} plugin_data;
} handler_ctx;
int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
int ssi_eval_expr(server *srv, connection *con, handler_ctx *p, const char *expr);
#endif

View File

@ -43,7 +43,7 @@ int ssi_val_tobool(ssi_val_t *B) {
}
}
static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p,
static int ssi_expr_tokenizer(server *srv, connection *con, handler_ctx *p,
ssi_tokenizer_t *t, int *token_id, buffer *token) {
int tid = 0;
size_t i;
@ -272,7 +272,7 @@ static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p,
return 0;
}
int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr) {
int ssi_eval_expr(server *srv, connection *con, handler_ctx *p, const char *expr) {
ssi_tokenizer_t t;
void *pParser;
int token_id;