Skip to content

Commit

Permalink
feat: add the function to easily create http download servers
Browse files Browse the repository at this point in the history
  • Loading branch information
helintongh committed Sep 5, 2023
1 parent 5e2b585 commit f3856bb
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ CMakeUserPresets.json
.DS_Store
node_modules
/CMakeSettings.json
!cmake/build.cmake
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,20 @@ cinatra目前支持了multipart和octet-stream格式的上传。
//chunked download
//cinatra will send you the file, if the file is big file(more than 5M) the file will be downloaded by chunked. support continues download

同时可以使用set_http_file_server(std::string path);函数来将cinatra转换为一个http文件下载服务器,path为该文件服务器的路径。示例如下:

#include "cinatra.hpp"
using namespace cinatra;

int main() {
http_server server(std::thread::hardware_concurrency());
server.set_http_file_server("http_file_server");
server.listen("0.0.0.0", "8080");
// 略
}

此时访问当前服务器的`http_file_server`路径时会在浏览器展示所有可下载文件,点击即可下载。

## 示例6:websocket

#include "cinatra.hpp"
Expand Down
1 change: 1 addition & 0 deletions example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ int main() {
// test_ssl_server();
// test_download();
http_server server(std::thread::hardware_concurrency());
server.set_http_file_server("http_download_file_server");
bool r = server.listen("0.0.0.0", "8090");
if (!r) {
// LOG_INFO << "listen failed";
Expand Down
53 changes: 53 additions & 0 deletions include/cinatra/http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ class http_server_ : private noncopyable {
set_file_dir(std::move(path), upload_dir_);
}

void set_http_file_server(std::string path) {
download_display_file_dir_ = path;
}

const std::string &static_dir() const { return static_dir_; }

// xM
Expand Down Expand Up @@ -346,6 +350,16 @@ class http_server_ : private noncopyable {
}
}

if (!download_display_file_dir_.empty()) {
std::string ret = "";
bool is_need_download_lists_response =
build_http_download_lists_response(req, std::move(ret));
if (is_need_download_lists_response) {
res.set_status_and_content(status_type::ok, std::move(ret));
return;
}
}

auto state = req.get_state();
switch (state) {
case cinatra::data_proc_state::data_begin: {
Expand Down Expand Up @@ -587,6 +601,35 @@ class http_server_ : private noncopyable {
}
}

bool build_http_download_lists_response(request &req,
std::string &&resp_str) {
std::string res_str = "";
std::string href_of_head = "<br><a href=\"http://" +
std::string(req.get_header_value("host")) + "/";
std::string href_of_tail = "\"target=\"_blank\">";
if (req.get_res_path() == download_display_file_dir_) {
std::string file_dir_str = static_dir_;
std::filesystem::path dir_path(file_dir_str);

for (const auto &entry : std::filesystem::directory_iterator(dir_path)) {
if (!entry.is_directory()) {
auto u8_file_name = entry.path().filename().u8string();
std::string file_name_str(u8_file_name.begin(), u8_file_name.end());
std::string full_href = href_of_head + file_name_str + href_of_tail +
file_name_str + "</a></br>";
res_str += full_href;
}
}
std::string ret =
download_dir_response_head_ + res_str + download_dir_response_tail_;
resp_str = std::move(ret);
return true;
}
else {
return false;
}
}

service_pool_policy io_service_pool_;

std::size_t max_req_buf_size_ =
Expand All @@ -596,6 +639,7 @@ class http_server_ : private noncopyable {
http_router http_router_;
std::string static_dir_ = fs::absolute("www").string(); // default
std::string upload_dir_ = fs::absolute("www").string(); // default
std::string download_display_file_dir_ = "";
std::time_t static_res_cache_max_age_ = 0;

bool enable_timeout_ = true;
Expand All @@ -620,6 +664,15 @@ class http_server_ : private noncopyable {
uint64_t conn_id_ = 0;
std::unordered_map<uint64_t, std::shared_ptr<connection<ScoketType>>> conns_;
std::mutex conns_mtx_;

std::string download_dir_response_head_ =
"<html>"
"<head><meta charset=\"utf-8\"><title>http file download "
"server</title></head>"
"<body>";
std::string download_dir_response_tail_ =
"</body>"
"</html>";
};

template <typename T>
Expand Down
16 changes: 16 additions & 0 deletions lang/english/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,22 @@ http://127.0.0.1:8080/purecpp/static/show.jpg
//cinatra will send you the file, if the file is big file(more than 5M) the file will be downloaded by chunked. support continues download
```

At the same time, you can use the `set_http_file_server(std::string path);` function to build an http file download server. The parameter path is the path of all downloadable files. Examples are as follows:

```cpp
#include "cinatra.hpp"
using namespace cinatra;

int main() {
http_server server(std::thread::hardware_concurrency());
server.set_http_file_server("http_file_server");
server.listen("0.0.0.0", "8080");
// ......
}
```

In this time, when accessing the `http_file_server` path of the current server, all downloadable files will be displayed in the browser, and you can download them by clicking on them.

### Example 6: WebSocket

```cpp
Expand Down

0 comments on commit f3856bb

Please sign in to comment.