Skip to content

Commit

Permalink
Revert "Changed set_file_content to accept only a regular file path."
Browse files Browse the repository at this point in the history
This reverts commit 7ab9c11.
  • Loading branch information
yhirose committed Sep 10, 2024
1 parent 7ab9c11 commit 3f00e1b
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 90 deletions.
164 changes: 88 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,37 @@ int main(void)

Server svr;

svr.Get("/hi", [](const Request &req, Response &res) {
svr.Get("/hi", [](const Request& req, Response& res) {
res.set_content("Hello World!", "text/plain");
});

// Match the request path against a regular expression
// and extract its captures
svr.Get(R"(/numbers/(\d+))", [&](const Request &req, Response &res) {
svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
auto numbers = req.matches[1];
res.set_content(numbers, "text/plain");
});

// Capture the second segment of the request path as "id" path param
svr.Get("/users/:id", [&](const Request &req, Response &res) {
svr.Get("/users/:id", [&](const Request& req, Response& res) {
auto user_id = req.path_params.at("id");
res.set_content(user_id, "text/plain");
});

// Extract values from HTTP headers and URL query params
svr.Get("/body-header-param", [](const Request &req, Response &res) {
svr.Get("/body-header-param", [](const Request& req, Response& res) {
if (req.has_header("Content-Length")) {
auto val = req.get_header_value("Content-Length");
}
if (req.has_param("key")) { auto val = req.get_param_value("key"); }
if (req.has_param("key")) {
auto val = req.get_param_value("key");
}
res.set_content(req.body, "text/plain");
});

svr.Get("/stop", [&](const Request &req, Response &res) { svr.stop(); });
svr.Get("/stop", [&](const Request& req, Response& res) {
svr.stop();
});

svr.listen("localhost", 1234);
}
Expand Down Expand Up @@ -272,7 +276,7 @@ svr.set_post_routing_handler([](const auto& req, auto& res) {
svr.Post("/multipart", [&](const auto& req, auto& res) {
auto size = req.files.size();
auto ret = req.has_file("name1");
const auto &file = req.get_file_value("name1");
const auto& file = req.get_file_value("name1");
// file.filename;
// file.content_type;
// file.content;
Expand All @@ -284,10 +288,10 @@ svr.Post("/multipart", [&](const auto& req, auto& res) {
```cpp
svr.Post("/content_receiver",
[&](const Request &req, Response &res, const ContentReader &content_reader) {
if (req.is_multipart_form_data()) {
// NOTE: `content_reader` is blocking until every form data field is read
MultipartFormDataItems files;
content_reader(
if (req.is_multipart_form_data()) {
// NOTE: `content_reader` is blocking until every form data field is read
MultipartFormDataItems files;
content_reader(
[&](const MultipartFormData &file) {
files.push_back(file);
return true;
Expand All @@ -296,13 +300,13 @@ svr.Post("/content_receiver",
files.back().content.append(data, data_length);
return true;
});
} else {
std::string body;
content_reader([&](const char *data, size_t data_length) {
body.append(data, data_length);
return true;
});
}
} else {
std::string body;
content_reader([&](const char *data, size_t data_length) {
body.append(data, data_length);
return true;
});
}
});
```
Expand All @@ -315,14 +319,14 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
auto data = new std::string("abcdefg");
res.set_content_provider(
data->size(), // Content length
"text/plain", // Content type
[&, data](size_t offset, size_t length, DataSink &sink) {
const auto &d = *data;
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
return true; // return 'false' if you want to cancel the process.
},
[data](bool success) { delete data; });
data->size(), // Content length
"text/plain", // Content type
[&, data](size_t offset, size_t length, DataSink &sink) {
const auto &d = *data;
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
return true; // return 'false' if you want to cancel the process.
},
[data](bool success) { delete data; });
});
```

Expand All @@ -331,17 +335,17 @@ Without content length:
```cpp
svr.Get("/stream", [&](const Request &req, Response &res) {
res.set_content_provider(
"text/plain", // Content type
[&](size_t offset, DataSink &sink) {
if (/* there is still data */) {
std::vector<char> data;
// prepare data...
sink.write(data.data(), data.size());
} else {
sink.done(); // No more data
}
return true; // return 'false' if you want to cancel the process.
});
"text/plain", // Content type
[&](size_t offset, DataSink &sink) {
if (/* there is still data */) {
std::vector<char> data;
// prepare data...
sink.write(data.data(), data.size());
} else {
sink.done(); // No more data
}
return true; // return 'false' if you want to cancel the process.
});
});
```

Expand All @@ -350,13 +354,15 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
```cpp
svr.Get("/chunked", [&](const Request& req, Response& res) {
res.set_chunked_content_provider(
"text/plain", [](size_t offset, DataSink &sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done(); // No more data
return true; // return 'false' if you want to cancel the process.
});
"text/plain",
[](size_t offset, DataSink &sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done(); // No more data
return true; // return 'false' if you want to cancel the process.
}
);
});
```

Expand All @@ -365,21 +371,24 @@ With trailer:
```cpp
svr.Get("/chunked", [&](const Request& req, Response& res) {
res.set_header("Trailer", "Dummy1, Dummy2");
res.set_chunked_content_provider("text/plain", [](size_t offset,
DataSink &sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done_with_trailer({{"Dummy1", "DummyVal1"}, {"Dummy2", "DummyVal2"}});
return true;
});
res.set_chunked_content_provider(
"text/plain",
[](size_t offset, DataSink &sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done_with_trailer({
{"Dummy1", "DummyVal1"},
{"Dummy2", "DummyVal2"}
});
return true;
}
);
});
```

### Send file content

We can set a file path for the response body. It's a user's responsibility to pass a valid regular file path. If the path doesn't exist, or a directory path, cpp-httplib throws an exception.

```cpp
svr.Get("/content", [&](const Request &req, Response &res) {
res.set_file_content("./path/to/conent.html");
Expand Down Expand Up @@ -443,17 +452,15 @@ Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/e
If you want to set the thread count at runtime, there is no convenient way... But here is how.

```cpp
svr.new_task_queue = [] {
return new ThreadPool(12); };
svr.new_task_queue = [] { return new ThreadPool(12); };
```
You can also provide an optional parameter to limit the maximum number
of pending requests, i.e. requests `accept()`ed by the listener but
still waiting to be serviced by worker threads.
```cpp
svr.new_task_queue = [] {
return new ThreadPool(/*num_threads=*/12, /*max_queued_requests=*/18); };
svr.new_task_queue = [] { return new ThreadPool(/*num_threads=*/12, /*max_queued_requests=*/18); };
```

Default limit is 0 (unlimited). Once the limit is reached, the listener
Expand All @@ -466,15 +473,19 @@ You can supply your own thread pool implementation according to your need.
```cpp
class YourThreadPoolTaskQueue : public TaskQueue {
public:
YourThreadPoolTaskQueue(size_t n) { pool_.start_with_thread_count(n); }
YourThreadPoolTaskQueue(size_t n) {
pool_.start_with_thread_count(n);
}

virtual bool enqueue(std::function<void()> fn) override {
/* Return true if the task was actually enqueued, or false
* if the caller must drop the corresponding connection. */
return pool_.enqueue(fn);
}

virtual void shutdown() override { pool_.shutdown_gracefully(); }
virtual void shutdown() override {
pool_.shutdown_gracefully();
}

private:
YourThreadPool pool_;
Expand Down Expand Up @@ -637,8 +648,8 @@ std::string body;

auto res = cli.Get("/large-data",
[&](const char *data, size_t data_length) {
body.append(data, data_length);
return true;
body.append(data, data_length);
return true;
});
```
Expand All @@ -648,12 +659,12 @@ std::string body;
auto res = cli.Get(
"/stream", Headers(),
[&](const Response &response) {
EXPECT_EQ(StatusCode::OK_200, response.status);
return true; // return 'false' if you want to cancel the request.
EXPECT_EQ(StatusCode::OK_200, response.status);
return true; // return 'false' if you want to cancel the request.
},
[&](const char *data, size_t data_length) {
body.append(data, data_length);
return true; // return 'false' if you want to cancel the request.
body.append(data, data_length);
return true; // return 'false' if you want to cancel the request.
});
```

Expand All @@ -665,8 +676,8 @@ std::string body = ...;
auto res = cli.Post(
"/stream", body.size(),
[](size_t offset, size_t length, DataSink &sink) {
sink.write(body.data() + offset, length);
return true; // return 'false' if you want to cancel the request.
sink.write(body.data() + offset, length);
return true; // return 'false' if you want to cancel the request.
},
"text/plain");
```
Expand All @@ -677,11 +688,11 @@ auto res = cli.Post(
auto res = cli.Post(
"/stream",
[](size_t offset, DataSink &sink) {
sink.os << "chunked data 1";
sink.os << "chunked data 2";
sink.os << "chunked data 3";
sink.done();
return true; // return 'false' if you want to cancel the request.
sink.os << "chunked data 1";
sink.os << "chunked data 2";
sink.os << "chunked data 3";
sink.done();
return true; // return 'false' if you want to cancel the request.
},
"text/plain");
```
Expand All @@ -693,8 +704,9 @@ httplib::Client cli(url, port);

// prints: 0 / 000 bytes => 50% complete
auto res = cli.Get("/", [](uint64_t len, uint64_t total) {
printf("%lld / %lld bytes => %d%% complete\n", len, total,
(int)(len * 100 / total));
printf("%lld / %lld bytes => %d%% complete\n",
len, total,
(int)(len*100/total));
return true; // return 'false' if you want to cancel the request.
}
);
Expand Down Expand Up @@ -892,8 +904,8 @@ g++ 4.8 and below cannot build this library since `<regex>` in the versions are
Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32_LEAN_AND_MEAN` beforehand.

```cpp
#include <Windows.h>
#include <httplib.h>
#include <Windows.h>
```

```cpp
Expand Down
15 changes: 3 additions & 12 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5752,21 +5752,12 @@ inline void Response::set_chunked_content_provider(

inline void Response::set_file_content(const std::string &path,
const std::string &content_type) {
detail::FileStat stat(dir);
if (stat.is_file(path)) {
file_content_path_ = path;
file_content_content_type_ = content_type;
return;
}

#ifndef CPPHTTPLIB_NO_EXCEPTIONS
std::string msg = "'" + path + "' is not a regular file.";
throw std::invalid_argument(msg);
#endif
file_content_path_ = path;
file_content_content_type_ = content_type;
}

inline void Response::set_file_content(const std::string &path) {
return set_file_content(path, std::string());
file_content_path_ = path;
}

// Result implementation
Expand Down
2 changes: 0 additions & 2 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2288,8 +2288,6 @@ class ServerTest : public ::testing::Test {
{
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
cli_.enable_server_certificate_verification(false);
#else
#error no ssl
#endif
}

Expand Down

0 comments on commit 3f00e1b

Please sign in to comment.