2012-09-27 18:05:36 -07:00
cpp-httplib
===========
2012-09-21 19:38:33 -07:00
2019-09-19 21:31:26 -07:00
[![ ](https://github.com/yhirose/cpp-httplib/workflows/.github/workflows/test.yml/badge.svg )](https://github.com/yhirose/cpp-httplib/actions)
2019-01-11 18:31:06 -07:00
[![Build Status ](https://travis-ci.org/yhirose/cpp-httplib.svg?branch=master )](https://travis-ci.org/yhirose/cpp-httplib)
[![Bulid Status ](https://ci.appveyor.com/api/projects/status/github/yhirose/cpp-httplib?branch=master&svg=true )](https://ci.appveyor.com/project/yhirose/cpp-httplib)
2019-07-23 22:22:06 -07:00
A C++ single-file header-only cross platform HTTP/HTTPS library.
2012-09-22 21:41:21 -07:00
2012-10-05 10:58:56 -07:00
It's extremely easy to setup. Just include **httplib.h** file in your code!
2012-09-27 18:05:36 -07:00
Server Example
--------------
2012-09-25 19:21:42 -07:00
2015-02-06 20:43:06 -07:00
```c++
#include <httplib.h>
2012-09-25 19:21:42 -07:00
2015-02-06 20:43:06 -07:00
int main(void)
{
using namespace httplib;
2012-10-05 10:58:56 -07:00
2015-02-06 20:43:06 -07:00
Server svr;
2012-09-27 18:05:36 -07:00
2018-05-06 18:16:35 -07:00
svr.Get("/hi", [](const Request& req, Response& res) {
2015-02-06 20:43:06 -07:00
res.set_content("Hello World!", "text/plain");
});
2012-09-27 18:05:36 -07:00
2018-05-06 18:16:35 -07:00
svr.Get(R"(/numbers/(\d+))", [& ](const Request& req, Response& res ) {
2016-06-26 11:51:34 -07:00
auto numbers = req.matches[1];
2015-02-06 20:43:06 -07:00
res.set_content(numbers, "text/plain");
});
2019-07-23 05:05:51 -07:00
svr.Get("/stop", [& ](const Request& req, Response& res ) {
2019-07-23 05:20:01 -07:00
svr.stop();
2019-07-23 05:05:51 -07:00
});
2015-02-06 20:43:06 -07:00
svr.listen("localhost", 1234);
}
```
2012-09-25 19:21:42 -07:00
2018-05-06 18:16:35 -07:00
`Post` , `Put` , `Delete` and `Options` methods are also supported.
2018-11-07 19:46:53 -07:00
### Bind a socket to multiple interfaces and any available port
```cpp
2018-11-09 21:30:58 -07:00
int port = svr.bind_to_any_port("0.0.0.0");
2018-11-07 19:46:53 -07:00
svr.listen_after_bind();
```
2017-11-25 09:59:28 -07:00
### Static File Server
```cpp
svr.set_base_dir("./www");
```
### Logging
```cpp
svr.set_logger([](const auto& req, const auto& res) {
your_logger(req, res);
});
```
### Error Handler
```cpp
svr.set_error_handler([](const auto& req, auto& res) {
const char* fmt = "< p > Error Status: < span style = 'color:red;' > %d< / span > < / p > ";
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), fmt, res.status);
res.set_content(buf, "text/html");
});
```
2017-12-12 20:22:10 -07:00
### 'multipart/form-data' POST data
2017-12-05 17:30:13 -07:00
```cpp
2018-05-06 18:16:35 -07:00
svr.Post("/multipart", [& ](const auto& req, auto& res ) {
2017-12-05 17:30:13 -07:00
auto size = req.files.size();
auto ret = req.has_file("name1"));
const auto& file = req.get_file_value("name1");
// file.filename;
// file.content_type;
auto body = req.body.substr(file.offset, file.length));
})
```
2019-08-01 06:08:40 -07:00
### Stream content with Content provider
```cpp
const uint64_t DATA_CHUNK_SIZE = 4;
svr.Get("/stream", [& ](const Request &req, Response &res ) {
2019-08-04 18:51:27 -07:00
auto data = new std::string("abcdefg");
2019-08-01 06:08:40 -07:00
res.set_content_provider(
data->size(), // Content length
[data ](uint64_t offset, uint64_t length, Out out ) {
const auto & d = *data;
out(& d[offset], std::min(length, DATA_CHUNK_SIZE));
2019-08-04 18:51:27 -07:00
},
[data] { delete data; });
2019-08-01 06:08:40 -07:00
});
```
### Chunked transfer encoding
```cpp
svr.Get("/chunked", [& ](const Request& req, Response& res ) {
res.set_chunked_content_provider(
[](uint64_t offset, Out out, Done done) {
out("123", 3);
out("345", 3);
out("789", 3);
done();
}
);
});
```
2019-08-05 02:17:40 -07:00
### Default thread pool supporet
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);
};
```
2012-10-03 22:18:18 -07:00
Client Example
--------------
2017-12-05 17:30:13 -07:00
### GET
2015-02-06 20:43:06 -07:00
```c++
#include <httplib.h>
#include <iostream>
2012-10-03 22:18:18 -07:00
2015-02-06 20:43:06 -07:00
int main(void)
{
httplib::Client cli("localhost", 1234);
2012-10-03 22:18:18 -07:00
2018-05-06 18:16:35 -07:00
auto res = cli.Get("/hi");
2015-02-06 20:43:06 -07:00
if (res & & res->status == 200) {
std::cout < < res- > body < < std::endl ;
2012-10-03 22:18:18 -07:00
}
2015-02-06 20:43:06 -07:00
}
```
2012-10-03 22:18:18 -07:00
2019-07-23 05:05:51 -07:00
### GET with HTTP headers
```c++
httplib::Headers headers = {
2019-07-23 05:11:41 -07:00
{ "Accept-Encoding", "gzip, deflate" }
2019-07-23 05:05:51 -07:00
};
2019-07-23 05:11:41 -07:00
auto res = cli.Get("/hi", headers);
2019-07-23 05:05:51 -07:00
```
2019-07-17 18:33:47 -07:00
### GET with Content Receiver
```c++
std::string body;
2019-08-05 02:24:30 -07:00
auto res = cli.Get("/large-data",
[& ](const char *data, uint64_t data_length, uint64_t offset, uint64_t content_length ) {
body.append(data, data_length);
});
2019-07-17 20:46:02 -07:00
assert(res->body.empty());
2019-07-17 18:33:47 -07:00
```
2017-12-05 17:30:13 -07:00
### POST
```c++
2018-05-06 18:16:35 -07:00
res = cli.Post("/post", "text", "text/plain");
res = cli.Post("/person", "name=john1& note=coder", "application/x-www-form-urlencoded");
2017-12-05 17:30:13 -07:00
```
### POST with parameters
```c++
2018-05-09 04:17:45 -07:00
httplib::Params params;
2018-05-18 13:43:08 -07:00
params.emplace("name", "john");
params.emplace("note", "coder");
auto res = cli.Post("/post", params);
```
or
```c++
httplib::Params params{
{ "name", "john" },
{ "note", "coder" }
};
2018-05-06 18:16:35 -07:00
auto res = cli.Post("/post", params);
```
2019-07-23 06:52:12 -07:00
### POST with Multipart Form Data
```c++
httplib::MultipartFormDataItems items = {
{ "text1", "text default", "", "" },
{ "text2", "aωb", "", "" },
{ "file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain" },
{ "file2", "{\n \"world\", true\n}\n", "world.json", "application/json" },
{ "file3", "", "", "application/octet-stream" },
};
auto res = cli.Post("/multipart", items);
```
2018-05-06 18:16:35 -07:00
### PUT
```c++
2018-05-09 04:17:45 -07:00
res = cli.Put("/resource/foo", "text", "text/plain");
2018-05-06 18:16:35 -07:00
```
### DELETE
```c++
res = cli.Delete("/resource/foo");
```
### OPTIONS
```c++
res = cli.Options("*");
res = cli.Options("/resource/foo");
2017-12-05 17:30:13 -07:00
```
2017-12-30 12:47:55 -07:00
### Connection Timeout
```c++
httplib::Client cli("localhost", 8080, 5); // timeouts in 5 seconds
```
2017-11-24 19:39:17 -07:00
### With Progress Callback
```cpp
httplib::Client client(url, port);
// prints: 0 / 000 bytes => 50% complete
2017-12-12 20:20:40 -07:00
std::shared_ptr< httplib::Response > res =
2018-05-06 18:16:35 -07:00
cli.Get("/", [](uint64_t len, uint64_t total) {
2017-12-12 20:20:40 -07:00
printf("%lld / %lld bytes => %d%% complete\n",
2017-11-24 19:39:17 -07:00
len, total,
(int)((len/total)*100));
2018-08-06 19:52:48 -07:00
return true; // return 'false' if you want to cancel the request.
2017-11-24 19:39:17 -07:00
}
);
```
2017-12-12 20:22:10 -07:00
![progress ](https://user-images.githubusercontent.com/236374/33138910-495c4ecc-cf86-11e7-8693-2fc6d09615c4.gif )
This feature was contributed by [underscorediscovery ](https://github.com/yhirose/cpp-httplib/pull/23 ).
2019-07-19 08:38:06 -07:00
### Basic Authentication
2017-12-12 20:20:40 -07:00
```cpp
2019-07-19 08:38:06 -07:00
httplib::Client cli("httplib.org");
auto res = cli.Get("/basic-auth/hello/world", {
httplib::make_basic_authentication_header("hello", "world")
});
// res->status should be 200
// res->body should be "{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n".
```
2017-12-12 20:20:40 -07:00
2019-07-19 08:38:06 -07:00
### Range
```cpp
httplib::Client cli("httpbin.org");
2017-12-12 20:20:40 -07:00
2019-07-19 08:38:06 -07:00
auto res = cli.Get("/range/32", {
2019-08-01 06:08:40 -07:00
httplib::make_range_header({{1, 10}}) // 'Range: bytes=1-10'
2019-07-19 08:38:06 -07:00
});
2017-12-12 20:20:40 -07:00
// res->status should be 206.
// res->body should be "bcdefghijk".
```
2019-08-01 06:08:40 -07:00
```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'
```
2019-08-31 15:01:45 -07:00
### 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) {
...
}
}
```
2019-09-05 21:26:57 -07:00
### Redirect
```cpp
httplib::Client cli("yahoo.com");
2019-09-06 15:16:42 -07:00
2019-09-06 15:16:42 -07:00
auto res = cli.Get("/");
2019-09-06 15:16:42 -07:00
res->status; // 301
cli.follow_location(true);
res = cli.Get("/");
2019-09-06 15:16:42 -07:00
res->status; // 200
2019-09-05 21:26:57 -07:00
```
2018-06-14 09:25:55 -07:00
OpenSSL Support
---------------
2017-04-21 20:00:00 -07:00
2018-06-14 09:25:55 -07:00
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT` . `libssl` and `libcrypto` should be linked.
2017-04-21 20:00:00 -07:00
```c++
#define CPPHTTPLIB_OPENSSL_SUPPORT
2017-08-28 06:33:27 -07:00
SSLServer svr("./cert.pem", "./key.pem");
2017-04-21 20:00:00 -07:00
SSLClient cli("localhost", 8080);
2019-05-07 13:54:51 -07:00
cli.set_ca_cert_path("./ca-bundle.crt");
cli.enable_server_certificate_verification(true);
2017-04-21 20:00:00 -07:00
```
2017-12-28 18:47:52 -07:00
Zlib Support
------------
'gzip' compression is available with `CPPHTTPLIB_ZLIB_SUPPORT` .
The server applies gzip compression to the following MIME type contents:
* all text types
* image/svg+xml
* application/javascript
* application/json
* application/xml
* application/xhtml+xml
2019-01-15 06:24:17 -07:00
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 ).
2017-12-20 15:27:36 -07:00
License
-------
2019-01-15 06:24:17 -07:00
MIT license (© 2019 Yuji Hirose)