Skip to content

Commit

Permalink
utf8 path (#488)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jan 15, 2024
1 parent 49b951d commit ec7f8d6
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 20 deletions.
3 changes: 3 additions & 0 deletions include/cinatra/coro_http_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,9 @@ class coro_http_client : public std::enable_shared_from_this<coro_http_client> {
std::pair<bool, uri_t> handle_uri(resp_data &data, const S &uri) {
uri_t u;
if (!u.parse_from(uri.data())) {
CINATRA_LOG_WARNING
<< uri
<< ", the url is not right, maybe need to encode the url firstly";
data.net_err = std::make_error_code(std::errc::protocol_error);
data.status = 404;
return {false, {}};
Expand Down
6 changes: 6 additions & 0 deletions include/cinatra/coro_http_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ class coro_http_connection
parser_.method().data(),
parser_.method().length() + 1 + parser_.url().length()};

std::string decode_key;
if (parser_.url().find('%') != std::string_view::npos) {
decode_key = code_utils::url_decode(key);
key = decode_key;
}

if (!body_.empty()) {
request_.set_body(body_);
}
Expand Down
4 changes: 2 additions & 2 deletions include/cinatra/coro_http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,12 @@ class coro_http_server {
}

std::filesystem::path router_path =
std::filesystem::path(static_dir_router_path_);
std::filesystem::u8path(static_dir_router_path_);

std::string uri;
for (auto &file : files_) {
auto relative_path =
std::filesystem::path(file.substr(static_dir_.length())).string();
std::filesystem::u8path(file.substr(static_dir_.length())).string();
if (size_t pos = relative_path.find('\\') != std::string::npos) {
replace_all(relative_path, "\\", "/");
}
Expand Down
46 changes: 31 additions & 15 deletions include/cinatra/url_encode_decode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,40 @@ inline static std::string url_encode(const std::string &value) noexcept {
return result;
}

inline static std::string url_decode(const std::string &value) noexcept {
inline static std::string url_decode(std::string_view str) noexcept {
std::string result;
result.reserve(value.size() / 3 +
(value.size() % 3)); // Minimum size of result

for (std::size_t i = 0; i < value.size(); ++i) {
auto &chr = value[i];
if (chr == '%' && i + 2 < value.size()) {
auto hex = value.substr(i + 1, 2);
auto decoded_chr =
static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
result += decoded_chr;
i += 2;
result.reserve(str.size());

for (size_t i = 0; i < str.size(); ++i) {
char ch = str[i];
if (ch == '%') {
constexpr char hex[] = "0123456789ABCDEF";

if (++i == str.size()) {
result.push_back('?');
break;
}

int hi = (int)(std::find(hex, hex + 16, toupper(str[i])) - hex);

if (++i == str.size()) {
result.push_back('?');
break;
}

int lo = (int)(std::find(hex, hex + 16, toupper(str[i])) - hex);

if ((hi >= 16) || (lo >= 16)) {
result.push_back('?');
break;
}

result.push_back((char)((hi << 4) + lo));
}
else if (chr == '+')
result += ' ';
else if (ch == '+')
result.push_back(' ');
else
result += chr;
result.push_back(ch);
}

return result;
Expand Down
41 changes: 38 additions & 3 deletions tests/test_coro_http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,15 @@ TEST_CASE("coro_server example, will block") {
CHECK(server.port() > 0);
}

bool create_file(std::string_view filename, size_t file_size = 1024) {
std::ofstream out(filename.data(), std::ios::binary);
template <typename View>
bool create_file(View filename, size_t file_size = 1024) {
std::cout << "begin to open file: " << filename << "\n";
std::ofstream out(filename, std::ios::binary);
if (!out.is_open()) {
std::cout << "open file: " << filename << " failed\n";
return false;
}

std::cout << "open file: " << filename << " ok\n";
std::string str(file_size, 'A');
out.write(str.data(), str.size());
return true;
Expand Down Expand Up @@ -175,11 +178,43 @@ TEST_CASE("test multiple download") {

TEST_CASE("test range download") {
create_file("range_test.txt", 64);
#ifdef ASIO_WINDOWS
#else
create_file("中文测试.txt", 64);
create_file(fs::u8path("utf8中文.txt").string(), 64);
#endif
std::cout << fs::current_path() << "\n";
coro_http_server server(1, 9001);
server.set_static_res_dir("", "");
server.set_file_resp_format_type(file_resp_format_type::range);
server.async_start();
std::this_thread::sleep_for(300ms);

#ifdef ASIO_WINDOWS
#else
{
// test Chinese file name
coro_http_client client{};
std::string local_filename = "temp.txt";

std::string base_uri = "http://127.0.0.1:9001/";
std::string path = code_utils::url_encode("中文测试.txt");
auto result = client.download(base_uri + path, local_filename);
CHECK(result.status == 200);
CHECK(fs::file_size(local_filename) == 64);
}

{
coro_http_client client{};
std::string local_filename = "temp1.txt";
std::string base_uri = "http://127.0.0.1:9001/";
std::string path =
code_utils::url_encode(fs::u8path("utf8中文.txt").string());
auto result = client.download(base_uri + path, local_filename);
CHECK(result.status == 200);
CHECK(fs::file_size(local_filename) == 64);
}
#endif

coro_http_client client{};
std::string filename = "test1.txt";
Expand Down

0 comments on commit ec7f8d6

Please sign in to comment.