Annotation of embedaddon/nginx/src/http/modules/ngx_http_static_module.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_http.h>
! 11:
! 12:
! 13: static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
! 14: static ngx_int_t ngx_http_static_init(ngx_conf_t *cf);
! 15:
! 16:
! 17: ngx_http_module_t ngx_http_static_module_ctx = {
! 18: NULL, /* preconfiguration */
! 19: ngx_http_static_init, /* postconfiguration */
! 20:
! 21: NULL, /* create main configuration */
! 22: NULL, /* init main configuration */
! 23:
! 24: NULL, /* create server configuration */
! 25: NULL, /* merge server configuration */
! 26:
! 27: NULL, /* create location configuration */
! 28: NULL /* merge location configuration */
! 29: };
! 30:
! 31:
! 32: ngx_module_t ngx_http_static_module = {
! 33: NGX_MODULE_V1,
! 34: &ngx_http_static_module_ctx, /* module context */
! 35: NULL, /* module directives */
! 36: NGX_HTTP_MODULE, /* module type */
! 37: NULL, /* init master */
! 38: NULL, /* init module */
! 39: NULL, /* init process */
! 40: NULL, /* init thread */
! 41: NULL, /* exit thread */
! 42: NULL, /* exit process */
! 43: NULL, /* exit master */
! 44: NGX_MODULE_V1_PADDING
! 45: };
! 46:
! 47:
! 48: static ngx_int_t
! 49: ngx_http_static_handler(ngx_http_request_t *r)
! 50: {
! 51: u_char *last, *location;
! 52: size_t root, len;
! 53: ngx_str_t path;
! 54: ngx_int_t rc;
! 55: ngx_uint_t level;
! 56: ngx_log_t *log;
! 57: ngx_buf_t *b;
! 58: ngx_chain_t out;
! 59: ngx_open_file_info_t of;
! 60: ngx_http_core_loc_conf_t *clcf;
! 61:
! 62: if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
! 63: return NGX_HTTP_NOT_ALLOWED;
! 64: }
! 65:
! 66: if (r->uri.data[r->uri.len - 1] == '/') {
! 67: return NGX_DECLINED;
! 68: }
! 69:
! 70: log = r->connection->log;
! 71:
! 72: /*
! 73: * ngx_http_map_uri_to_path() allocates memory for terminating '\0'
! 74: * so we do not need to reserve memory for '/' for possible redirect
! 75: */
! 76:
! 77: last = ngx_http_map_uri_to_path(r, &path, &root, 0);
! 78: if (last == NULL) {
! 79: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 80: }
! 81:
! 82: path.len = last - path.data;
! 83:
! 84: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
! 85: "http filename: \"%s\"", path.data);
! 86:
! 87: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
! 88:
! 89: ngx_memzero(&of, sizeof(ngx_open_file_info_t));
! 90:
! 91: of.read_ahead = clcf->read_ahead;
! 92: of.directio = clcf->directio;
! 93: of.valid = clcf->open_file_cache_valid;
! 94: of.min_uses = clcf->open_file_cache_min_uses;
! 95: of.errors = clcf->open_file_cache_errors;
! 96: of.events = clcf->open_file_cache_events;
! 97:
! 98: if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
! 99: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 100: }
! 101:
! 102: if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
! 103: != NGX_OK)
! 104: {
! 105: switch (of.err) {
! 106:
! 107: case 0:
! 108: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 109:
! 110: case NGX_ENOENT:
! 111: case NGX_ENOTDIR:
! 112: case NGX_ENAMETOOLONG:
! 113:
! 114: level = NGX_LOG_ERR;
! 115: rc = NGX_HTTP_NOT_FOUND;
! 116: break;
! 117:
! 118: case NGX_EACCES:
! 119: #if (NGX_HAVE_OPENAT)
! 120: case NGX_EMLINK:
! 121: case NGX_ELOOP:
! 122: #endif
! 123:
! 124: level = NGX_LOG_ERR;
! 125: rc = NGX_HTTP_FORBIDDEN;
! 126: break;
! 127:
! 128: default:
! 129:
! 130: level = NGX_LOG_CRIT;
! 131: rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 132: break;
! 133: }
! 134:
! 135: if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
! 136: ngx_log_error(level, log, of.err,
! 137: "%s \"%s\" failed", of.failed, path.data);
! 138: }
! 139:
! 140: return rc;
! 141: }
! 142:
! 143: r->root_tested = !r->error_page;
! 144:
! 145: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
! 146:
! 147: if (of.is_dir) {
! 148:
! 149: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
! 150:
! 151: ngx_http_clear_location(r);
! 152:
! 153: r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
! 154: if (r->headers_out.location == NULL) {
! 155: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 156: }
! 157:
! 158: len = r->uri.len + 1;
! 159:
! 160: if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
! 161: location = path.data + clcf->root.len;
! 162:
! 163: *last = '/';
! 164:
! 165: } else {
! 166: if (r->args.len) {
! 167: len += r->args.len + 1;
! 168: }
! 169:
! 170: location = ngx_pnalloc(r->pool, len);
! 171: if (location == NULL) {
! 172: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 173: }
! 174:
! 175: last = ngx_copy(location, r->uri.data, r->uri.len);
! 176:
! 177: *last = '/';
! 178:
! 179: if (r->args.len) {
! 180: *++last = '?';
! 181: ngx_memcpy(++last, r->args.data, r->args.len);
! 182: }
! 183: }
! 184:
! 185: /*
! 186: * we do not need to set the r->headers_out.location->hash and
! 187: * r->headers_out.location->key fields
! 188: */
! 189:
! 190: r->headers_out.location->value.len = len;
! 191: r->headers_out.location->value.data = location;
! 192:
! 193: return NGX_HTTP_MOVED_PERMANENTLY;
! 194: }
! 195:
! 196: #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
! 197:
! 198: if (!of.is_file) {
! 199: ngx_log_error(NGX_LOG_CRIT, log, 0,
! 200: "\"%s\" is not a regular file", path.data);
! 201:
! 202: return NGX_HTTP_NOT_FOUND;
! 203: }
! 204:
! 205: #endif
! 206:
! 207: if (r->method & NGX_HTTP_POST) {
! 208: return NGX_HTTP_NOT_ALLOWED;
! 209: }
! 210:
! 211: rc = ngx_http_discard_request_body(r);
! 212:
! 213: if (rc != NGX_OK) {
! 214: return rc;
! 215: }
! 216:
! 217: log->action = "sending response to client";
! 218:
! 219: r->headers_out.status = NGX_HTTP_OK;
! 220: r->headers_out.content_length_n = of.size;
! 221: r->headers_out.last_modified_time = of.mtime;
! 222:
! 223: if (ngx_http_set_etag(r) != NGX_OK) {
! 224: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 225: }
! 226:
! 227: if (ngx_http_set_content_type(r) != NGX_OK) {
! 228: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 229: }
! 230:
! 231: if (r != r->main && of.size == 0) {
! 232: return ngx_http_send_header(r);
! 233: }
! 234:
! 235: r->allow_ranges = 1;
! 236:
! 237: /* we need to allocate all before the header would be sent */
! 238:
! 239: b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
! 240: if (b == NULL) {
! 241: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 242: }
! 243:
! 244: b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
! 245: if (b->file == NULL) {
! 246: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 247: }
! 248:
! 249: rc = ngx_http_send_header(r);
! 250:
! 251: if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
! 252: return rc;
! 253: }
! 254:
! 255: b->file_pos = 0;
! 256: b->file_last = of.size;
! 257:
! 258: b->in_file = b->file_last ? 1: 0;
! 259: b->last_buf = (r == r->main) ? 1: 0;
! 260: b->last_in_chain = 1;
! 261:
! 262: b->file->fd = of.fd;
! 263: b->file->name = path;
! 264: b->file->log = log;
! 265: b->file->directio = of.is_directio;
! 266:
! 267: out.buf = b;
! 268: out.next = NULL;
! 269:
! 270: return ngx_http_output_filter(r, &out);
! 271: }
! 272:
! 273:
! 274: static ngx_int_t
! 275: ngx_http_static_init(ngx_conf_t *cf)
! 276: {
! 277: ngx_http_handler_pt *h;
! 278: ngx_http_core_main_conf_t *cmcf;
! 279:
! 280: cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
! 281:
! 282: h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
! 283: if (h == NULL) {
! 284: return NGX_ERROR;
! 285: }
! 286:
! 287: *h = ngx_http_static_handler;
! 288:
! 289: return NGX_OK;
! 290: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>