如何修改 Nginx 的自动索引,以便它生成索引的 JSON 版本而不是 HTML?或者是否有一个模块可以做到这一点?
我想要这个;
代替;
这位博客作者似乎已经做到了;
http://lamsonproject.net/blog/2009-08-03.html
但他并未提及具体方法。
答案1
答案2
Zed(博客文章的所有者与我分享了他的代码,您需要重新编译自动索引模块,它就在那里。
“是的,就是这样。事实证明我使用了 netbsd pkgsrc,所以这是我为软件包构建制作的干净补丁。应该适用于 netbsd 版本 nginx-0.8.20。
—— Zed A. Shaw”
=== modified file 'src/http/modules/ngx_http_autoindex_module.c'
--- old/src/http/modules/ngx_http_autoindex_module.c 2009-07-28 22:17:45 +0000
+++ src/http/modules/ngx_http_autoindex_module.c 2009-07-29 06:16:22 +0000
@@ -1,6 +1,7 @@
/*
* Copyright (C) Igor Sysoev
+ * modified by Zed A. Shaw.
*/
@@ -44,11 +45,7 @@
#define NGX_HTTP_AUTOINDEX_PREALLOCATE 50
-#define NGX_HTTP_AUTOINDEX_NAME_LEN 50
-
-
-static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one,
- const void *two);
+
static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
ngx_dir_t *dir, ngx_str_t *name);
static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf);
@@ -115,46 +112,93 @@
};
-static u_char title[] =
-"<html>" CRLF
-"<head><title>Index of "
-;
-
-
-static u_char header[] =
-"</title></head>" CRLF
-"<body bgcolor=\"white\">" CRLF
-"<h1>Index of "
-;
-
-static u_char tail[] =
-"</body>" CRLF
-"</html>" CRLF
-;
+#define MAX_NAME_LEN 512
+
+static ngx_buf_t *
+autoindex_generate_html(ngx_http_request_t *r, ngx_array_t entries,
+ ngx_http_autoindex_loc_conf_t *alcf)
+{
+ size_t len = 0;
+ ngx_http_autoindex_entry_t *entry;
+ ngx_uint_t i;
+ ngx_buf_t *b;
+
+ entry = entries.elts;
+
+ len = MAX_NAME_LEN * entries.nelts + 1024;
+
+ b = ngx_create_temp_buf(r->pool, len);
+ if (b == NULL) return NULL;
+
+ *b->last++ = '[';
+ *b->last++ = '"';
+ b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+ *b->last++ = '"';
+ *b->last++ = ',';
+ *b->last++ = '[';
+
+ for (i = 0; i < entries.nelts; i++) {
+ if(entry[i].name.len >= MAX_NAME_LEN) {
+ // this name is too long, it's illegal
+ continue;
+ }
+
+ *b->last++ = '"';
+
+ if (entry[i].colon) {
+ *b->last++ = '.';
+ *b->last++ = '/';
+ }
+
+ if (entry[i].escape) {
+ ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
+ NGX_ESCAPE_HTML);
+
+ b->last += entry[i].name.len + entry[i].escape;
+
+ // needs to be escaped
+ } else {
+ b->last = ngx_cpymem(b->last, entry[i].name.data,
+ entry[i].name.len);
+ // otherwise, it's done
+ }
+
+ if (entry[i].dir) {
+ *b->last++ = '/';
+ }
+
+ *b->last++ = '"';
+
+ if(i < entries.nelts-1) {
+ *b->last++ = ',';
+ }
+ }
+
+ *b->last++ = ']';
+ *b->last++ = ']';
+
+ return b;
+}
static ngx_int_t
ngx_http_autoindex_handler(ngx_http_request_t *r)
{
- u_char *last, *filename, scale;
- off_t length;
- size_t len, utf_len, allocated, root;
- ngx_tm_t tm;
+ u_char *last, *filename;
+ size_t len, allocated, root;
ngx_err_t err;
ngx_buf_t *b;
- ngx_int_t rc, size;
+ ngx_int_t rc;
ngx_str_t path;
ngx_dir_t dir;
- ngx_uint_t i, level, utf8;
+ ngx_uint_t level, utf8;
ngx_pool_t *pool;
- ngx_time_t *tp;
ngx_chain_t out;
ngx_array_t entries;
- ngx_http_autoindex_entry_t *entry;
ngx_http_autoindex_loc_conf_t *alcf;
+ ngx_http_autoindex_entry_t *entry;
- static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
if (r->uri.data[r->uri.len - 1] != '/') {
return NGX_DECLINED;
@@ -234,9 +278,9 @@
}
r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_type_len = sizeof("text/html") - 1;
- r->headers_out.content_type.len = sizeof("text/html") - 1;
- r->headers_out.content_type.data = (u_char *) "text/html";
+ r->headers_out.content_type_len = sizeof("application/javascript") - 1;
+ r->headers_out.content_type.len = sizeof("application/javascript") - 1;
+ r->headers_out.content_type.data = (u_char *) "application/javascript";
rc = ngx_http_send_header(r);
@@ -363,184 +407,7 @@
ngx_close_dir_n " \"%s\" failed", &path);
}
- len = sizeof(title) - 1
- + r->uri.len
- + sizeof(header) - 1
- + r->uri.len
- + sizeof("</h1>") - 1
- + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
- + sizeof("</pre><hr>") - 1
- + sizeof(tail) - 1;
-
- entry = entries.elts;
- for (i = 0; i < entries.nelts; i++) {
- len += sizeof("<a href=\"") - 1
- + entry[i].name.len + entry[i].escape
- + 1 /* 1 is for "/" */
- + sizeof("\">") - 1
- + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2
- + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2
- + sizeof("</a>") - 1
- + sizeof(" 28-Sep-1970 12:00 ") - 1
- + 20 /* the file size */
- + 2;
- }
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (entries.nelts > 1) {
- ngx_qsort(entry, (size_t) entries.nelts,
- sizeof(ngx_http_autoindex_entry_t),
- ngx_http_autoindex_cmp_entries);
- }
-
- b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
- b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
- b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
-
- b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
- sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);
-
- tp = ngx_timeofday();
-
- for (i = 0; i < entries.nelts; i++) {
- b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
-
- if (entry[i].colon) {
- *b->last++ = '.';
- *b->last++ = '/';
- }
-
- if (entry[i].escape) {
- ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
- NGX_ESCAPE_HTML);
-
- b->last += entry[i].name.len + entry[i].escape;
-
- } else {
- b->last = ngx_cpymem(b->last, entry[i].name.data,
- entry[i].name.len);
- }
-
- if (entry[i].dir) {
- *b->last++ = '/';
- }
-
- *b->last++ = '"';
- *b->last++ = '>';
-
- len = entry[i].utf_len;
-
- if (entry[i].name.len != len) {
- if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
-
- } else {
- utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
- }
-
- b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
- utf_len, entry[i].name.len + 1);
- last = b->last;
-
- } else {
- b->last = ngx_cpystrn(b->last, entry[i].name.data,
- NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
- last = b->last - 3;
- }
-
- if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1);
-
- } else {
- if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
- *b->last++ = '/';
- len++;
- }
-
- b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
- ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
- b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
- }
-
- *b->last++ = ' ';
-
- ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);
-
- b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
- tm.ngx_tm_mday,
- months[tm.ngx_tm_mon - 1],
- tm.ngx_tm_year,
- tm.ngx_tm_hour,
- tm.ngx_tm_min);
-
- if (alcf->exact_size) {
- if (entry[i].dir) {
- b->last = ngx_cpymem(b->last, " -",
- sizeof(" -") - 1);
- } else {
- b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
- }
-
- } else {
- if (entry[i].dir) {
- b->last = ngx_cpymem(b->last, " -",
- sizeof(" -") - 1);
-
- } else {
- length = entry[i].size;
-
- if (length > 1024 * 1024 * 1024 - 1) {
- size = (ngx_int_t) (length / (1024 * 1024 * 1024));
- if ((length % (1024 * 1024 * 1024))
- > (1024 * 1024 * 1024 / 2 - 1))
- {
- size++;
- }
- scale = 'G';
-
- } else if (length > 1024 * 1024 - 1) {
- size = (ngx_int_t) (length / (1024 * 1024));
- if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
- size++;
- }
- scale = 'M';
-
- } else if (length > 9999) {
- size = (ngx_int_t) (length / 1024);
- if (length % 1024 > 511) {
- size++;
- }
- scale = 'K';
-
- } else {
- size = (ngx_int_t) length;
- scale = '\0';
- }
-
- if (scale) {
- b->last = ngx_sprintf(b->last, "%6i%c", size, scale);
-
- } else {
- b->last = ngx_sprintf(b->last, " %6i", size);
- }
- }
- }
-
- *b->last++ = CR;
- *b->last++ = LF;
- }
-
- /* TODO: free temporary pool */
-
- b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
-
- b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
+ b = autoindex_generate_html(r, entries, alcf);
if (r == r->main) {
b->last_buf = 1;
@@ -555,63 +422,6 @@
}
-static int ngx_libc_cdecl
-ngx_http_autoindex_cmp_entries(const void *one, const void *two)
-{
- ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
- ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
-
- if (first->dir && !second->dir) {
- /* move the directories to the start */
- return -1;
- }
-
- if (!first->dir && second->dir) {
- /* move the directories to the start */
- return 1;
- }
-
- return (int) ngx_strcmp(first->name.data, second->name.data);
-}
-
-
-#if 0
-
-static ngx_buf_t *
-ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size)
-{
- ngx_chain_t *cl;
-
- if (ctx->buf) {
-
- if ((size_t) (ctx->buf->end - ctx->buf->last) >= size) {
- return ctx->buf;
- }
-
- ctx->size += ctx->buf->last - ctx->buf->pos;
- }
-
- ctx->buf = ngx_create_temp_buf(ctx->pool, ctx->alloc_size);
- if (ctx->buf == NULL) {
- return NULL;
- }
-
- cl = ngx_alloc_chain_link(ctx->pool);
- if (cl == NULL) {
- return NULL;
- }
-
- cl->buf = ctx->buf;
- cl->next = NULL;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return ctx->buf;
-}
-
-#endif
-
static ngx_int_t
ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name)