httplib.h 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412
  1. //
  2. // httplib.h
  3. //
  4. // Copyright (c) 2026 Yuji Hirose. All rights reserved.
  5. // MIT License
  6. //
  7. #ifndef CPPHTTPLIB_HTTPLIB_H
  8. #define CPPHTTPLIB_HTTPLIB_H
  9. #define CPPHTTPLIB_VERSION "0.30.0"
  10. #define CPPHTTPLIB_VERSION_NUM "0x001E00"
  11. /*
  12. * Platform compatibility check
  13. */
  14. #if defined(_WIN32) && !defined(_WIN64)
  15. #if defined(_MSC_VER)
  16. #pragma message( \
  17. "cpp-httplib doesn't support 32-bit Windows. Please use a 64-bit compiler.")
  18. #else
  19. #warning \
  20. "cpp-httplib doesn't support 32-bit Windows. Please use a 64-bit compiler."
  21. #endif
  22. #elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ < 8
  23. #warning \
  24. "cpp-httplib doesn't support 32-bit platforms. Please use a 64-bit compiler."
  25. #elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ < 8
  26. #warning \
  27. "cpp-httplib doesn't support platforms where size_t is less than 64 bits."
  28. #endif
  29. #ifdef _WIN32
  30. #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
  31. #error \
  32. "cpp-httplib doesn't support Windows 8 or lower. Please use Windows 10 or later."
  33. #endif
  34. #endif
  35. /*
  36. * Configuration
  37. */
  38. #ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND
  39. #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
  40. #endif
  41. #ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND
  42. #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND 10000
  43. #endif
  44. #ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
  45. #define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 100
  46. #endif
  47. #ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND
  48. #define CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND 300
  49. #endif
  50. #ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND
  51. #define CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND 0
  52. #endif
  53. #ifndef CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND
  54. #define CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND 5
  55. #endif
  56. #ifndef CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND
  57. #define CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND 0
  58. #endif
  59. #ifndef CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND
  60. #define CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND 5
  61. #endif
  62. #ifndef CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND
  63. #define CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND 0
  64. #endif
  65. #ifndef CPPHTTPLIB_CLIENT_READ_TIMEOUT_SECOND
  66. #define CPPHTTPLIB_CLIENT_READ_TIMEOUT_SECOND 300
  67. #endif
  68. #ifndef CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND
  69. #define CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND 0
  70. #endif
  71. #ifndef CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND
  72. #define CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND 5
  73. #endif
  74. #ifndef CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND
  75. #define CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND 0
  76. #endif
  77. #ifndef CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND
  78. #define CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND 0
  79. #endif
  80. #ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND
  81. #define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0
  82. #endif
  83. #ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND
  84. #ifdef _WIN32
  85. #define CPPHTTPLIB_IDLE_INTERVAL_USECOND 1000
  86. #else
  87. #define CPPHTTPLIB_IDLE_INTERVAL_USECOND 0
  88. #endif
  89. #endif
  90. #ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH
  91. #define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192
  92. #endif
  93. #ifndef CPPHTTPLIB_HEADER_MAX_LENGTH
  94. #define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  95. #endif
  96. #ifndef CPPHTTPLIB_HEADER_MAX_COUNT
  97. #define CPPHTTPLIB_HEADER_MAX_COUNT 100
  98. #endif
  99. #ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT
  100. #define CPPHTTPLIB_REDIRECT_MAX_COUNT 20
  101. #endif
  102. #ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT
  103. #define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024
  104. #endif
  105. #ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH
  106. #define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits<size_t>::max)())
  107. #endif
  108. #ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH
  109. #define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192
  110. #endif
  111. #ifndef CPPHTTPLIB_RANGE_MAX_COUNT
  112. #define CPPHTTPLIB_RANGE_MAX_COUNT 1024
  113. #endif
  114. #ifndef CPPHTTPLIB_TCP_NODELAY
  115. #define CPPHTTPLIB_TCP_NODELAY false
  116. #endif
  117. #ifndef CPPHTTPLIB_IPV6_V6ONLY
  118. #define CPPHTTPLIB_IPV6_V6ONLY false
  119. #endif
  120. #ifndef CPPHTTPLIB_RECV_BUFSIZ
  121. #define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  122. #endif
  123. #ifndef CPPHTTPLIB_SEND_BUFSIZ
  124. #define CPPHTTPLIB_SEND_BUFSIZ size_t(16384u)
  125. #endif
  126. #ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ
  127. #define CPPHTTPLIB_COMPRESSION_BUFSIZ size_t(16384u)
  128. #endif
  129. #ifndef CPPHTTPLIB_THREAD_POOL_COUNT
  130. #define CPPHTTPLIB_THREAD_POOL_COUNT \
  131. ((std::max)(8u, std::thread::hardware_concurrency() > 0 \
  132. ? std::thread::hardware_concurrency() - 1 \
  133. : 0))
  134. #endif
  135. #ifndef CPPHTTPLIB_RECV_FLAGS
  136. #define CPPHTTPLIB_RECV_FLAGS 0
  137. #endif
  138. #ifndef CPPHTTPLIB_SEND_FLAGS
  139. #define CPPHTTPLIB_SEND_FLAGS 0
  140. #endif
  141. #ifndef CPPHTTPLIB_LISTEN_BACKLOG
  142. #define CPPHTTPLIB_LISTEN_BACKLOG 5
  143. #endif
  144. #ifndef CPPHTTPLIB_MAX_LINE_LENGTH
  145. #define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  146. #endif
  147. /*
  148. * Headers
  149. */
  150. #ifdef _WIN32
  151. #ifndef _CRT_SECURE_NO_WARNINGS
  152. #define _CRT_SECURE_NO_WARNINGS
  153. #endif //_CRT_SECURE_NO_WARNINGS
  154. #ifndef _CRT_NONSTDC_NO_DEPRECATE
  155. #define _CRT_NONSTDC_NO_DEPRECATE
  156. #endif //_CRT_NONSTDC_NO_DEPRECATE
  157. #if defined(_MSC_VER)
  158. #if _MSC_VER < 1900
  159. #error Sorry, Visual Studio versions prior to 2015 are not supported
  160. #endif
  161. #pragma comment(lib, "ws2_32.lib")
  162. using ssize_t = __int64;
  163. #endif // _MSC_VER
  164. #ifndef S_ISREG
  165. #define S_ISREG(m) (((m) & S_IFREG) == S_IFREG)
  166. #endif // S_ISREG
  167. #ifndef S_ISDIR
  168. #define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR)
  169. #endif // S_ISDIR
  170. #ifndef NOMINMAX
  171. #define NOMINMAX
  172. #endif // NOMINMAX
  173. #include <io.h>
  174. #include <winsock2.h>
  175. #include <ws2tcpip.h>
  176. #if defined(__has_include)
  177. #if __has_include(<afunix.h>)
  178. // afunix.h uses types declared in winsock2.h, so has to be included after it.
  179. #include <afunix.h>
  180. #define CPPHTTPLIB_HAVE_AFUNIX_H 1
  181. #endif
  182. #endif
  183. #ifndef WSA_FLAG_NO_HANDLE_INHERIT
  184. #define WSA_FLAG_NO_HANDLE_INHERIT 0x80
  185. #endif
  186. using nfds_t = unsigned long;
  187. using socket_t = SOCKET;
  188. using socklen_t = int;
  189. #else // not _WIN32
  190. #include <arpa/inet.h>
  191. #if !defined(_AIX) && !defined(__MVS__)
  192. #include <ifaddrs.h>
  193. #endif
  194. #ifdef __MVS__
  195. #include <strings.h>
  196. #ifndef NI_MAXHOST
  197. #define NI_MAXHOST 1025
  198. #endif
  199. #endif
  200. #include <net/if.h>
  201. #include <netdb.h>
  202. #include <netinet/in.h>
  203. #ifdef __linux__
  204. #include <resolv.h>
  205. #undef _res // Undefine _res macro to avoid conflicts with user code (#2278)
  206. #endif
  207. #include <csignal>
  208. #include <netinet/tcp.h>
  209. #include <poll.h>
  210. #include <pthread.h>
  211. #include <sys/mman.h>
  212. #include <sys/socket.h>
  213. #include <sys/un.h>
  214. #include <unistd.h>
  215. using socket_t = int;
  216. #ifndef INVALID_SOCKET
  217. #define INVALID_SOCKET (-1)
  218. #endif
  219. #endif //_WIN32
  220. #if defined(__APPLE__)
  221. #include <TargetConditionals.h>
  222. #endif
  223. #include <algorithm>
  224. #include <array>
  225. #include <atomic>
  226. #include <cassert>
  227. #include <cctype>
  228. #include <climits>
  229. #include <condition_variable>
  230. #include <cstring>
  231. #include <errno.h>
  232. #include <exception>
  233. #include <fcntl.h>
  234. #include <functional>
  235. #include <iomanip>
  236. #include <iostream>
  237. #include <list>
  238. #include <map>
  239. #include <memory>
  240. #include <mutex>
  241. #include <random>
  242. #include <regex>
  243. #include <set>
  244. #include <sstream>
  245. #include <string>
  246. #include <sys/stat.h>
  247. #include <thread>
  248. #include <unordered_map>
  249. #include <unordered_set>
  250. #include <utility>
  251. #if defined(CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO) || \
  252. defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
  253. #if TARGET_OS_MAC
  254. #include <CFNetwork/CFHost.h>
  255. #include <CoreFoundation/CoreFoundation.h>
  256. #endif
  257. #endif // CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO or
  258. // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN
  259. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  260. #ifdef _WIN32
  261. #include <wincrypt.h>
  262. // these are defined in wincrypt.h and it breaks compilation if BoringSSL is
  263. // used
  264. #undef X509_NAME
  265. #undef X509_CERT_PAIR
  266. #undef X509_EXTENSIONS
  267. #undef PKCS7_SIGNER_INFO
  268. #ifdef _MSC_VER
  269. #pragma comment(lib, "crypt32.lib")
  270. #endif
  271. #endif // _WIN32
  272. #if defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
  273. #if TARGET_OS_MAC
  274. #include <Security/Security.h>
  275. #endif
  276. #endif // CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO
  277. #include <openssl/err.h>
  278. #include <openssl/evp.h>
  279. #include <openssl/ssl.h>
  280. #include <openssl/x509v3.h>
  281. #if defined(_WIN32) && defined(OPENSSL_USE_APPLINK)
  282. #include <openssl/applink.c>
  283. #endif
  284. #include <iostream>
  285. #include <sstream>
  286. #if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
  287. #if OPENSSL_VERSION_NUMBER < 0x1010107f
  288. #error Please use OpenSSL or a current version of BoringSSL
  289. #endif
  290. #define SSL_get1_peer_certificate SSL_get_peer_certificate
  291. #elif OPENSSL_VERSION_NUMBER < 0x30000000L
  292. #error Sorry, OpenSSL versions prior to 3.0.0 are not supported
  293. #endif
  294. #endif // CPPHTTPLIB_OPENSSL_SUPPORT
  295. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  296. #include <zlib.h>
  297. #endif
  298. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  299. #include <brotli/decode.h>
  300. #include <brotli/encode.h>
  301. #endif
  302. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  303. #include <zstd.h>
  304. #endif
  305. /*
  306. * Declaration
  307. */
  308. namespace httplib {
  309. namespace detail {
  310. /*
  311. * Backport std::make_unique from C++14.
  312. *
  313. * NOTE: This code came up with the following stackoverflow post:
  314. * https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique
  315. *
  316. */
  317. template <class T, class... Args>
  318. typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
  319. make_unique(Args &&...args) {
  320. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  321. }
  322. template <class T>
  323. typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
  324. make_unique(std::size_t n) {
  325. typedef typename std::remove_extent<T>::type RT;
  326. return std::unique_ptr<T>(new RT[n]);
  327. }
  328. namespace case_ignore {
  329. inline unsigned char to_lower(int c) {
  330. const static unsigned char table[256] = {
  331. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  332. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  333. 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
  334. 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
  335. 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
  336. 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
  337. 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
  338. 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
  339. 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
  340. 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
  341. 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
  342. 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
  343. 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226,
  344. 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
  345. 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224,
  346. 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  347. 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
  348. 255,
  349. };
  350. return table[(unsigned char)(char)c];
  351. }
  352. inline bool equal(const std::string &a, const std::string &b) {
  353. return a.size() == b.size() &&
  354. std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  355. return to_lower(ca) == to_lower(cb);
  356. });
  357. }
  358. struct equal_to {
  359. bool operator()(const std::string &a, const std::string &b) const {
  360. return equal(a, b);
  361. }
  362. };
  363. struct hash {
  364. size_t operator()(const std::string &key) const {
  365. return hash_core(key.data(), key.size(), 0);
  366. }
  367. size_t hash_core(const char *s, size_t l, size_t h) const {
  368. return (l == 0) ? h
  369. : hash_core(s + 1, l - 1,
  370. // Unsets the 6 high bits of h, therefore no
  371. // overflow happens
  372. (((std::numeric_limits<size_t>::max)() >> 6) &
  373. h * 33) ^
  374. static_cast<unsigned char>(to_lower(*s)));
  375. }
  376. };
  377. template <typename T>
  378. using unordered_set = std::unordered_set<T, detail::case_ignore::hash,
  379. detail::case_ignore::equal_to>;
  380. } // namespace case_ignore
  381. // This is based on
  382. // "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189".
  383. struct scope_exit {
  384. explicit scope_exit(std::function<void(void)> &&f)
  385. : exit_function(std::move(f)), execute_on_destruction{true} {}
  386. scope_exit(scope_exit &&rhs) noexcept
  387. : exit_function(std::move(rhs.exit_function)),
  388. execute_on_destruction{rhs.execute_on_destruction} {
  389. rhs.release();
  390. }
  391. ~scope_exit() {
  392. if (execute_on_destruction) { this->exit_function(); }
  393. }
  394. void release() { this->execute_on_destruction = false; }
  395. private:
  396. scope_exit(const scope_exit &) = delete;
  397. void operator=(const scope_exit &) = delete;
  398. scope_exit &operator=(scope_exit &&) = delete;
  399. std::function<void(void)> exit_function;
  400. bool execute_on_destruction;
  401. };
  402. } // namespace detail
  403. enum SSLVerifierResponse {
  404. // no decision has been made, use the built-in certificate verifier
  405. NoDecisionMade,
  406. // connection certificate is verified and accepted
  407. CertificateAccepted,
  408. // connection certificate was processed but is rejected
  409. CertificateRejected
  410. };
  411. enum StatusCode {
  412. // Information responses
  413. Continue_100 = 100,
  414. SwitchingProtocol_101 = 101,
  415. Processing_102 = 102,
  416. EarlyHints_103 = 103,
  417. // Successful responses
  418. OK_200 = 200,
  419. Created_201 = 201,
  420. Accepted_202 = 202,
  421. NonAuthoritativeInformation_203 = 203,
  422. NoContent_204 = 204,
  423. ResetContent_205 = 205,
  424. PartialContent_206 = 206,
  425. MultiStatus_207 = 207,
  426. AlreadyReported_208 = 208,
  427. IMUsed_226 = 226,
  428. // Redirection messages
  429. MultipleChoices_300 = 300,
  430. MovedPermanently_301 = 301,
  431. Found_302 = 302,
  432. SeeOther_303 = 303,
  433. NotModified_304 = 304,
  434. UseProxy_305 = 305,
  435. unused_306 = 306,
  436. TemporaryRedirect_307 = 307,
  437. PermanentRedirect_308 = 308,
  438. // Client error responses
  439. BadRequest_400 = 400,
  440. Unauthorized_401 = 401,
  441. PaymentRequired_402 = 402,
  442. Forbidden_403 = 403,
  443. NotFound_404 = 404,
  444. MethodNotAllowed_405 = 405,
  445. NotAcceptable_406 = 406,
  446. ProxyAuthenticationRequired_407 = 407,
  447. RequestTimeout_408 = 408,
  448. Conflict_409 = 409,
  449. Gone_410 = 410,
  450. LengthRequired_411 = 411,
  451. PreconditionFailed_412 = 412,
  452. PayloadTooLarge_413 = 413,
  453. UriTooLong_414 = 414,
  454. UnsupportedMediaType_415 = 415,
  455. RangeNotSatisfiable_416 = 416,
  456. ExpectationFailed_417 = 417,
  457. ImATeapot_418 = 418,
  458. MisdirectedRequest_421 = 421,
  459. UnprocessableContent_422 = 422,
  460. Locked_423 = 423,
  461. FailedDependency_424 = 424,
  462. TooEarly_425 = 425,
  463. UpgradeRequired_426 = 426,
  464. PreconditionRequired_428 = 428,
  465. TooManyRequests_429 = 429,
  466. RequestHeaderFieldsTooLarge_431 = 431,
  467. UnavailableForLegalReasons_451 = 451,
  468. // Server error responses
  469. InternalServerError_500 = 500,
  470. NotImplemented_501 = 501,
  471. BadGateway_502 = 502,
  472. ServiceUnavailable_503 = 503,
  473. GatewayTimeout_504 = 504,
  474. HttpVersionNotSupported_505 = 505,
  475. VariantAlsoNegotiates_506 = 506,
  476. InsufficientStorage_507 = 507,
  477. LoopDetected_508 = 508,
  478. NotExtended_510 = 510,
  479. NetworkAuthenticationRequired_511 = 511,
  480. };
  481. using Headers =
  482. std::unordered_multimap<std::string, std::string, detail::case_ignore::hash,
  483. detail::case_ignore::equal_to>;
  484. using Params = std::multimap<std::string, std::string>;
  485. using Match = std::smatch;
  486. using DownloadProgress = std::function<bool(size_t current, size_t total)>;
  487. using UploadProgress = std::function<bool(size_t current, size_t total)>;
  488. struct Response;
  489. using ResponseHandler = std::function<bool(const Response &response)>;
  490. struct FormData {
  491. std::string name;
  492. std::string content;
  493. std::string filename;
  494. std::string content_type;
  495. Headers headers;
  496. };
  497. struct FormField {
  498. std::string name;
  499. std::string content;
  500. Headers headers;
  501. };
  502. using FormFields = std::multimap<std::string, FormField>;
  503. using FormFiles = std::multimap<std::string, FormData>;
  504. struct MultipartFormData {
  505. FormFields fields; // Text fields from multipart
  506. FormFiles files; // Files from multipart
  507. // Text field access
  508. std::string get_field(const std::string &key, size_t id = 0) const;
  509. std::vector<std::string> get_fields(const std::string &key) const;
  510. bool has_field(const std::string &key) const;
  511. size_t get_field_count(const std::string &key) const;
  512. // File access
  513. FormData get_file(const std::string &key, size_t id = 0) const;
  514. std::vector<FormData> get_files(const std::string &key) const;
  515. bool has_file(const std::string &key) const;
  516. size_t get_file_count(const std::string &key) const;
  517. };
  518. struct UploadFormData {
  519. std::string name;
  520. std::string content;
  521. std::string filename;
  522. std::string content_type;
  523. };
  524. using UploadFormDataItems = std::vector<UploadFormData>;
  525. class DataSink {
  526. public:
  527. DataSink() : os(&sb_), sb_(*this) {}
  528. DataSink(const DataSink &) = delete;
  529. DataSink &operator=(const DataSink &) = delete;
  530. DataSink(DataSink &&) = delete;
  531. DataSink &operator=(DataSink &&) = delete;
  532. std::function<bool(const char *data, size_t data_len)> write;
  533. std::function<bool()> is_writable;
  534. std::function<void()> done;
  535. std::function<void(const Headers &trailer)> done_with_trailer;
  536. std::ostream os;
  537. private:
  538. class data_sink_streambuf final : public std::streambuf {
  539. public:
  540. explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}
  541. protected:
  542. std::streamsize xsputn(const char *s, std::streamsize n) override {
  543. sink_.write(s, static_cast<size_t>(n));
  544. return n;
  545. }
  546. private:
  547. DataSink &sink_;
  548. };
  549. data_sink_streambuf sb_;
  550. };
  551. using ContentProvider =
  552. std::function<bool(size_t offset, size_t length, DataSink &sink)>;
  553. using ContentProviderWithoutLength =
  554. std::function<bool(size_t offset, DataSink &sink)>;
  555. using ContentProviderResourceReleaser = std::function<void(bool success)>;
  556. struct FormDataProvider {
  557. std::string name;
  558. ContentProviderWithoutLength provider;
  559. std::string filename;
  560. std::string content_type;
  561. };
  562. using FormDataProviderItems = std::vector<FormDataProvider>;
  563. using ContentReceiverWithProgress = std::function<bool(
  564. const char *data, size_t data_length, size_t offset, size_t total_length)>;
  565. using ContentReceiver =
  566. std::function<bool(const char *data, size_t data_length)>;
  567. using FormDataHeader = std::function<bool(const FormData &file)>;
  568. class ContentReader {
  569. public:
  570. using Reader = std::function<bool(ContentReceiver receiver)>;
  571. using FormDataReader =
  572. std::function<bool(FormDataHeader header, ContentReceiver receiver)>;
  573. ContentReader(Reader reader, FormDataReader multipart_reader)
  574. : reader_(std::move(reader)),
  575. formdata_reader_(std::move(multipart_reader)) {}
  576. bool operator()(FormDataHeader header, ContentReceiver receiver) const {
  577. return formdata_reader_(std::move(header), std::move(receiver));
  578. }
  579. bool operator()(ContentReceiver receiver) const {
  580. return reader_(std::move(receiver));
  581. }
  582. Reader reader_;
  583. FormDataReader formdata_reader_;
  584. };
  585. using Range = std::pair<ssize_t, ssize_t>;
  586. using Ranges = std::vector<Range>;
  587. struct Request {
  588. std::string method;
  589. std::string path;
  590. std::string matched_route;
  591. Params params;
  592. Headers headers;
  593. Headers trailers;
  594. std::string body;
  595. std::string remote_addr;
  596. int remote_port = -1;
  597. std::string local_addr;
  598. int local_port = -1;
  599. // for server
  600. std::string version;
  601. std::string target;
  602. MultipartFormData form;
  603. Ranges ranges;
  604. Match matches;
  605. std::unordered_map<std::string, std::string> path_params;
  606. std::function<bool()> is_connection_closed = []() { return true; };
  607. // for client
  608. std::vector<std::string> accept_content_types;
  609. ResponseHandler response_handler;
  610. ContentReceiverWithProgress content_receiver;
  611. DownloadProgress download_progress;
  612. UploadProgress upload_progress;
  613. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  614. const SSL *ssl = nullptr;
  615. #endif
  616. bool has_header(const std::string &key) const;
  617. std::string get_header_value(const std::string &key, const char *def = "",
  618. size_t id = 0) const;
  619. size_t get_header_value_u64(const std::string &key, size_t def = 0,
  620. size_t id = 0) const;
  621. size_t get_header_value_count(const std::string &key) const;
  622. void set_header(const std::string &key, const std::string &val);
  623. bool has_trailer(const std::string &key) const;
  624. std::string get_trailer_value(const std::string &key, size_t id = 0) const;
  625. size_t get_trailer_value_count(const std::string &key) const;
  626. bool has_param(const std::string &key) const;
  627. std::string get_param_value(const std::string &key, size_t id = 0) const;
  628. size_t get_param_value_count(const std::string &key) const;
  629. bool is_multipart_form_data() const;
  630. // private members...
  631. size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT;
  632. size_t content_length_ = 0;
  633. ContentProvider content_provider_;
  634. bool is_chunked_content_provider_ = false;
  635. size_t authorization_count_ = 0;
  636. std::chrono::time_point<std::chrono::steady_clock> start_time_ =
  637. (std::chrono::steady_clock::time_point::min)();
  638. };
  639. struct Response {
  640. std::string version;
  641. int status = -1;
  642. std::string reason;
  643. Headers headers;
  644. Headers trailers;
  645. std::string body;
  646. std::string location; // Redirect location
  647. bool has_header(const std::string &key) const;
  648. std::string get_header_value(const std::string &key, const char *def = "",
  649. size_t id = 0) const;
  650. size_t get_header_value_u64(const std::string &key, size_t def = 0,
  651. size_t id = 0) const;
  652. size_t get_header_value_count(const std::string &key) const;
  653. void set_header(const std::string &key, const std::string &val);
  654. bool has_trailer(const std::string &key) const;
  655. std::string get_trailer_value(const std::string &key, size_t id = 0) const;
  656. size_t get_trailer_value_count(const std::string &key) const;
  657. void set_redirect(const std::string &url, int status = StatusCode::Found_302);
  658. void set_content(const char *s, size_t n, const std::string &content_type);
  659. void set_content(const std::string &s, const std::string &content_type);
  660. void set_content(std::string &&s, const std::string &content_type);
  661. void set_content_provider(
  662. size_t length, const std::string &content_type, ContentProvider provider,
  663. ContentProviderResourceReleaser resource_releaser = nullptr);
  664. void set_content_provider(
  665. const std::string &content_type, ContentProviderWithoutLength provider,
  666. ContentProviderResourceReleaser resource_releaser = nullptr);
  667. void set_chunked_content_provider(
  668. const std::string &content_type, ContentProviderWithoutLength provider,
  669. ContentProviderResourceReleaser resource_releaser = nullptr);
  670. void set_file_content(const std::string &path,
  671. const std::string &content_type);
  672. void set_file_content(const std::string &path);
  673. Response() = default;
  674. Response(const Response &) = default;
  675. Response &operator=(const Response &) = default;
  676. Response(Response &&) = default;
  677. Response &operator=(Response &&) = default;
  678. ~Response() {
  679. if (content_provider_resource_releaser_) {
  680. content_provider_resource_releaser_(content_provider_success_);
  681. }
  682. }
  683. // private members...
  684. size_t content_length_ = 0;
  685. ContentProvider content_provider_;
  686. ContentProviderResourceReleaser content_provider_resource_releaser_;
  687. bool is_chunked_content_provider_ = false;
  688. bool content_provider_success_ = false;
  689. std::string file_content_path_;
  690. std::string file_content_content_type_;
  691. };
  692. enum class Error {
  693. Success = 0,
  694. Unknown,
  695. Connection,
  696. BindIPAddress,
  697. Read,
  698. Write,
  699. ExceedRedirectCount,
  700. Canceled,
  701. SSLConnection,
  702. SSLLoadingCerts,
  703. SSLServerVerification,
  704. SSLServerHostnameVerification,
  705. UnsupportedMultipartBoundaryChars,
  706. Compression,
  707. ConnectionTimeout,
  708. ProxyConnection,
  709. ConnectionClosed,
  710. Timeout,
  711. ResourceExhaustion,
  712. TooManyFormDataFiles,
  713. ExceedMaxPayloadSize,
  714. ExceedUriMaxLength,
  715. ExceedMaxSocketDescriptorCount,
  716. InvalidRequestLine,
  717. InvalidHTTPMethod,
  718. InvalidHTTPVersion,
  719. InvalidHeaders,
  720. MultipartParsing,
  721. OpenFile,
  722. Listen,
  723. GetSockName,
  724. UnsupportedAddressFamily,
  725. HTTPParsing,
  726. InvalidRangeHeader,
  727. // For internal use only
  728. SSLPeerCouldBeClosed_,
  729. };
  730. std::string to_string(Error error);
  731. std::ostream &operator<<(std::ostream &os, const Error &obj);
  732. class Stream {
  733. public:
  734. virtual ~Stream() = default;
  735. virtual bool is_readable() const = 0;
  736. virtual bool wait_readable() const = 0;
  737. virtual bool wait_writable() const = 0;
  738. virtual ssize_t read(char *ptr, size_t size) = 0;
  739. virtual ssize_t write(const char *ptr, size_t size) = 0;
  740. virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0;
  741. virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0;
  742. virtual socket_t socket() const = 0;
  743. virtual time_t duration() const = 0;
  744. ssize_t write(const char *ptr);
  745. ssize_t write(const std::string &s);
  746. Error get_error() const { return error_; }
  747. protected:
  748. Error error_ = Error::Success;
  749. };
  750. class TaskQueue {
  751. public:
  752. TaskQueue() = default;
  753. virtual ~TaskQueue() = default;
  754. virtual bool enqueue(std::function<void()> fn) = 0;
  755. virtual void shutdown() = 0;
  756. virtual void on_idle() {}
  757. };
  758. class ThreadPool final : public TaskQueue {
  759. public:
  760. explicit ThreadPool(size_t n, size_t mqr = 0)
  761. : shutdown_(false), max_queued_requests_(mqr) {
  762. threads_.reserve(n);
  763. while (n) {
  764. threads_.emplace_back(worker(*this));
  765. n--;
  766. }
  767. }
  768. ThreadPool(const ThreadPool &) = delete;
  769. ~ThreadPool() override = default;
  770. bool enqueue(std::function<void()> fn) override {
  771. {
  772. std::unique_lock<std::mutex> lock(mutex_);
  773. if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) {
  774. return false;
  775. }
  776. jobs_.push_back(std::move(fn));
  777. }
  778. cond_.notify_one();
  779. return true;
  780. }
  781. void shutdown() override {
  782. // Stop all worker threads...
  783. {
  784. std::unique_lock<std::mutex> lock(mutex_);
  785. shutdown_ = true;
  786. }
  787. cond_.notify_all();
  788. // Join...
  789. for (auto &t : threads_) {
  790. t.join();
  791. }
  792. }
  793. private:
  794. struct worker {
  795. explicit worker(ThreadPool &pool) : pool_(pool) {}
  796. void operator()() {
  797. for (;;) {
  798. std::function<void()> fn;
  799. {
  800. std::unique_lock<std::mutex> lock(pool_.mutex_);
  801. pool_.cond_.wait(
  802. lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; });
  803. if (pool_.shutdown_ && pool_.jobs_.empty()) { break; }
  804. fn = pool_.jobs_.front();
  805. pool_.jobs_.pop_front();
  806. }
  807. assert(true == static_cast<bool>(fn));
  808. fn();
  809. }
  810. #if defined(CPPHTTPLIB_OPENSSL_SUPPORT) && !defined(OPENSSL_IS_BORINGSSL) && \
  811. !defined(LIBRESSL_VERSION_NUMBER)
  812. OPENSSL_thread_stop();
  813. #endif
  814. }
  815. ThreadPool &pool_;
  816. };
  817. friend struct worker;
  818. std::vector<std::thread> threads_;
  819. std::list<std::function<void()>> jobs_;
  820. bool shutdown_;
  821. size_t max_queued_requests_ = 0;
  822. std::condition_variable cond_;
  823. std::mutex mutex_;
  824. };
  825. using Logger = std::function<void(const Request &, const Response &)>;
  826. // Forward declaration for Error type
  827. enum class Error;
  828. using ErrorLogger = std::function<void(const Error &, const Request *)>;
  829. using SocketOptions = std::function<void(socket_t sock)>;
  830. void default_socket_options(socket_t sock);
  831. const char *status_message(int status);
  832. std::string to_string(Error error);
  833. std::ostream &operator<<(std::ostream &os, const Error &obj);
  834. std::string get_bearer_token_auth(const Request &req);
  835. namespace detail {
  836. class MatcherBase {
  837. public:
  838. MatcherBase(std::string pattern) : pattern_(std::move(pattern)) {}
  839. virtual ~MatcherBase() = default;
  840. const std::string &pattern() const { return pattern_; }
  841. // Match request path and populate its matches and
  842. virtual bool match(Request &request) const = 0;
  843. private:
  844. std::string pattern_;
  845. };
  846. /**
  847. * Captures parameters in request path and stores them in Request::path_params
  848. *
  849. * Capture name is a substring of a pattern from : to /.
  850. * The rest of the pattern is matched against the request path directly
  851. * Parameters are captured starting from the next character after
  852. * the end of the last matched static pattern fragment until the next /.
  853. *
  854. * Example pattern:
  855. * "/path/fragments/:capture/more/fragments/:second_capture"
  856. * Static fragments:
  857. * "/path/fragments/", "more/fragments/"
  858. *
  859. * Given the following request path:
  860. * "/path/fragments/:1/more/fragments/:2"
  861. * the resulting capture will be
  862. * {{"capture", "1"}, {"second_capture", "2"}}
  863. */
  864. class PathParamsMatcher final : public MatcherBase {
  865. public:
  866. PathParamsMatcher(const std::string &pattern);
  867. bool match(Request &request) const override;
  868. private:
  869. // Treat segment separators as the end of path parameter capture
  870. // Does not need to handle query parameters as they are parsed before path
  871. // matching
  872. static constexpr char separator = '/';
  873. // Contains static path fragments to match against, excluding the '/' after
  874. // path params
  875. // Fragments are separated by path params
  876. std::vector<std::string> static_fragments_;
  877. // Stores the names of the path parameters to be used as keys in the
  878. // Request::path_params map
  879. std::vector<std::string> param_names_;
  880. };
  881. /**
  882. * Performs std::regex_match on request path
  883. * and stores the result in Request::matches
  884. *
  885. * Note that regex match is performed directly on the whole request.
  886. * This means that wildcard patterns may match multiple path segments with /:
  887. * "/begin/(.*)/end" will match both "/begin/middle/end" and "/begin/1/2/end".
  888. */
  889. class RegexMatcher final : public MatcherBase {
  890. public:
  891. RegexMatcher(const std::string &pattern)
  892. : MatcherBase(pattern), regex_(pattern) {}
  893. bool match(Request &request) const override;
  894. private:
  895. std::regex regex_;
  896. };
  897. int close_socket(socket_t sock);
  898. ssize_t write_headers(Stream &strm, const Headers &headers);
  899. } // namespace detail
  900. class Server {
  901. public:
  902. using Handler = std::function<void(const Request &, Response &)>;
  903. using ExceptionHandler =
  904. std::function<void(const Request &, Response &, std::exception_ptr ep)>;
  905. enum class HandlerResponse {
  906. Handled,
  907. Unhandled,
  908. };
  909. using HandlerWithResponse =
  910. std::function<HandlerResponse(const Request &, Response &)>;
  911. using HandlerWithContentReader = std::function<void(
  912. const Request &, Response &, const ContentReader &content_reader)>;
  913. using Expect100ContinueHandler =
  914. std::function<int(const Request &, Response &)>;
  915. Server();
  916. virtual ~Server();
  917. virtual bool is_valid() const;
  918. Server &Get(const std::string &pattern, Handler handler);
  919. Server &Post(const std::string &pattern, Handler handler);
  920. Server &Post(const std::string &pattern, HandlerWithContentReader handler);
  921. Server &Put(const std::string &pattern, Handler handler);
  922. Server &Put(const std::string &pattern, HandlerWithContentReader handler);
  923. Server &Patch(const std::string &pattern, Handler handler);
  924. Server &Patch(const std::string &pattern, HandlerWithContentReader handler);
  925. Server &Delete(const std::string &pattern, Handler handler);
  926. Server &Delete(const std::string &pattern, HandlerWithContentReader handler);
  927. Server &Options(const std::string &pattern, Handler handler);
  928. bool set_base_dir(const std::string &dir,
  929. const std::string &mount_point = std::string());
  930. bool set_mount_point(const std::string &mount_point, const std::string &dir,
  931. Headers headers = Headers());
  932. bool remove_mount_point(const std::string &mount_point);
  933. Server &set_file_extension_and_mimetype_mapping(const std::string &ext,
  934. const std::string &mime);
  935. Server &set_default_file_mimetype(const std::string &mime);
  936. Server &set_file_request_handler(Handler handler);
  937. template <class ErrorHandlerFunc>
  938. Server &set_error_handler(ErrorHandlerFunc &&handler) {
  939. return set_error_handler_core(
  940. std::forward<ErrorHandlerFunc>(handler),
  941. std::is_convertible<ErrorHandlerFunc, HandlerWithResponse>{});
  942. }
  943. Server &set_exception_handler(ExceptionHandler handler);
  944. Server &set_pre_routing_handler(HandlerWithResponse handler);
  945. Server &set_post_routing_handler(Handler handler);
  946. Server &set_pre_request_handler(HandlerWithResponse handler);
  947. Server &set_expect_100_continue_handler(Expect100ContinueHandler handler);
  948. Server &set_logger(Logger logger);
  949. Server &set_pre_compression_logger(Logger logger);
  950. Server &set_error_logger(ErrorLogger error_logger);
  951. Server &set_address_family(int family);
  952. Server &set_tcp_nodelay(bool on);
  953. Server &set_ipv6_v6only(bool on);
  954. Server &set_socket_options(SocketOptions socket_options);
  955. Server &set_default_headers(Headers headers);
  956. Server &
  957. set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
  958. Server &set_trusted_proxies(const std::vector<std::string> &proxies);
  959. Server &set_keep_alive_max_count(size_t count);
  960. Server &set_keep_alive_timeout(time_t sec);
  961. Server &set_read_timeout(time_t sec, time_t usec = 0);
  962. template <class Rep, class Period>
  963. Server &set_read_timeout(const std::chrono::duration<Rep, Period> &duration);
  964. Server &set_write_timeout(time_t sec, time_t usec = 0);
  965. template <class Rep, class Period>
  966. Server &set_write_timeout(const std::chrono::duration<Rep, Period> &duration);
  967. Server &set_idle_interval(time_t sec, time_t usec = 0);
  968. template <class Rep, class Period>
  969. Server &set_idle_interval(const std::chrono::duration<Rep, Period> &duration);
  970. Server &set_payload_max_length(size_t length);
  971. bool bind_to_port(const std::string &host, int port, int socket_flags = 0);
  972. int bind_to_any_port(const std::string &host, int socket_flags = 0);
  973. bool listen_after_bind();
  974. bool listen(const std::string &host, int port, int socket_flags = 0);
  975. bool is_running() const;
  976. void wait_until_ready() const;
  977. void stop();
  978. void decommission();
  979. std::function<TaskQueue *(void)> new_task_queue;
  980. protected:
  981. bool process_request(Stream &strm, const std::string &remote_addr,
  982. int remote_port, const std::string &local_addr,
  983. int local_port, bool close_connection,
  984. bool &connection_closed,
  985. const std::function<void(Request &)> &setup_request);
  986. std::atomic<socket_t> svr_sock_{INVALID_SOCKET};
  987. std::vector<std::string> trusted_proxies_;
  988. size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
  989. time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
  990. time_t read_timeout_sec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND;
  991. time_t read_timeout_usec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_USECOND;
  992. time_t write_timeout_sec_ = CPPHTTPLIB_SERVER_WRITE_TIMEOUT_SECOND;
  993. time_t write_timeout_usec_ = CPPHTTPLIB_SERVER_WRITE_TIMEOUT_USECOND;
  994. time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
  995. time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
  996. size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
  997. private:
  998. using Handlers =
  999. std::vector<std::pair<std::unique_ptr<detail::MatcherBase>, Handler>>;
  1000. using HandlersForContentReader =
  1001. std::vector<std::pair<std::unique_ptr<detail::MatcherBase>,
  1002. HandlerWithContentReader>>;
  1003. static std::unique_ptr<detail::MatcherBase>
  1004. make_matcher(const std::string &pattern);
  1005. Server &set_error_handler_core(HandlerWithResponse handler, std::true_type);
  1006. Server &set_error_handler_core(Handler handler, std::false_type);
  1007. socket_t create_server_socket(const std::string &host, int port,
  1008. int socket_flags,
  1009. SocketOptions socket_options) const;
  1010. int bind_internal(const std::string &host, int port, int socket_flags);
  1011. bool listen_internal();
  1012. bool routing(Request &req, Response &res, Stream &strm);
  1013. bool handle_file_request(Request &req, Response &res);
  1014. bool check_if_not_modified(const Request &req, Response &res,
  1015. const std::string &etag, time_t mtime) const;
  1016. bool check_if_range(Request &req, const std::string &etag,
  1017. time_t mtime) const;
  1018. bool dispatch_request(Request &req, Response &res,
  1019. const Handlers &handlers) const;
  1020. bool dispatch_request_for_content_reader(
  1021. Request &req, Response &res, ContentReader content_reader,
  1022. const HandlersForContentReader &handlers) const;
  1023. bool parse_request_line(const char *s, Request &req) const;
  1024. void apply_ranges(const Request &req, Response &res,
  1025. std::string &content_type, std::string &boundary) const;
  1026. bool write_response(Stream &strm, bool close_connection, Request &req,
  1027. Response &res);
  1028. bool write_response_with_content(Stream &strm, bool close_connection,
  1029. const Request &req, Response &res);
  1030. bool write_response_core(Stream &strm, bool close_connection,
  1031. const Request &req, Response &res,
  1032. bool need_apply_ranges);
  1033. bool write_content_with_provider(Stream &strm, const Request &req,
  1034. Response &res, const std::string &boundary,
  1035. const std::string &content_type);
  1036. bool read_content(Stream &strm, Request &req, Response &res);
  1037. bool read_content_with_content_receiver(Stream &strm, Request &req,
  1038. Response &res,
  1039. ContentReceiver receiver,
  1040. FormDataHeader multipart_header,
  1041. ContentReceiver multipart_receiver);
  1042. bool read_content_core(Stream &strm, Request &req, Response &res,
  1043. ContentReceiver receiver,
  1044. FormDataHeader multipart_header,
  1045. ContentReceiver multipart_receiver) const;
  1046. virtual bool process_and_close_socket(socket_t sock);
  1047. void output_log(const Request &req, const Response &res) const;
  1048. void output_pre_compression_log(const Request &req,
  1049. const Response &res) const;
  1050. void output_error_log(const Error &err, const Request *req) const;
  1051. std::atomic<bool> is_running_{false};
  1052. std::atomic<bool> is_decommissioned{false};
  1053. struct MountPointEntry {
  1054. std::string mount_point;
  1055. std::string base_dir;
  1056. Headers headers;
  1057. };
  1058. std::vector<MountPointEntry> base_dirs_;
  1059. std::map<std::string, std::string> file_extension_and_mimetype_map_;
  1060. std::string default_file_mimetype_ = "application/octet-stream";
  1061. Handler file_request_handler_;
  1062. Handlers get_handlers_;
  1063. Handlers post_handlers_;
  1064. HandlersForContentReader post_handlers_for_content_reader_;
  1065. Handlers put_handlers_;
  1066. HandlersForContentReader put_handlers_for_content_reader_;
  1067. Handlers patch_handlers_;
  1068. HandlersForContentReader patch_handlers_for_content_reader_;
  1069. Handlers delete_handlers_;
  1070. HandlersForContentReader delete_handlers_for_content_reader_;
  1071. Handlers options_handlers_;
  1072. HandlerWithResponse error_handler_;
  1073. ExceptionHandler exception_handler_;
  1074. HandlerWithResponse pre_routing_handler_;
  1075. Handler post_routing_handler_;
  1076. HandlerWithResponse pre_request_handler_;
  1077. Expect100ContinueHandler expect_100_continue_handler_;
  1078. mutable std::mutex logger_mutex_;
  1079. Logger logger_;
  1080. Logger pre_compression_logger_;
  1081. ErrorLogger error_logger_;
  1082. int address_family_ = AF_UNSPEC;
  1083. bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
  1084. bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;
  1085. SocketOptions socket_options_ = default_socket_options;
  1086. Headers default_headers_;
  1087. std::function<ssize_t(Stream &, Headers &)> header_writer_ =
  1088. detail::write_headers;
  1089. };
  1090. class Result {
  1091. public:
  1092. Result() = default;
  1093. Result(std::unique_ptr<Response> &&res, Error err,
  1094. Headers &&request_headers = Headers{})
  1095. : res_(std::move(res)), err_(err),
  1096. request_headers_(std::move(request_headers)) {}
  1097. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1098. Result(std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
  1099. int ssl_error)
  1100. : res_(std::move(res)), err_(err),
  1101. request_headers_(std::move(request_headers)), ssl_error_(ssl_error) {}
  1102. Result(std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
  1103. int ssl_error, unsigned long ssl_openssl_error)
  1104. : res_(std::move(res)), err_(err),
  1105. request_headers_(std::move(request_headers)), ssl_error_(ssl_error),
  1106. ssl_openssl_error_(ssl_openssl_error) {}
  1107. #endif
  1108. // Response
  1109. operator bool() const { return res_ != nullptr; }
  1110. bool operator==(std::nullptr_t) const { return res_ == nullptr; }
  1111. bool operator!=(std::nullptr_t) const { return res_ != nullptr; }
  1112. const Response &value() const { return *res_; }
  1113. Response &value() { return *res_; }
  1114. const Response &operator*() const { return *res_; }
  1115. Response &operator*() { return *res_; }
  1116. const Response *operator->() const { return res_.get(); }
  1117. Response *operator->() { return res_.get(); }
  1118. // Error
  1119. Error error() const { return err_; }
  1120. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1121. // SSL Error
  1122. int ssl_error() const { return ssl_error_; }
  1123. // OpenSSL Error
  1124. unsigned long ssl_openssl_error() const { return ssl_openssl_error_; }
  1125. #endif
  1126. // Request Headers
  1127. bool has_request_header(const std::string &key) const;
  1128. std::string get_request_header_value(const std::string &key,
  1129. const char *def = "",
  1130. size_t id = 0) const;
  1131. size_t get_request_header_value_u64(const std::string &key, size_t def = 0,
  1132. size_t id = 0) const;
  1133. size_t get_request_header_value_count(const std::string &key) const;
  1134. private:
  1135. std::unique_ptr<Response> res_;
  1136. Error err_ = Error::Unknown;
  1137. Headers request_headers_;
  1138. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1139. int ssl_error_ = 0;
  1140. unsigned long ssl_openssl_error_ = 0;
  1141. #endif
  1142. };
  1143. struct ClientConnection {
  1144. socket_t sock = INVALID_SOCKET;
  1145. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1146. SSL *ssl = nullptr;
  1147. #endif
  1148. bool is_open() const { return sock != INVALID_SOCKET; }
  1149. ClientConnection() = default;
  1150. ~ClientConnection() {
  1151. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1152. if (ssl) {
  1153. SSL_free(ssl);
  1154. ssl = nullptr;
  1155. }
  1156. #endif
  1157. if (sock != INVALID_SOCKET) {
  1158. detail::close_socket(sock);
  1159. sock = INVALID_SOCKET;
  1160. }
  1161. }
  1162. ClientConnection(const ClientConnection &) = delete;
  1163. ClientConnection &operator=(const ClientConnection &) = delete;
  1164. ClientConnection(ClientConnection &&other) noexcept
  1165. : sock(other.sock)
  1166. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1167. ,
  1168. ssl(other.ssl)
  1169. #endif
  1170. {
  1171. other.sock = INVALID_SOCKET;
  1172. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1173. other.ssl = nullptr;
  1174. #endif
  1175. }
  1176. ClientConnection &operator=(ClientConnection &&other) noexcept {
  1177. if (this != &other) {
  1178. sock = other.sock;
  1179. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1180. ssl = other.ssl;
  1181. #endif
  1182. other.sock = INVALID_SOCKET;
  1183. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1184. other.ssl = nullptr;
  1185. #endif
  1186. }
  1187. return *this;
  1188. }
  1189. };
  1190. namespace detail {
  1191. struct ChunkedDecoder;
  1192. struct BodyReader {
  1193. Stream *stream = nullptr;
  1194. size_t content_length = 0;
  1195. size_t bytes_read = 0;
  1196. bool chunked = false;
  1197. bool eof = false;
  1198. std::unique_ptr<ChunkedDecoder> chunked_decoder;
  1199. Error last_error = Error::Success;
  1200. ssize_t read(char *buf, size_t len);
  1201. bool has_error() const { return last_error != Error::Success; }
  1202. };
  1203. inline ssize_t read_body_content(Stream *stream, BodyReader &br, char *buf,
  1204. size_t len) {
  1205. (void)stream;
  1206. return br.read(buf, len);
  1207. }
  1208. class decompressor;
  1209. } // namespace detail
  1210. class ClientImpl {
  1211. public:
  1212. explicit ClientImpl(const std::string &host);
  1213. explicit ClientImpl(const std::string &host, int port);
  1214. explicit ClientImpl(const std::string &host, int port,
  1215. const std::string &client_cert_path,
  1216. const std::string &client_key_path);
  1217. virtual ~ClientImpl();
  1218. virtual bool is_valid() const;
  1219. struct StreamHandle {
  1220. std::unique_ptr<Response> response;
  1221. Error error = Error::Success;
  1222. StreamHandle() = default;
  1223. StreamHandle(const StreamHandle &) = delete;
  1224. StreamHandle &operator=(const StreamHandle &) = delete;
  1225. StreamHandle(StreamHandle &&) = default;
  1226. StreamHandle &operator=(StreamHandle &&) = default;
  1227. ~StreamHandle() = default;
  1228. bool is_valid() const {
  1229. return response != nullptr && error == Error::Success;
  1230. }
  1231. ssize_t read(char *buf, size_t len);
  1232. void parse_trailers_if_needed();
  1233. Error get_read_error() const { return body_reader_.last_error; }
  1234. bool has_read_error() const { return body_reader_.has_error(); }
  1235. bool trailers_parsed_ = false;
  1236. private:
  1237. friend class ClientImpl;
  1238. ssize_t read_with_decompression(char *buf, size_t len);
  1239. std::unique_ptr<ClientConnection> connection_;
  1240. std::unique_ptr<Stream> socket_stream_;
  1241. Stream *stream_ = nullptr;
  1242. detail::BodyReader body_reader_;
  1243. std::unique_ptr<detail::decompressor> decompressor_;
  1244. std::string decompress_buffer_;
  1245. size_t decompress_offset_ = 0;
  1246. };
  1247. // clang-format off
  1248. Result Get(const std::string &path, DownloadProgress progress = nullptr);
  1249. Result Get(const std::string &path, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1250. Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1251. Result Get(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
  1252. Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1253. Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1254. Result Get(const std::string &path, const Params &params, const Headers &headers, DownloadProgress progress = nullptr);
  1255. Result Get(const std::string &path, const Params &params, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1256. Result Get(const std::string &path, const Params &params, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1257. Result Head(const std::string &path);
  1258. Result Head(const std::string &path, const Headers &headers);
  1259. Result Post(const std::string &path);
  1260. Result Post(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1261. Result Post(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1262. Result Post(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1263. Result Post(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1264. Result Post(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1265. Result Post(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1266. Result Post(const std::string &path, const Params &params);
  1267. Result Post(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1268. Result Post(const std::string &path, const Headers &headers);
  1269. Result Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1270. Result Post(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1271. Result Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1272. Result Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1273. Result Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1274. Result Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1275. Result Post(const std::string &path, const Headers &headers, const Params &params);
  1276. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1277. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1278. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1279. Result Post(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1280. Result Put(const std::string &path);
  1281. Result Put(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1282. Result Put(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1283. Result Put(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1284. Result Put(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1285. Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1286. Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1287. Result Put(const std::string &path, const Params &params);
  1288. Result Put(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1289. Result Put(const std::string &path, const Headers &headers);
  1290. Result Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1291. Result Put(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1292. Result Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1293. Result Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1294. Result Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1295. Result Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1296. Result Put(const std::string &path, const Headers &headers, const Params &params);
  1297. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1298. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1299. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1300. Result Put(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1301. Result Patch(const std::string &path);
  1302. Result Patch(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1303. Result Patch(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1304. Result Patch(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1305. Result Patch(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1306. Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1307. Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1308. Result Patch(const std::string &path, const Params &params);
  1309. Result Patch(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1310. Result Patch(const std::string &path, const Headers &headers, UploadProgress progress = nullptr);
  1311. Result Patch(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1312. Result Patch(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1313. Result Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1314. Result Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1315. Result Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1316. Result Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1317. Result Patch(const std::string &path, const Headers &headers, const Params &params);
  1318. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1319. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1320. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1321. Result Patch(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1322. Result Delete(const std::string &path, DownloadProgress progress = nullptr);
  1323. Result Delete(const std::string &path, const char *body, size_t content_length, const std::string &content_type, DownloadProgress progress = nullptr);
  1324. Result Delete(const std::string &path, const std::string &body, const std::string &content_type, DownloadProgress progress = nullptr);
  1325. Result Delete(const std::string &path, const Params &params, DownloadProgress progress = nullptr);
  1326. Result Delete(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
  1327. Result Delete(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, DownloadProgress progress = nullptr);
  1328. Result Delete(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, DownloadProgress progress = nullptr);
  1329. Result Delete(const std::string &path, const Headers &headers, const Params &params, DownloadProgress progress = nullptr);
  1330. Result Options(const std::string &path);
  1331. Result Options(const std::string &path, const Headers &headers);
  1332. // clang-format on
  1333. // Streaming API: Open a stream for reading response body incrementally
  1334. // Socket ownership is transferred to StreamHandle for true streaming
  1335. // Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE, etc.)
  1336. StreamHandle open_stream(const std::string &method, const std::string &path,
  1337. const Params &params = {},
  1338. const Headers &headers = {},
  1339. const std::string &body = {},
  1340. const std::string &content_type = {});
  1341. bool send(Request &req, Response &res, Error &error);
  1342. Result send(const Request &req);
  1343. void stop();
  1344. std::string host() const;
  1345. int port() const;
  1346. size_t is_socket_open() const;
  1347. socket_t socket() const;
  1348. void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
  1349. void set_default_headers(Headers headers);
  1350. void
  1351. set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
  1352. void set_address_family(int family);
  1353. void set_tcp_nodelay(bool on);
  1354. void set_ipv6_v6only(bool on);
  1355. void set_socket_options(SocketOptions socket_options);
  1356. void set_connection_timeout(time_t sec, time_t usec = 0);
  1357. template <class Rep, class Period>
  1358. void
  1359. set_connection_timeout(const std::chrono::duration<Rep, Period> &duration);
  1360. void set_read_timeout(time_t sec, time_t usec = 0);
  1361. template <class Rep, class Period>
  1362. void set_read_timeout(const std::chrono::duration<Rep, Period> &duration);
  1363. void set_write_timeout(time_t sec, time_t usec = 0);
  1364. template <class Rep, class Period>
  1365. void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);
  1366. void set_max_timeout(time_t msec);
  1367. template <class Rep, class Period>
  1368. void set_max_timeout(const std::chrono::duration<Rep, Period> &duration);
  1369. void set_basic_auth(const std::string &username, const std::string &password);
  1370. void set_bearer_token_auth(const std::string &token);
  1371. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1372. void set_digest_auth(const std::string &username,
  1373. const std::string &password);
  1374. #endif
  1375. void set_keep_alive(bool on);
  1376. void set_follow_location(bool on);
  1377. void set_path_encode(bool on);
  1378. void set_compress(bool on);
  1379. void set_decompress(bool on);
  1380. void set_interface(const std::string &intf);
  1381. void set_proxy(const std::string &host, int port);
  1382. void set_proxy_basic_auth(const std::string &username,
  1383. const std::string &password);
  1384. void set_proxy_bearer_token_auth(const std::string &token);
  1385. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1386. void set_proxy_digest_auth(const std::string &username,
  1387. const std::string &password);
  1388. #endif
  1389. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1390. void set_ca_cert_path(const std::string &ca_cert_file_path,
  1391. const std::string &ca_cert_dir_path = std::string());
  1392. void set_ca_cert_store(X509_STORE *ca_cert_store);
  1393. X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
  1394. #endif
  1395. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1396. void enable_server_certificate_verification(bool enabled);
  1397. void enable_server_hostname_verification(bool enabled);
  1398. void set_server_certificate_verifier(
  1399. std::function<SSLVerifierResponse(SSL *ssl)> verifier);
  1400. #endif
  1401. void set_logger(Logger logger);
  1402. void set_error_logger(ErrorLogger error_logger);
  1403. protected:
  1404. struct Socket {
  1405. socket_t sock = INVALID_SOCKET;
  1406. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1407. SSL *ssl = nullptr;
  1408. #endif
  1409. bool is_open() const { return sock != INVALID_SOCKET; }
  1410. };
  1411. virtual bool create_and_connect_socket(Socket &socket, Error &error);
  1412. virtual bool ensure_socket_connection(Socket &socket, Error &error);
  1413. // All of:
  1414. // shutdown_ssl
  1415. // shutdown_socket
  1416. // close_socket
  1417. // should ONLY be called when socket_mutex_ is locked.
  1418. // Also, shutdown_ssl and close_socket should also NOT be called concurrently
  1419. // with a DIFFERENT thread sending requests using that socket.
  1420. virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully);
  1421. void shutdown_socket(Socket &socket) const;
  1422. void close_socket(Socket &socket);
  1423. bool process_request(Stream &strm, Request &req, Response &res,
  1424. bool close_connection, Error &error);
  1425. bool write_content_with_provider(Stream &strm, const Request &req,
  1426. Error &error) const;
  1427. void copy_settings(const ClientImpl &rhs);
  1428. void output_log(const Request &req, const Response &res) const;
  1429. void output_error_log(const Error &err, const Request *req) const;
  1430. // Socket endpoint information
  1431. const std::string host_;
  1432. const int port_;
  1433. // Current open socket
  1434. Socket socket_;
  1435. mutable std::mutex socket_mutex_;
  1436. std::recursive_mutex request_mutex_;
  1437. // These are all protected under socket_mutex
  1438. size_t socket_requests_in_flight_ = 0;
  1439. std::thread::id socket_requests_are_from_thread_ = std::thread::id();
  1440. bool socket_should_be_closed_when_request_is_done_ = false;
  1441. // Hostname-IP map
  1442. std::map<std::string, std::string> addr_map_;
  1443. // Default headers
  1444. Headers default_headers_;
  1445. // Header writer
  1446. std::function<ssize_t(Stream &, Headers &)> header_writer_ =
  1447. detail::write_headers;
  1448. // Settings
  1449. std::string client_cert_path_;
  1450. std::string client_key_path_;
  1451. time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
  1452. time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
  1453. time_t read_timeout_sec_ = CPPHTTPLIB_CLIENT_READ_TIMEOUT_SECOND;
  1454. time_t read_timeout_usec_ = CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND;
  1455. time_t write_timeout_sec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND;
  1456. time_t write_timeout_usec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND;
  1457. time_t max_timeout_msec_ = CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND;
  1458. std::string basic_auth_username_;
  1459. std::string basic_auth_password_;
  1460. std::string bearer_token_auth_token_;
  1461. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1462. std::string digest_auth_username_;
  1463. std::string digest_auth_password_;
  1464. #endif
  1465. bool keep_alive_ = false;
  1466. bool follow_location_ = false;
  1467. bool path_encode_ = true;
  1468. int address_family_ = AF_UNSPEC;
  1469. bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
  1470. bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;
  1471. SocketOptions socket_options_ = nullptr;
  1472. bool compress_ = false;
  1473. bool decompress_ = true;
  1474. std::string interface_;
  1475. std::string proxy_host_;
  1476. int proxy_port_ = -1;
  1477. std::string proxy_basic_auth_username_;
  1478. std::string proxy_basic_auth_password_;
  1479. std::string proxy_bearer_token_auth_token_;
  1480. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1481. std::string proxy_digest_auth_username_;
  1482. std::string proxy_digest_auth_password_;
  1483. #endif
  1484. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1485. std::string ca_cert_file_path_;
  1486. std::string ca_cert_dir_path_;
  1487. X509_STORE *ca_cert_store_ = nullptr;
  1488. #endif
  1489. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1490. bool server_certificate_verification_ = true;
  1491. bool server_hostname_verification_ = true;
  1492. std::function<SSLVerifierResponse(SSL *ssl)> server_certificate_verifier_;
  1493. #endif
  1494. mutable std::mutex logger_mutex_;
  1495. Logger logger_;
  1496. ErrorLogger error_logger_;
  1497. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1498. int last_ssl_error_ = 0;
  1499. unsigned long last_openssl_error_ = 0;
  1500. #endif
  1501. private:
  1502. bool send_(Request &req, Response &res, Error &error);
  1503. Result send_(Request &&req);
  1504. socket_t create_client_socket(Error &error) const;
  1505. bool read_response_line(Stream &strm, const Request &req,
  1506. Response &res) const;
  1507. bool write_request(Stream &strm, Request &req, bool close_connection,
  1508. Error &error);
  1509. void prepare_default_headers(Request &r, bool for_stream,
  1510. const std::string &ct);
  1511. bool redirect(Request &req, Response &res, Error &error);
  1512. bool create_redirect_client(const std::string &scheme,
  1513. const std::string &host, int port, Request &req,
  1514. Response &res, const std::string &path,
  1515. const std::string &location, Error &error);
  1516. template <typename ClientType> void setup_redirect_client(ClientType &client);
  1517. bool handle_request(Stream &strm, Request &req, Response &res,
  1518. bool close_connection, Error &error);
  1519. std::unique_ptr<Response> send_with_content_provider_and_receiver(
  1520. Request &req, const char *body, size_t content_length,
  1521. ContentProvider content_provider,
  1522. ContentProviderWithoutLength content_provider_without_length,
  1523. const std::string &content_type, ContentReceiver content_receiver,
  1524. Error &error);
  1525. Result send_with_content_provider_and_receiver(
  1526. const std::string &method, const std::string &path,
  1527. const Headers &headers, const char *body, size_t content_length,
  1528. ContentProvider content_provider,
  1529. ContentProviderWithoutLength content_provider_without_length,
  1530. const std::string &content_type, ContentReceiver content_receiver,
  1531. UploadProgress progress);
  1532. ContentProviderWithoutLength get_multipart_content_provider(
  1533. const std::string &boundary, const UploadFormDataItems &items,
  1534. const FormDataProviderItems &provider_items) const;
  1535. virtual bool
  1536. process_socket(const Socket &socket,
  1537. std::chrono::time_point<std::chrono::steady_clock> start_time,
  1538. std::function<bool(Stream &strm)> callback);
  1539. virtual bool is_ssl() const;
  1540. void transfer_socket_ownership_to_handle(StreamHandle &handle);
  1541. };
  1542. class Client {
  1543. public:
  1544. // Universal interface
  1545. explicit Client(const std::string &scheme_host_port);
  1546. explicit Client(const std::string &scheme_host_port,
  1547. const std::string &client_cert_path,
  1548. const std::string &client_key_path);
  1549. // HTTP only interface
  1550. explicit Client(const std::string &host, int port);
  1551. explicit Client(const std::string &host, int port,
  1552. const std::string &client_cert_path,
  1553. const std::string &client_key_path);
  1554. Client(Client &&) = default;
  1555. Client &operator=(Client &&) = default;
  1556. ~Client();
  1557. bool is_valid() const;
  1558. // clang-format off
  1559. Result Get(const std::string &path, DownloadProgress progress = nullptr);
  1560. Result Get(const std::string &path, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1561. Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1562. Result Get(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
  1563. Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1564. Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1565. Result Get(const std::string &path, const Params &params, const Headers &headers, DownloadProgress progress = nullptr);
  1566. Result Get(const std::string &path, const Params &params, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1567. Result Get(const std::string &path, const Params &params, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1568. Result Head(const std::string &path);
  1569. Result Head(const std::string &path, const Headers &headers);
  1570. Result Post(const std::string &path);
  1571. Result Post(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1572. Result Post(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1573. Result Post(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1574. Result Post(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1575. Result Post(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1576. Result Post(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1577. Result Post(const std::string &path, const Params &params);
  1578. Result Post(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1579. Result Post(const std::string &path, const Headers &headers);
  1580. Result Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1581. Result Post(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1582. Result Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1583. Result Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1584. Result Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1585. Result Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1586. Result Post(const std::string &path, const Headers &headers, const Params &params);
  1587. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1588. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1589. Result Post(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1590. Result Post(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1591. Result Put(const std::string &path);
  1592. Result Put(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1593. Result Put(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1594. Result Put(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1595. Result Put(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1596. Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1597. Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1598. Result Put(const std::string &path, const Params &params);
  1599. Result Put(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1600. Result Put(const std::string &path, const Headers &headers);
  1601. Result Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1602. Result Put(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1603. Result Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1604. Result Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1605. Result Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1606. Result Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1607. Result Put(const std::string &path, const Headers &headers, const Params &params);
  1608. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1609. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1610. Result Put(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1611. Result Put(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1612. Result Patch(const std::string &path);
  1613. Result Patch(const std::string &path, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1614. Result Patch(const std::string &path, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1615. Result Patch(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1616. Result Patch(const std::string &path, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1617. Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1618. Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1619. Result Patch(const std::string &path, const Params &params);
  1620. Result Patch(const std::string &path, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1621. Result Patch(const std::string &path, const Headers &headers);
  1622. Result Patch(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, UploadProgress progress = nullptr);
  1623. Result Patch(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, UploadProgress progress = nullptr);
  1624. Result Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1625. Result Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1626. Result Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, UploadProgress progress = nullptr);
  1627. Result Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, const std::string &content_type, ContentReceiver content_receiver, UploadProgress progress = nullptr);
  1628. Result Patch(const std::string &path, const Headers &headers, const Params &params);
  1629. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, UploadProgress progress = nullptr);
  1630. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const std::string &boundary, UploadProgress progress = nullptr);
  1631. Result Patch(const std::string &path, const Headers &headers, const UploadFormDataItems &items, const FormDataProviderItems &provider_items, UploadProgress progress = nullptr);
  1632. Result Patch(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
  1633. Result Delete(const std::string &path, DownloadProgress progress = nullptr);
  1634. Result Delete(const std::string &path, const char *body, size_t content_length, const std::string &content_type, DownloadProgress progress = nullptr);
  1635. Result Delete(const std::string &path, const std::string &body, const std::string &content_type, DownloadProgress progress = nullptr);
  1636. Result Delete(const std::string &path, const Params &params, DownloadProgress progress = nullptr);
  1637. Result Delete(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
  1638. Result Delete(const std::string &path, const Headers &headers, const char *body, size_t content_length, const std::string &content_type, DownloadProgress progress = nullptr);
  1639. Result Delete(const std::string &path, const Headers &headers, const std::string &body, const std::string &content_type, DownloadProgress progress = nullptr);
  1640. Result Delete(const std::string &path, const Headers &headers, const Params &params, DownloadProgress progress = nullptr);
  1641. Result Options(const std::string &path);
  1642. Result Options(const std::string &path, const Headers &headers);
  1643. // clang-format on
  1644. // Streaming API: Open a stream for reading response body incrementally
  1645. // Socket ownership is transferred to StreamHandle for true streaming
  1646. // Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE, etc.)
  1647. ClientImpl::StreamHandle open_stream(const std::string &method,
  1648. const std::string &path,
  1649. const Params &params = {},
  1650. const Headers &headers = {},
  1651. const std::string &body = {},
  1652. const std::string &content_type = {});
  1653. bool send(Request &req, Response &res, Error &error);
  1654. Result send(const Request &req);
  1655. void stop();
  1656. std::string host() const;
  1657. int port() const;
  1658. size_t is_socket_open() const;
  1659. socket_t socket() const;
  1660. void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
  1661. void set_default_headers(Headers headers);
  1662. void
  1663. set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
  1664. void set_address_family(int family);
  1665. void set_tcp_nodelay(bool on);
  1666. void set_socket_options(SocketOptions socket_options);
  1667. void set_connection_timeout(time_t sec, time_t usec = 0);
  1668. template <class Rep, class Period>
  1669. void
  1670. set_connection_timeout(const std::chrono::duration<Rep, Period> &duration);
  1671. void set_read_timeout(time_t sec, time_t usec = 0);
  1672. template <class Rep, class Period>
  1673. void set_read_timeout(const std::chrono::duration<Rep, Period> &duration);
  1674. void set_write_timeout(time_t sec, time_t usec = 0);
  1675. template <class Rep, class Period>
  1676. void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);
  1677. void set_max_timeout(time_t msec);
  1678. template <class Rep, class Period>
  1679. void set_max_timeout(const std::chrono::duration<Rep, Period> &duration);
  1680. void set_basic_auth(const std::string &username, const std::string &password);
  1681. void set_bearer_token_auth(const std::string &token);
  1682. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1683. void set_digest_auth(const std::string &username,
  1684. const std::string &password);
  1685. #endif
  1686. void set_keep_alive(bool on);
  1687. void set_follow_location(bool on);
  1688. void set_path_encode(bool on);
  1689. void set_url_encode(bool on);
  1690. void set_compress(bool on);
  1691. void set_decompress(bool on);
  1692. void set_interface(const std::string &intf);
  1693. void set_proxy(const std::string &host, int port);
  1694. void set_proxy_basic_auth(const std::string &username,
  1695. const std::string &password);
  1696. void set_proxy_bearer_token_auth(const std::string &token);
  1697. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1698. void set_proxy_digest_auth(const std::string &username,
  1699. const std::string &password);
  1700. #endif
  1701. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1702. void enable_server_certificate_verification(bool enabled);
  1703. void enable_server_hostname_verification(bool enabled);
  1704. void set_server_certificate_verifier(
  1705. std::function<SSLVerifierResponse(SSL *ssl)> verifier);
  1706. #endif
  1707. void set_logger(Logger logger);
  1708. void set_error_logger(ErrorLogger error_logger);
  1709. // SSL
  1710. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1711. void set_ca_cert_path(const std::string &ca_cert_file_path,
  1712. const std::string &ca_cert_dir_path = std::string());
  1713. void set_ca_cert_store(X509_STORE *ca_cert_store);
  1714. void load_ca_cert_store(const char *ca_cert, std::size_t size);
  1715. long get_openssl_verify_result() const;
  1716. SSL_CTX *ssl_context() const;
  1717. #endif
  1718. private:
  1719. std::unique_ptr<ClientImpl> cli_;
  1720. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1721. bool is_ssl_ = false;
  1722. #endif
  1723. };
  1724. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1725. class SSLServer : public Server {
  1726. public:
  1727. SSLServer(const char *cert_path, const char *private_key_path,
  1728. const char *client_ca_cert_file_path = nullptr,
  1729. const char *client_ca_cert_dir_path = nullptr,
  1730. const char *private_key_password = nullptr);
  1731. SSLServer(X509 *cert, EVP_PKEY *private_key,
  1732. X509_STORE *client_ca_cert_store = nullptr);
  1733. SSLServer(
  1734. const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback);
  1735. ~SSLServer() override;
  1736. bool is_valid() const override;
  1737. SSL_CTX *ssl_context() const;
  1738. void update_certs(X509 *cert, EVP_PKEY *private_key,
  1739. X509_STORE *client_ca_cert_store = nullptr);
  1740. int ssl_last_error() const { return last_ssl_error_; }
  1741. private:
  1742. bool process_and_close_socket(socket_t sock) override;
  1743. STACK_OF(X509_NAME) * extract_ca_names_from_x509_store(X509_STORE *store);
  1744. SSL_CTX *ctx_;
  1745. std::mutex ctx_mutex_;
  1746. int last_ssl_error_ = 0;
  1747. };
  1748. class SSLClient final : public ClientImpl {
  1749. public:
  1750. explicit SSLClient(const std::string &host);
  1751. explicit SSLClient(const std::string &host, int port);
  1752. explicit SSLClient(const std::string &host, int port,
  1753. const std::string &client_cert_path,
  1754. const std::string &client_key_path,
  1755. const std::string &private_key_password = std::string());
  1756. explicit SSLClient(const std::string &host, int port, X509 *client_cert,
  1757. EVP_PKEY *client_key,
  1758. const std::string &private_key_password = std::string());
  1759. ~SSLClient() override;
  1760. bool is_valid() const override;
  1761. void set_ca_cert_store(X509_STORE *ca_cert_store);
  1762. void load_ca_cert_store(const char *ca_cert, std::size_t size);
  1763. long get_openssl_verify_result() const;
  1764. SSL_CTX *ssl_context() const;
  1765. private:
  1766. bool create_and_connect_socket(Socket &socket, Error &error) override;
  1767. bool ensure_socket_connection(Socket &socket, Error &error) override;
  1768. void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override;
  1769. void shutdown_ssl_impl(Socket &socket, bool shutdown_gracefully);
  1770. bool
  1771. process_socket(const Socket &socket,
  1772. std::chrono::time_point<std::chrono::steady_clock> start_time,
  1773. std::function<bool(Stream &strm)> callback) override;
  1774. bool is_ssl() const override;
  1775. bool connect_with_proxy(
  1776. Socket &sock,
  1777. std::chrono::time_point<std::chrono::steady_clock> start_time,
  1778. Response &res, bool &success, Error &error);
  1779. bool initialize_ssl(Socket &socket, Error &error);
  1780. bool load_certs();
  1781. bool verify_host(X509 *server_cert) const;
  1782. bool verify_host_with_subject_alt_name(X509 *server_cert) const;
  1783. bool verify_host_with_common_name(X509 *server_cert) const;
  1784. bool check_host_name(const char *pattern, size_t pattern_len) const;
  1785. SSL_CTX *ctx_;
  1786. std::mutex ctx_mutex_;
  1787. std::once_flag initialize_cert_;
  1788. std::vector<std::string> host_components_;
  1789. long verify_result_ = 0;
  1790. friend class ClientImpl;
  1791. };
  1792. #endif
  1793. /*
  1794. * Implementation of template methods.
  1795. */
  1796. namespace detail {
  1797. template <typename T, typename U>
  1798. inline void duration_to_sec_and_usec(const T &duration, U callback) {
  1799. auto sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
  1800. auto usec = std::chrono::duration_cast<std::chrono::microseconds>(
  1801. duration - std::chrono::seconds(sec))
  1802. .count();
  1803. callback(static_cast<time_t>(sec), static_cast<time_t>(usec));
  1804. }
  1805. template <size_t N> inline constexpr size_t str_len(const char (&)[N]) {
  1806. return N - 1;
  1807. }
  1808. inline bool is_numeric(const std::string &str) {
  1809. return !str.empty() &&
  1810. std::all_of(str.cbegin(), str.cend(),
  1811. [](unsigned char c) { return std::isdigit(c); });
  1812. }
  1813. inline size_t get_header_value_u64(const Headers &headers,
  1814. const std::string &key, size_t def,
  1815. size_t id, bool &is_invalid_value) {
  1816. is_invalid_value = false;
  1817. auto rng = headers.equal_range(key);
  1818. auto it = rng.first;
  1819. std::advance(it, static_cast<ssize_t>(id));
  1820. if (it != rng.second) {
  1821. if (is_numeric(it->second)) {
  1822. return std::strtoull(it->second.data(), nullptr, 10);
  1823. } else {
  1824. is_invalid_value = true;
  1825. }
  1826. }
  1827. return def;
  1828. }
  1829. inline size_t get_header_value_u64(const Headers &headers,
  1830. const std::string &key, size_t def,
  1831. size_t id) {
  1832. auto dummy = false;
  1833. return get_header_value_u64(headers, key, def, id, dummy);
  1834. }
  1835. } // namespace detail
  1836. inline size_t Request::get_header_value_u64(const std::string &key, size_t def,
  1837. size_t id) const {
  1838. return detail::get_header_value_u64(headers, key, def, id);
  1839. }
  1840. inline size_t Response::get_header_value_u64(const std::string &key, size_t def,
  1841. size_t id) const {
  1842. return detail::get_header_value_u64(headers, key, def, id);
  1843. }
  1844. namespace detail {
  1845. inline bool set_socket_opt_impl(socket_t sock, int level, int optname,
  1846. const void *optval, socklen_t optlen) {
  1847. return setsockopt(sock, level, optname,
  1848. #ifdef _WIN32
  1849. reinterpret_cast<const char *>(optval),
  1850. #else
  1851. optval,
  1852. #endif
  1853. optlen) == 0;
  1854. }
  1855. inline bool set_socket_opt(socket_t sock, int level, int optname, int optval) {
  1856. return set_socket_opt_impl(sock, level, optname, &optval, sizeof(optval));
  1857. }
  1858. inline bool set_socket_opt_time(socket_t sock, int level, int optname,
  1859. time_t sec, time_t usec) {
  1860. #ifdef _WIN32
  1861. auto timeout = static_cast<uint32_t>(sec * 1000 + usec / 1000);
  1862. #else
  1863. timeval timeout;
  1864. timeout.tv_sec = static_cast<long>(sec);
  1865. timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(usec);
  1866. #endif
  1867. return set_socket_opt_impl(sock, level, optname, &timeout, sizeof(timeout));
  1868. }
  1869. } // namespace detail
  1870. inline void default_socket_options(socket_t sock) {
  1871. detail::set_socket_opt(sock, SOL_SOCKET,
  1872. #ifdef SO_REUSEPORT
  1873. SO_REUSEPORT,
  1874. #else
  1875. SO_REUSEADDR,
  1876. #endif
  1877. 1);
  1878. }
  1879. inline std::string get_bearer_token_auth(const Request &req) {
  1880. if (req.has_header("Authorization")) {
  1881. constexpr auto bearer_header_prefix_len = detail::str_len("Bearer ");
  1882. return req.get_header_value("Authorization")
  1883. .substr(bearer_header_prefix_len);
  1884. }
  1885. return "";
  1886. }
  1887. template <class Rep, class Period>
  1888. inline Server &
  1889. Server::set_read_timeout(const std::chrono::duration<Rep, Period> &duration) {
  1890. detail::duration_to_sec_and_usec(
  1891. duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); });
  1892. return *this;
  1893. }
  1894. template <class Rep, class Period>
  1895. inline Server &
  1896. Server::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
  1897. detail::duration_to_sec_and_usec(
  1898. duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); });
  1899. return *this;
  1900. }
  1901. template <class Rep, class Period>
  1902. inline Server &
  1903. Server::set_idle_interval(const std::chrono::duration<Rep, Period> &duration) {
  1904. detail::duration_to_sec_and_usec(
  1905. duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); });
  1906. return *this;
  1907. }
  1908. inline size_t Result::get_request_header_value_u64(const std::string &key,
  1909. size_t def,
  1910. size_t id) const {
  1911. return detail::get_header_value_u64(request_headers_, key, def, id);
  1912. }
  1913. template <class Rep, class Period>
  1914. inline void ClientImpl::set_connection_timeout(
  1915. const std::chrono::duration<Rep, Period> &duration) {
  1916. detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
  1917. set_connection_timeout(sec, usec);
  1918. });
  1919. }
  1920. template <class Rep, class Period>
  1921. inline void ClientImpl::set_read_timeout(
  1922. const std::chrono::duration<Rep, Period> &duration) {
  1923. detail::duration_to_sec_and_usec(
  1924. duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); });
  1925. }
  1926. template <class Rep, class Period>
  1927. inline void ClientImpl::set_write_timeout(
  1928. const std::chrono::duration<Rep, Period> &duration) {
  1929. detail::duration_to_sec_and_usec(
  1930. duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); });
  1931. }
  1932. template <class Rep, class Period>
  1933. inline void ClientImpl::set_max_timeout(
  1934. const std::chrono::duration<Rep, Period> &duration) {
  1935. auto msec =
  1936. std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
  1937. set_max_timeout(msec);
  1938. }
  1939. template <class Rep, class Period>
  1940. inline void Client::set_connection_timeout(
  1941. const std::chrono::duration<Rep, Period> &duration) {
  1942. cli_->set_connection_timeout(duration);
  1943. }
  1944. template <class Rep, class Period>
  1945. inline void
  1946. Client::set_read_timeout(const std::chrono::duration<Rep, Period> &duration) {
  1947. cli_->set_read_timeout(duration);
  1948. }
  1949. template <class Rep, class Period>
  1950. inline void
  1951. Client::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
  1952. cli_->set_write_timeout(duration);
  1953. }
  1954. inline void Client::set_max_timeout(time_t msec) {
  1955. cli_->set_max_timeout(msec);
  1956. }
  1957. template <class Rep, class Period>
  1958. inline void
  1959. Client::set_max_timeout(const std::chrono::duration<Rep, Period> &duration) {
  1960. cli_->set_max_timeout(duration);
  1961. }
  1962. /*
  1963. * Forward declarations and types that will be part of the .h file if split into
  1964. * .h + .cc.
  1965. */
  1966. std::string hosted_at(const std::string &hostname);
  1967. void hosted_at(const std::string &hostname, std::vector<std::string> &addrs);
  1968. // JavaScript-style URL encoding/decoding functions
  1969. std::string encode_uri_component(const std::string &value);
  1970. std::string encode_uri(const std::string &value);
  1971. std::string decode_uri_component(const std::string &value);
  1972. std::string decode_uri(const std::string &value);
  1973. // RFC 3986 compliant URL component encoding/decoding functions
  1974. std::string encode_path_component(const std::string &component);
  1975. std::string decode_path_component(const std::string &component);
  1976. std::string encode_query_component(const std::string &component,
  1977. bool space_as_plus = true);
  1978. std::string decode_query_component(const std::string &component,
  1979. bool plus_as_space = true);
  1980. std::string append_query_params(const std::string &path, const Params &params);
  1981. std::pair<std::string, std::string> make_range_header(const Ranges &ranges);
  1982. std::pair<std::string, std::string>
  1983. make_basic_authentication_header(const std::string &username,
  1984. const std::string &password,
  1985. bool is_proxy = false);
  1986. namespace detail {
  1987. #if defined(_WIN32)
  1988. inline std::wstring u8string_to_wstring(const char *s) {
  1989. std::wstring ws;
  1990. auto len = static_cast<int>(strlen(s));
  1991. auto wlen = ::MultiByteToWideChar(CP_UTF8, 0, s, len, nullptr, 0);
  1992. if (wlen > 0) {
  1993. ws.resize(wlen);
  1994. wlen = ::MultiByteToWideChar(
  1995. CP_UTF8, 0, s, len,
  1996. const_cast<LPWSTR>(reinterpret_cast<LPCWSTR>(ws.data())), wlen);
  1997. if (wlen != static_cast<int>(ws.size())) { ws.clear(); }
  1998. }
  1999. return ws;
  2000. }
  2001. #endif
  2002. struct FileStat {
  2003. FileStat(const std::string &path);
  2004. bool is_file() const;
  2005. bool is_dir() const;
  2006. time_t mtime() const;
  2007. size_t size() const;
  2008. private:
  2009. #if defined(_WIN32)
  2010. struct _stat st_;
  2011. #else
  2012. struct stat st_;
  2013. #endif
  2014. int ret_ = -1;
  2015. };
  2016. std::string make_host_and_port_string(const std::string &host, int port,
  2017. bool is_ssl);
  2018. std::string trim_copy(const std::string &s);
  2019. void divide(
  2020. const char *data, std::size_t size, char d,
  2021. std::function<void(const char *, std::size_t, const char *, std::size_t)>
  2022. fn);
  2023. void divide(
  2024. const std::string &str, char d,
  2025. std::function<void(const char *, std::size_t, const char *, std::size_t)>
  2026. fn);
  2027. void split(const char *b, const char *e, char d,
  2028. std::function<void(const char *, const char *)> fn);
  2029. void split(const char *b, const char *e, char d, size_t m,
  2030. std::function<void(const char *, const char *)> fn);
  2031. bool process_client_socket(
  2032. socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
  2033. time_t write_timeout_sec, time_t write_timeout_usec,
  2034. time_t max_timeout_msec,
  2035. std::chrono::time_point<std::chrono::steady_clock> start_time,
  2036. std::function<bool(Stream &)> callback);
  2037. socket_t create_client_socket(const std::string &host, const std::string &ip,
  2038. int port, int address_family, bool tcp_nodelay,
  2039. bool ipv6_v6only, SocketOptions socket_options,
  2040. time_t connection_timeout_sec,
  2041. time_t connection_timeout_usec,
  2042. time_t read_timeout_sec, time_t read_timeout_usec,
  2043. time_t write_timeout_sec,
  2044. time_t write_timeout_usec,
  2045. const std::string &intf, Error &error);
  2046. const char *get_header_value(const Headers &headers, const std::string &key,
  2047. const char *def, size_t id);
  2048. std::string params_to_query_str(const Params &params);
  2049. void parse_query_text(const char *data, std::size_t size, Params &params);
  2050. void parse_query_text(const std::string &s, Params &params);
  2051. bool parse_multipart_boundary(const std::string &content_type,
  2052. std::string &boundary);
  2053. bool parse_range_header(const std::string &s, Ranges &ranges);
  2054. bool parse_accept_header(const std::string &s,
  2055. std::vector<std::string> &content_types);
  2056. int close_socket(socket_t sock);
  2057. ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags);
  2058. ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags);
  2059. enum class EncodingType { None = 0, Gzip, Brotli, Zstd };
  2060. EncodingType encoding_type(const Request &req, const Response &res);
  2061. class BufferStream final : public Stream {
  2062. public:
  2063. BufferStream() = default;
  2064. ~BufferStream() override = default;
  2065. bool is_readable() const override;
  2066. bool wait_readable() const override;
  2067. bool wait_writable() const override;
  2068. ssize_t read(char *ptr, size_t size) override;
  2069. ssize_t write(const char *ptr, size_t size) override;
  2070. void get_remote_ip_and_port(std::string &ip, int &port) const override;
  2071. void get_local_ip_and_port(std::string &ip, int &port) const override;
  2072. socket_t socket() const override;
  2073. time_t duration() const override;
  2074. const std::string &get_buffer() const;
  2075. private:
  2076. std::string buffer;
  2077. size_t position = 0;
  2078. };
  2079. class compressor {
  2080. public:
  2081. virtual ~compressor() = default;
  2082. typedef std::function<bool(const char *data, size_t data_len)> Callback;
  2083. virtual bool compress(const char *data, size_t data_length, bool last,
  2084. Callback callback) = 0;
  2085. };
  2086. class decompressor {
  2087. public:
  2088. virtual ~decompressor() = default;
  2089. virtual bool is_valid() const = 0;
  2090. typedef std::function<bool(const char *data, size_t data_len)> Callback;
  2091. virtual bool decompress(const char *data, size_t data_length,
  2092. Callback callback) = 0;
  2093. };
  2094. class nocompressor final : public compressor {
  2095. public:
  2096. ~nocompressor() override = default;
  2097. bool compress(const char *data, size_t data_length, bool /*last*/,
  2098. Callback callback) override;
  2099. };
  2100. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  2101. class gzip_compressor final : public compressor {
  2102. public:
  2103. gzip_compressor();
  2104. ~gzip_compressor() override;
  2105. bool compress(const char *data, size_t data_length, bool last,
  2106. Callback callback) override;
  2107. private:
  2108. bool is_valid_ = false;
  2109. z_stream strm_;
  2110. };
  2111. class gzip_decompressor final : public decompressor {
  2112. public:
  2113. gzip_decompressor();
  2114. ~gzip_decompressor() override;
  2115. bool is_valid() const override;
  2116. bool decompress(const char *data, size_t data_length,
  2117. Callback callback) override;
  2118. private:
  2119. bool is_valid_ = false;
  2120. z_stream strm_;
  2121. };
  2122. #endif
  2123. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  2124. class brotli_compressor final : public compressor {
  2125. public:
  2126. brotli_compressor();
  2127. ~brotli_compressor();
  2128. bool compress(const char *data, size_t data_length, bool last,
  2129. Callback callback) override;
  2130. private:
  2131. BrotliEncoderState *state_ = nullptr;
  2132. };
  2133. class brotli_decompressor final : public decompressor {
  2134. public:
  2135. brotli_decompressor();
  2136. ~brotli_decompressor();
  2137. bool is_valid() const override;
  2138. bool decompress(const char *data, size_t data_length,
  2139. Callback callback) override;
  2140. private:
  2141. BrotliDecoderResult decoder_r;
  2142. BrotliDecoderState *decoder_s = nullptr;
  2143. };
  2144. #endif
  2145. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  2146. class zstd_compressor : public compressor {
  2147. public:
  2148. zstd_compressor();
  2149. ~zstd_compressor();
  2150. bool compress(const char *data, size_t data_length, bool last,
  2151. Callback callback) override;
  2152. private:
  2153. ZSTD_CCtx *ctx_ = nullptr;
  2154. };
  2155. class zstd_decompressor : public decompressor {
  2156. public:
  2157. zstd_decompressor();
  2158. ~zstd_decompressor();
  2159. bool is_valid() const override;
  2160. bool decompress(const char *data, size_t data_length,
  2161. Callback callback) override;
  2162. private:
  2163. ZSTD_DCtx *ctx_ = nullptr;
  2164. };
  2165. #endif
  2166. // NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer`
  2167. // to store data. The call can set memory on stack for performance.
  2168. class stream_line_reader {
  2169. public:
  2170. stream_line_reader(Stream &strm, char *fixed_buffer,
  2171. size_t fixed_buffer_size);
  2172. const char *ptr() const;
  2173. size_t size() const;
  2174. bool end_with_crlf() const;
  2175. bool getline();
  2176. private:
  2177. void append(char c);
  2178. Stream &strm_;
  2179. char *fixed_buffer_;
  2180. const size_t fixed_buffer_size_;
  2181. size_t fixed_buffer_used_size_ = 0;
  2182. std::string growable_buffer_;
  2183. };
  2184. bool parse_trailers(stream_line_reader &line_reader, Headers &dest,
  2185. const Headers &src_headers);
  2186. struct ChunkedDecoder {
  2187. Stream &strm;
  2188. size_t chunk_remaining = 0;
  2189. bool finished = false;
  2190. char line_buf[64];
  2191. size_t last_chunk_total = 0;
  2192. size_t last_chunk_offset = 0;
  2193. explicit ChunkedDecoder(Stream &s);
  2194. ssize_t read_payload(char *buf, size_t len, size_t &out_chunk_offset,
  2195. size_t &out_chunk_total);
  2196. bool parse_trailers_into(Headers &dest, const Headers &src_headers);
  2197. };
  2198. class mmap {
  2199. public:
  2200. mmap(const char *path);
  2201. ~mmap();
  2202. bool open(const char *path);
  2203. void close();
  2204. bool is_open() const;
  2205. size_t size() const;
  2206. const char *data() const;
  2207. private:
  2208. #if defined(_WIN32)
  2209. HANDLE hFile_ = NULL;
  2210. HANDLE hMapping_ = NULL;
  2211. #else
  2212. int fd_ = -1;
  2213. #endif
  2214. size_t size_ = 0;
  2215. void *addr_ = nullptr;
  2216. bool is_open_empty_file = false;
  2217. };
  2218. // NOTE: https://www.rfc-editor.org/rfc/rfc9110#section-5
  2219. namespace fields {
  2220. bool is_token_char(char c);
  2221. bool is_token(const std::string &s);
  2222. bool is_field_name(const std::string &s);
  2223. bool is_vchar(char c);
  2224. bool is_obs_text(char c);
  2225. bool is_field_vchar(char c);
  2226. bool is_field_content(const std::string &s);
  2227. bool is_field_value(const std::string &s);
  2228. } // namespace fields
  2229. } // namespace detail
  2230. namespace stream {
  2231. class Result {
  2232. public:
  2233. Result() : chunk_size_(8192) {}
  2234. explicit Result(ClientImpl::StreamHandle &&handle, size_t chunk_size = 8192)
  2235. : handle_(std::move(handle)), chunk_size_(chunk_size) {}
  2236. Result(Result &&other) noexcept
  2237. : handle_(std::move(other.handle_)), buffer_(std::move(other.buffer_)),
  2238. current_size_(other.current_size_), chunk_size_(other.chunk_size_),
  2239. finished_(other.finished_) {
  2240. other.current_size_ = 0;
  2241. other.finished_ = true;
  2242. }
  2243. Result &operator=(Result &&other) noexcept {
  2244. if (this != &other) {
  2245. handle_ = std::move(other.handle_);
  2246. buffer_ = std::move(other.buffer_);
  2247. current_size_ = other.current_size_;
  2248. chunk_size_ = other.chunk_size_;
  2249. finished_ = other.finished_;
  2250. other.current_size_ = 0;
  2251. other.finished_ = true;
  2252. }
  2253. return *this;
  2254. }
  2255. Result(const Result &) = delete;
  2256. Result &operator=(const Result &) = delete;
  2257. // Check if the result is valid (connection succeeded and response received)
  2258. bool is_valid() const { return handle_.is_valid(); }
  2259. explicit operator bool() const { return is_valid(); }
  2260. // Response status code
  2261. int status() const {
  2262. return handle_.response ? handle_.response->status : -1;
  2263. }
  2264. // Response headers
  2265. const Headers &headers() const {
  2266. static const Headers empty_headers;
  2267. return handle_.response ? handle_.response->headers : empty_headers;
  2268. }
  2269. std::string get_header_value(const std::string &key,
  2270. const char *def = "") const {
  2271. return handle_.response ? handle_.response->get_header_value(key, def)
  2272. : def;
  2273. }
  2274. bool has_header(const std::string &key) const {
  2275. return handle_.response ? handle_.response->has_header(key) : false;
  2276. }
  2277. // Error information
  2278. Error error() const { return handle_.error; }
  2279. Error read_error() const { return handle_.get_read_error(); }
  2280. bool has_read_error() const { return handle_.has_read_error(); }
  2281. // Streaming iteration API
  2282. // Call next() to read the next chunk, then access data via data()/size()
  2283. // Returns true if data was read, false when stream is exhausted
  2284. bool next() {
  2285. if (!handle_.is_valid() || finished_) { return false; }
  2286. if (buffer_.size() < chunk_size_) { buffer_.resize(chunk_size_); }
  2287. ssize_t n = handle_.read(&buffer_[0], chunk_size_);
  2288. if (n > 0) {
  2289. current_size_ = static_cast<size_t>(n);
  2290. return true;
  2291. }
  2292. current_size_ = 0;
  2293. finished_ = true;
  2294. return false;
  2295. }
  2296. // Pointer to current chunk data (valid after next() returns true)
  2297. const char *data() const { return buffer_.data(); }
  2298. // Size of current chunk (valid after next() returns true)
  2299. size_t size() const { return current_size_; }
  2300. // Convenience method: read all remaining data into a string
  2301. std::string read_all() {
  2302. std::string result;
  2303. while (next()) {
  2304. result.append(data(), size());
  2305. }
  2306. return result;
  2307. }
  2308. private:
  2309. ClientImpl::StreamHandle handle_;
  2310. std::string buffer_;
  2311. size_t current_size_ = 0;
  2312. size_t chunk_size_;
  2313. bool finished_ = false;
  2314. };
  2315. // GET
  2316. template <typename ClientType>
  2317. inline Result Get(ClientType &cli, const std::string &path,
  2318. size_t chunk_size = 8192) {
  2319. return Result{cli.open_stream("GET", path), chunk_size};
  2320. }
  2321. template <typename ClientType>
  2322. inline Result Get(ClientType &cli, const std::string &path,
  2323. const Headers &headers, size_t chunk_size = 8192) {
  2324. return Result{cli.open_stream("GET", path, {}, headers), chunk_size};
  2325. }
  2326. template <typename ClientType>
  2327. inline Result Get(ClientType &cli, const std::string &path,
  2328. const Params &params, size_t chunk_size = 8192) {
  2329. return Result{cli.open_stream("GET", path, params), chunk_size};
  2330. }
  2331. template <typename ClientType>
  2332. inline Result Get(ClientType &cli, const std::string &path,
  2333. const Params &params, const Headers &headers,
  2334. size_t chunk_size = 8192) {
  2335. return Result{cli.open_stream("GET", path, params, headers), chunk_size};
  2336. }
  2337. // POST
  2338. template <typename ClientType>
  2339. inline Result Post(ClientType &cli, const std::string &path,
  2340. const std::string &body, const std::string &content_type,
  2341. size_t chunk_size = 8192) {
  2342. return Result{cli.open_stream("POST", path, {}, {}, body, content_type),
  2343. chunk_size};
  2344. }
  2345. template <typename ClientType>
  2346. inline Result Post(ClientType &cli, const std::string &path,
  2347. const Headers &headers, const std::string &body,
  2348. const std::string &content_type, size_t chunk_size = 8192) {
  2349. return Result{cli.open_stream("POST", path, {}, headers, body, content_type),
  2350. chunk_size};
  2351. }
  2352. template <typename ClientType>
  2353. inline Result Post(ClientType &cli, const std::string &path,
  2354. const Params &params, const std::string &body,
  2355. const std::string &content_type, size_t chunk_size = 8192) {
  2356. return Result{cli.open_stream("POST", path, params, {}, body, content_type),
  2357. chunk_size};
  2358. }
  2359. template <typename ClientType>
  2360. inline Result Post(ClientType &cli, const std::string &path,
  2361. const Params &params, const Headers &headers,
  2362. const std::string &body, const std::string &content_type,
  2363. size_t chunk_size = 8192) {
  2364. return Result{
  2365. cli.open_stream("POST", path, params, headers, body, content_type),
  2366. chunk_size};
  2367. }
  2368. // PUT
  2369. template <typename ClientType>
  2370. inline Result Put(ClientType &cli, const std::string &path,
  2371. const std::string &body, const std::string &content_type,
  2372. size_t chunk_size = 8192) {
  2373. return Result{cli.open_stream("PUT", path, {}, {}, body, content_type),
  2374. chunk_size};
  2375. }
  2376. template <typename ClientType>
  2377. inline Result Put(ClientType &cli, const std::string &path,
  2378. const Headers &headers, const std::string &body,
  2379. const std::string &content_type, size_t chunk_size = 8192) {
  2380. return Result{cli.open_stream("PUT", path, {}, headers, body, content_type),
  2381. chunk_size};
  2382. }
  2383. template <typename ClientType>
  2384. inline Result Put(ClientType &cli, const std::string &path,
  2385. const Params &params, const std::string &body,
  2386. const std::string &content_type, size_t chunk_size = 8192) {
  2387. return Result{cli.open_stream("PUT", path, params, {}, body, content_type),
  2388. chunk_size};
  2389. }
  2390. template <typename ClientType>
  2391. inline Result Put(ClientType &cli, const std::string &path,
  2392. const Params &params, const Headers &headers,
  2393. const std::string &body, const std::string &content_type,
  2394. size_t chunk_size = 8192) {
  2395. return Result{
  2396. cli.open_stream("PUT", path, params, headers, body, content_type),
  2397. chunk_size};
  2398. }
  2399. // PATCH
  2400. template <typename ClientType>
  2401. inline Result Patch(ClientType &cli, const std::string &path,
  2402. const std::string &body, const std::string &content_type,
  2403. size_t chunk_size = 8192) {
  2404. return Result{cli.open_stream("PATCH", path, {}, {}, body, content_type),
  2405. chunk_size};
  2406. }
  2407. template <typename ClientType>
  2408. inline Result Patch(ClientType &cli, const std::string &path,
  2409. const Headers &headers, const std::string &body,
  2410. const std::string &content_type, size_t chunk_size = 8192) {
  2411. return Result{cli.open_stream("PATCH", path, {}, headers, body, content_type),
  2412. chunk_size};
  2413. }
  2414. template <typename ClientType>
  2415. inline Result Patch(ClientType &cli, const std::string &path,
  2416. const Params &params, const std::string &body,
  2417. const std::string &content_type, size_t chunk_size = 8192) {
  2418. return Result{cli.open_stream("PATCH", path, params, {}, body, content_type),
  2419. chunk_size};
  2420. }
  2421. template <typename ClientType>
  2422. inline Result Patch(ClientType &cli, const std::string &path,
  2423. const Params &params, const Headers &headers,
  2424. const std::string &body, const std::string &content_type,
  2425. size_t chunk_size = 8192) {
  2426. return Result{
  2427. cli.open_stream("PATCH", path, params, headers, body, content_type),
  2428. chunk_size};
  2429. }
  2430. // DELETE
  2431. template <typename ClientType>
  2432. inline Result Delete(ClientType &cli, const std::string &path,
  2433. size_t chunk_size = 8192) {
  2434. return Result{cli.open_stream("DELETE", path), chunk_size};
  2435. }
  2436. template <typename ClientType>
  2437. inline Result Delete(ClientType &cli, const std::string &path,
  2438. const Headers &headers, size_t chunk_size = 8192) {
  2439. return Result{cli.open_stream("DELETE", path, {}, headers), chunk_size};
  2440. }
  2441. template <typename ClientType>
  2442. inline Result Delete(ClientType &cli, const std::string &path,
  2443. const std::string &body, const std::string &content_type,
  2444. size_t chunk_size = 8192) {
  2445. return Result{cli.open_stream("DELETE", path, {}, {}, body, content_type),
  2446. chunk_size};
  2447. }
  2448. template <typename ClientType>
  2449. inline Result Delete(ClientType &cli, const std::string &path,
  2450. const Headers &headers, const std::string &body,
  2451. const std::string &content_type,
  2452. size_t chunk_size = 8192) {
  2453. return Result{
  2454. cli.open_stream("DELETE", path, {}, headers, body, content_type),
  2455. chunk_size};
  2456. }
  2457. template <typename ClientType>
  2458. inline Result Delete(ClientType &cli, const std::string &path,
  2459. const Params &params, size_t chunk_size = 8192) {
  2460. return Result{cli.open_stream("DELETE", path, params), chunk_size};
  2461. }
  2462. template <typename ClientType>
  2463. inline Result Delete(ClientType &cli, const std::string &path,
  2464. const Params &params, const Headers &headers,
  2465. size_t chunk_size = 8192) {
  2466. return Result{cli.open_stream("DELETE", path, params, headers), chunk_size};
  2467. }
  2468. template <typename ClientType>
  2469. inline Result Delete(ClientType &cli, const std::string &path,
  2470. const Params &params, const std::string &body,
  2471. const std::string &content_type,
  2472. size_t chunk_size = 8192) {
  2473. return Result{cli.open_stream("DELETE", path, params, {}, body, content_type),
  2474. chunk_size};
  2475. }
  2476. template <typename ClientType>
  2477. inline Result Delete(ClientType &cli, const std::string &path,
  2478. const Params &params, const Headers &headers,
  2479. const std::string &body, const std::string &content_type,
  2480. size_t chunk_size = 8192) {
  2481. return Result{
  2482. cli.open_stream("DELETE", path, params, headers, body, content_type),
  2483. chunk_size};
  2484. }
  2485. // HEAD
  2486. template <typename ClientType>
  2487. inline Result Head(ClientType &cli, const std::string &path,
  2488. size_t chunk_size = 8192) {
  2489. return Result{cli.open_stream("HEAD", path), chunk_size};
  2490. }
  2491. template <typename ClientType>
  2492. inline Result Head(ClientType &cli, const std::string &path,
  2493. const Headers &headers, size_t chunk_size = 8192) {
  2494. return Result{cli.open_stream("HEAD", path, {}, headers), chunk_size};
  2495. }
  2496. template <typename ClientType>
  2497. inline Result Head(ClientType &cli, const std::string &path,
  2498. const Params &params, size_t chunk_size = 8192) {
  2499. return Result{cli.open_stream("HEAD", path, params), chunk_size};
  2500. }
  2501. template <typename ClientType>
  2502. inline Result Head(ClientType &cli, const std::string &path,
  2503. const Params &params, const Headers &headers,
  2504. size_t chunk_size = 8192) {
  2505. return Result{cli.open_stream("HEAD", path, params, headers), chunk_size};
  2506. }
  2507. // OPTIONS
  2508. template <typename ClientType>
  2509. inline Result Options(ClientType &cli, const std::string &path,
  2510. size_t chunk_size = 8192) {
  2511. return Result{cli.open_stream("OPTIONS", path), chunk_size};
  2512. }
  2513. template <typename ClientType>
  2514. inline Result Options(ClientType &cli, const std::string &path,
  2515. const Headers &headers, size_t chunk_size = 8192) {
  2516. return Result{cli.open_stream("OPTIONS", path, {}, headers), chunk_size};
  2517. }
  2518. template <typename ClientType>
  2519. inline Result Options(ClientType &cli, const std::string &path,
  2520. const Params &params, size_t chunk_size = 8192) {
  2521. return Result{cli.open_stream("OPTIONS", path, params), chunk_size};
  2522. }
  2523. template <typename ClientType>
  2524. inline Result Options(ClientType &cli, const std::string &path,
  2525. const Params &params, const Headers &headers,
  2526. size_t chunk_size = 8192) {
  2527. return Result{cli.open_stream("OPTIONS", path, params, headers), chunk_size};
  2528. }
  2529. } // namespace stream
  2530. namespace sse {
  2531. struct SSEMessage {
  2532. std::string event; // Event type (default: "message")
  2533. std::string data; // Event payload
  2534. std::string id; // Event ID for Last-Event-ID header
  2535. SSEMessage() : event("message") {}
  2536. void clear() {
  2537. event = "message";
  2538. data.clear();
  2539. id.clear();
  2540. }
  2541. };
  2542. class SSEClient {
  2543. public:
  2544. using MessageHandler = std::function<void(const SSEMessage &)>;
  2545. using ErrorHandler = std::function<void(Error)>;
  2546. using OpenHandler = std::function<void()>;
  2547. SSEClient(Client &client, const std::string &path)
  2548. : client_(client), path_(path) {}
  2549. SSEClient(Client &client, const std::string &path, const Headers &headers)
  2550. : client_(client), path_(path), headers_(headers) {}
  2551. ~SSEClient() { stop(); }
  2552. SSEClient(const SSEClient &) = delete;
  2553. SSEClient &operator=(const SSEClient &) = delete;
  2554. // Event handlers
  2555. SSEClient &on_message(MessageHandler handler) {
  2556. on_message_ = std::move(handler);
  2557. return *this;
  2558. }
  2559. SSEClient &on_event(const std::string &type, MessageHandler handler) {
  2560. event_handlers_[type] = std::move(handler);
  2561. return *this;
  2562. }
  2563. SSEClient &on_open(OpenHandler handler) {
  2564. on_open_ = std::move(handler);
  2565. return *this;
  2566. }
  2567. SSEClient &on_error(ErrorHandler handler) {
  2568. on_error_ = std::move(handler);
  2569. return *this;
  2570. }
  2571. SSEClient &set_reconnect_interval(int ms) {
  2572. reconnect_interval_ms_ = ms;
  2573. return *this;
  2574. }
  2575. SSEClient &set_max_reconnect_attempts(int n) {
  2576. max_reconnect_attempts_ = n;
  2577. return *this;
  2578. }
  2579. // State accessors
  2580. bool is_connected() const { return connected_.load(); }
  2581. const std::string &last_event_id() const { return last_event_id_; }
  2582. // Blocking start - runs event loop with auto-reconnect
  2583. void start() {
  2584. running_.store(true);
  2585. run_event_loop();
  2586. }
  2587. // Non-blocking start - runs in background thread
  2588. void start_async() {
  2589. running_.store(true);
  2590. async_thread_ = std::thread([this]() { run_event_loop(); });
  2591. }
  2592. // Stop the client (thread-safe)
  2593. void stop() {
  2594. running_.store(false);
  2595. client_.stop(); // Cancel any pending operations
  2596. if (async_thread_.joinable()) { async_thread_.join(); }
  2597. }
  2598. private:
  2599. // Parse a single SSE field line
  2600. // Returns true if this line ends an event (blank line)
  2601. bool parse_sse_line(const std::string &line, SSEMessage &msg, int &retry_ms) {
  2602. // Blank line signals end of event
  2603. if (line.empty() || line == "\r") { return true; }
  2604. // Lines starting with ':' are comments (ignored)
  2605. if (!line.empty() && line[0] == ':') { return false; }
  2606. // Find the colon separator
  2607. auto colon_pos = line.find(':');
  2608. if (colon_pos == std::string::npos) {
  2609. // Line with no colon is treated as field name with empty value
  2610. return false;
  2611. }
  2612. auto field = line.substr(0, colon_pos);
  2613. std::string value;
  2614. // Value starts after colon, skip optional single space
  2615. if (colon_pos + 1 < line.size()) {
  2616. auto value_start = colon_pos + 1;
  2617. if (line[value_start] == ' ') { value_start++; }
  2618. value = line.substr(value_start);
  2619. // Remove trailing \r if present
  2620. if (!value.empty() && value.back() == '\r') { value.pop_back(); }
  2621. }
  2622. // Handle known fields
  2623. if (field == "event") {
  2624. msg.event = value;
  2625. } else if (field == "data") {
  2626. // Multiple data lines are concatenated with newlines
  2627. if (!msg.data.empty()) { msg.data += "\n"; }
  2628. msg.data += value;
  2629. } else if (field == "id") {
  2630. // Empty id is valid (clears the last event ID)
  2631. msg.id = value;
  2632. } else if (field == "retry") {
  2633. // Parse retry interval in milliseconds
  2634. try {
  2635. retry_ms = std::stoi(value);
  2636. } catch (...) {
  2637. // Invalid retry value, ignore
  2638. }
  2639. }
  2640. // Unknown fields are ignored per SSE spec
  2641. return false;
  2642. }
  2643. // Main event loop with auto-reconnect
  2644. void run_event_loop() {
  2645. auto reconnect_count = 0;
  2646. while (running_.load()) {
  2647. // Build headers, including Last-Event-ID if we have one
  2648. auto request_headers = headers_;
  2649. if (!last_event_id_.empty()) {
  2650. request_headers.emplace("Last-Event-ID", last_event_id_);
  2651. }
  2652. // Open streaming connection
  2653. auto result = stream::Get(client_, path_, request_headers);
  2654. // Connection error handling
  2655. if (!result) {
  2656. connected_.store(false);
  2657. if (on_error_) { on_error_(result.error()); }
  2658. if (!should_reconnect(reconnect_count)) { break; }
  2659. wait_for_reconnect();
  2660. reconnect_count++;
  2661. continue;
  2662. }
  2663. if (result.status() != 200) {
  2664. connected_.store(false);
  2665. // For certain errors, don't reconnect
  2666. if (result.status() == 204 || // No Content - server wants us to stop
  2667. result.status() == 404 || // Not Found
  2668. result.status() == 401 || // Unauthorized
  2669. result.status() == 403) { // Forbidden
  2670. if (on_error_) { on_error_(Error::Connection); }
  2671. break;
  2672. }
  2673. if (on_error_) { on_error_(Error::Connection); }
  2674. if (!should_reconnect(reconnect_count)) { break; }
  2675. wait_for_reconnect();
  2676. reconnect_count++;
  2677. continue;
  2678. }
  2679. // Connection successful
  2680. connected_.store(true);
  2681. reconnect_count = 0;
  2682. if (on_open_) { on_open_(); }
  2683. // Event receiving loop
  2684. std::string buffer;
  2685. SSEMessage current_msg;
  2686. while (running_.load() && result.next()) {
  2687. buffer.append(result.data(), result.size());
  2688. // Process complete lines in the buffer
  2689. size_t line_start = 0;
  2690. size_t newline_pos;
  2691. while ((newline_pos = buffer.find('\n', line_start)) !=
  2692. std::string::npos) {
  2693. auto line = buffer.substr(line_start, newline_pos - line_start);
  2694. line_start = newline_pos + 1;
  2695. // Parse the line and check if event is complete
  2696. auto event_complete =
  2697. parse_sse_line(line, current_msg, reconnect_interval_ms_);
  2698. if (event_complete && !current_msg.data.empty()) {
  2699. // Update last_event_id for reconnection
  2700. if (!current_msg.id.empty()) { last_event_id_ = current_msg.id; }
  2701. // Dispatch event to appropriate handler
  2702. dispatch_event(current_msg);
  2703. current_msg.clear();
  2704. }
  2705. }
  2706. // Keep unprocessed data in buffer
  2707. buffer.erase(0, line_start);
  2708. }
  2709. // Connection ended
  2710. connected_.store(false);
  2711. if (!running_.load()) { break; }
  2712. // Check for read errors
  2713. if (result.has_read_error()) {
  2714. if (on_error_) { on_error_(result.read_error()); }
  2715. }
  2716. if (!should_reconnect(reconnect_count)) { break; }
  2717. wait_for_reconnect();
  2718. reconnect_count++;
  2719. }
  2720. connected_.store(false);
  2721. }
  2722. // Dispatch event to appropriate handler
  2723. void dispatch_event(const SSEMessage &msg) {
  2724. // Check for specific event type handler first
  2725. auto it = event_handlers_.find(msg.event);
  2726. if (it != event_handlers_.end()) {
  2727. it->second(msg);
  2728. return;
  2729. }
  2730. // Fall back to generic message handler
  2731. if (on_message_) { on_message_(msg); }
  2732. }
  2733. // Check if we should attempt to reconnect
  2734. bool should_reconnect(int count) const {
  2735. if (!running_.load()) { return false; }
  2736. if (max_reconnect_attempts_ == 0) { return true; } // unlimited
  2737. return count < max_reconnect_attempts_;
  2738. }
  2739. // Wait for reconnect interval
  2740. void wait_for_reconnect() {
  2741. // Use small increments to check running_ flag frequently
  2742. auto waited = 0;
  2743. while (running_.load() && waited < reconnect_interval_ms_) {
  2744. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  2745. waited += 100;
  2746. }
  2747. }
  2748. // Client and path
  2749. Client &client_;
  2750. std::string path_;
  2751. Headers headers_;
  2752. // Callbacks
  2753. MessageHandler on_message_;
  2754. std::map<std::string, MessageHandler> event_handlers_;
  2755. OpenHandler on_open_;
  2756. ErrorHandler on_error_;
  2757. // Configuration
  2758. int reconnect_interval_ms_ = 3000;
  2759. int max_reconnect_attempts_ = 0; // 0 = unlimited
  2760. // State
  2761. std::atomic<bool> running_{false};
  2762. std::atomic<bool> connected_{false};
  2763. std::string last_event_id_;
  2764. // Async support
  2765. std::thread async_thread_;
  2766. };
  2767. } // namespace sse
  2768. } // namespace httplib
  2769. #endif // CPPHTTPLIB_HTTPLIB_H