mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-17 10:59:39 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
No files matched your search
@@ -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
|
||||||
@@ -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)
|
||||||
|
|
||||||
@@ -76,12 +77,13 @@ 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));
|
auto body = req.body.substr(file.offset, file.length);
|
||||||
})
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stream content with Content provider
|
### Stream content with Content provider
|
||||||
|
|||||||
@@ -8,6 +8,49 @@
|
|||||||
#ifndef CPPHTTPLIB_HTTPLIB_H
|
#ifndef CPPHTTPLIB_HTTPLIB_H
|
||||||
#define CPPHTTPLIB_HTTPLIB_H
|
#define CPPHTTPLIB_HTTPLIB_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration
|
||||||
|
*/
|
||||||
|
#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND
|
||||||
|
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND
|
||||||
|
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
|
||||||
|
#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_READ_TIMEOUT_SECOND
|
||||||
|
#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_READ_TIMEOUT_USECOND
|
||||||
|
#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH
|
||||||
|
#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT
|
||||||
|
#define CPPHTTPLIB_REDIRECT_MAX_COUNT 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH
|
||||||
|
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH (std::numeric_limits<size_t>::max)()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_RECV_BUFSIZ
|
||||||
|
#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CPPHTTPLIB_THREAD_POOL_COUNT
|
||||||
|
#define CPPHTTPLIB_THREAD_POOL_COUNT 8
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
@@ -45,18 +88,32 @@ typedef int ssize_t;
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
#ifndef WSA_FLAG_NO_HANDLE_INHERIT
|
||||||
|
#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef strcasecmp
|
#ifndef strcasecmp
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
#endif // strcasecmp
|
#endif // strcasecmp
|
||||||
|
|
||||||
typedef SOCKET socket_t;
|
typedef SOCKET socket_t;
|
||||||
#else
|
#ifdef CPPHTTPLIB_USE_POLL
|
||||||
|
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // not _WIN32
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#ifdef CPPHTTPLIB_USE_POLL
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
@@ -70,6 +127,7 @@ typedef int socket_t;
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -104,20 +162,6 @@ inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) {
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Configuration
|
|
||||||
*/
|
|
||||||
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
|
|
||||||
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND 0
|
|
||||||
#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5
|
|
||||||
#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5
|
|
||||||
#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0
|
|
||||||
#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192
|
|
||||||
#define CPPHTTPLIB_REDIRECT_MAX_COUNT 20
|
|
||||||
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH (std::numeric_limits<size_t>::max)()
|
|
||||||
#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u)
|
|
||||||
#define CPPHTTPLIB_THREAD_POOL_COUNT 8
|
|
||||||
|
|
||||||
namespace httplib {
|
namespace httplib {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -153,6 +197,9 @@ typedef std::function<bool(const char *data, size_t data_length, size_t offset,
|
|||||||
|
|
||||||
typedef std::function<bool(uint64_t current, uint64_t total)> Progress;
|
typedef std::function<bool(uint64_t current, uint64_t total)> Progress;
|
||||||
|
|
||||||
|
struct Response;
|
||||||
|
typedef std::function<bool(const Response &response)> ResponseHandler;
|
||||||
|
|
||||||
struct MultipartFile {
|
struct MultipartFile {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string content_type;
|
std::string content_type;
|
||||||
@@ -188,6 +235,7 @@ struct Request {
|
|||||||
|
|
||||||
// for client
|
// for client
|
||||||
size_t redirect_count = CPPHTTPLIB_REDIRECT_MAX_COUNT;
|
size_t redirect_count = CPPHTTPLIB_REDIRECT_MAX_COUNT;
|
||||||
|
ResponseHandler response_handler;
|
||||||
ContentReceiver content_receiver;
|
ContentReceiver content_receiver;
|
||||||
Progress progress;
|
Progress progress;
|
||||||
|
|
||||||
@@ -354,7 +402,7 @@ private:
|
|||||||
pool_.jobs_.pop_front();
|
pool_.jobs_.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(true == (bool)fn);
|
assert(true == static_cast<bool>(fn));
|
||||||
fn();
|
fn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,6 +566,15 @@ public:
|
|||||||
ContentReceiver content_receiver,
|
ContentReceiver content_receiver,
|
||||||
Progress progress);
|
Progress progress);
|
||||||
|
|
||||||
|
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||||
|
ResponseHandler response_handler,
|
||||||
|
ContentReceiver content_receiver);
|
||||||
|
|
||||||
|
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||||
|
ResponseHandler response_handler,
|
||||||
|
ContentReceiver content_receiver,
|
||||||
|
Progress progress);
|
||||||
|
|
||||||
std::shared_ptr<Response> Head(const char *path);
|
std::shared_ptr<Response> Head(const char *path);
|
||||||
|
|
||||||
std::shared_ptr<Response> Head(const char *path, const Headers &headers);
|
std::shared_ptr<Response> Head(const char *path, const Headers &headers);
|
||||||
@@ -684,6 +741,8 @@ public:
|
|||||||
|
|
||||||
long get_openssl_verify_result() const;
|
long get_openssl_verify_result() const;
|
||||||
|
|
||||||
|
SSL_CTX* ssl_context() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool process_and_close_socket(
|
virtual bool process_and_close_socket(
|
||||||
socket_t sock, size_t request_count,
|
socket_t sock, size_t request_count,
|
||||||
@@ -973,6 +1032,15 @@ inline int close_socket(socket_t sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int select_read(socket_t sock, time_t sec, time_t usec) {
|
inline int select_read(socket_t sock, time_t sec, time_t usec) {
|
||||||
|
#ifdef CPPHTTPLIB_USE_POLL
|
||||||
|
struct pollfd pfd_read;
|
||||||
|
pfd_read.fd = sock;
|
||||||
|
pfd_read.events = POLLIN;
|
||||||
|
|
||||||
|
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
||||||
|
|
||||||
|
return poll(&pfd_read, 1, timeout);
|
||||||
|
#else
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(sock, &fds);
|
FD_SET(sock, &fds);
|
||||||
@@ -982,9 +1050,26 @@ inline int select_read(socket_t sock, time_t sec, time_t usec) {
|
|||||||
tv.tv_usec = static_cast<long>(usec);
|
tv.tv_usec = static_cast<long>(usec);
|
||||||
|
|
||||||
return select(static_cast<int>(sock + 1), &fds, nullptr, nullptr, &tv);
|
return select(static_cast<int>(sock + 1), &fds, nullptr, nullptr, &tv);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
|
inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
|
||||||
|
#ifdef CPPHTTPLIB_USE_POLL
|
||||||
|
struct pollfd pfd_read;
|
||||||
|
pfd_read.fd = sock;
|
||||||
|
pfd_read.events = POLLIN | POLLOUT;
|
||||||
|
|
||||||
|
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
||||||
|
|
||||||
|
if (poll(&pfd_read, 1, timeout) > 0 &&
|
||||||
|
pfd_read.revents & (POLLIN | POLLOUT)) {
|
||||||
|
int error = 0;
|
||||||
|
socklen_t len = sizeof(error);
|
||||||
|
return getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &len) >= 0 &&
|
||||||
|
!error;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
fd_set fdsr;
|
fd_set fdsr;
|
||||||
FD_ZERO(&fdsr);
|
FD_ZERO(&fdsr);
|
||||||
FD_SET(sock, &fdsr);
|
FD_SET(sock, &fdsr);
|
||||||
@@ -996,20 +1081,15 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
|
|||||||
tv.tv_sec = static_cast<long>(sec);
|
tv.tv_sec = static_cast<long>(sec);
|
||||||
tv.tv_usec = static_cast<long>(usec);
|
tv.tv_usec = static_cast<long>(usec);
|
||||||
|
|
||||||
if (select(static_cast<int>(sock + 1), &fdsr, &fdsw, &fdse, &tv) < 0) {
|
if (select(static_cast<int>(sock + 1), &fdsr, &fdsw, &fdse, &tv) > 0 &&
|
||||||
return false;
|
(FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) {
|
||||||
} else if (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw)) {
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
socklen_t len = sizeof(error);
|
socklen_t len = sizeof(error);
|
||||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0 ||
|
return getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) >= 0 &&
|
||||||
error) {
|
!error;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return true;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -1096,9 +1176,9 @@ socket_t create_socket(const char *host, int port, Fn fn,
|
|||||||
|
|
||||||
// Make 'reuse address' option available
|
// Make 'reuse address' option available
|
||||||
int yes = 1;
|
int yes = 1;
|
||||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&yes), sizeof(yes));
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&yes, sizeof(yes));
|
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast<char*>(&yes), sizeof(yes));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// bind or connect
|
// bind or connect
|
||||||
@@ -1137,10 +1217,10 @@ inline std::string get_remote_addr(socket_t sock) {
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t len = sizeof(addr);
|
socklen_t len = sizeof(addr);
|
||||||
|
|
||||||
if (!getpeername(sock, (struct sockaddr *)&addr, &len)) {
|
if (!getpeername(sock, reinterpret_cast<struct sockaddr *>(&addr), &len)) {
|
||||||
char ipstr[NI_MAXHOST];
|
char ipstr[NI_MAXHOST];
|
||||||
|
|
||||||
if (!getnameinfo((struct sockaddr *)&addr, len, ipstr, sizeof(ipstr),
|
if (!getnameinfo(reinterpret_cast<struct sockaddr *>(&addr), len, ipstr, sizeof(ipstr),
|
||||||
nullptr, 0, NI_NUMERICHOST)) {
|
nullptr, 0, NI_NUMERICHOST)) {
|
||||||
return ipstr;
|
return ipstr;
|
||||||
}
|
}
|
||||||
@@ -1222,7 +1302,7 @@ inline bool compress(std::string &content) {
|
|||||||
if (ret != Z_OK) { return false; }
|
if (ret != Z_OK) { return false; }
|
||||||
|
|
||||||
strm.avail_in = content.size();
|
strm.avail_in = content.size();
|
||||||
strm.next_in = (Bytef *)content.data();
|
strm.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(content.data()));
|
||||||
|
|
||||||
std::string compressed;
|
std::string compressed;
|
||||||
|
|
||||||
@@ -1230,7 +1310,7 @@ inline bool compress(std::string &content) {
|
|||||||
char buff[bufsiz];
|
char buff[bufsiz];
|
||||||
do {
|
do {
|
||||||
strm.avail_out = bufsiz;
|
strm.avail_out = bufsiz;
|
||||||
strm.next_out = (Bytef *)buff;
|
strm.next_out = reinterpret_cast<Bytef*>(buff);
|
||||||
ret = deflate(&strm, Z_FINISH);
|
ret = deflate(&strm, Z_FINISH);
|
||||||
assert(ret != Z_STREAM_ERROR);
|
assert(ret != Z_STREAM_ERROR);
|
||||||
compressed.append(buff, bufsiz - strm.avail_out);
|
compressed.append(buff, bufsiz - strm.avail_out);
|
||||||
@@ -1267,13 +1347,13 @@ public:
|
|||||||
int ret = Z_OK;
|
int ret = Z_OK;
|
||||||
|
|
||||||
strm.avail_in = data_length;
|
strm.avail_in = data_length;
|
||||||
strm.next_in = (Bytef *)data;
|
strm.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef *>(data));
|
||||||
|
|
||||||
const auto bufsiz = 16384;
|
const auto bufsiz = 16384;
|
||||||
char buff[bufsiz];
|
char buff[bufsiz];
|
||||||
do {
|
do {
|
||||||
strm.avail_out = bufsiz;
|
strm.avail_out = bufsiz;
|
||||||
strm.next_out = (Bytef *)buff;
|
strm.next_out = reinterpret_cast<Bytef*>(buff);
|
||||||
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
assert(ret != Z_STREAM_ERROR);
|
assert(ret != Z_STREAM_ERROR);
|
||||||
@@ -1555,6 +1635,7 @@ inline bool redirect(T &cli, const Request &req, Response &res,
|
|||||||
new_req.headers = req.headers;
|
new_req.headers = req.headers;
|
||||||
new_req.body = req.body;
|
new_req.body = req.body;
|
||||||
new_req.redirect_count = req.redirect_count - 1;
|
new_req.redirect_count = req.redirect_count - 1;
|
||||||
|
new_req.response_handler = req.response_handler;
|
||||||
new_req.content_receiver = req.content_receiver;
|
new_req.content_receiver = req.content_receiver;
|
||||||
new_req.progress = req.progress;
|
new_req.progress = req.progress;
|
||||||
|
|
||||||
@@ -2241,7 +2322,7 @@ inline void Server::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool Server::parse_request_line(const char *s, Request &req) {
|
inline bool Server::parse_request_line(const char *s, Request &req) {
|
||||||
static std::regex re("(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS) "
|
static std::regex re("(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH|PRI) "
|
||||||
"(([^?]+)(?:\\?(.+?))?) (HTTP/1\\.[01])\r\n");
|
"(([^?]+)(?:\\?(.+?))?) (HTTP/1\\.[01])\r\n");
|
||||||
|
|
||||||
std::cmatch m;
|
std::cmatch m;
|
||||||
@@ -2499,6 +2580,12 @@ inline bool Server::listen_internal() {
|
|||||||
socket_t sock = accept(svr_sock_, nullptr, nullptr);
|
socket_t sock = accept(svr_sock_, nullptr, nullptr);
|
||||||
|
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
|
if (errno == EMFILE) {
|
||||||
|
// The per-process limit of open file descriptors has been reached.
|
||||||
|
// Try to accept new connections after a short sleep.
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (svr_sock_ != INVALID_SOCKET) {
|
if (svr_sock_ != INVALID_SOCKET) {
|
||||||
detail::close_socket(svr_sock_);
|
detail::close_socket(svr_sock_);
|
||||||
ret = false;
|
ret = false;
|
||||||
@@ -2527,13 +2614,15 @@ inline bool Server::routing(Request &req, Response &res) {
|
|||||||
return dispatch_request(req, res, post_handlers_);
|
return dispatch_request(req, res, post_handlers_);
|
||||||
} else if (req.method == "PUT") {
|
} else if (req.method == "PUT") {
|
||||||
return dispatch_request(req, res, put_handlers_);
|
return dispatch_request(req, res, put_handlers_);
|
||||||
} else if (req.method == "PATCH") {
|
|
||||||
return dispatch_request(req, res, patch_handlers_);
|
|
||||||
} else if (req.method == "DELETE") {
|
} else if (req.method == "DELETE") {
|
||||||
return dispatch_request(req, res, delete_handlers_);
|
return dispatch_request(req, res, delete_handlers_);
|
||||||
} else if (req.method == "OPTIONS") {
|
} else if (req.method == "OPTIONS") {
|
||||||
return dispatch_request(req, res, options_handlers_);
|
return dispatch_request(req, res, options_handlers_);
|
||||||
|
} else if (req.method == "PATCH") {
|
||||||
|
return dispatch_request(req, res, patch_handlers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.status = 400;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2595,7 +2684,7 @@ Server::process_request(Stream &strm, bool last_connection,
|
|||||||
req.set_header("REMOTE_ADDR", strm.get_remote_addr());
|
req.set_header("REMOTE_ADDR", strm.get_remote_addr());
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH") {
|
if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" || req.method == "PRI") {
|
||||||
if (!detail::read_content(strm, req, payload_max_length_, res.status,
|
if (!detail::read_content(strm, req, payload_max_length_, res.status,
|
||||||
Progress(), [&](const char *buf, size_t n) {
|
Progress(), [&](const char *buf, size_t n) {
|
||||||
if (req.body.size() + n > req.body.max_size()) {
|
if (req.body.size() + n > req.body.max_size()) {
|
||||||
@@ -2633,7 +2722,7 @@ Server::process_request(Stream &strm, bool last_connection,
|
|||||||
if (routing(req, res)) {
|
if (routing(req, res)) {
|
||||||
if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; }
|
if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; }
|
||||||
} else {
|
} else {
|
||||||
res.status = 404;
|
if (res.status == -1) { res.status = 404; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return write_response(strm, last_connection, req, res);
|
return write_response(strm, last_connection, req, res);
|
||||||
@@ -2727,7 +2816,7 @@ inline bool Client::send(const std::vector<Request> &requests,
|
|||||||
|
|
||||||
if (!process_and_close_socket(
|
if (!process_and_close_socket(
|
||||||
sock, requests.size() - i,
|
sock, requests.size() - i,
|
||||||
[&](Stream &strm, bool last_connection, bool &connection_close) {
|
[&](Stream &strm, bool last_connection, bool &connection_close) -> bool {
|
||||||
auto &req = requests[i];
|
auto &req = requests[i];
|
||||||
auto res = Response();
|
auto res = Response();
|
||||||
i++;
|
i++;
|
||||||
@@ -2869,6 +2958,10 @@ inline bool Client::process_request(Stream &strm, const Request &req,
|
|||||||
connection_close = true;
|
connection_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req.response_handler) {
|
||||||
|
if (!req.response_handler(res)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
if (req.method != "HEAD") {
|
if (req.method != "HEAD") {
|
||||||
detail::ContentReceiverCore out = [&](const char *buf, size_t n) {
|
detail::ContentReceiverCore out = [&](const char *buf, size_t n) {
|
||||||
@@ -2940,30 +3033,47 @@ Client::Get(const char *path, const Headers &headers, Progress progress) {
|
|||||||
inline std::shared_ptr<Response> Client::Get(const char *path,
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
ContentReceiver content_receiver) {
|
ContentReceiver content_receiver) {
|
||||||
Progress dummy;
|
Progress dummy;
|
||||||
return Get(path, Headers(), content_receiver, dummy);
|
return Get(path, Headers(), nullptr, content_receiver, dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::Get(const char *path,
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
ContentReceiver content_receiver,
|
ContentReceiver content_receiver,
|
||||||
Progress progress) {
|
Progress progress) {
|
||||||
return Get(path, Headers(), content_receiver, progress);
|
return Get(path, Headers(), nullptr, content_receiver, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::Get(const char *path,
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
const Headers &headers,
|
const Headers &headers,
|
||||||
ContentReceiver content_receiver) {
|
ContentReceiver content_receiver) {
|
||||||
Progress dummy;
|
Progress dummy;
|
||||||
return Get(path, headers, content_receiver, dummy);
|
return Get(path, headers, nullptr, content_receiver, dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::Get(const char *path,
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
const Headers &headers,
|
const Headers &headers,
|
||||||
ContentReceiver content_receiver,
|
ContentReceiver content_receiver,
|
||||||
Progress progress) {
|
Progress progress) {
|
||||||
|
return Get(path, headers, nullptr, content_receiver, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
|
const Headers &headers,
|
||||||
|
ResponseHandler response_handler,
|
||||||
|
ContentReceiver content_receiver) {
|
||||||
|
Progress dummy;
|
||||||
|
return Get(path, headers, response_handler, content_receiver, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::Get(const char *path,
|
||||||
|
const Headers &headers,
|
||||||
|
ResponseHandler response_handler,
|
||||||
|
ContentReceiver content_receiver,
|
||||||
|
Progress progress) {
|
||||||
Request req;
|
Request req;
|
||||||
req.method = "GET";
|
req.method = "GET";
|
||||||
req.path = path;
|
req.path = path;
|
||||||
req.headers = headers;
|
req.headers = headers;
|
||||||
|
req.response_handler = response_handler;
|
||||||
req.content_receiver = content_receiver;
|
req.content_receiver = content_receiver;
|
||||||
req.progress = progress;
|
req.progress = progress;
|
||||||
|
|
||||||
@@ -3192,7 +3302,7 @@ inline bool process_and_close_socket_ssl(bool is_client_request, socket_t sock,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bio = BIO_new_socket(sock, BIO_NOCLOSE);
|
auto bio = BIO_new_socket(static_cast<int>(sock), BIO_NOCLOSE);
|
||||||
SSL_set_bio(ssl, bio, bio);
|
SSL_set_bio(ssl, bio, bio);
|
||||||
|
|
||||||
if (!setup(ssl)) {
|
if (!setup(ssl)) {
|
||||||
@@ -3298,13 +3408,13 @@ inline int SSLSocketStream::read(char *ptr, size_t size) {
|
|||||||
if (SSL_pending(ssl_) > 0 ||
|
if (SSL_pending(ssl_) > 0 ||
|
||||||
detail::select_read(sock_, CPPHTTPLIB_READ_TIMEOUT_SECOND,
|
detail::select_read(sock_, CPPHTTPLIB_READ_TIMEOUT_SECOND,
|
||||||
CPPHTTPLIB_READ_TIMEOUT_USECOND) > 0) {
|
CPPHTTPLIB_READ_TIMEOUT_USECOND) > 0) {
|
||||||
return SSL_read(ssl_, ptr, size);
|
return SSL_read(ssl_, ptr, static_cast<int>(size));
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int SSLSocketStream::write(const char *ptr, size_t size) {
|
inline int SSLSocketStream::write(const char *ptr, size_t size) {
|
||||||
return SSL_write(ssl_, ptr, size);
|
return SSL_write(ssl_, ptr, static_cast<int>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int SSLSocketStream::write(const char *ptr) {
|
inline int SSLSocketStream::write(const char *ptr) {
|
||||||
@@ -3417,6 +3527,10 @@ inline long SSLClient::get_openssl_verify_result() const {
|
|||||||
return verify_result_;
|
return verify_result_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline SSL_CTX* SSLClient::ssl_context() const noexcept {
|
||||||
|
return ctx_;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SSLClient::process_and_close_socket(
|
inline bool SSLClient::process_and_close_socket(
|
||||||
socket_t sock, size_t request_count,
|
socket_t sock, size_t request_count,
|
||||||
std::function<bool(Stream &strm, bool last_connection,
|
std::function<bool(Stream &strm, bool last_connection,
|
||||||
|
|||||||
+47
-3
@@ -242,6 +242,38 @@ TEST(ChunkedEncodingTest, WithContentReceiver) {
|
|||||||
EXPECT_EQ(out, body);
|
EXPECT_EQ(out, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) {
|
||||||
|
auto host = "www.httpwatch.com";
|
||||||
|
auto sec = 2;
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
auto port = 443;
|
||||||
|
httplib::SSLClient cli(host, port, sec);
|
||||||
|
#else
|
||||||
|
auto port = 80;
|
||||||
|
httplib::Client cli(host, port, sec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string body;
|
||||||
|
auto res =
|
||||||
|
cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137", Headers(),
|
||||||
|
[&](const Response& response) {
|
||||||
|
EXPECT_EQ(200, response.status);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[&](const char *data, size_t data_length, uint64_t, uint64_t) {
|
||||||
|
body.append(data, data_length);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
|
||||||
|
std::string out;
|
||||||
|
httplib::detail::read_file("./image.jpg", out);
|
||||||
|
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
EXPECT_EQ(out, body);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RangeTest, FromHTTPBin) {
|
TEST(RangeTest, FromHTTPBin) {
|
||||||
auto host = "httpbin.org";
|
auto host = "httpbin.org";
|
||||||
auto sec = 5;
|
auto sec = 5;
|
||||||
@@ -303,7 +335,7 @@ TEST(RangeTest, FromHTTPBin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(ConnectionErrorTest, InvalidHost) {
|
TEST(ConnectionErrorTest, InvalidHost) {
|
||||||
auto host = "abcde.com";
|
auto host = "-abcde.com";
|
||||||
auto sec = 2;
|
auto sec = 2;
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
@@ -504,7 +536,7 @@ TEST(YahooRedirectTest, Redirect) {
|
|||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Https2HttpRedirectTest, Redirect) {
|
TEST(HttpsToHttpRedirectTest, Redirect) {
|
||||||
httplib::SSLClient cli("httpbin.org");
|
httplib::SSLClient cli("httpbin.org");
|
||||||
cli.follow_location(true);
|
cli.follow_location(true);
|
||||||
auto res = cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
|
auto res = cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
|
||||||
@@ -605,7 +637,7 @@ protected:
|
|||||||
size_t DATA_CHUNK_SIZE = 4;
|
size_t DATA_CHUNK_SIZE = 4;
|
||||||
const auto &d = *data;
|
const auto &d = *data;
|
||||||
auto out_len = std::min(static_cast<size_t>(length), DATA_CHUNK_SIZE);
|
auto out_len = std::min(static_cast<size_t>(length), DATA_CHUNK_SIZE);
|
||||||
sink(&d[offset], out_len);
|
sink(&d[static_cast<size_t>(offset)], out_len);
|
||||||
},
|
},
|
||||||
[data] { delete data; });
|
[data] { delete data; });
|
||||||
})
|
})
|
||||||
@@ -1361,6 +1393,18 @@ TEST_F(ServerTest, NoMultipleHeaders) {
|
|||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTest, HTTP2Magic) {
|
||||||
|
Request req;
|
||||||
|
req.method = "PRI";
|
||||||
|
req.path = "*";
|
||||||
|
req.body = "SM";
|
||||||
|
|
||||||
|
auto res = std::make_shared<Response>();
|
||||||
|
auto ret = cli_.send(req, *res);
|
||||||
|
|
||||||
|
ASSERT_TRUE(ret);
|
||||||
|
EXPECT_EQ(400, res->status);
|
||||||
|
}
|
||||||
TEST_F(ServerTest, KeepAlive) {
|
TEST_F(ServerTest, KeepAlive) {
|
||||||
cli_.set_keep_alive_max_count(4);
|
cli_.set_keep_alive_max_count(4);
|
||||||
|
|
||||||
|
|||||||
+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>
|
||||||
|
|||||||
Reference in new issue
Block a user