diff src/http/modules/ngx_http_static_handler.c @ 148:5afee0074707

nginx-0.0.1-2003-10-17-00:19:16 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 16 Oct 2003 20:19:16 +0000
parents 5526213be452
children c71aeb75c071
line wrap: on
line diff
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -4,7 +4,188 @@
 #include <ngx_http.h>
 
 
-int ngx_http_static_handler(ngx_http_request_t *r)
+static int ngx_http_static_handler(ngx_http_request_t *r);
+static int ngx_http_static_init(ngx_cycle_t *cycle);
+
+
+static ngx_command_t  ngx_http_static_commands[] = {
+
+    ngx_null_command
+};
+
+
+
+ngx_http_module_t  ngx_http_static_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+    
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+    
+    NULL,                                  /* create location configuration */
+    NULL                                   /* merge location configuration */
+};  
+
+
+ngx_module_t  ngx_http_static_module = {
+    NGX_MODULE,
+    &ngx_http_static_module_ctx,           /* module context */
+    ngx_http_static_commands,              /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_static_init,                  /* init module */
+    NULL                                   /* init child */
+};
+
+
+int ngx_http_static_translate_handler(ngx_http_request_t *r)
+{
+    char                      *location, *last;
+    ngx_err_t                  err;
+    ngx_table_elt_t           *h;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
+        return NGX_HTTP_NOT_ALLOWED;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (r->uri.data[r->uri.len - 1] == '/') {
+        if (r->path.data == NULL) {
+            ngx_test_null(r->path.data,
+                          ngx_palloc(r->pool,
+                                     clcf->doc_root.len + r->uri.len),
+                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+            ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data,
+                                   clcf->doc_root.len),
+                        r->uri.data, r->uri.len + 1);
+
+        } else {
+            r->path.data[r->path.len] = '\0';
+        }
+
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "directory index of \"%s\" is forbidden", r->path.data);
+
+        return NGX_HTTP_FORBIDDEN;
+    }
+
+    /* "+ 2" is for trailing '/' in redirect and '\0' */
+    ngx_test_null(r->file.name.data,
+                  ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2),
+                  NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+    location = ngx_cpymem(r->file.name.data, clcf->doc_root.data,
+                          clcf->doc_root.len),
+
+    last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1);
+
+ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
+
+#if (WIN9X)
+
+    /*
+     * There is no way to open a file or a directory in Win9X with
+     * one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag.
+     * so we need to check its type before the opening
+     */
+
+    r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data);
+    if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
+        err = ngx_errno;
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
+                      ngx_file_type_n " \"%s\" failed", r->file.name.data);
+
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+            return NGX_HTTP_NOT_FOUND;
+
+        } else if (err == NGX_EACCES) {
+            return NGX_HTTP_FORBIDDEN;
+
+        } else {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+    }
+
+#else
+
+    if (r->file.fd == NGX_INVALID_FILE) {
+        r->file.fd = ngx_open_file(r->file.name.data,
+                                   NGX_FILE_RDONLY, NGX_FILE_OPEN);
+    }
+
+    if (r->file.fd == NGX_INVALID_FILE) {
+        err = ngx_errno;
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
+                      ngx_open_file_n " \"%s\" failed", r->file.name.data);
+
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+            return NGX_HTTP_NOT_FOUND;
+
+        } else if (err == NGX_EACCES) {
+            return NGX_HTTP_FORBIDDEN;
+
+        } else {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+    }
+
+ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd);
+
+    if (!r->file.info_valid) {
+        if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+                          ngx_stat_fd_n " \"%s\" failed", r->file.name.data);
+
+            if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                              ngx_close_file_n " \"%s\" failed",
+                              r->file.name.data);
+            }
+
+            r->file.fd = NGX_INVALID_FILE;
+
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        r->file.info_valid = 1;
+    }
+#endif
+
+    if (ngx_is_dir(r->file.info)) {
+ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
+
+#if !(WIN9X)
+        if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed", r->file.name.data);
+        }
+
+        r->file.fd = NGX_INVALID_FILE;
+#endif
+
+        ngx_test_null(h, ngx_push_table(r->headers_out.headers),
+                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+        *last++ = '/';
+        *last = '\0';
+        h->key.len = 8;
+        h->key.data = "Location" ;
+        h->value.len = last - location;
+        h->value.data = location;
+        r->headers_out.location = h;
+
+        return NGX_HTTP_MOVED_PERMANENTLY;
+    }
+
+    r->content_handler = ngx_http_static_handler;
+
+    return NGX_OK;
+}
+
+
+static int ngx_http_static_handler(ngx_http_request_t *r)
 {
     int                        rc, key, i;
     ngx_log_e                  level;
@@ -20,10 +201,6 @@ int ngx_http_static_handler(ngx_http_req
         return rc;
     }
 
-    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
-        return NGX_HTTP_NOT_ALLOWED;
-    }
-
     ctx = r->connection->log->data;
     ctx->action = "sending response";
 
@@ -142,3 +319,22 @@ int ngx_http_static_handler(ngx_http_req
 
     return ngx_http_output_filter(r, h);
 }
+
+
+static int ngx_http_static_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_conf_ctx_t        *ctx;
+    ngx_http_core_main_conf_t  *cmcf;
+    
+    ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
+    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
+    
+    ngx_test_null(h, ngx_push_array(
+                             &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
+                  NGX_ERROR);
+    *h = ngx_http_static_translate_handler;
+
+    return NGX_OK;
+}
+