⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request.cxx

📁 PTypes (C++ Portable Types Library) is a simple alternative to the STL that includes multithreading
💻 CXX
📖 第 1 页 / 共 2 页
字号:
            {                del(fvalue, 0, 6);                const char* p = fvalue;                char* e;                int rmin = strtol(p, &e, 10);                if (*e == '-')                {                    p = e + 1;                    int rmax = strtol(p, &e, 10);                    if (e == p)                        rmax = -1;                    // we don't support multiple ranges, neither negative ranges                    if (*e == 0 && rmin >= 0)                    {                        partial = true;                        range_min = rmin;                        range_max = rmax;                    }                }            }        }        // other headers go to request_rec::headers for use in         // custom plugins/modules. so called "coalesce" headers        // are not supported yet        else            put(headers, fname, fvalue);    }    // convert the referer URI to relative if on the same host    if (!isempty(referer))    {        string s = "http://" + host;        if (strncmp(s, referer, length(s)) == 0)            del(referer, 0, length(s));        if (isempty(referer))            referer = "/";    }    sockin->skipline();}void request_rec::analyze_uri(){    string s = uri;    if (!isurl(uri))    {        // if request URI is just a path        if (*pconst(uri) != '/')            rsp_bad_request();        if (version > HTTP_VER_09 && isempty(host))            rsp_bad_request();        s = "http://" + host + uri;    }    urlcrack(s, url);    // split the path into components    strlist pathlist;    split_path(url.path, pathlist);    abs_path = cfg_document_root + '/';    rel_path = '/';    file_type = FT_DIRECTORY;    // we respond to "http://localhost/.wstat" by showing the server status report    if (length(pathlist) > 0 && getstr(pathlist, 0) == DEF_STAT_PATH)        rsp_wstat();    // analyze path components one by one and stop where the    // component does not exist, or where we see a file, not a    // directory. note, that the request-uri may be longer and    // may contain extra components which are ignored. f.ex.    // the request uri is /dir/file.html/other/stuff/. the    // scan stops at file.html and ignores the rest. this is the    // way apache and most other daemons work.    // besides, we may pass a non-existent path to a registered    // path handler.    int i = 0;    while (i < length(pathlist))    {        string s = getstr(pathlist, i);        abs_path += s;        rel_path += s;        file_type = get_file_type(abs_path);        if (file_type == FT_DIRECTORY)        {            abs_path += '/';            rel_path += '/';        }        else if (file_type == FT_FILE)        {            file_name = s;            break;        }        else if (file_type == FT_OTHER) // pipe or device            rsp_forbidden();        else        {            handler_info* h = find_handler(path_list, rel_path);            if (h != 0)            {                path_callback(h->callback)(*this);                // the handler must throw an ehttp exception                fatal(253, "Internal error 253");            }            else                rsp_not_found();        }        i++;    }    if (file_type == FT_DIRECTORY)    {        // check for the trailing slash and redirect to the canonical        // form if necessary        if (trail_char(url.path) != '/')        {            url.path += '/';            rsp_redirect(urlcreate(url));        }        // find the default index file        if (cfg_def_index_files)        {            const char** idx = cfg_index_files;            while (*idx != nil)            {                string t = abs_path + *idx;                if (is_file(t))                {                    abs_path = t;                    file_type = FT_FILE;                    file_name = *idx;                    break;                }                idx++;            }        }    }    // other useful info about the object    sym_link = is_symlink(abs_path);    executable = is_executable(abs_path);    if (!isempty(file_name))    {        file_ext = get_file_ext(file_name);        handler_info* h = find_handler(file_list, file_ext);        if (h != 0)        {            file_callback(h->callback)(*this);            // the handler must throw an ehttp exception            fatal(251, "Internal error 251");        }    }}void request_rec::rsp_dir_index(){    if (!cfg_dir_indexes)        rsp_dir_index_forbidden();    filist list(slflags(SL_SORTED | SL_CASESENS | SL_OWNOBJECTS));    get_directory(list, abs_path, true, 500);    if (length(list) == 0)        rsp_forbidden();    // we don't know the length of the resulting file    keep_alive = false;    begin_response(200, "OK");        if (method == HTTP_GET)     // not HEAD        put_content_type("text/html");    end_headers();    // build an index HTML page    std_html_header(*sockout, "Index of " + rel_path);    sockout->put("<hr noshade size=1>\n");    sockout->put("<pre>\n");    html_show_file_list(*sockout, list);    clear(list);    get_directory(list, abs_path, false, 500);    html_show_file_list(*sockout, list);        sockout->put("</pre>\n");    std_html_footer(*sockout);            end_response();}static void show_lifetime(outstm* sockout, datetime t){    datetime diff = now() - t;    int d = days(diff);    if (d > 0)        sockout->putf("%dd ", d);    sockout->put(dttostring(diff, "%H:%M:%S"));}static ipaddress localhost(127, 0, 0, 1);void request_rec::rsp_wstat(){    // only requests from localhost are allowed    if (client_ip != localhost)        rsp_forbidden();    keep_alive = false;    begin_response(200, "OK");        if (method == HTTP_GET)     // not HEAD        put_content_type("text/html");    end_headers();    std_html_header(*sockout, "wshare status report");    sockout->put("<pre>\n");    sockout->putf("  Requests: %d\n", thread_seq);    sockout->put("  Running: ");    show_lifetime(sockout, ::started);    sockout->put("\n\n");    sockout->put("  Client          Status Lifetime  Request\n");//    sockout->put("</pre>\n");    sockout->put("<hr noshade size=1>\n");//    sockout->put("<pre>\n");    for (int i = 0; i < threads.count; i++)    {        if (threads.list[i] == 0)            continue;        // copy all parameters to local vars to free the thread_list mutex earlier        ipaddress tclient_ip = 0;        req_stat_t tstat = STAT_READ;        datetime tstarted = invdatetime;        string treq_line;        threads.lock.rdlock();        try        {            client_thread* t = threads.list[i];            if (t != 0)            {                tclient_ip = t->client_ip;                tstat = t->stat;                tstarted = t->started;                treq_line = t->req_line;            }        }        catch(...)        {            threads.lock.unlock();        }        threads.lock.unlock();        if (tclient_ip == 0)            continue;        sockout->putf("  %-15s %s", pconst(iptostring(tclient_ip)), stat_str[tstat]);        show_lifetime(sockout, tstarted);        sockout->put("  ");        html_encode(*sockout, treq_line);        sockout->put("\n");    }    sockout->put("</pre>\n");    std_html_footer(*sockout);    end_response();}void request_rec::rsp_file(){    // .ht* files are forbidden, like with Apache    if (strncmp(file_name, ".ht", 3) == 0)        rsp_forbidden();    large fsize64 = get_file_size(abs_path);    // large files are not supported yet    if (fsize64 >= (large)INT_MAX)        rsp_not_found();        int fsize = (int)fsize64;    if (fsize < 0)        rsp_not_found();    // test the file for readability    infile f(abs_path);    try    {        f.set_bufsize(0);        f.open();    }    catch(estream* e)    {        delete e;        rsp_forbidden();    }    // partial content    int txsize = fsize;    if (partial)    {        if (range_max == -1)            range_max = fsize - 1;        if (range_min >= 0 && range_min < range_max && range_max < fsize)            txsize = range_max - range_min + 1;        else            partial = false;    }    // send headers    datetime fmtime = get_file_mtime(abs_path);    if (if_modified != invdatetime && fmtime != invdatetime && fmtime <= if_modified)        rsp_not_modified();        if (partial)        begin_response(206, "Partial Content");    else        begin_response(200, "OK");    put_content_type(get_mimetype(abs_path));    put_content_length(txsize);    if (partial)        put_header("Content-Range",         "bytes " + itostring(range_min) + '-' + itostring(range_max) + '/' + itostring(fsize));    if (cfg_file_mtime)        put_header("Last-Modified", http_time_stamp(fmtime));    end_headers();    // send content    if (partial)        f.seek(range_min); // will implement 64-bit seek in the future    char buf[FILE_BUF_SIZE];    while (txsize > 0)    {        int r = f.read(buf, imin(sizeof(buf), txsize));        if (r <= 0)            break;        sockout->write(buf, r);        txsize -= r;    }        // if for some reason the number of bytes sent does not correspond to the    // promised content length, just close the connection    if (txsize != 0)        keep_alive = false;    end_response();}void request_rec::respond(){    try    {        if (thread_count > cfg_max_clients)            rsp_overloaded();        parse_method();        parse_request_line();        parse_headers();        analyze_uri();        if (file_type == FT_DIRECTORY)            rsp_dir_index();        else if (file_type == FT_FILE)            rsp_file();        else            rsp_not_found();        // all branches must throw an ehttp exception        // before reaching this point        fatal(254, "Internal error 254");    }    catch(ehttp e)    {        if (keep_alive)        {            sockout->flush();            stat = STAT_WAIT;        }        else        {            sockin->close();            sockout->close();        }        htlog_write(client_ip, req_line, e.code, sockout->tell() - hdr_size, referer);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -