configless vhost
Igor Sysoev
is at rambler-co.ru
Fri Jun 27 00:40:10 MSD 2008
On Thu, Jun 26, 2008 at 04:26:54AM -0300, Marcos Neves wrote:
> I have virtualhost with configuration less feature that works like a charm!
>
> server {
> server_name _;
> set $host_without_www $host;
> if ($host ~* www\.(.*)) {
> set $host_without_www $1;
> }
> root /var/www/$host_without_www/;
> access_log logs/$host_without_www.log;
>
> unfortunately, access_log don?t parses variables, so a file named
> $host_without_www.log
> is created instead.
>
> There?s any way to keep access logs separated by host, without need to
> configure one by one by hand?
The attached patch allows variables in access_log.
It's a proof-of-concept: for every log operation it opens/creates log,
writes, and then closes. It does not keep open frequently used logs.
It does not try to create log if a response status is 404 and there is
no root for the request.
--
Igor Sysoev
http://sysoev.ru/en/
-------------- next part --------------
Index: src/http/modules/ngx_http_log_module.c
===================================================================
--- src/http/modules/ngx_http_log_module.c (revision 1389)
+++ src/http/modules/ngx_http_log_module.c (working copy)
@@ -40,7 +40,14 @@
typedef struct {
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+} ngx_http_log_script_t;
+
+
+typedef struct {
ngx_open_file_t *file;
+ ngx_http_log_script_t *script;
time_t disk_full_time;
time_t error_log_time;
ngx_array_t *ops; /* array of ngx_http_log_op_t */
@@ -62,6 +69,8 @@
static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
u_char *buf, size_t len);
+static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
+ ngx_http_log_script_t *script, u_char *buf, size_t len);
static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op);
@@ -235,7 +244,7 @@
file = log[l].file;
- if (file->buffer) {
+ if (file && file->buffer) {
if (len > (size_t) (file->last - file->pos)) {
@@ -289,8 +298,13 @@
ssize_t n;
ngx_err_t err;
- n = ngx_write_fd(log->file->fd, buf, len);
+ if (log->script == NULL) {
+ n = ngx_write_fd(log->file->fd, buf, len);
+ } else {
+ n = ngx_http_log_script_write(r, log->script, buf, len);
+ }
+
if (n == (ssize_t) len) {
return;
}
@@ -325,6 +339,87 @@
}
+static ssize_t
+ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
+ u_char *buf, size_t len)
+{
+ size_t root;
+ ssize_t n;
+ ngx_fd_t fd;
+ ngx_err_t err;
+ ngx_str_t name, path;
+ ngx_uint_t status;
+ ngx_open_file_info_t of;
+ ngx_http_core_loc_conf_t *clcf;
+
+ status = r->err_status ? r->err_status : r->headers_out.status;
+
+ if (status == NGX_HTTP_NOT_FOUND) {
+
+ /* test root directory existance */
+
+ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
+ return -1;
+ }
+
+ path.data[root] = '\0';
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
+ of.valid = clcf->open_file_cache_valid;
+ of.min_uses = clcf->open_file_cache_min_uses;
+ of.errors = clcf->open_file_cache_errors;
+ of.events = clcf->open_file_cache_events;
+
+ if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
+ != NGX_OK
+ || !of.is_dir)
+ {
+ /* no root directory: simulate successfull logging */
+
+ return len;
+ }
+ }
+
+ if (ngx_http_script_run(r, &name, script->lengths->elts, 1,
+ script->values->elts)
+ == NULL)
+ {
+ return -1;
+ }
+
+ name.data[name.len - 1] = '\0';
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http log \"%s\"", name.data);
+
+ fd = ngx_open_file(name.data, NGX_FILE_RDWR,
+ NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND,
+ NGX_FILE_DEFAULT_ACCESS);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+ ngx_open_file_n " \"%s\" failed", name.data);
+ return -1;
+ }
+
+ n = ngx_write_fd(fd, buf, len);
+
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ err = ngx_errno;
+
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", name.data);
+
+ ngx_set_errno(err);
+ }
+
+ return n;
+}
+
+
static u_char *
ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
@@ -678,12 +773,13 @@
{
ngx_http_log_loc_conf_t *llcf = conf;
- ssize_t buf;
- ngx_uint_t i;
- ngx_str_t *value, name;
- ngx_http_log_t *log;
- ngx_http_log_fmt_t *fmt;
- ngx_http_log_main_conf_t *lmcf;
+ ssize_t buf;
+ ngx_uint_t i, n;
+ ngx_str_t *value, name;
+ ngx_http_log_t *log;
+ ngx_http_log_fmt_t *fmt;
+ ngx_http_log_main_conf_t *lmcf;
+ ngx_http_script_compile_t sc;
value = cf->args->elts;
@@ -706,14 +802,41 @@
return NGX_CONF_ERROR;
}
- log->file = ngx_conf_open_file(cf->cycle, &value[1]);
- if (log->file == NULL) {
- return NGX_CONF_ERROR;
+ ngx_memzero(log, sizeof(ngx_http_log_t));
+
+ n = ngx_http_script_variables_count(&value[1]);
+
+ if (n == 0) {
+ log->file = ngx_conf_open_file(cf->cycle, &value[1]);
+ if (log->file == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ if (ngx_conf_full_name(cf->cycle, &value[1], 0) == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
+ if (log->script == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &value[1];
+ sc.lengths = &log->script->lengths;
+ sc.values = &log->script->values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
}
- log->disk_full_time = 0;
- log->error_log_time = 0;
-
if (cf->args->nelts >= 3) {
name = value[2];
@@ -750,6 +873,12 @@
return NGX_CONF_ERROR;
}
+ if (log->script) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "buffered logs can not have variables in name");
+ return NGX_CONF_ERROR;
+ }
+
name.len = value[3].len - 7;
name.data = value[3].data + 7;
More information about the nginx
mailing list