mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-06 15:20:19 +07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
953600c177 | ||
|
|
536e7eb7f2 | ||
|
|
6d66721ba1 | ||
|
|
3b29cd0bdc | ||
|
|
109b624dfe | ||
|
|
0ed70c4d9f | ||
|
|
a50b7591ca | ||
|
|
bf8fc11b53 | ||
|
|
bc4a613b6d | ||
|
|
4bb001351c | ||
|
|
e155ba44bb | ||
|
|
a4a9637738 | ||
|
|
5292142046 | ||
|
|
cc5147ad72 | ||
|
|
fffbf1a669 | ||
|
|
d37bc0fb4d | ||
|
|
6d60dc8839 | ||
|
|
b713a3a651 | ||
|
|
7e8db1dc68 | ||
|
|
316add860b | ||
|
|
79ce6f1745 | ||
|
|
09fdf4eacd | ||
|
|
143b2dd15a | ||
|
|
e2c4e9d95c | ||
|
|
d87082f04b | ||
|
|
cc14855ba0 | ||
|
|
56c418745f | ||
|
|
4ce9911837 | ||
|
|
559c407552 | ||
|
|
a2f4e29a7b | ||
|
|
b8cf739d27 | ||
|
|
aec2f9521d | ||
|
|
7b55ecdc59 | ||
|
|
e9575bcb78 | ||
|
|
308aeb187b | ||
|
|
05d18f2bc5 | ||
|
|
3da4a0ac69 | ||
|
|
9d12b3f20e | ||
|
|
852a374748 | ||
|
|
3b5bab3308 | ||
|
|
69e75f4a67 | ||
|
|
b0fd4befb1 | ||
|
|
3e80666a74 | ||
|
|
3e4567bae8 | ||
|
|
db075d8cf9 | ||
|
|
16df0ef37e | ||
|
|
f1a2ac5108 | ||
|
|
e5743b358d | ||
|
|
1184bbe4cb | ||
|
|
9dcffda7ae | ||
|
|
e5903635e2 | ||
|
|
510b4eaaae | ||
|
|
d7e63b4316 | ||
|
|
e5dd410256 | ||
|
|
951e46929e | ||
|
|
c8adac30f4 | ||
|
|
b2b4f7635f | ||
|
|
649b1d2172 | ||
|
|
dc5f9ba164 | ||
|
|
cf084e1db1 | ||
|
|
e0e5898601 | ||
|
|
dfec2de5b5 | ||
|
|
04002d57bd | ||
|
|
38a7706c8b | ||
|
|
abaf875c42 | ||
|
|
5f76cb01c7 | ||
|
|
ae54e833ea | ||
|
|
0dd3659de5 | ||
|
|
999f6abd2c | ||
|
|
48da75dd35 | ||
|
|
4f84eeb298 | ||
|
|
a5b4cfadb9 |
@@ -20,13 +20,16 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: install brotli library on ubuntu
|
- name: install brotli library on ubuntu
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt-get install -y libbrotli-dev
|
run: sudo apt update && sudo apt-get install -y libbrotli-dev
|
||||||
- name: install brotli library on macOS
|
- name: install brotli library on macOS
|
||||||
if: matrix.os == 'macOS-latest'
|
if: matrix.os == 'macOS-latest'
|
||||||
run: brew install brotli
|
run: brew install brotli
|
||||||
- name: make
|
- name: make
|
||||||
if: matrix.os != 'windows-latest'
|
if: matrix.os != 'windows-latest'
|
||||||
run: cd test && make
|
run: cd test && make
|
||||||
|
- name: check fuzz test target
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: cd test && make -f Makefile.fuzz_test
|
||||||
- name: setup msbuild on windows
|
- name: setup msbuild on windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
uses: warrenbuckley/Setup-MSBuild@v1
|
uses: warrenbuckley/Setup-MSBuild@v1
|
||||||
|
|||||||
+18
-13
@@ -1,6 +1,6 @@
|
|||||||
#[[
|
#[[
|
||||||
Build options:
|
Build options:
|
||||||
* BUILD_SHARED_LIBS (default off) builds as a static library (if HTTPLIB_COMPILE is ON)
|
* BUILD_SHARED_LIBS (default off) builds as a shared library (if HTTPLIB_COMPILE is ON)
|
||||||
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
||||||
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
||||||
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
||||||
@@ -60,17 +60,22 @@
|
|||||||
]]
|
]]
|
||||||
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
||||||
|
|
||||||
# Gets the latest tag as a string like "v0.6.6"
|
# On systems without Git installed, there were errors since execute_process seemed to not throw an error without it?
|
||||||
# Can silently fail if git isn't on the system
|
find_package(Git QUIET)
|
||||||
execute_process(COMMAND git describe --tags --abbrev=0
|
if(Git_FOUND)
|
||||||
OUTPUT_VARIABLE _raw_version_string
|
# Gets the latest tag as a string like "v0.6.6"
|
||||||
ERROR_VARIABLE _git_tag_error
|
# Can silently fail if git isn't on the system
|
||||||
)
|
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE _raw_version_string
|
||||||
|
ERROR_VARIABLE _git_tag_error
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# execute_process can fail silenty, so check for an error
|
# execute_process can fail silenty, so check for an error
|
||||||
# if there was an error, just use the user agent as a version
|
# if there was an error, just use the user agent as a version
|
||||||
if(_git_tag_error)
|
if(_git_tag_error OR NOT Git_FOUND)
|
||||||
message(WARNING "cpp-httplib failed to find the latest git tag, falling back to using user agent as the version.")
|
message(WARNING "cpp-httplib failed to find the latest Git tag, falling back to using user agent as the version.")
|
||||||
# Get the user agent and use it as a version
|
# Get the user agent and use it as a version
|
||||||
# This gets the string with the user agent from the header.
|
# This gets the string with the user agent from the header.
|
||||||
# This is so the maintainer doesn't actually need to update this manually.
|
# This is so the maintainer doesn't actually need to update this manually.
|
||||||
@@ -101,7 +106,7 @@ if(HTTPLIB_COMPILE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
||||||
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli compression support." ON)
|
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
||||||
# Defaults to static library
|
# Defaults to static library
|
||||||
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
||||||
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
||||||
@@ -231,9 +236,9 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|||||||
|
|
||||||
# Set the definitions to enable optional features
|
# Set the definitions to enable optional features
|
||||||
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:"CPPHTTPLIB_BROTLI_SUPPORT">
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:"CPPHTTPLIB_ZLIB_SUPPORT">
|
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:"CPPHTTPLIB_OPENSSL_SUPPORT">
|
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cmake's find_package search path is different based on the system
|
# Cmake's find_package search path is different based on the system
|
||||||
|
|||||||
@@ -7,8 +7,41 @@ A C++11 single-file header-only cross platform HTTP/HTTPS library.
|
|||||||
|
|
||||||
It's extremely easy to setup. Just include **httplib.h** file in your code!
|
It's extremely easy to setup. Just include **httplib.h** file in your code!
|
||||||
|
|
||||||
Server Example
|
NOTE: This is a 'blocking' HTTP library. If you are looking for a 'non-blocking' library, this is not the one that you want.
|
||||||
--------------
|
|
||||||
|
Simple examples
|
||||||
|
---------------
|
||||||
|
|
||||||
|
#### Server
|
||||||
|
|
||||||
|
```c++
|
||||||
|
httplib::Server svr;
|
||||||
|
|
||||||
|
svr.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
|
||||||
|
res.set_content("Hello World!", "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.listen("0.0.0.0", 8080);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Client
|
||||||
|
|
||||||
|
```c++
|
||||||
|
httplib::Client cli("http://cpp-httplib-server.yhirose.repl.co");
|
||||||
|
|
||||||
|
auto res = cli.Get("/hi");
|
||||||
|
|
||||||
|
res->status; // 200
|
||||||
|
res->body; // "Hello World!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Try out the examples on Repl.it!
|
||||||
|
|
||||||
|
1. Run server at https://repl.it/@yhirose/cpp-httplib-server
|
||||||
|
2. Run client at https://repl.it/@yhirose/cpp-httplib-client
|
||||||
|
|
||||||
|
Server
|
||||||
|
------
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#include <httplib.h>
|
#include <httplib.h>
|
||||||
@@ -175,6 +208,7 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
|
|||||||
|
|
||||||
res.set_content_provider(
|
res.set_content_provider(
|
||||||
data->size(), // Content length
|
data->size(), // Content length
|
||||||
|
"text/plain", // Content type
|
||||||
[data](size_t offset, size_t length, DataSink &sink) {
|
[data](size_t offset, size_t length, DataSink &sink) {
|
||||||
const auto &d = *data;
|
const auto &d = *data;
|
||||||
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||||
@@ -184,6 +218,25 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Without content length:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.Get("/stream", [&](const Request &req, Response &res) {
|
||||||
|
res.set_content_provider(
|
||||||
|
"text/plain", // Content type
|
||||||
|
[&](size_t offset, size_t length, 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.
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### Chunked transfer encoding
|
### Chunked transfer encoding
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@@ -193,7 +246,7 @@ svr.Get("/chunked", [&](const Request& req, Response& res) {
|
|||||||
sink.write("123", 3);
|
sink.write("123", 3);
|
||||||
sink.write("345", 3);
|
sink.write("345", 3);
|
||||||
sink.write("789", 3);
|
sink.write("789", 3);
|
||||||
sink.done();
|
sink.done(); // No more data
|
||||||
return true; // return 'false' if you want to cancel the process.
|
return true; // return 'false' if you want to cancel the process.
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -244,13 +297,18 @@ Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/e
|
|||||||
|
|
||||||
### Default thread pool support
|
### Default thread pool support
|
||||||
|
|
||||||
|
`ThreadPool` is used as a **default** task queue, and the default thread count is 8, or `std::thread::hardware_concurrency()`. You can change it with `CPPHTTPLIB_THREAD_POOL_COUNT`.
|
||||||
|
|
||||||
`ThreadPool` is used as a default task queue, and the default thread count is set to value from `std::thread::hardware_concurrency()`.
|
If you want to set the thread count at runtime, there is no convenient way... But here is how.
|
||||||
|
|
||||||
You can change the thread count by setting `CPPHTTPLIB_THREAD_POOL_COUNT`.
|
```cpp
|
||||||
|
svr.new_task_queue = [] { return new ThreadPool(12); };
|
||||||
|
```
|
||||||
|
|
||||||
### Override the default thread pool with yours
|
### Override the default thread pool with yours
|
||||||
|
|
||||||
|
You can supply your own thread pool implementation according to your need.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class YourThreadPoolTaskQueue : public TaskQueue {
|
class YourThreadPoolTaskQueue : public TaskQueue {
|
||||||
public:
|
public:
|
||||||
@@ -275,8 +333,8 @@ svr.new_task_queue = [] {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Client Example
|
Client
|
||||||
--------------
|
------
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#include <httplib.h>
|
#include <httplib.h>
|
||||||
@@ -286,9 +344,13 @@ int main(void)
|
|||||||
{
|
{
|
||||||
httplib::Client cli("localhost", 1234);
|
httplib::Client cli("localhost", 1234);
|
||||||
|
|
||||||
auto res = cli.Get("/hi");
|
if (auto res = cli.Get("/hi")) {
|
||||||
if (res && res->status == 200) {
|
if (res->status == 200) {
|
||||||
std::cout << res->body << std::endl;
|
std::cout << res->body << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto err = res.error();
|
||||||
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -311,6 +373,13 @@ httplib::Headers headers = {
|
|||||||
};
|
};
|
||||||
auto res = cli.Get("/hi", headers);
|
auto res = cli.Get("/hi", headers);
|
||||||
```
|
```
|
||||||
|
or
|
||||||
|
```c++
|
||||||
|
cli.set_default_headers({
|
||||||
|
{ "Accept-Encoding", "gzip, deflate" }
|
||||||
|
});
|
||||||
|
auto res = cli.Get("/hi");
|
||||||
|
```
|
||||||
|
|
||||||
### POST
|
### POST
|
||||||
|
|
||||||
@@ -427,13 +496,12 @@ auto res = cli_.Post(
|
|||||||
httplib::Client client(url, port);
|
httplib::Client client(url, port);
|
||||||
|
|
||||||
// prints: 0 / 000 bytes => 50% complete
|
// prints: 0 / 000 bytes => 50% complete
|
||||||
std::shared_ptr<httplib::Response> res =
|
auto res = cli.Get("/", [](uint64_t len, uint64_t total) {
|
||||||
cli.Get("/", [](uint64_t len, uint64_t total) {
|
printf("%lld / %lld bytes => %d%% complete\n",
|
||||||
printf("%lld / %lld bytes => %d%% complete\n",
|
len, total,
|
||||||
len, total,
|
(int)(len*100/total));
|
||||||
(int)(len*100/total));
|
return true; // return 'false' if you want to cancel the request.
|
||||||
return true; // return 'false' if you want to cancel the request.
|
}
|
||||||
}
|
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -447,6 +515,9 @@ cli.set_basic_auth("user", "pass");
|
|||||||
|
|
||||||
// Digest Authentication
|
// Digest Authentication
|
||||||
cli.set_digest_auth("user", "pass");
|
cli.set_digest_auth("user", "pass");
|
||||||
|
|
||||||
|
// Bearer Token Authentication
|
||||||
|
cli.set_bearer_token_auth("token");
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: OpenSSL is required for Digest Authentication.
|
NOTE: OpenSSL is required for Digest Authentication.
|
||||||
@@ -461,6 +532,9 @@ cli.set_proxy_basic_auth("user", "pass");
|
|||||||
|
|
||||||
// Digest Authentication
|
// Digest Authentication
|
||||||
cli.set_proxy_digest_auth("user", "pass");
|
cli.set_proxy_digest_auth("user", "pass");
|
||||||
|
|
||||||
|
// Bearer Token Authentication
|
||||||
|
cli.set_proxy_bearer_token_auth("pass");
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: OpenSSL is required for Digest Authentication.
|
NOTE: OpenSSL is required for Digest Authentication.
|
||||||
@@ -528,9 +602,9 @@ NOTE: cpp-httplib currently supports only version 1.1.1.
|
|||||||
```c++
|
```c++
|
||||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
|
||||||
SSLServer svr("./cert.pem", "./key.pem");
|
httplib::SSLServer svr("./cert.pem", "./key.pem");
|
||||||
|
|
||||||
SSLClient cli("localhost", 8080);
|
httplib::SSLClient cli("localhost", 1234); // or `httplib::Client cli("https://localhost:1234");`
|
||||||
cli.set_ca_cert_path("./ca-bundle.crt");
|
cli.set_ca_cert_path("./ca-bundle.crt");
|
||||||
cli.enable_server_certificate_verification(true);
|
cli.enable_server_certificate_verification(true);
|
||||||
```
|
```
|
||||||
|
|||||||
+128
-135
@@ -5,181 +5,174 @@
|
|||||||
# The targets will have the same names, but it will use the static libs.
|
# The targets will have the same names, but it will use the static libs.
|
||||||
#
|
#
|
||||||
# Valid find_package COMPONENTS names: "decoder", "encoder", and "common"
|
# Valid find_package COMPONENTS names: "decoder", "encoder", and "common"
|
||||||
|
# Note that if you're requiring "decoder" or "encoder", then "common" will be automatically added as required.
|
||||||
#
|
#
|
||||||
# Defines the libraries (if found): Brotli::decoder, Brotli::encoder, Brotli::common
|
# Defines the libraries (if found): Brotli::decoder, Brotli::encoder, Brotli::common
|
||||||
# and the includes path variable: Brotli_INCLUDE_DIR
|
# and the includes path variable: Brotli_INCLUDE_DIR
|
||||||
|
#
|
||||||
|
# If it's failing to find the libraries, try setting BROTLI_ROOT_DIR to the folder containing your library & include dir.
|
||||||
|
|
||||||
function(brotli_err_msg _err_msg)
|
# If they asked for a specific version, warn/fail since we don't support it.
|
||||||
|
# TODO: if they start distributing the version somewhere, implement finding it.
|
||||||
|
# But currently there's a version header that doesn't seem to get installed.
|
||||||
|
if(Brotli_FIND_VERSION)
|
||||||
|
set(_brotli_version_error_msg "FindBrotli.cmake doesn't have version support!")
|
||||||
# If the package is required, throw a fatal error
|
# If the package is required, throw a fatal error
|
||||||
# Otherwise, if not running quietly, we throw a warning
|
# Otherwise, if not running quietly, we throw a warning
|
||||||
if(Brotli_FIND_REQUIRED)
|
if(Brotli_FIND_REQUIRED)
|
||||||
message(FATAL_ERROR "${_err_msg}")
|
message(FATAL_ERROR "${_brotli_version_error_msg}")
|
||||||
elseif(NOT Brotli_FIND_QUIETLY)
|
elseif(NOT Brotli_FIND_QUIETLY)
|
||||||
message(WARNING "${_err_msg}")
|
message(WARNING "${_brotli_version_error_msg}")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# If they asked for a specific version, warn/fail since we don't support it.
|
|
||||||
if(Brotli_FIND_VERSION)
|
|
||||||
brotli_err_msg("FindBrotli.cmake doesn't have version support!")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Since both decoder & encoder require the common lib (I think), force its requirement..
|
# Since both decoder & encoder require the common lib, force its requirement..
|
||||||
# if the user is requiring either of those other libs.
|
# if the user is requiring either of those other libs.
|
||||||
if(Brotli_FIND_REQUIRED_decoder OR Brotli_FIND_REQUIRED_encoder)
|
if(Brotli_FIND_REQUIRED_decoder OR Brotli_FIND_REQUIRED_encoder)
|
||||||
set(Brotli_FIND_REQUIRED_common TRUE)
|
set(Brotli_FIND_REQUIRED_common TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
|
||||||
|
# Credit to FindOpenSSL.cmake for this
|
||||||
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
|
set(_brotli_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
|
if(WIN32)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
|
else()
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Make PkgConfig optional, since some users (mainly Windows) don't have it.
|
# Make PkgConfig optional, since some users (mainly Windows) don't have it.
|
||||||
# But it's a lot more clean than manually using find_library.
|
# But it's a lot more clean than manually using find_library.
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
if(PKG_CONFIG_FOUND)
|
|
||||||
if(BROTLI_USE_STATIC_LIBS)
|
|
||||||
pkg_check_modules(Brotli_common_STATIC QUIET IMPORTED_TARGET libbrotlicommon)
|
|
||||||
pkg_check_modules(Brotli_decoder_STATIC QUIET IMPORTED_TARGET libbrotlidec)
|
|
||||||
pkg_check_modules(Brotli_encoder_STATIC QUIET IMPORTED_TARGET libbrotlienc)
|
|
||||||
else()
|
|
||||||
pkg_check_modules(Brotli_common QUIET IMPORTED_TARGET libbrotlicommon)
|
|
||||||
pkg_check_modules(Brotli_decoder QUIET IMPORTED_TARGET libbrotlidec)
|
|
||||||
pkg_check_modules(Brotli_encoder QUIET IMPORTED_TARGET libbrotlienc)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Only used if the PkgConfig libraries aren't used.
|
# Only used if the PkgConfig libraries aren't used.
|
||||||
find_path(Brotli_INCLUDE_DIR
|
find_path(Brotli_INCLUDE_DIR
|
||||||
NAMES "brotli/decode.h" "brotli/encode.h"
|
NAMES
|
||||||
PATH_SUFFIXES "include" "includes"
|
"brotli/decode.h"
|
||||||
|
"brotli/encode.h"
|
||||||
|
HINTS
|
||||||
|
${BROTLI_ROOT_DIR}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"include"
|
||||||
|
"includes"
|
||||||
DOC "The path to Brotli's include directory."
|
DOC "The path to Brotli's include directory."
|
||||||
)
|
)
|
||||||
|
# Hides this var from the GUI
|
||||||
|
mark_as_advanced(Brotli_INCLUDE_DIR)
|
||||||
|
|
||||||
# Also check if Brotli_decoder was defined, as it can be passed by the end-user
|
# Just used for PkgConfig stuff in the loop below
|
||||||
if(NOT TARGET PkgConfig::Brotli_decoder AND NOT Brotli_decoder)
|
set(_brotli_stat_str "")
|
||||||
if(BROTLI_USE_STATIC_LIBS)
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
list(APPEND _brotli_decoder_lib_names
|
set(_brotli_stat_str "_STATIC")
|
||||||
"brotlidec-static"
|
|
||||||
"libbrotlidec-static"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
list(APPEND _brotli_decoder_lib_names
|
|
||||||
"brotlidec"
|
|
||||||
"libbrotlidec"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
find_library(Brotli_decoder
|
|
||||||
NAMES ${_brotli_decoder_lib_names}
|
|
||||||
PATH_SUFFIXES
|
|
||||||
"lib"
|
|
||||||
"lib64"
|
|
||||||
"libs"
|
|
||||||
"libs64"
|
|
||||||
"lib/x86_64-linux-gnu"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Also check if Brotli_encoder was defined, as it can be passed by the end-user
|
# Lets us know we are using the PkgConfig libraries
|
||||||
if(NOT TARGET PkgConfig::Brotli_encoder AND NOT Brotli_encoder)
|
# Will be set false if any non-pkgconf vars are used
|
||||||
if(BROTLI_USE_STATIC_LIBS)
|
set(_brotli_using_pkgconf TRUE)
|
||||||
list(APPEND _brotli_encoder_lib_names
|
|
||||||
"brotlienc-static"
|
# Each string here is "ComponentName;LiteralName" (the semi-colon is a delimiter)
|
||||||
"libbrotlienc-static"
|
foreach(_listvar "common;common" "decoder;dec" "encoder;enc")
|
||||||
)
|
# Split the component name and literal library name from the listvar
|
||||||
else()
|
list(GET _listvar 0 _component_name)
|
||||||
list(APPEND _brotli_encoder_lib_names
|
list(GET _listvar 1 _libname)
|
||||||
"brotlienc"
|
|
||||||
"libbrotlienc"
|
if(PKG_CONFIG_FOUND)
|
||||||
)
|
# These need to be GLOBAL for MinGW when making ALIAS libraries against them.
|
||||||
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
|
# Have to use _STATIC to tell PkgConfig to find the static libs.
|
||||||
|
pkg_check_modules(Brotli_${_component_name}_STATIC QUIET GLOBAL IMPORTED_TARGET libbrotli${_libname})
|
||||||
|
else()
|
||||||
|
pkg_check_modules(Brotli_${_component_name} QUIET GLOBAL IMPORTED_TARGET libbrotli${_libname})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
find_library(Brotli_encoder
|
|
||||||
NAMES ${_brotli_encoder_lib_names}
|
|
||||||
PATH_SUFFIXES
|
|
||||||
"lib"
|
|
||||||
"lib64"
|
|
||||||
"libs"
|
|
||||||
"libs64"
|
|
||||||
"lib/x86_64-linux-gnu"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Also check if Brotli_common was defined, as it can be passed by the end-user
|
# Check if the target was already found by Pkgconf
|
||||||
if(NOT TARGET PkgConfig::Brotli_common AND NOT Brotli_common)
|
if(TARGET PkgConfig::Brotli_${_component_name} OR TARGET PkgConfig::Brotli_${_component_name}_STATIC)
|
||||||
if(BROTLI_USE_STATIC_LIBS)
|
# Can't use generators for ALIAS targets, so you get this jank
|
||||||
list(APPEND _brotli_common_lib_names
|
add_library(Brotli::${_component_name} ALIAS PkgConfig::Brotli_${_component_name}${_brotli_stat_str})
|
||||||
"brotlicommon-static"
|
|
||||||
"libbrotlicommon-static"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
list(APPEND _brotli_common_lib_names
|
|
||||||
"brotlicommon"
|
|
||||||
"libbrotlicommon"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
find_library(Brotli_common
|
|
||||||
NAMES ${_brotli_common_lib_names}
|
|
||||||
PATH_SUFFIXES
|
|
||||||
"lib"
|
|
||||||
"lib64"
|
|
||||||
"libs"
|
|
||||||
"libs64"
|
|
||||||
"lib/x86_64-linux-gnu"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_brotli_req_vars "")
|
# Tells HANDLE_COMPONENTS we found the component
|
||||||
# Generic loop to either create all the aliases for the end-user, or throw errors/warnings.
|
set(Brotli_${_component_name}_FOUND TRUE)
|
||||||
# Note that the case here needs to match the case we used elsewhere in this file.
|
if(Brotli_FIND_REQUIRED_${_component_name})
|
||||||
foreach(_target_name "common" "decoder" "encoder")
|
# If the lib is required, we can add its literal path as a required var for FindPackageHandleStandardArgs
|
||||||
# The PkgConfig IMPORTED_TARGET has PkgConfig:: prefixed to it.
|
# Since it won't accept the PkgConfig targets
|
||||||
if(TARGET PkgConfig::Brotli_${_target_name})
|
|
||||||
add_library(Brotli::${_target_name} ALIAS PkgConfig::Brotli_${_target_name})
|
|
||||||
|
|
||||||
if(Brotli_FIND_REQUIRED_${_target_name})
|
|
||||||
# The PkgConfig version of the library has a slightly different path to its lib.
|
|
||||||
if(BROTLI_USE_STATIC_LIBS)
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
list(APPEND _brotli_req_vars "Brotli_${_target_name}_STATIC_LINK_LIBRARIES")
|
list(APPEND _brotli_req_vars "Brotli_${_component_name}_STATIC_LIBRARIES")
|
||||||
else()
|
else()
|
||||||
list(APPEND _brotli_req_vars "Brotli_${_target_name}_LINK_LIBRARIES")
|
list(APPEND _brotli_req_vars "Brotli_${_component_name}_LINK_LIBRARIES")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
# This will only trigger for libraries we found using find_library
|
|
||||||
elseif(Brotli_${_target_name})
|
# Skip searching for the libs with find_library since it was already found by Pkgconf
|
||||||
add_library("Brotli::${_target_name}" UNKNOWN IMPORTED)
|
continue()
|
||||||
# Safety-check the includes dir
|
endif()
|
||||||
if(NOT Brotli_INCLUDE_DIR)
|
|
||||||
brotli_err_msg("Failed to find Brotli's includes directory. Try manually defining \"Brotli_INCLUDE_DIR\" to Brotli's header path on your system.")
|
# Lets us know we aren't using the PkgConfig libraries
|
||||||
endif()
|
set(_brotli_using_pkgconf FALSE)
|
||||||
# Attach the literal library and include dir to the IMPORTED target for the end-user
|
if(Brotli_FIND_REQUIRED_${_component_name})
|
||||||
set_target_properties("Brotli::${_target_name}" PROPERTIES
|
# If it's required, we can set the name used in find_library as a required var for FindPackageHandleStandardArgs
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${Brotli_INCLUDE_DIR}"
|
list(APPEND _brotli_req_vars "Brotli_${_component_name}")
|
||||||
IMPORTED_LOCATION "${Brotli_${_target_name}}"
|
endif()
|
||||||
|
|
||||||
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
|
list(APPEND _brotli_lib_names
|
||||||
|
"brotli${_libname}-static"
|
||||||
|
"libbrotli${_libname}-static"
|
||||||
)
|
)
|
||||||
# Attach the library from find_library to our required vars (if it's required)
|
else()
|
||||||
if(Brotli_FIND_REQUIRED_${_target_name})
|
list(APPEND _brotli_lib_names
|
||||||
list(APPEND _brotli_req_vars "Brotli_${_target_name}")
|
"brotli${_libname}"
|
||||||
endif()
|
"libbrotli${_libname}"
|
||||||
# This will only happen if it's a required library but we didn't find it.
|
)
|
||||||
elseif(Brotli_FIND_REQUIRED_${_target_name})
|
endif()
|
||||||
# Only bother with an error/failure if they actually required the lib.
|
|
||||||
brotli_err_msg("Failed to find Brotli's ${_target_name} library. Try manually defining \"Brotli_${_target_name}\" to its path on your system.")
|
find_library(Brotli_${_component_name}
|
||||||
|
NAMES ${_brotli_lib_names}
|
||||||
|
HINTS ${BROTLI_ROOT_DIR}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib"
|
||||||
|
"lib64"
|
||||||
|
"libs"
|
||||||
|
"libs64"
|
||||||
|
"lib/x86_64-linux-gnu"
|
||||||
|
)
|
||||||
|
# Hide the library variable from the Cmake GUI
|
||||||
|
mark_as_advanced(Brotli_${_component_name})
|
||||||
|
|
||||||
|
# Unset since otherwise it'll stick around for the next loop and break things
|
||||||
|
unset(_brotli_lib_names)
|
||||||
|
|
||||||
|
# Check if find_library found the library
|
||||||
|
if(Brotli_${_component_name})
|
||||||
|
# Tells HANDLE_COMPONENTS we found the component
|
||||||
|
set(Brotli_${_component_name}_FOUND TRUE)
|
||||||
|
|
||||||
|
add_library("Brotli::${_component_name}" UNKNOWN IMPORTED)
|
||||||
|
# Attach the literal library and include dir to the IMPORTED target for the end-user
|
||||||
|
set_target_properties("Brotli::${_component_name}" PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${Brotli_INCLUDE_DIR}"
|
||||||
|
IMPORTED_LOCATION "${Brotli_${_component_name}}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# Tells HANDLE_COMPONENTS we found the component
|
||||||
|
set(Brotli_${_component_name}_FOUND FALSE)
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
# Sets Brotli_FOUND, and fails the find_package(Brotli) call if it was REQUIRED but missing libs.
|
||||||
find_package_handle_standard_args(Brotli
|
find_package_handle_standard_args(Brotli
|
||||||
FOUND_VAR Brotli_FOUND
|
FOUND_VAR
|
||||||
REQUIRED_VARS ${_brotli_req_vars}
|
Brotli_FOUND
|
||||||
|
REQUIRED_VARS
|
||||||
|
Brotli_INCLUDE_DIR
|
||||||
|
${_brotli_required_targets}
|
||||||
|
HANDLE_COMPONENTS
|
||||||
)
|
)
|
||||||
|
|
||||||
if(Brotli_FOUND)
|
# Restore the original find library ordering
|
||||||
include(FindPackageMessage)
|
if(BROTLI_USE_STATIC_LIBS)
|
||||||
foreach(_lib_name ${_brotli_req_vars})
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_brotli_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
# TODO: remove this if/when The Cmake PkgConfig file fixes the non-quiet message about libbrotlicommon being found.
|
|
||||||
if(${_lib_name} MATCHES "common")
|
|
||||||
# This avoids a duplicate "Found Brotli: /usr/lib/libbrotlicommon.so" type message.
|
|
||||||
continue()
|
|
||||||
endif()
|
|
||||||
# Double-expand the var to get the actual path instead of the variable's name.
|
|
||||||
find_package_message(Brotli "Found Brotli: ${${_lib_name}}"
|
|
||||||
"[${${_lib_name}}][${Brotli_INCLUDE_DIR}]"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#CXX = clang++
|
#CXX = clang++
|
||||||
CXXFLAGS = -std=c++14 -I.. -Wall -Wextra -pthread
|
CXXFLAGS = -std=c++11 -I.. -Wall -Wextra -pthread
|
||||||
|
|
||||||
OPENSSL_DIR = /usr/local/opt/openssl
|
OPENSSL_DIR = /usr/local/opt/openssl
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
|
|||||||
+2
-2
@@ -23,12 +23,12 @@ int main(void) {
|
|||||||
httplib::Client cli("localhost", 8080);
|
httplib::Client cli("localhost", 8080);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto res = cli.Get("/hi");
|
if (auto res = cli.Get("/hi")) {
|
||||||
if (res) {
|
|
||||||
cout << res->status << endl;
|
cout << res->status << endl;
|
||||||
cout << res->get_header_value("Content-Type") << endl;
|
cout << res->get_header_value("Content-Type") << endl;
|
||||||
cout << res->body << endl;
|
cout << res->body << endl;
|
||||||
} else {
|
} else {
|
||||||
|
cout << "error code: " << res.error() << std::endl;
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
auto result = cli.get_openssl_verify_result();
|
auto result = cli.get_openssl_verify_result();
|
||||||
if (result) {
|
if (result) {
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ int main(void) {
|
|||||||
auto scheme_host_port = "http://localhost:8080";
|
auto scheme_host_port = "http://localhost:8080";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto res = httplib::Client2(scheme_host_port).Get("/hi");
|
if (auto res = httplib::Client(scheme_host_port).Get("/hi")) {
|
||||||
|
|
||||||
if (res) {
|
|
||||||
cout << res->status << endl;
|
cout << res->status << endl;
|
||||||
cout << res->get_header_value("Content-Type") << endl;
|
cout << res->get_header_value("Content-Type") << endl;
|
||||||
cout << res->body << endl;
|
cout << res->body << endl;
|
||||||
|
} else {
|
||||||
|
cout << res.error() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
httplib::Client2("http://localhost:1234")
|
httplib::Client("http://localhost:1234")
|
||||||
.Get("/event1", [&](const char *data, size_t data_length) {
|
.Get("/event1", [&](const char *data, size_t data_length) {
|
||||||
std::cout << string(data, data_length);
|
std::cout << string(data, data_length);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
#CXX = clang++
|
#CXX = clang++
|
||||||
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion
|
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion #-fsanitize=address
|
||||||
|
|
||||||
OPENSSL_DIR = /usr/local/opt/openssl@1.1
|
OPENSSL_DIR = /usr/local/opt/openssl@1.1
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
#CXX = clang++
|
||||||
|
CXXFLAGS += -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion
|
||||||
|
|
||||||
|
OPENSSL_DIR = /usr/local/opt/openssl@1.1
|
||||||
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
|
|
||||||
|
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||||
|
|
||||||
|
BROTLI_DIR = /usr/local/opt/brotli
|
||||||
|
BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec
|
||||||
|
|
||||||
|
# By default, use standalone_fuzz_target_runner.
|
||||||
|
# This runner does no fuzzing, but simply executes the inputs
|
||||||
|
# provided via parameters.
|
||||||
|
# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
|
||||||
|
# to link the fuzzer(s) against a real fuzzing engine.
|
||||||
|
# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
|
||||||
|
LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o
|
||||||
|
|
||||||
|
# Runs server_fuzzer.cc based on value of $(LIB_FUZZING_ENGINE).
|
||||||
|
# Usage: make fuzz_test LIB_FUZZING_ENGINE=/path/to/libFuzzer
|
||||||
|
all fuzz_test: server_fuzzer
|
||||||
|
./server_fuzzer fuzzing/corpus/*
|
||||||
|
|
||||||
|
# Fuzz target, so that you can choose which $(LIB_FUZZING_ENGINE) to use.
|
||||||
|
server_fuzzer : fuzzing/server_fuzzer.cc ../httplib.h standalone_fuzz_target_runner.o
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ $< $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT) $(BROTLI_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread
|
||||||
|
|
||||||
|
# Standalone fuzz runner, which just reads inputs from fuzzing/corpus/ dir and
|
||||||
|
# feeds it to server_fuzzer.
|
||||||
|
standalone_fuzz_target_runner.o : fuzzing/standalone_fuzz_target_runner.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f server_fuzzer pem *.0 *.o *.1 *.srl *.zip
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#CXX = clang++
|
||||||
|
# Do not add default sanitizer flags here as OSS-fuzz adds its own sanitizer flags.
|
||||||
|
CXXFLAGS += -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I../.. -I. -Wall -Wextra -Wtype-limits -Wconversion
|
||||||
|
|
||||||
|
OPENSSL_DIR = /usr/local/opt/openssl@1.1
|
||||||
|
|
||||||
|
# Using full path to libssl and libcrypto to avoid accidentally picking openssl libs brought in by msan.
|
||||||
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -I$(OPENSSL_DIR)/lib /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a
|
||||||
|
|
||||||
|
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||||
|
|
||||||
|
BROTLI_DIR = /usr/local/opt/brotli
|
||||||
|
# BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec
|
||||||
|
|
||||||
|
# Runs all the tests and also fuzz tests against seed corpus.
|
||||||
|
all : server_fuzzer
|
||||||
|
./server_fuzzer corpus/*
|
||||||
|
|
||||||
|
# Fuzz target, so that you can choose which $(LIB_FUZZING_ENGINE) to use.
|
||||||
|
server_fuzzer : server_fuzzer.cc ../../httplib.h
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ $< -Wl,-Bstatic $(OPENSSL_SUPPORT) -Wl,-Bdynamic -ldl $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread
|
||||||
|
zip -q -r server_fuzzer_seed_corpus.zip corpus
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f server_fuzzer pem *.0 *.o *.1 *.srl *.zip
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
PUT /search/sample?a=12 HTTP/1.1
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
GET /hello.htm HTTP/1.1
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
|
||||||
|
Accept-Language: en-us
|
||||||
|
Accept-Encoding: gzip, deflate
|
||||||
|
Connection: Keep-Alive
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include <memory>
|
||||||
|
#include <httplib.h>
|
||||||
|
|
||||||
|
class FuzzedStream : public httplib::Stream {
|
||||||
|
public:
|
||||||
|
FuzzedStream(const uint8_t* data, size_t size)
|
||||||
|
: data_(data), size_(size), read_pos_(0) {}
|
||||||
|
|
||||||
|
ssize_t read(char* ptr, size_t size) override {
|
||||||
|
if (size + read_pos_ > size_) {
|
||||||
|
size = size_ - read_pos_;
|
||||||
|
}
|
||||||
|
memcpy(ptr, data_ + read_pos_, size);
|
||||||
|
read_pos_ += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t write(const char* ptr, size_t size) override {
|
||||||
|
response_.append(ptr, size);
|
||||||
|
return static_cast<int>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int write(const char* ptr) { return write(ptr, strlen(ptr)); }
|
||||||
|
|
||||||
|
int write(const std::string& s) { return write(s.data(), s.size()); }
|
||||||
|
|
||||||
|
std::string get_remote_addr() const { return ""; }
|
||||||
|
|
||||||
|
bool is_readable() const override { return true; }
|
||||||
|
|
||||||
|
bool is_writable() const override { return true; }
|
||||||
|
|
||||||
|
void get_remote_ip_and_port(std::string &ip, int &port) const override {
|
||||||
|
ip = "127.0.0.1";
|
||||||
|
port = 8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t* data_;
|
||||||
|
size_t size_;
|
||||||
|
size_t read_pos_;
|
||||||
|
std::string response_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuzzableServer : public httplib::Server {
|
||||||
|
public:
|
||||||
|
void ProcessFuzzedRequest(FuzzedStream& stream) {
|
||||||
|
bool connection_close = false;
|
||||||
|
process_request(stream, /*last_connection=*/false, connection_close,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static FuzzableServer g_server;
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||||
|
g_server.Get(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
g_server.Post(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
g_server.Put(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
g_server.Patch(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
g_server.Delete(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
g_server.Options(R"(.*)",
|
||||||
|
[&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
res.set_content("response content", "text/plain");
|
||||||
|
});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
FuzzedStream stream{data, size};
|
||||||
|
g_server.ProcessFuzzedRequest(stream);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
# Sources: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
|
||||||
|
|
||||||
|
# misc
|
||||||
|
"HTTP/1.1"
|
||||||
|
|
||||||
|
# verbs
|
||||||
|
"CONNECT"
|
||||||
|
"DELETE"
|
||||||
|
"GET"
|
||||||
|
"HEAD"
|
||||||
|
"OPTIONS"
|
||||||
|
"PATCH"
|
||||||
|
"POST"
|
||||||
|
"PUT"
|
||||||
|
"TRACE"
|
||||||
|
|
||||||
|
|
||||||
|
# Webdav/caldav verbs
|
||||||
|
"ACL"
|
||||||
|
"BASELINE-CONTROL"
|
||||||
|
"BIND"
|
||||||
|
"CHECKIN"
|
||||||
|
"CHECKOUT"
|
||||||
|
"COPY"
|
||||||
|
"LABEL"
|
||||||
|
"LINK"
|
||||||
|
"LOCK"
|
||||||
|
"MERGE"
|
||||||
|
"MKACTIVITY"
|
||||||
|
"MKCALENDAR"
|
||||||
|
"MKCOL"
|
||||||
|
"MKREDIRECTREF"
|
||||||
|
"MKWORKSPACE"
|
||||||
|
"MOVE"
|
||||||
|
"ORDERPATCH"
|
||||||
|
"PRI"
|
||||||
|
"PROPFIND"
|
||||||
|
"PROPPATCH"
|
||||||
|
"REBIND"
|
||||||
|
"REPORT"
|
||||||
|
"SEARCH"
|
||||||
|
"UNBIND"
|
||||||
|
"UNCHECKOUT"
|
||||||
|
"UNLINK"
|
||||||
|
"UNLOCK"
|
||||||
|
"UPDATE"
|
||||||
|
"UPDATEREDIRECTREF"
|
||||||
|
"VERSION-CONTROL"
|
||||||
|
|
||||||
|
|
||||||
|
# Fields
|
||||||
|
"A-IM"
|
||||||
|
"Accept"
|
||||||
|
"Accept-Charset"
|
||||||
|
"Accept-Datetime"
|
||||||
|
"Accept-Encoding"
|
||||||
|
"Accept-Language"
|
||||||
|
"Accept-Patch"
|
||||||
|
"Accept-Ranges"
|
||||||
|
"Access-Control-Allow-Credentials"
|
||||||
|
"Access-Control-Allow-Headers"
|
||||||
|
"Access-Control-Allow-Methods"
|
||||||
|
"Access-Control-Allow-Origin"
|
||||||
|
"Access-Control-Expose-Headers"
|
||||||
|
"Access-Control-Max-Age"
|
||||||
|
"Access-Control-Request-Headers"
|
||||||
|
"Access-Control-Request-Method"
|
||||||
|
"Age"
|
||||||
|
"Allow"
|
||||||
|
"Alt-Svc"
|
||||||
|
"Authorization"
|
||||||
|
"Cache-Control"
|
||||||
|
"Connection"
|
||||||
|
"Connection:"
|
||||||
|
"Content-Disposition"
|
||||||
|
"Content-Encoding"
|
||||||
|
"Content-Language"
|
||||||
|
"Content-Length"
|
||||||
|
"Content-Location"
|
||||||
|
"Content-MD5"
|
||||||
|
"Content-Range"
|
||||||
|
"Content-Security-Policy"
|
||||||
|
"Content-Type"
|
||||||
|
"Cookie"
|
||||||
|
"DNT"
|
||||||
|
"Date"
|
||||||
|
"Delta-Base"
|
||||||
|
"ETag"
|
||||||
|
"Expect"
|
||||||
|
"Expires"
|
||||||
|
"Forwarded"
|
||||||
|
"From"
|
||||||
|
"Front-End-Https"
|
||||||
|
"HTTP2-Settings"
|
||||||
|
"Host"
|
||||||
|
"IM"
|
||||||
|
"If-Match"
|
||||||
|
"If-Modified-Since"
|
||||||
|
"If-None-Match"
|
||||||
|
"If-Range"
|
||||||
|
"If-Unmodified-Since"
|
||||||
|
"Last-Modified"
|
||||||
|
"Link"
|
||||||
|
"Location"
|
||||||
|
"Max-Forwards"
|
||||||
|
"Origin"
|
||||||
|
"P3P"
|
||||||
|
"Pragma"
|
||||||
|
"Proxy-Authenticate"
|
||||||
|
"Proxy-Authorization"
|
||||||
|
"Proxy-Connection"
|
||||||
|
"Public-Key-Pins"
|
||||||
|
"Range"
|
||||||
|
"Referer"
|
||||||
|
"Refresh"
|
||||||
|
"Retry-After"
|
||||||
|
"Save-Data"
|
||||||
|
"Server"
|
||||||
|
"Set-Cookie"
|
||||||
|
"Status"
|
||||||
|
"Strict-Transport-Security"
|
||||||
|
"TE"
|
||||||
|
"Timing-Allow-Origin"
|
||||||
|
"Tk"
|
||||||
|
"Trailer"
|
||||||
|
"Transfer-Encoding"
|
||||||
|
"Upgrade"
|
||||||
|
"Upgrade-Insecure-Requests"
|
||||||
|
"User-Agent"
|
||||||
|
"Vary"
|
||||||
|
"Via"
|
||||||
|
"WWW-Authenticate"
|
||||||
|
"Warning"
|
||||||
|
"X-ATT-DeviceId"
|
||||||
|
"X-Content-Duration"
|
||||||
|
"X-Content-Security-Policy"
|
||||||
|
"X-Content-Type-Options"
|
||||||
|
"X-Correlation-ID"
|
||||||
|
"X-Csrf-Token"
|
||||||
|
"X-Forwarded-For"
|
||||||
|
"X-Forwarded-Host"
|
||||||
|
"X-Forwarded-Proto"
|
||||||
|
"X-Frame-Options"
|
||||||
|
"X-Http-Method-Override"
|
||||||
|
"X-Powered-By"
|
||||||
|
"X-Request-ID"
|
||||||
|
"X-Requested-With"
|
||||||
|
"X-UA-Compatible"
|
||||||
|
"X-UIDH"
|
||||||
|
"X-Wap-Profile"
|
||||||
|
"X-WebKit-CSP"
|
||||||
|
"X-XSS-Protection"
|
||||||
|
|
||||||
|
# Source: string and character literals in httplib.h
|
||||||
|
" "
|
||||||
|
"&"
|
||||||
|
", "
|
||||||
|
"-"
|
||||||
|
"--"
|
||||||
|
"."
|
||||||
|
".."
|
||||||
|
":"
|
||||||
|
"="
|
||||||
|
" = = "
|
||||||
|
"0123456789abcdef"
|
||||||
|
"%02X"
|
||||||
|
"%0A"
|
||||||
|
"\\x0a\\x0d"
|
||||||
|
"%0D"
|
||||||
|
"%20"
|
||||||
|
"%27"
|
||||||
|
"%2B"
|
||||||
|
"%2C"
|
||||||
|
"%3A"
|
||||||
|
"%3B"
|
||||||
|
"application/javascript"
|
||||||
|
"application/json"
|
||||||
|
"application/pdf"
|
||||||
|
"application/xhtml+xml"
|
||||||
|
"application/xml"
|
||||||
|
"application/x-www-form-urlencoded"
|
||||||
|
"Bad Request"
|
||||||
|
"boundary="
|
||||||
|
"bytes="
|
||||||
|
"chunked"
|
||||||
|
"close"
|
||||||
|
"CONNECT"
|
||||||
|
"css"
|
||||||
|
"Forbidden"
|
||||||
|
"Found"
|
||||||
|
"gif"
|
||||||
|
"gzip"
|
||||||
|
"html"
|
||||||
|
"ico"
|
||||||
|
"image/gif"
|
||||||
|
"image/jpg"
|
||||||
|
"image/png"
|
||||||
|
"image/svg+xml"
|
||||||
|
"image/x-icon"
|
||||||
|
"index.html"
|
||||||
|
"Internal Server Error"
|
||||||
|
"jpeg"
|
||||||
|
"js"
|
||||||
|
"json"
|
||||||
|
"Location"
|
||||||
|
"Moved Permanently"
|
||||||
|
"multipart/form-data"
|
||||||
|
"Not Found"
|
||||||
|
"Not Modified"
|
||||||
|
"OK"
|
||||||
|
"pdf"
|
||||||
|
"png"
|
||||||
|
"Range"
|
||||||
|
"REMOTE_ADDR"
|
||||||
|
"See Other"
|
||||||
|
"svg"
|
||||||
|
"text/"
|
||||||
|
"text/css"
|
||||||
|
"text/html"
|
||||||
|
"text/plain"
|
||||||
|
"txt"
|
||||||
|
"Unsupported Media Type"
|
||||||
|
"xhtml"
|
||||||
|
"xml"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|
||||||
|
// This runner does not do any fuzzing, but allows us to run the fuzz target
|
||||||
|
// on the test corpus or on a single file,
|
||||||
|
// e.g. the one that comes from a bug report.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Forward declare the "fuzz target" interface.
|
||||||
|
// We deliberately keep this inteface simple and header-free.
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||||
|
|
||||||
|
// It reads all files passed as parameters and feeds their contents
|
||||||
|
// one by one into the fuzz target (LLVMFuzzerTestOneInput).
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
std::ifstream in(argv[i]);
|
||||||
|
in.seekg(0, in.end);
|
||||||
|
size_t length = in.tellg();
|
||||||
|
in.seekg (0, in.beg);
|
||||||
|
std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
|
||||||
|
// Allocate exactly length bytes so that we reliably catch buffer overflows.
|
||||||
|
std::vector<char> bytes(length);
|
||||||
|
in.read(bytes.data(), bytes.size());
|
||||||
|
LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()),
|
||||||
|
bytes.size());
|
||||||
|
std::cout << "Execution successful" << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "Execution finished" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+626
-276
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user