Skip to content

【错误与需求】Nginx与chunked模式 #618

Open
@CsVeryLoveXieWenLi

Description

@CsVeryLoveXieWenLi

1. 使用环境

OS:Linux armbian 5.4.279-ophub #1 SMP PREEMPT Wed Jul 10 10:53:39 EDT 2024 aarch64 aarch64 aarch64 GNU/Linux
Version:Cinatra-0.9.2

2. 问题代码

#ifdef _WIN32
#define _WIN32_WINNT 0x0601
#endif

#define BUFFER_SIZE 1024 * 100


#include <cinatra.hpp>


using namespace cinatra;


// Tools
async_simple::coro::Lazy<void> sends(coro_http_response& response, std::filesystem::path& path) {
    // Type
    std::string      _path     = path.string();
    std::string_view extension = get_extension(_path);
    std::string_view mime      = get_mime_type(extension);

    response.add_header("content-type", mime.data());


    // Format
    response.set_format_type(format_type::chunked);


    // Open
    coro_io::coro_file file{};
    file.open(_path, std::ios::in);


    // Read And Send
    bool        ok;
    bool        end;
    std::string buffer;

    // reserve
    buffer.reserve(BUFFER_SIZE);

    // start
    ok = co_await response.get_conn()->begin_chunked();
    if (!ok) {
        file.close();
        co_return;
    }

    // read
    while (true) {
        auto [_, size] = co_await file.async_read(buffer.data(), BUFFER_SIZE);

        end = file.eof();
        ok  = co_await response.get_conn()->write_chunked(std::string_view(buffer.data(), size), end);

        if (!ok || end) {
            file.close();
            co_return;
        }
    }
}


// Main
int main(int argc, char* argv[]) {
    // Command
    if (argc != 5) {
        printf("Use: StaticWeb [cpus] [host] [port] [dir]\n");
        return 1;
    }

    // Static
    std::filesystem::path dir(argv[4]);
    std::filesystem::path nfound = dir / "404.html";


    // Create
    coro_http_server server(atoi(argv[1]), atoi(argv[3]), argv[2], true);


    // Default
    server.set_default_handler(
        [&](coro_http_request& request, coro_http_response& response) -> async_simple::coro::Lazy<void> {
            // Is Get Method?
            if (request.get_method() != "GET" || request.is_upgrade()) co_return;


            // Get Path
            std::string   _pathname = code_utils::url_decode(request.get_url()).substr(1);
            std::u8string pathname(_pathname.begin(), _pathname.end());


            // Src File
            std::filesystem::path vpath = dir / pathname;


            // Not Exixts
            if (!std::filesystem::exists(vpath)) vpath = nfound;


            // Not Dir
            if (!std::filesystem::is_directory(vpath)) {
                co_await sends(response, vpath);
                co_return;
            }

            // Is Dir
            vpath /= "index.html";

            std::filesystem::exists(vpath) ? co_await sends(response, vpath)
                                           : response.set_status_and_content_view(status_type::method_not_allowed, "");
        }
    );


    // Run
    return server.sync_start().value();
}

4. Nginx配置

# 反代主页
server
{
    listen [::]:80;
    server_name xxx.xxx.cn;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:83;
        chunked_transfer_encoding on;
    }
}

5. 问题描述

当我使用chunked模式传输的时候,会直接被Nginx关闭socket?我使用了Nginx作为反向代理。

为何我会这么认为?我使用curl访问127.0.0.1:83的时候一切正常,会返回请求的相应文件。

当我使用Nginx,访问xxx.xxx.cn,被转发到127.0.0.1:83,通过Nginx的逻辑进行访问,会出现 “async_write error: Bad file descriptor”。

socket也是一个文件描述符(?)其中唯一的写入只有write_chunked,不测试set_status_and_content_view。

这是我的项目,如有疑问请访问:https://github.com/CsVeryLoveXieWenLi/StaticWeb

6. 其他

我并未测试直接返回,不使用chunked模式,但是我觉得就是这样,请稍等我测试直接返回。

我们是否应该出一个流式访问而非chunked模式,相关的API接口?不应该读取保存全部到内存。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions