Team Ai
Apppublic

KBaba7/llama.cpp

sourceHugging Faceapache-2.0updated 2y agoView on Hugging Face
0likes
httplib.h10352 linesDownload Raw Back to server
1//2//  httplib.h3//4//  Copyright (c) 2024 Yuji Hirose. All rights reserved.5//  MIT License6//7 8#ifndef CPPHTTPLIB_HTTPLIB_H9#define CPPHTTPLIB_HTTPLIB_H10 11#define CPPHTTPLIB_VERSION "0.18.5"12 13/*14 * Configuration15 */16 17#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND18#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 519#endif20 21#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND22#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND 1000023#endif24 25#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT26#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 10027#endif28 29#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND30#define CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND 30031#endif32 33#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND34#define CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND 035#endif36 37#ifndef CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND38#define CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND 539#endif40 41#ifndef CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND42#define CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND 043#endif44 45#ifndef CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND46#define CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND 547#endif48 49#ifndef CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND50#define CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND 051#endif52 53#ifndef CPPHTTPLIB_CLIENT_READ_TIMEOUT_SECOND54#define CPPHTTPLIB_CLIENT_READ_TIMEOUT_SECOND 30055#endif56 57#ifndef CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND58#define CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND 059#endif60 61#ifndef CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND62#define CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND 563#endif64 65#ifndef CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND66#define CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND 067#endif68 69#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND70#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 071#endif72 73#ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND74#ifdef _WIN3275#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 1000076#else77#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 078#endif79#endif80 81#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH82#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 819283#endif84 85#ifndef CPPHTTPLIB_HEADER_MAX_LENGTH86#define CPPHTTPLIB_HEADER_MAX_LENGTH 819287#endif88 89#ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT90#define CPPHTTPLIB_REDIRECT_MAX_COUNT 2091#endif92 93#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT94#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 102495#endif96 97#ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH98#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits<size_t>::max)())99#endif100 101#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH102#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192103#endif104 105#ifndef CPPHTTPLIB_RANGE_MAX_COUNT106#define CPPHTTPLIB_RANGE_MAX_COUNT 1024107#endif108 109#ifndef CPPHTTPLIB_TCP_NODELAY110#define CPPHTTPLIB_TCP_NODELAY false111#endif112 113#ifndef CPPHTTPLIB_IPV6_V6ONLY114#define CPPHTTPLIB_IPV6_V6ONLY false115#endif116 117#ifndef CPPHTTPLIB_RECV_BUFSIZ118#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)119#endif120 121#ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ122#define CPPHTTPLIB_COMPRESSION_BUFSIZ size_t(16384u)123#endif124 125#ifndef CPPHTTPLIB_THREAD_POOL_COUNT126#define CPPHTTPLIB_THREAD_POOL_COUNT                                           \127  ((std::max)(8u, std::thread::hardware_concurrency() > 0                      \128                      ? std::thread::hardware_concurrency() - 1                \129                      : 0))130#endif131 132#ifndef CPPHTTPLIB_RECV_FLAGS133#define CPPHTTPLIB_RECV_FLAGS 0134#endif135 136#ifndef CPPHTTPLIB_SEND_FLAGS137#define CPPHTTPLIB_SEND_FLAGS 0138#endif139 140#ifndef CPPHTTPLIB_LISTEN_BACKLOG141#define CPPHTTPLIB_LISTEN_BACKLOG 5142#endif143 144/*145 * Headers146 */147 148#ifdef _WIN32149#ifndef _CRT_SECURE_NO_WARNINGS150#define _CRT_SECURE_NO_WARNINGS151#endif //_CRT_SECURE_NO_WARNINGS152 153#ifndef _CRT_NONSTDC_NO_DEPRECATE154#define _CRT_NONSTDC_NO_DEPRECATE155#endif //_CRT_NONSTDC_NO_DEPRECATE156 157#if defined(_MSC_VER)158#if _MSC_VER < 1900159#error Sorry, Visual Studio versions prior to 2015 are not supported160#endif161 162#pragma comment(lib, "ws2_32.lib")163 164#ifdef _WIN64165using ssize_t = __int64;166#else167using ssize_t = long;168#endif169#endif // _MSC_VER170 171#ifndef S_ISREG172#define S_ISREG(m) (((m) & S_IFREG) == S_IFREG)173#endif // S_ISREG174 175#ifndef S_ISDIR176#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR)177#endif // S_ISDIR178 179#ifndef NOMINMAX180#define NOMINMAX181#endif // NOMINMAX182 183#include <io.h>184#include <winsock2.h>185#include <ws2tcpip.h>186 187#ifndef WSA_FLAG_NO_HANDLE_INHERIT188#define WSA_FLAG_NO_HANDLE_INHERIT 0x80189#endif190 191using socket_t = SOCKET;192#ifdef CPPHTTPLIB_USE_POLL193#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)194#endif195 196#else // not _WIN32197 198#include <arpa/inet.h>199#if !defined(_AIX) && !defined(__MVS__)200#include <ifaddrs.h>201#endif202#ifdef __MVS__203#include <strings.h>204#ifndef NI_MAXHOST205#define NI_MAXHOST 1025206#endif207#endif208#include <net/if.h>209#include <netdb.h>210#include <netinet/in.h>211#ifdef __linux__212#include <resolv.h>213#endif214#include <netinet/tcp.h>215#ifdef CPPHTTPLIB_USE_POLL216#include <poll.h>217#endif218#include <csignal>219#include <pthread.h>220#include <sys/mman.h>221#include <sys/select.h>222#include <sys/socket.h>223#include <sys/un.h>224#include <unistd.h>225 226using socket_t = int;227#ifndef INVALID_SOCKET228#define INVALID_SOCKET (-1)229#endif230#endif //_WIN32231 232#include <algorithm>233#include <array>234#include <atomic>235#include <cassert>236#include <cctype>237#include <climits>238#include <condition_variable>239#include <cstring>240#include <errno.h>241#include <exception>242#include <fcntl.h>243#include <fstream>244#include <functional>245#include <iomanip>246#include <iostream>247#include <list>248#include <map>249#include <memory>250#include <mutex>251#include <random>252#include <regex>253#include <set>254#include <sstream>255#include <string>256#include <sys/stat.h>257#include <thread>258#include <unordered_map>259#include <unordered_set>260#include <utility>261 262#ifdef CPPHTTPLIB_OPENSSL_SUPPORT263#ifdef _WIN32264#include <wincrypt.h>265 266// these are defined in wincrypt.h and it breaks compilation if BoringSSL is267// used268#undef X509_NAME269#undef X509_CERT_PAIR270#undef X509_EXTENSIONS271#undef PKCS7_SIGNER_INFO272 273#ifdef _MSC_VER274#pragma comment(lib, "crypt32.lib")275#endif276#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)277#include <TargetConditionals.h>278#if TARGET_OS_OSX279#include <CoreFoundation/CoreFoundation.h>280#include <Security/Security.h>281#endif // TARGET_OS_OSX282#endif // _WIN32283 284#include <openssl/err.h>285#include <openssl/evp.h>286#include <openssl/ssl.h>287#include <openssl/x509v3.h>288 289#if defined(_WIN32) && defined(OPENSSL_USE_APPLINK)290#include <openssl/applink.c>291#endif292 293#include <iostream>294#include <sstream>295 296#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)297#if OPENSSL_VERSION_NUMBER < 0x1010107f298#error Please use OpenSSL or a current version of BoringSSL299#endif300#define SSL_get1_peer_certificate SSL_get_peer_certificate301#elif OPENSSL_VERSION_NUMBER < 0x30000000L302#error Sorry, OpenSSL versions prior to 3.0.0 are not supported303#endif304 305#endif306 307#ifdef CPPHTTPLIB_ZLIB_SUPPORT308#include <zlib.h>309#endif310 311#ifdef CPPHTTPLIB_BROTLI_SUPPORT312#include <brotli/decode.h>313#include <brotli/encode.h>314#endif315 316/*317 * Declaration318 */319namespace httplib {320 321namespace detail {322 323/*324 * Backport std::make_unique from C++14.325 *326 * NOTE: This code came up with the following stackoverflow post:327 * https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique328 *329 */330 331template <class T, class... Args>332typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type333make_unique(Args &&...args) {334  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));335}336 337template <class T>338typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type339make_unique(std::size_t n) {340  typedef typename std::remove_extent<T>::type RT;341  return std::unique_ptr<T>(new RT[n]);342}343 344namespace case_ignore {345 346inline unsigned char to_lower(int c) {347  const static unsigned char table[256] = {348      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,349      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,350      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,351      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,352      60,  61,  62,  63,  64,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,353      107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,354      122, 91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,355      105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,356      120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,357      135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,358      150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,359      165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,360      180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226,361      227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,362      242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224,363      225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,364      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,365      255,366  };367  return table[(unsigned char)(char)c];368}369 370inline bool equal(const std::string &a, const std::string &b) {371  return a.size() == b.size() &&372         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {373           return to_lower(ca) == to_lower(cb);374         });375}376 377struct equal_to {378  bool operator()(const std::string &a, const std::string &b) const {379    return equal(a, b);380  }381};382 383struct hash {384  size_t operator()(const std::string &key) const {385    return hash_core(key.data(), key.size(), 0);386  }387 388  size_t hash_core(const char *s, size_t l, size_t h) const {389    return (l == 0) ? h390                    : hash_core(s + 1, l - 1,391                                // Unsets the 6 high bits of h, therefore no392                                // overflow happens393                                (((std::numeric_limits<size_t>::max)() >> 6) &394                                 h * 33) ^395                                    static_cast<unsigned char>(to_lower(*s)));396  }397};398 399} // namespace case_ignore400 401// This is based on402// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189".403 404struct scope_exit {405  explicit scope_exit(std::function<void(void)> &&f)406      : exit_function(std::move(f)), execute_on_destruction{true} {}407 408  scope_exit(scope_exit &&rhs) noexcept409      : exit_function(std::move(rhs.exit_function)),410        execute_on_destruction{rhs.execute_on_destruction} {411    rhs.release();412  }413 414  ~scope_exit() {415    if (execute_on_destruction) { this->exit_function(); }416  }417 418  void release() { this->execute_on_destruction = false; }419 420private:421  scope_exit(const scope_exit &) = delete;422  void operator=(const scope_exit &) = delete;423  scope_exit &operator=(scope_exit &&) = delete;424 425  std::function<void(void)> exit_function;426  bool execute_on_destruction;427};428 429} // namespace detail430 431enum StatusCode {432  // Information responses433  Continue_100 = 100,434  SwitchingProtocol_101 = 101,435  Processing_102 = 102,436  EarlyHints_103 = 103,437 438  // Successful responses439  OK_200 = 200,440  Created_201 = 201,441  Accepted_202 = 202,442  NonAuthoritativeInformation_203 = 203,443  NoContent_204 = 204,444  ResetContent_205 = 205,445  PartialContent_206 = 206,446  MultiStatus_207 = 207,447  AlreadyReported_208 = 208,448  IMUsed_226 = 226,449 450  // Redirection messages451  MultipleChoices_300 = 300,452  MovedPermanently_301 = 301,453  Found_302 = 302,454  SeeOther_303 = 303,455  NotModified_304 = 304,456  UseProxy_305 = 305,457  unused_306 = 306,458  TemporaryRedirect_307 = 307,459  PermanentRedirect_308 = 308,460 461  // Client error responses462  BadRequest_400 = 400,463  Unauthorized_401 = 401,464  PaymentRequired_402 = 402,465  Forbidden_403 = 403,466  NotFound_404 = 404,467  MethodNotAllowed_405 = 405,468  NotAcceptable_406 = 406,469  ProxyAuthenticationRequired_407 = 407,470  RequestTimeout_408 = 408,471  Conflict_409 = 409,472  Gone_410 = 410,473  LengthRequired_411 = 411,474  PreconditionFailed_412 = 412,475  PayloadTooLarge_413 = 413,476  UriTooLong_414 = 414,477  UnsupportedMediaType_415 = 415,478  RangeNotSatisfiable_416 = 416,479  ExpectationFailed_417 = 417,480  ImATeapot_418 = 418,481  MisdirectedRequest_421 = 421,482  UnprocessableContent_422 = 422,483  Locked_423 = 423,484  FailedDependency_424 = 424,485  TooEarly_425 = 425,486  UpgradeRequired_426 = 426,487  PreconditionRequired_428 = 428,488  TooManyRequests_429 = 429,489  RequestHeaderFieldsTooLarge_431 = 431,490  UnavailableForLegalReasons_451 = 451,491 492  // Server error responses493  InternalServerError_500 = 500,494  NotImplemented_501 = 501,495  BadGateway_502 = 502,496  ServiceUnavailable_503 = 503,497  GatewayTimeout_504 = 504,498  HttpVersionNotSupported_505 = 505,499  VariantAlsoNegotiates_506 = 506,500  InsufficientStorage_507 = 507,501  LoopDetected_508 = 508,502  NotExtended_510 = 510,503  NetworkAuthenticationRequired_511 = 511,504};505 506using Headers =507    std::unordered_multimap<std::string, std::string, detail::case_ignore::hash,508                            detail::case_ignore::equal_to>;509 510using Params = std::multimap<std::string, std::string>;511using Match = std::smatch;512 513using Progress = std::function<bool(uint64_t current, uint64_t total)>;514 515struct Response;516using ResponseHandler = std::function<bool(const Response &response)>;517 518struct MultipartFormData {519  std::string name;520  std::string content;521  std::string filename;522  std::string content_type;523};524using MultipartFormDataItems = std::vector<MultipartFormData>;525using MultipartFormDataMap = std::multimap<std::string, MultipartFormData>;526 527class DataSink {528public:529  DataSink() : os(&sb_), sb_(*this) {}530 531  DataSink(const DataSink &) = delete;532  DataSink &operator=(const DataSink &) = delete;533  DataSink(DataSink &&) = delete;534  DataSink &operator=(DataSink &&) = delete;535 536  std::function<bool(const char *data, size_t data_len)> write;537  std::function<bool()> is_writable;538  std::function<void()> done;539  std::function<void(const Headers &trailer)> done_with_trailer;540  std::ostream os;541 542private:543  class data_sink_streambuf final : public std::streambuf {544  public:545    explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}546 547  protected:548    std::streamsize xsputn(const char *s, std::streamsize n) override {549      sink_.write(s, static_cast<size_t>(n));550      return n;551    }552 553  private:554    DataSink &sink_;555  };556 557  data_sink_streambuf sb_;558};559 560using ContentProvider =561    std::function<bool(size_t offset, size_t length, DataSink &sink)>;562 563using ContentProviderWithoutLength =564    std::function<bool(size_t offset, DataSink &sink)>;565 566using ContentProviderResourceReleaser = std::function<void(bool success)>;567 568struct MultipartFormDataProvider {569  std::string name;570  ContentProviderWithoutLength provider;571  std::string filename;572  std::string content_type;573};574using MultipartFormDataProviderItems = std::vector<MultipartFormDataProvider>;575 576using ContentReceiverWithProgress =577    std::function<bool(const char *data, size_t data_length, uint64_t offset,578                       uint64_t total_length)>;579 580using ContentReceiver =581    std::function<bool(const char *data, size_t data_length)>;582 583using MultipartContentHeader =584    std::function<bool(const MultipartFormData &file)>;585 586class ContentReader {587public:588  using Reader = std::function<bool(ContentReceiver receiver)>;589  using MultipartReader = std::function<bool(MultipartContentHeader header,590                                             ContentReceiver receiver)>;591 592  ContentReader(Reader reader, MultipartReader multipart_reader)593      : reader_(std::move(reader)),594        multipart_reader_(std::move(multipart_reader)) {}595 596  bool operator()(MultipartContentHeader header,597                  ContentReceiver receiver) const {598    return multipart_reader_(std::move(header), std::move(receiver));599  }600 601  bool operator()(ContentReceiver receiver) const {602    return reader_(std::move(receiver));603  }604 605  Reader reader_;606  MultipartReader multipart_reader_;607};608 609using Range = std::pair<ssize_t, ssize_t>;610using Ranges = std::vector<Range>;611 612struct Request {613  std::string method;614  std::string path;615  Params params;616  Headers headers;617  std::string body;618 619  std::string remote_addr;620  int remote_port = -1;621  std::string local_addr;622  int local_port = -1;623 624  // for server625  std::string version;626  std::string target;627  MultipartFormDataMap files;628  Ranges ranges;629  Match matches;630  std::unordered_map<std::string, std::string> path_params;631  std::function<bool()> is_connection_closed = []() { return true; };632 633  // for client634  ResponseHandler response_handler;635  ContentReceiverWithProgress content_receiver;636  Progress progress;637#ifdef CPPHTTPLIB_OPENSSL_SUPPORT638  const SSL *ssl = nullptr;639#endif640 641  bool has_header(const std::string &key) const;642  std::string get_header_value(const std::string &key, const char *def = "",643                               size_t id = 0) const;644  uint64_t get_header_value_u64(const std::string &key, uint64_t def = 0,645                                size_t id = 0) const;646  size_t get_header_value_count(const std::string &key) const;647  void set_header(const std::string &key, const std::string &val);648 649  bool has_param(const std::string &key) const;650  std::string get_param_value(const std::string &key, size_t id = 0) const;651  size_t get_param_value_count(const std::string &key) const;652 653  bool is_multipart_form_data() const;654 655  bool has_file(const std::string &key) const;656  MultipartFormData get_file_value(const std::string &key) const;657  std::vector<MultipartFormData> get_file_values(const std::string &key) const;658 659  // private members...660  size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT;661  size_t content_length_ = 0;662  ContentProvider content_provider_;663  bool is_chunked_content_provider_ = false;664  size_t authorization_count_ = 0;665};666 667struct Response {668  std::string version;669  int status = -1;670  std::string reason;671  Headers headers;672  std::string body;673  std::string location; // Redirect location674 675  bool has_header(const std::string &key) const;676  std::string get_header_value(const std::string &key, const char *def = "",677                               size_t id = 0) const;678  uint64_t get_header_value_u64(const std::string &key, uint64_t def = 0,679                                size_t id = 0) const;680  size_t get_header_value_count(const std::string &key) const;681  void set_header(const std::string &key, const std::string &val);682 683  void set_redirect(const std::string &url, int status = StatusCode::Found_302);684  void set_content(const char *s, size_t n, const std::string &content_type);685  void set_content(const std::string &s, const std::string &content_type);686  void set_content(std::string &&s, const std::string &content_type);687 688  void set_content_provider(689      size_t length, const std::string &content_type, ContentProvider provider,690      ContentProviderResourceReleaser resource_releaser = nullptr);691 692  void set_content_provider(693      const std::string &content_type, ContentProviderWithoutLength provider,694      ContentProviderResourceReleaser resource_releaser = nullptr);695 696  void set_chunked_content_provider(697      const std::string &content_type, ContentProviderWithoutLength provider,698      ContentProviderResourceReleaser resource_releaser = nullptr);699 700  void set_file_content(const std::string &path,701                        const std::string &content_type);702  void set_file_content(const std::string &path);703 704  Response() = default;705  Response(const Response &) = default;706  Response &operator=(const Response &) = default;707  Response(Response &&) = default;708  Response &operator=(Response &&) = default;709  ~Response() {710    if (content_provider_resource_releaser_) {711      content_provider_resource_releaser_(content_provider_success_);712    }713  }714 715  // private members...716  size_t content_length_ = 0;717  ContentProvider content_provider_;718  ContentProviderResourceReleaser content_provider_resource_releaser_;719  bool is_chunked_content_provider_ = false;720  bool content_provider_success_ = false;721  std::string file_content_path_;722  std::string file_content_content_type_;723};724 725class Stream {726public:727  virtual ~Stream() = default;728 729  virtual bool is_readable() const = 0;730  virtual bool is_writable() const = 0;731 732  virtual ssize_t read(char *ptr, size_t size) = 0;733  virtual ssize_t write(const char *ptr, size_t size) = 0;734  virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0;735  virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0;736  virtual socket_t socket() const = 0;737 738  ssize_t write(const char *ptr);739  ssize_t write(const std::string &s);740};741 742class TaskQueue {743public:744  TaskQueue() = default;745  virtual ~TaskQueue() = default;746 747  virtual bool enqueue(std::function<void()> fn) = 0;748  virtual void shutdown() = 0;749 750  virtual void on_idle() {}751};752 753class ThreadPool final : public TaskQueue {754public:755  explicit ThreadPool(size_t n, size_t mqr = 0)756      : shutdown_(false), max_queued_requests_(mqr) {757    while (n) {758      threads_.emplace_back(worker(*this));759      n--;760    }761  }762 763  ThreadPool(const ThreadPool &) = delete;764  ~ThreadPool() override = default;765 766  bool enqueue(std::function<void()> fn) override {767    {768      std::unique_lock<std::mutex> lock(mutex_);769      if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) {770        return false;771      }772      jobs_.push_back(std::move(fn));773    }774 775    cond_.notify_one();776    return true;777  }778 779  void shutdown() override {780    // Stop all worker threads...781    {782      std::unique_lock<std::mutex> lock(mutex_);783      shutdown_ = true;784    }785 786    cond_.notify_all();787 788    // Join...789    for (auto &t : threads_) {790      t.join();791    }792  }793 794private:795  struct worker {796    explicit worker(ThreadPool &pool) : pool_(pool) {}797 798    void operator()() {799      for (;;) {800        std::function<void()> fn;801        {802          std::unique_lock<std::mutex> lock(pool_.mutex_);803 804          pool_.cond_.wait(805              lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; });806 807          if (pool_.shutdown_ && pool_.jobs_.empty()) { break; }808 809          fn = pool_.jobs_.front();810          pool_.jobs_.pop_front();811        }812 813        assert(true == static_cast<bool>(fn));814        fn();815      }816 817#if defined(CPPHTTPLIB_OPENSSL_SUPPORT) && !defined(OPENSSL_IS_BORINGSSL) &&   \818    !defined(LIBRESSL_VERSION_NUMBER)819      OPENSSL_thread_stop();820#endif821    }822 823    ThreadPool &pool_;824  };825  friend struct worker;826 827  std::vector<std::thread> threads_;828  std::list<std::function<void()>> jobs_;829 830  bool shutdown_;831  size_t max_queued_requests_ = 0;832 833  std::condition_variable cond_;834  std::mutex mutex_;835};836 837using Logger = std::function<void(const Request &, const Response &)>;838 839using SocketOptions = std::function<void(socket_t sock)>;840 841void default_socket_options(socket_t sock);842 843const char *status_message(int status);844 845std::string get_bearer_token_auth(const Request &req);846 847namespace detail {848 849class MatcherBase {850public:851  virtual ~MatcherBase() = default;852 853  // Match request path and populate its matches and854  virtual bool match(Request &request) const = 0;855};856 857/**858 * Captures parameters in request path and stores them in Request::path_params859 *860 * Capture name is a substring of a pattern from : to /.861 * The rest of the pattern is matched agains the request path directly862 * Parameters are captured starting from the next character after863 * the end of the last matched static pattern fragment until the next /.864 *865 * Example pattern:866 * "/path/fragments/:capture/more/fragments/:second_capture"867 * Static fragments:868 * "/path/fragments/", "more/fragments/"869 *870 * Given the following request path:871 * "/path/fragments/:1/more/fragments/:2"872 * the resulting capture will be873 * {{"capture", "1"}, {"second_capture", "2"}}874 */875class PathParamsMatcher final : public MatcherBase {876public:877  PathParamsMatcher(const std::string &pattern);878 879  bool match(Request &request) const override;880 881private:882  // Treat segment separators as the end of path parameter capture883  // Does not need to handle query parameters as they are parsed before path884  // matching885  static constexpr char separator = '/';886 887  // Contains static path fragments to match against, excluding the '/' after888  // path params889  // Fragments are separated by path params890  std::vector<std::string> static_fragments_;891  // Stores the names of the path parameters to be used as keys in the892  // Request::path_params map893  std::vector<std::string> param_names_;894};895 896/**897 * Performs std::regex_match on request path898 * and stores the result in Request::matches899 *900 * Note that regex match is performed directly on the whole request.901 * This means that wildcard patterns may match multiple path segments with /:902 * "/begin/(.*)/end" will match both "/begin/middle/end" and "/begin/1/2/end".903 */904class RegexMatcher final : public MatcherBase {905public:906  RegexMatcher(const std::string &pattern) : regex_(pattern) {}907 908  bool match(Request &request) const override;909 910private:911  std::regex regex_;912};913 914ssize_t write_headers(Stream &strm, const Headers &headers);915 916} // namespace detail917 918class Server {919public:920  using Handler = std::function<void(const Request &, Response &)>;921 922  using ExceptionHandler =923      std::function<void(const Request &, Response &, std::exception_ptr ep)>;924 925  enum class HandlerResponse {926    Handled,927    Unhandled,928  };929  using HandlerWithResponse =930      std::function<HandlerResponse(const Request &, Response &)>;931 932  using HandlerWithContentReader = std::function<void(933      const Request &, Response &, const ContentReader &content_reader)>;934 935  using Expect100ContinueHandler =936      std::function<int(const Request &, Response &)>;937 938  Server();939 940  virtual ~Server();941 942  virtual bool is_valid() const;943 944  Server &Get(const std::string &pattern, Handler handler);945  Server &Post(const std::string &pattern, Handler handler);946  Server &Post(const std::string &pattern, HandlerWithContentReader handler);947  Server &Put(const std::string &pattern, Handler handler);948  Server &Put(const std::string &pattern, HandlerWithContentReader handler);949  Server &Patch(const std::string &pattern, Handler handler);950  Server &Patch(const std::string &pattern, HandlerWithContentReader handler);951  Server &Delete(const std::string &pattern, Handler handler);952  Server &Delete(const std::string &pattern, HandlerWithContentReader handler);953  Server &Options(const std::string &pattern, Handler handler);954 955  bool set_base_dir(const std::string &dir,956                    const std::string &mount_point = std::string());957  bool set_mount_point(const std::string &mount_point, const std::string &dir,958                       Headers headers = Headers());959  bool remove_mount_point(const std::string &mount_point);960  Server &set_file_extension_and_mimetype_mapping(const std::string &ext,961                                                  const std::string &mime);962  Server &set_default_file_mimetype(const std::string &mime);963  Server &set_file_request_handler(Handler handler);964 965  template <class ErrorHandlerFunc>966  Server &set_error_handler(ErrorHandlerFunc &&handler) {967    return set_error_handler_core(968        std::forward<ErrorHandlerFunc>(handler),969        std::is_convertible<ErrorHandlerFunc, HandlerWithResponse>{});970  }971 972  Server &set_exception_handler(ExceptionHandler handler);973  Server &set_pre_routing_handler(HandlerWithResponse handler);974  Server &set_post_routing_handler(Handler handler);975 976  Server &set_expect_100_continue_handler(Expect100ContinueHandler handler);977  Server &set_logger(Logger logger);978 979  Server &set_address_family(int family);980  Server &set_tcp_nodelay(bool on);981  Server &set_ipv6_v6only(bool on);982  Server &set_socket_options(SocketOptions socket_options);983 984  Server &set_default_headers(Headers headers);985  Server &986  set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);987 988  Server &set_keep_alive_max_count(size_t count);989  Server &set_keep_alive_timeout(time_t sec);990 991  Server &set_read_timeout(time_t sec, time_t usec = 0);992  template <class Rep, class Period>993  Server &set_read_timeout(const std::chrono::duration<Rep, Period> &duration);994 995  Server &set_write_timeout(time_t sec, time_t usec = 0);996  template <class Rep, class Period>997  Server &set_write_timeout(const std::chrono::duration<Rep, Period> &duration);998 999  Server &set_idle_interval(time_t sec, time_t usec = 0);1000  template <class Rep, class Period>1001  Server &set_idle_interval(const std::chrono::duration<Rep, Period> &duration);1002 1003  Server &set_payload_max_length(size_t length);1004 1005  bool bind_to_port(const std::string &host, int port, int socket_flags = 0);1006  int bind_to_any_port(const std::string &host, int socket_flags = 0);1007  bool listen_after_bind();1008 1009  bool listen(const std::string &host, int port, int socket_flags = 0);1010 1011  bool is_running() const;1012  void wait_until_ready() const;1013  void stop();1014  void decommission();1015 1016  std::function<TaskQueue *(void)> new_task_queue;1017 1018protected:1019  bool process_request(Stream &strm, const std::string &remote_addr,1020                       int remote_port, const std::string &local_addr,1021                       int local_port, bool close_connection,1022                       bool &connection_closed,1023                       const std::function<void(Request &)> &setup_request);1024 1025  std::atomic<socket_t> svr_sock_{INVALID_SOCKET};1026  size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;1027  time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;1028  time_t read_timeout_sec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND;1029  time_t read_timeout_usec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND;1030  time_t write_timeout_sec_ = CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND;1031  time_t write_timeout_usec_ = CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND;1032  time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;1033  time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;1034  size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;1035 1036private:1037  using Handlers =1038      std::vector<std::pair<std::unique_ptr<detail::MatcherBase>, Handler>>;1039  using HandlersForContentReader =1040      std::vector<std::pair<std::unique_ptr<detail::MatcherBase>,1041                            HandlerWithContentReader>>;1042 1043  static std::unique_ptr<detail::MatcherBase>1044  make_matcher(const std::string &pattern);1045 1046  Server &set_error_handler_core(HandlerWithResponse handler, std::true_type);1047  Server &set_error_handler_core(Handler handler, std::false_type);1048 1049  socket_t create_server_socket(const std::string &host, int port,1050                                int socket_flags,1051                                SocketOptions socket_options) const;1052  int bind_internal(const std::string &host, int port, int socket_flags);1053  bool listen_internal();1054 1055  bool routing(Request &req, Response &res, Stream &strm);1056  bool handle_file_request(const Request &req, Response &res,1057                           bool head = false);1058  bool dispatch_request(Request &req, Response &res,1059                        const Handlers &handlers) const;1060  bool dispatch_request_for_content_reader(1061      Request &req, Response &res, ContentReader content_reader,1062      const HandlersForContentReader &handlers) const;1063 1064  bool parse_request_line(const char *s, Request &req) const;1065  void apply_ranges(const Request &req, Response &res,1066                    std::string &content_type, std::string &boundary) const;1067  bool write_response(Stream &strm, bool close_connection, Request &req,1068                      Response &res);1069  bool write_response_with_content(Stream &strm, bool close_connection,1070                                   const Request &req, Response &res);1071  bool write_response_core(Stream &strm, bool close_connection,1072                           const Request &req, Response &res,1073                           bool need_apply_ranges);1074  bool write_content_with_provider(Stream &strm, const Request &req,1075                                   Response &res, const std::string &boundary,1076                                   const std::string &content_type);1077  bool read_content(Stream &strm, Request &req, Response &res);1078  bool1079  read_content_with_content_receiver(Stream &strm, Request &req, Response &res,1080                                     ContentReceiver receiver,1081                                     MultipartContentHeader multipart_header,1082                                     ContentReceiver multipart_receiver);1083  bool read_content_core(Stream &strm, Request &req, Response &res,1084                         ContentReceiver receiver,1085                         MultipartContentHeader multipart_header,1086                         ContentReceiver multipart_receiver) const;1087 1088  virtual bool process_and_close_socket(socket_t sock);1089 1090  std::atomic<bool> is_running_{false};1091  std::atomic<bool> is_decommisioned{false};1092 1093  struct MountPointEntry {1094    std::string mount_point;1095    std::string base_dir;1096    Headers headers;1097  };1098  std::vector<MountPointEntry> base_dirs_;1099  std::map<std::string, std::string> file_extension_and_mimetype_map_;1100  std::string default_file_mimetype_ = "application/octet-stream";1101  Handler file_request_handler_;1102 1103  Handlers get_handlers_;1104  Handlers post_handlers_;1105  HandlersForContentReader post_handlers_for_content_reader_;1106  Handlers put_handlers_;1107  HandlersForContentReader put_handlers_for_content_reader_;1108  Handlers patch_handlers_;1109  HandlersForContentReader patch_handlers_for_content_reader_;1110  Handlers delete_handlers_;1111  HandlersForContentReader delete_handlers_for_content_reader_;1112  Handlers options_handlers_;1113 1114  HandlerWithResponse error_handler_;1115  ExceptionHandler exception_handler_;1116  HandlerWithResponse pre_routing_handler_;1117  Handler post_routing_handler_;1118  Expect100ContinueHandler expect_100_continue_handler_;1119 1120  Logger logger_;1121 1122  int address_family_ = AF_UNSPEC;1123  bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;1124  bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;1125  SocketOptions socket_options_ = default_socket_options;1126 1127  Headers default_headers_;1128  std::function<ssize_t(Stream &, Headers &)> header_writer_ =1129      detail::write_headers;1130};1131 1132enum class Error {1133  Success = 0,1134  Unknown,1135  Connection,1136  BindIPAddress,1137  Read,1138  Write,1139  ExceedRedirectCount,1140  Canceled,1141  SSLConnection,1142  SSLLoadingCerts,1143  SSLServerVerification,1144  SSLServerHostnameVerification,1145  UnsupportedMultipartBoundaryChars,1146  Compression,1147  ConnectionTimeout,1148  ProxyConnection,1149 1150  // For internal use only1151  SSLPeerCouldBeClosed_,1152};1153 1154std::string to_string(Error error);1155 1156std::ostream &operator<<(std::ostream &os, const Error &obj);1157 1158class Result {1159public:1160  Result() = default;1161  Result(std::unique_ptr<Response> &&res, Error err,1162         Headers &&request_headers = Headers{})1163      : res_(std::move(res)), err_(err),1164        request_headers_(std::move(request_headers)) {}1165  // Response1166  operator bool() const { return res_ != nullptr; }1167  bool operator==(std::nullptr_t) const { return res_ == nullptr; }1168  bool operator!=(std::nullptr_t) const { return res_ != nullptr; }1169  const Response &value() const { return *res_; }1170  Response &value() { return *res_; }1171  const Response &operator*() const { return *res_; }1172  Response &operator*() { return *res_; }1173  const Response *operator->() const { return res_.get(); }1174  Response *operator->() { return res_.get(); }1175 1176  // Error1177  Error error() const { return err_; }1178 1179  // Request Headers1180  bool has_request_header(const std::string &key) const;1181  std::string get_request_header_value(const std::string &key,1182                                       const char *def = "",1183                                       size_t id = 0) const;1184  uint64_t get_request_header_value_u64(const std::string &key,1185                                        uint64_t def = 0, size_t id = 0) const;1186  size_t get_request_header_value_count(const std::string &key) const;1187 1188private:1189  std::unique_ptr<Response> res_;1190  Error err_ = Error::Unknown;1191  Headers request_headers_;1192};1193 1194class ClientImpl {1195public:1196  explicit ClientImpl(const std::string &host);1197 1198  explicit ClientImpl(const std::string &host, int port);1199 1200  explicit ClientImpl(const std::string &host, int port,

Showing the first 1,200 of 10352 lines. Download the file for the rest.