Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How can I modify to Nginx’s autoindex so that it will generate a JSON version of the index instead of HTML? Or is there a module that already does that?

I want to have this;

http://u.kodingen.com/ClrG

Instead of;

http://u.kodingen.com/Cls2N

This blog writer seems to have done it;

http://u.kodingen.com/Clz3F

http://lamsonproject.net/blog/2009-08-03.html

But he didn't mention how.

share|improve this question
add comment

1 Answer

up vote 1 down vote accepted

Zed (owner of the blog post shared his code with me, you need to recompile autoindex module and it's there.

"Yep here you go. Turns out I used the netbsd pkgsrc so it's a clean patch that I made for the package build. should work with netbsd version 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("&gt;") - 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, "..&gt;</a>", sizeof("..&gt;</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)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.