Пример #1
0
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);
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}