Open
Description
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接口?不应该读取保存全部到内存。
Metadata
Metadata
Assignees
Labels
No labels
Activity