int handle_request()

in net/http/server.cpp [194:251]


    int handle_request(Request &req, Response &resp, std::string_view prefix) override {
        LOG_DEBUG("enter fs handler");
        DEFER(LOG_DEBUG("leave fs handler"));
        auto target = req.target();
        auto pos = target.find("?");
        estring_view query;
        if (pos != std::string_view::npos) {
            query = target.substr(pos + 1);
            target = target.substr(0, pos);
        }

        estring_view filename(target);
        if (!prefix.empty())
            filename = filename.substr(prefix.size() - 1);

        LOG_DEBUG(VALUE(filename));
        auto file = m_fs->open(filename.extract_c_str(), O_RDONLY);
        if (!file) {
            failed_resp(resp);
            LOG_ERROR_RETURN(0, 0, "open file ` failed", target);
        }
        DEFER(delete file);
        if (!query.empty())
            file->ioctl(fs::HTTP_URL_PARAM, (const char*) query.extract_c_str());

        struct stat buf;
        if (file->fstat(&buf) < 0) {
            failed_resp(resp);
            LOG_ERROR_RETURN(0, 0, "stat file ` failed", target);
        }
        auto file_end_pos = buf.st_size - 1;
        auto range = req.headers.range();
        if (range.first < 0) {
            range.first = file_end_pos - range.second;
            range.second = file_end_pos;
        }
        if (range.second < 0 || range.second > file_end_pos) {
            range.second = file_end_pos;
        }
        if (buf.st_size > 0 &&
            (range.second < range.first || range.first > file_end_pos)) {
            failed_resp(resp, 416);
            LOG_ERROR_RETURN(0, 0, "invalid request range ", target);
        }
        auto req_size = range.second - range.first + 1;
        if (req_size == buf.st_size)
            resp.set_result(200);
        else {
            resp.set_result(206);
            resp.headers.content_range(range.first, range.second, buf.st_size);
        }

        resp.headers.content_length(req_size);
        if (req.verb() == Verb::HEAD)
            return 0;
        file->lseek(range.first, SEEK_SET);
        return resp.write_stream(&*file, req_size);
    }