static int static_file_handle_error(response_t *resp, int fd) { int err = errno; if (fd > 0) (void) close(fd); // Don't care the failure switch(err) { case EACCES: case EISDIR: return response_send_status(resp, STATUS_FORBIDDEN); case ENOENT: default: return response_send_status(resp, STATUS_NOT_FOUND); } }
static int static_file_write_content(request_t *req, response_t *resp, handler_ctx_t *ctx) { int fd; size_t size, offset; size = context_pop(ctx)->as_long; offset = context_pop(ctx)->as_long; fd = context_peek(ctx)->as_int; debug("writing file"); if (response_send_file(resp, fd, offset, size, static_file_cleanup) < 0) { error("Error sending file"); return response_send_status(resp, STATUS_NOT_FOUND); } return HANDLER_UNFISHED; }
static VALUE response_run(connection_t *c) { /* Call the app to process the request */ VALUE response = rb_funcall_rescue(c->backend->app, sInternedCall, 1, c->env); unsigned sent = 0; if (response == Qundef) { /* log any error */ rb_funcall(c->backend->obj, rb_intern("log_last_exception"), 0); sent = 1; } else { /* store response info and prepare for writing */ int status = FIX2INT(rb_ary_entry(response, 0)); VALUE headers = rb_ary_entry(response, 1); VALUE body = rb_ary_entry(response, 2); /* read buffer no longer needed, free up now so we * can reuse some of it for write buffer */ buffer_reset(&c->read_buffer); connection_watch_writable(c); response_send_status(c, status); response_send_headers(c, headers); response_send_body(c, body); c->finished = 1; if (buffer_eof(&c->write_buffer)) sent = 1; } c->backend->thread_count--; c->thread.active = 0; if (sent) connection_close(c); return Qnil; }
int static_file_handle(request_t *req, response_t *resp, handler_ctx_t *ctx) { mod_static_conf_t *conf; char path[2048]; int fd = -1, res, use_301; struct stat st; size_t len, pathlen, filesize, fileoffset; ctx_state_t val; conf = (mod_static_conf_t*) ctx->conf; len = strlen(conf->root); strncpy(path, conf->root, 2048); if (path[len - 1] == '/') { path[len - 1] = '\0'; } if (req->path[0] != '/') { return response_send_status(resp, STATUS_BAD_REQUEST); } strncat(path, req->path, 2048 - len); debug("Request path: %s, real file path: %s", req->path, path); res = try_open_file(path, &fd, &st); if (res < 0) { return static_file_handle_error(resp, fd); } else if (res > 0) { // Is a directory, try index files. pathlen = strlen(path); use_301 = 0; if (path[pathlen - 1] != '/') { path[pathlen] = '/'; path[pathlen + 1] = '\0'; pathlen++; use_301 = 1; } //for (i = 0; i < 10 && res != 0 && conf->index[i] != NULL; i++) { // path[pathlen] = '\0'; // strncat(path, conf->index[i], 2048 - pathlen); // res = try_open_file(path, &fd, &st); //} path[pathlen] = '\0'; strncat(path, conf->index, 2048 - pathlen); res = try_open_file(path, &fd, &st); path[pathlen] = '\0'; if (res != 0) { if (conf->enable_list_dir) { if (use_301) { // TODO Support HTTPS snprintf(path, 2048, "http://%s%s/", req->host, req->path); response_set_header(resp, "Location", path); resp->status = STATUS_MOVED; resp->content_length = 0; response_send_headers(resp, NULL); return HANDLER_DONE; } show_hidden_file = conf->show_hidden_file; return static_file_listdir(resp, req->path, path); } else { return static_file_handle_error(resp, fd); } } } fileoffset = 0; filesize = st.st_size; res = handle_range(req, resp, &fileoffset, &filesize); if (res < 0) { resp->status = STATUS_OK; } else if (res == 0) { resp->status = STATUS_PARTIAL_CONTENT; } else { return response_send_status(resp, STATUS_RANGE_NOT_SATISFIABLE); } resp->content_length = filesize; handle_content_type(resp, path); if (handle_cache(req, resp, &st, conf)) { return response_send_status(resp, STATUS_NOT_MODIFIED); } val.as_int = fd; context_push(ctx, val); val.as_long = fileoffset; context_push(ctx, val); val.as_long = filesize; context_push(ctx, val); debug("sending headers"); response_send_headers(resp, static_file_write_content); return HANDLER_UNFISHED; }