mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-01 05:02:29 +07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a444b612af | ||
|
|
ed6d949f42 | ||
|
|
d28cd3f937 | ||
|
|
8cc3e6c434 | ||
|
|
26fbc1b7c0 | ||
|
|
0dc653f45a | ||
|
|
7a58c0a430 | ||
|
|
dabaa51a7d | ||
|
|
a1cfc0f377 | ||
|
|
eb4fcb5003 | ||
|
|
ae43c96984 | ||
|
|
9c81693801 | ||
|
|
80202c9f62 | ||
|
|
094a6a614a | ||
|
|
39c7bba7b9 | ||
|
|
f2476f21fc | ||
|
|
c776454c84 | ||
|
|
82a5ac735f | ||
|
|
08bf806e92 | ||
|
|
9a41b16cbb | ||
|
|
10759f0a38 | ||
|
|
58b2814fda | ||
|
|
260422b7d7 | ||
|
|
d2c7b447d5 | ||
|
|
72b20c08da | ||
|
|
afd6d5f9dc | ||
|
|
e5827ad16f | ||
|
|
5324b3d661 | ||
|
|
151ccba57e | ||
|
|
69a28d50f6 | ||
|
|
048f31109f | ||
|
|
d064fb7ff2 | ||
|
|
3c2736bb2a | ||
|
|
fd4e1b4112 | ||
|
|
f6a2365ca5 | ||
|
|
df1ff7510b | ||
|
|
379905bd34 | ||
|
|
66719ae3d4 | ||
|
|
bc9251ea49 | ||
|
|
a9e942d755 | ||
|
|
e1785d6723 | ||
|
|
b9539b8921 | ||
|
|
4c93b973ff | ||
|
|
033bc35723 | ||
|
|
d910bfc303 | ||
|
|
b69c0a1dcb | ||
|
|
5e37e38398 | ||
|
|
295e4d58aa | ||
|
|
448de6a9c6 | ||
|
|
6f58dc728f | ||
|
|
905f2d84f4 | ||
|
|
880f7fa62b | ||
|
|
8f3dbf7f21 | ||
|
|
924a557fa3 | ||
|
|
d8da740597 | ||
|
|
d45676b064 | ||
|
|
94d13e88a5 | ||
|
|
4f9d04cb8e | ||
|
|
9fb11986a5 | ||
|
|
55d04ee354 | ||
|
|
a62a48a7b5 | ||
|
|
c652919954 | ||
|
|
58753ba33c | ||
|
|
5706828d2c | ||
|
|
e743b8cd57 | ||
|
|
9d57899352 | ||
|
|
d03937e144 | ||
|
|
8fb37a449d | ||
|
|
f0b1b5dbfd | ||
|
|
5f32c424c2 | ||
|
|
f0683f2301 | ||
|
|
0d527e2b83 | ||
|
|
bea3ebd7af | ||
|
|
380f725713 | ||
|
|
a106bd314c | ||
|
|
e4fd9f19ca | ||
|
|
dfc01338eb | ||
|
|
c4ebc31345 | ||
|
|
d1abf96581 | ||
|
|
001b8a5529 | ||
|
|
7a3abd2768 | ||
|
|
4a52524f47 | ||
|
|
89e1e9b8fe | ||
|
|
98d16eb836 | ||
|
|
bcf0c32245 | ||
|
|
dcdb0d047b | ||
|
|
1f86e41d97 | ||
|
|
6d8302313c | ||
|
|
89440ec322 | ||
|
|
5edf455d72 | ||
|
|
5f49c13f95 | ||
|
|
760bccc3ad | ||
|
|
a99e02aeb3 | ||
|
|
4aae1dcc42 | ||
|
|
f23f9a06a9 | ||
|
|
46466b1e28 | ||
|
|
224119a60a | ||
|
|
c02849e269 | ||
|
|
71979b1e88 | ||
|
|
a62d1f79f4 | ||
|
|
b14b7b0f8f | ||
|
|
9dbe0d855c | ||
|
|
2cef8df6ae | ||
|
|
94fc229c44 | ||
|
|
a7052cba22 | ||
|
|
c47c6b3910 | ||
|
|
c946eb7699 | ||
|
|
1f99ad5d6e | ||
|
|
96e372bad2 | ||
|
|
fc56f39d17 | ||
|
|
5844432a7b | ||
|
|
b97420f363 | ||
|
|
81610ee080 | ||
|
|
c7f8561472 | ||
|
|
47bc7456d2 | ||
|
|
4ab9270660 | ||
|
|
d599a36c2a | ||
|
|
6f8f51496d | ||
|
|
0c293887d0 | ||
|
|
7e92ffec48 | ||
|
|
531708816a | ||
|
|
bfec81998b | ||
|
|
c9238434e1 | ||
|
|
e2babf315c | ||
|
|
c434d555bb | ||
|
|
359b06681b | ||
|
|
a0fe91e84d | ||
|
|
80f040cf69 | ||
|
|
037b4fc789 | ||
|
|
a782d1b609 | ||
|
|
6a03ddf912 | ||
|
|
1e82359329 | ||
|
|
a4160e6ac1 | ||
|
|
bdbfc6cfe7 | ||
|
|
22615f9682 | ||
|
|
64991a560a | ||
|
|
d7bb402ca7 | ||
|
|
d58deddbcc | ||
|
|
3629f87627 | ||
|
|
1b95bf8cc3 | ||
|
|
e383b277a4 | ||
|
|
bf541442ea | ||
|
|
2823a94fc1 | ||
|
|
5a13539e57 | ||
|
|
531f6ab84d | ||
|
|
f4aaba6362 | ||
|
|
c899462e75 | ||
|
|
9785cd47f2 | ||
|
|
579ff1a0a6 | ||
|
|
47312e6df9 | ||
|
|
66b81a1497 | ||
|
|
9d7b717504 | ||
|
|
3291bdad91 | ||
|
|
e8799383f3 | ||
|
|
58f72bc8b6 | ||
|
|
4c58b91e40 | ||
|
|
06b3dee5aa | ||
|
|
ba7f9fe4c3 | ||
|
|
8480850a3f | ||
|
|
d15df874b3 | ||
|
|
f40de531ab |
@@ -0,0 +1,5 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name: test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [macOS-latest, ubuntu-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
- name: make
|
||||||
|
run: cd test && make
|
||||||
@@ -6,6 +6,7 @@ example/hello
|
|||||||
example/simplesvr
|
example/simplesvr
|
||||||
example/benchmark
|
example/benchmark
|
||||||
example/redirect
|
example/redirect
|
||||||
|
example/upload
|
||||||
example/*.pem
|
example/*.pem
|
||||||
test/test
|
test/test
|
||||||
test/test.xcodeproj/xcuser*
|
test/test.xcodeproj/xcuser*
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
cpp-httplib
|
cpp-httplib
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
[](https://github.com/yhirose/cpp-httplib/actions)
|
||||||
[](https://travis-ci.org/yhirose/cpp-httplib)
|
[](https://travis-ci.org/yhirose/cpp-httplib)
|
||||||
[](https://ci.appveyor.com/project/yhirose/cpp-httplib)
|
[](https://ci.appveyor.com/project/yhirose/cpp-httplib)
|
||||||
|
|
||||||
@@ -49,7 +50,16 @@ svr.listen_after_bind();
|
|||||||
### Static File Server
|
### Static File Server
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
svr.set_base_dir("./www");
|
svr.set_base_dir("./www"); // This is same as `svr.set_base_dir("./www", "/")`;
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.set_base_dir("./www", "/public");
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.set_base_dir("./www1", "/public"); // 1st order
|
||||||
|
svr.set_base_dir("./www2", "/public"); // 2nd order
|
||||||
```
|
```
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
@@ -64,7 +74,7 @@ svr.set_logger([](const auto& req, const auto& res) {
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
svr.set_error_handler([](const auto& req, auto& res) {
|
svr.set_error_handler([](const auto& req, auto& res) {
|
||||||
const char* fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
|
auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
snprintf(buf, sizeof(buf), fmt, res.status);
|
snprintf(buf, sizeof(buf), fmt, res.status);
|
||||||
res.set_content(buf, "text/html");
|
res.set_content(buf, "text/html");
|
||||||
@@ -76,12 +86,113 @@ svr.set_error_handler([](const auto& req, auto& res) {
|
|||||||
```cpp
|
```cpp
|
||||||
svr.Post("/multipart", [&](const auto& req, auto& res) {
|
svr.Post("/multipart", [&](const auto& req, auto& res) {
|
||||||
auto size = req.files.size();
|
auto size = req.files.size();
|
||||||
auto ret = req.has_file("name1"));
|
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.filename;
|
||||||
// file.content_type;
|
// file.content_type;
|
||||||
auto body = req.body.substr(file.offset, file.length));
|
// file.content;
|
||||||
})
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Send content with Content provider
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const uint64_t DATA_CHUNK_SIZE = 4;
|
||||||
|
|
||||||
|
svr.Get("/stream", [&](const Request &req, Response &res) {
|
||||||
|
auto data = new std::string("abcdefg");
|
||||||
|
|
||||||
|
res.set_content_provider(
|
||||||
|
data->size(), // Content length
|
||||||
|
[data](uint64_t offset, uint64_t length, DataSink sink) {
|
||||||
|
const auto &d = *data;
|
||||||
|
sink(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||||
|
},
|
||||||
|
[data] { delete data; });
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Receive content with Content receiver
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.Post("/content_receiver",
|
||||||
|
[&](const Request &req, Response &res, const ContentReader &content_reader) {
|
||||||
|
if (req.is_multipart_form_data()) {
|
||||||
|
MultipartFormDataItems files;
|
||||||
|
content_reader(
|
||||||
|
[&](const MultipartFormData &file) {
|
||||||
|
files.push_back(file);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[&](const char *data, size_t data_length) {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
res.set_content(body, "text/plain");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chunked transfer encoding
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.Get("/chunked", [&](const Request& req, Response& res) {
|
||||||
|
res.set_chunked_content_provider(
|
||||||
|
[](uint64_t offset, DataSink sink, Done done) {
|
||||||
|
sink("123", 3);
|
||||||
|
sink("345", 3);
|
||||||
|
sink("789", 3);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Default thread pool support
|
||||||
|
|
||||||
|
Set thread count to 8:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define CPPHTTPLIB_THREAD_POOL_COUNT 8
|
||||||
|
```
|
||||||
|
|
||||||
|
Disable the default thread pool:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define CPPHTTPLIB_THREAD_POOL_COUNT 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Override the default thread pool with yours
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class YourThreadPoolTaskQueue : public TaskQueue {
|
||||||
|
public:
|
||||||
|
YourThreadPoolTaskQueue(size_t n) {
|
||||||
|
pool_.start_with_thread_count(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void enqueue(std::function<void()> fn) override {
|
||||||
|
pool_.enqueue(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void shutdown() override {
|
||||||
|
pool_.shutdown_gracefully();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
YourThreadPool pool_;
|
||||||
|
};
|
||||||
|
|
||||||
|
svr.new_task_queue = [] {
|
||||||
|
return new YourThreadPoolTaskQueue(12);
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Client Example
|
Client Example
|
||||||
@@ -117,9 +228,13 @@ int main(void)
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
std::string body;
|
std::string body;
|
||||||
auto res = cli.Get("/large-data", [&](const char *data, size_t len) {
|
|
||||||
body.append(data, len);
|
auto res = cli.Get("/large-data",
|
||||||
});
|
[&](const char *data, uint64_t data_length) {
|
||||||
|
body.append(data, data_length);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
assert(res->body.empty());
|
assert(res->body.empty());
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -186,7 +301,7 @@ res = cli.Options("/resource/foo");
|
|||||||
### Connection Timeout
|
### Connection Timeout
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
httplib::Client cli("localhost", 8080, 5); // timeouts in 5 seconds
|
cli.set_timeout_sec(5); // timeouts in 5 seconds
|
||||||
```
|
```
|
||||||
### With Progress Callback
|
### With Progress Callback
|
||||||
|
|
||||||
@@ -208,35 +323,97 @@ std::shared_ptr<httplib::Response> res =
|
|||||||
|
|
||||||
This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23).
|
This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23).
|
||||||
|
|
||||||
### Basic Authentication
|
### Authentication
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
httplib::Client cli("httplib.org");
|
// Basic Authentication
|
||||||
|
cli.set_basic_auth("user", "pass");
|
||||||
|
|
||||||
auto res = cli.Get("/basic-auth/hello/world", {
|
// Digest Authentication
|
||||||
httplib::make_basic_authentication_header("hello", "world")
|
cli.set_digest_auth("user", "pass");
|
||||||
});
|
|
||||||
// res->status should be 200
|
|
||||||
// res->body should be "{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n".
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NOTE: OpenSSL is required for Digest Authentication.
|
||||||
|
|
||||||
|
### Proxy server support
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
cli.set_proxy("host", port);
|
||||||
|
|
||||||
|
// Basic Authentication
|
||||||
|
cli.set_proxy_basic_auth("user", "pass");
|
||||||
|
|
||||||
|
// Digest Authentication
|
||||||
|
cli.set_proxy_digest_auth("user", "pass");
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: OpenSSL is required for Digest Authentication.
|
||||||
|
|
||||||
### Range
|
### Range
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
httplib::Client cli("httpbin.org");
|
httplib::Client cli("httpbin.org");
|
||||||
|
|
||||||
auto res = cli.Get("/range/32", {
|
auto res = cli.Get("/range/32", {
|
||||||
httplib::make_range_header(1, 10) // 'Range: bytes=1-10'
|
httplib::make_range_header({{1, 10}}) // 'Range: bytes=1-10'
|
||||||
});
|
});
|
||||||
// res->status should be 206.
|
// res->status should be 206.
|
||||||
// res->body should be "bcdefghijk".
|
// res->body should be "bcdefghijk".
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
httplib::make_range_header({{1, 10}, {20, -1}}) // 'Range: bytes=1-10, 20-'
|
||||||
|
httplib::make_range_header({{100, 199}, {500, 599}}) // 'Range: bytes=100-199, 500-599'
|
||||||
|
httplib::make_range_header({{0, 0}, {-1, 1}}) // 'Range: bytes=0-0, -1'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep-Alive connection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
cli.set_keep_alive_max_count(2); // Default is 5
|
||||||
|
|
||||||
|
std::vector<Request> requests;
|
||||||
|
Get(requests, "/get-request1");
|
||||||
|
Get(requests, "/get-request2");
|
||||||
|
Post(requests, "/post-request1", "text", "text/plain");
|
||||||
|
Post(requests, "/post-request2", "text", "text/plain");
|
||||||
|
|
||||||
|
std::vector<Response> responses;
|
||||||
|
if (cli.send(requests, responses)) {
|
||||||
|
for (const auto& res: responses) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Redirect
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
httplib::Client cli("yahoo.com");
|
||||||
|
|
||||||
|
auto res = cli.Get("/");
|
||||||
|
res->status; // 301
|
||||||
|
|
||||||
|
cli.set_follow_location(true);
|
||||||
|
res = cli.Get("/");
|
||||||
|
res->status; // 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use a specitic network interface
|
||||||
|
|
||||||
|
NOTE: This feature is not available on Windows, yet.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
cli.set_interface("eth0"); // Interface name, IP address or host name
|
||||||
|
```
|
||||||
|
|
||||||
OpenSSL Support
|
OpenSSL Support
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
|
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
|
||||||
|
|
||||||
|
NOTE: cpp-httplib supports 1.1.1 (until 2023-09-11) and 1.0.2 (2019-12-31).
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
|
||||||
@@ -261,10 +438,26 @@ The server applies gzip compression to the following MIME type contents:
|
|||||||
* application/xml
|
* application/xml
|
||||||
* application/xhtml+xml
|
* application/xhtml+xml
|
||||||
|
|
||||||
|
### Compress content on client
|
||||||
|
|
||||||
|
```c++
|
||||||
|
cli.set_compress(true);
|
||||||
|
res = cli.Post("/resource/foo", "...", "text/plain");
|
||||||
|
```
|
||||||
|
|
||||||
|
Split httplib.h into .h and .cc
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> python3 split.py
|
||||||
|
> ls out
|
||||||
|
httplib.h httplib.cc
|
||||||
|
```
|
||||||
|
|
||||||
NOTE
|
NOTE
|
||||||
----
|
----
|
||||||
|
|
||||||
g++ 4.8 cannot build this library since `<regex>` in g++4.8 is [broken](https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions).
|
g++ 4.8 and below cannot build this library since `<regex>` in the versions are [broken](https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions).
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|||||||
+7
-3
@@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
#CXX = clang++
|
#CXX = clang++
|
||||||
CXXFLAGS = -std=c++14 -I.. -Wall -Wextra -pthread
|
CXXFLAGS = -std=c++14 -I.. -Wall -Wextra -pthread
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib -lssl -lcrypto
|
OPENSSL_DIR = /usr/local/opt/openssl
|
||||||
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||||
|
|
||||||
all: server client hello simplesvr redirect benchmark
|
all: server client hello simplesvr upload redirect benchmark
|
||||||
|
|
||||||
server : server.cc ../httplib.h Makefile
|
server : server.cc ../httplib.h Makefile
|
||||||
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
@@ -18,6 +19,9 @@ hello : hello.cc ../httplib.h Makefile
|
|||||||
simplesvr : simplesvr.cc ../httplib.h Makefile
|
simplesvr : simplesvr.cc ../httplib.h Makefile
|
||||||
$(CXX) -o simplesvr $(CXXFLAGS) simplesvr.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o simplesvr $(CXXFLAGS) simplesvr.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
|
upload : upload.cc ../httplib.h Makefile
|
||||||
|
$(CXX) -o upload $(CXXFLAGS) upload.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
redirect : redirect.cc ../httplib.h Makefile
|
redirect : redirect.cc ../httplib.h Makefile
|
||||||
$(CXX) -o redirect $(CXXFLAGS) redirect.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
$(CXX) -o redirect $(CXXFLAGS) redirect.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||||
|
|
||||||
@@ -29,4 +33,4 @@ pem:
|
|||||||
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
|
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm server client hello simplesvr redirect *.pem
|
rm server client hello simplesvr upload redirect benchmark *.pem
|
||||||
|
|||||||
+12
-8
@@ -15,6 +15,9 @@ using namespace httplib;
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
// HTTP server
|
// HTTP server
|
||||||
Server http;
|
Server http;
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
SSLServer https(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||||
|
#endif
|
||||||
|
|
||||||
http.Get("/test", [](const Request & /*req*/, Response &res) {
|
http.Get("/test", [](const Request & /*req*/, Response &res) {
|
||||||
res.set_content("Test\n", "text/plain");
|
res.set_content("Test\n", "text/plain");
|
||||||
@@ -25,8 +28,7 @@ int main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// HTTPS server
|
// HTTPS server
|
||||||
SSLServer https(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
|
||||||
https.Get("/", [=](const Request & /*req*/, Response &res) {
|
https.Get("/", [=](const Request & /*req*/, Response &res) {
|
||||||
res.set_redirect("/hi");
|
res.set_redirect("/hi");
|
||||||
});
|
});
|
||||||
@@ -39,18 +41,20 @@ int main(void) {
|
|||||||
https.stop();
|
https.stop();
|
||||||
http.stop();
|
http.stop();
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
// Run servers
|
// Run servers
|
||||||
auto httpThread = std::thread([&]() {
|
auto httpThread = std::thread([&]() { http.listen("localhost", 8080); });
|
||||||
http.listen("localhost", 8080);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto httpsThread = std::thread([&]() {
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
https.listen("localhost", 8081);
|
auto httpsThread = std::thread([&]() { https.listen("localhost", 8081); });
|
||||||
});
|
#endif
|
||||||
|
|
||||||
httpThread.join();
|
httpThread.join();
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
httpsThread.join();
|
httpsThread.join();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ string dump_headers(const Headers &headers) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
string dump_multipart_files(const MultipartFiles &files) {
|
string dump_multipart_files(const MultipartFormDataMap &files) {
|
||||||
string s;
|
string s;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
@@ -46,10 +46,7 @@ string dump_multipart_files(const MultipartFiles &files) {
|
|||||||
snprintf(buf, sizeof(buf), "content type: %s\n", file.content_type.c_str());
|
snprintf(buf, sizeof(buf), "content type: %s\n", file.content_type.c_str());
|
||||||
s += buf;
|
s += buf;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "text offset: %lu\n", file.offset);
|
snprintf(buf, sizeof(buf), "text length: %lu\n", file.content.size());
|
||||||
s += buf;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "text length: %lu\n", file.length);
|
|
||||||
s += buf;
|
s += buf;
|
||||||
|
|
||||||
s += "----------------\n";
|
s += "----------------\n";
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// upload.cc
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Yuji Hirose. All rights reserved.
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <httplib.h>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace httplib;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const char *html = R"(
|
||||||
|
<form id="formElem">
|
||||||
|
<input type="file" name="file" accept="image/*">
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
formElem.onsubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let res = await fetch('/post', {
|
||||||
|
method: 'POST',
|
||||||
|
body: new FormData(formElem)
|
||||||
|
});
|
||||||
|
console.log(await res.text());
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
)";
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
Server svr;
|
||||||
|
|
||||||
|
svr.Get("/", [](const Request & /*req*/, Response &res) {
|
||||||
|
res.set_content(html, "text/html");
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.Post("/post", [](const Request &req, Response &res) {
|
||||||
|
auto file = req.get_file_value("file");
|
||||||
|
cout << "file length: " << file.content.length() << ":" << file.filename
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
ofstream ofs(file.filename, ios::binary);
|
||||||
|
ofs << file.content;
|
||||||
|
|
||||||
|
res.set_content("done", "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.listen("localhost", 1234);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
border = '// ----------------------------------------------------------------------------'
|
||||||
|
|
||||||
|
with open('httplib.h') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
inImplementation = False
|
||||||
|
os.makedirs('out', exist_ok=True)
|
||||||
|
with open('out/httplib.h', 'w') as fh:
|
||||||
|
with open('out/httplib.cc', 'w') as fc:
|
||||||
|
fc.write('#include "httplib.h"\n')
|
||||||
|
fc.write('namespace httplib {\n')
|
||||||
|
for line in lines:
|
||||||
|
isBorderLine = border in line
|
||||||
|
if isBorderLine:
|
||||||
|
inImplementation = not inImplementation
|
||||||
|
else:
|
||||||
|
if inImplementation:
|
||||||
|
fc.write(line.replace('inline ', ''))
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
fh.write(line)
|
||||||
|
pass
|
||||||
|
fc.write('} // namespace httplib\n')
|
||||||
+2
-1
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
#CXX = clang++
|
#CXX = clang++
|
||||||
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits
|
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib -lssl -lcrypto
|
OPENSSL_DIR = /usr/local/opt/openssl
|
||||||
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||||
|
|
||||||
all : test
|
all : test
|
||||||
|
|||||||
@@ -54,6 +54,11 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copyright 2005, Google Inc.
|
// Copyright 2005, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
@@ -19544,4 +19549,8 @@ bool StaticAssertTypeEq() {
|
|||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning( pop )
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
||||||
|
|||||||
+887
-208
File diff suppressed because it is too large
Load Diff
+20
-4
@@ -34,7 +34,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -69,15 +69,23 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>C:\Program Files\OpenSSL-Win64\lib\VC;C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -87,6 +95,8 @@
|
|||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>
|
||||||
|
</AdditionalUsingDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -102,11 +112,13 @@
|
|||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>
|
||||||
|
</AdditionalUsingDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@@ -119,6 +131,8 @@
|
|||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>
|
||||||
|
</AdditionalUsingDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -138,13 +152,15 @@
|
|||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>
|
||||||
|
</AdditionalUsingDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="/dir/test.html">Test</a>
|
||||||
|
<a href="/hi">hi</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
test.html
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="/dir/test.html">Test</a>
|
||||||
|
<a href="/hi">hi</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
test.html
|
||||||
Reference in New Issue
Block a user