httplib.cpp 250 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816
  1. #include "httplib.h"
  2. namespace httplib {
  3. /*
  4. * Implementation that will be part of the .cc file if split into .h + .cc.
  5. */
  6. namespace detail {
  7. bool is_hex(char c, int &v) {
  8. if (0x20 <= c && isdigit(c)) {
  9. v = c - '0';
  10. return true;
  11. } else if ('A' <= c && c <= 'F') {
  12. v = c - 'A' + 10;
  13. return true;
  14. } else if ('a' <= c && c <= 'f') {
  15. v = c - 'a' + 10;
  16. return true;
  17. }
  18. return false;
  19. }
  20. bool from_hex_to_i(const std::string &s, size_t i, size_t cnt,
  21. int &val) {
  22. if (i >= s.size()) { return false; }
  23. val = 0;
  24. for (; cnt; i++, cnt--) {
  25. if (!s[i]) { return false; }
  26. auto v = 0;
  27. if (is_hex(s[i], v)) {
  28. val = val * 16 + v;
  29. } else {
  30. return false;
  31. }
  32. }
  33. return true;
  34. }
  35. std::string from_i_to_hex(size_t n) {
  36. static const auto charset = "0123456789abcdef";
  37. std::string ret;
  38. do {
  39. ret = charset[n & 15] + ret;
  40. n >>= 4;
  41. } while (n > 0);
  42. return ret;
  43. }
  44. size_t to_utf8(int code, char *buff) {
  45. if (code < 0x0080) {
  46. buff[0] = static_cast<char>(code & 0x7F);
  47. return 1;
  48. } else if (code < 0x0800) {
  49. buff[0] = static_cast<char>(0xC0 | ((code >> 6) & 0x1F));
  50. buff[1] = static_cast<char>(0x80 | (code & 0x3F));
  51. return 2;
  52. } else if (code < 0xD800) {
  53. buff[0] = static_cast<char>(0xE0 | ((code >> 12) & 0xF));
  54. buff[1] = static_cast<char>(0x80 | ((code >> 6) & 0x3F));
  55. buff[2] = static_cast<char>(0x80 | (code & 0x3F));
  56. return 3;
  57. } else if (code < 0xE000) { // D800 - DFFF is invalid...
  58. return 0;
  59. } else if (code < 0x10000) {
  60. buff[0] = static_cast<char>(0xE0 | ((code >> 12) & 0xF));
  61. buff[1] = static_cast<char>(0x80 | ((code >> 6) & 0x3F));
  62. buff[2] = static_cast<char>(0x80 | (code & 0x3F));
  63. return 3;
  64. } else if (code < 0x110000) {
  65. buff[0] = static_cast<char>(0xF0 | ((code >> 18) & 0x7));
  66. buff[1] = static_cast<char>(0x80 | ((code >> 12) & 0x3F));
  67. buff[2] = static_cast<char>(0x80 | ((code >> 6) & 0x3F));
  68. buff[3] = static_cast<char>(0x80 | (code & 0x3F));
  69. return 4;
  70. }
  71. // NOTREACHED
  72. return 0;
  73. }
  74. // NOTE: This code came up with the following stackoverflow post:
  75. // https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c
  76. std::string base64_encode(const std::string &in) {
  77. static const auto lookup =
  78. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  79. std::string out;
  80. out.reserve(in.size());
  81. auto val = 0;
  82. auto valb = -6;
  83. for (auto c : in) {
  84. val = (val << 8) + static_cast<uint8_t>(c);
  85. valb += 8;
  86. while (valb >= 0) {
  87. out.push_back(lookup[(val >> valb) & 0x3F]);
  88. valb -= 6;
  89. }
  90. }
  91. if (valb > -6) { out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]); }
  92. while (out.size() % 4) {
  93. out.push_back('=');
  94. }
  95. return out;
  96. }
  97. bool is_valid_path(const std::string &path) {
  98. size_t level = 0;
  99. size_t i = 0;
  100. // Skip slash
  101. while (i < path.size() && path[i] == '/') {
  102. i++;
  103. }
  104. while (i < path.size()) {
  105. // Read component
  106. auto beg = i;
  107. while (i < path.size() && path[i] != '/') {
  108. if (path[i] == '\0') {
  109. return false;
  110. } else if (path[i] == '\\') {
  111. return false;
  112. }
  113. i++;
  114. }
  115. auto len = i - beg;
  116. assert(len > 0);
  117. if (!path.compare(beg, len, ".")) {
  118. ;
  119. } else if (!path.compare(beg, len, "..")) {
  120. if (level == 0) { return false; }
  121. level--;
  122. } else {
  123. level++;
  124. }
  125. // Skip slash
  126. while (i < path.size() && path[i] == '/') {
  127. i++;
  128. }
  129. }
  130. return true;
  131. }
  132. FileStat::FileStat(const std::string &path) {
  133. #if defined(_WIN32)
  134. auto wpath = u8string_to_wstring(path.c_str());
  135. ret_ = _wstat(wpath.c_str(), &st_);
  136. #else
  137. ret_ = stat(path.c_str(), &st_);
  138. #endif
  139. }
  140. bool FileStat::is_file() const {
  141. return ret_ >= 0 && S_ISREG(st_.st_mode);
  142. }
  143. bool FileStat::is_dir() const {
  144. return ret_ >= 0 && S_ISDIR(st_.st_mode);
  145. }
  146. std::string encode_query_param(const std::string &value) {
  147. std::ostringstream escaped;
  148. escaped.fill('0');
  149. escaped << std::hex;
  150. for (auto c : value) {
  151. if (std::isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' ||
  152. c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' ||
  153. c == ')') {
  154. escaped << c;
  155. } else {
  156. escaped << std::uppercase;
  157. escaped << '%' << std::setw(2)
  158. << static_cast<int>(static_cast<unsigned char>(c));
  159. escaped << std::nouppercase;
  160. }
  161. }
  162. return escaped.str();
  163. }
  164. std::string encode_url(const std::string &s) {
  165. std::string result;
  166. result.reserve(s.size());
  167. for (size_t i = 0; s[i]; i++) {
  168. switch (s[i]) {
  169. case ' ': result += "%20"; break;
  170. case '+': result += "%2B"; break;
  171. case '\r': result += "%0D"; break;
  172. case '\n': result += "%0A"; break;
  173. case '\'': result += "%27"; break;
  174. case ',': result += "%2C"; break;
  175. // case ':': result += "%3A"; break; // ok? probably...
  176. case ';': result += "%3B"; break;
  177. default:
  178. auto c = static_cast<uint8_t>(s[i]);
  179. if (c >= 0x80) {
  180. result += '%';
  181. char hex[4];
  182. auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c);
  183. assert(len == 2);
  184. result.append(hex, static_cast<size_t>(len));
  185. } else {
  186. result += s[i];
  187. }
  188. break;
  189. }
  190. }
  191. return result;
  192. }
  193. std::string decode_url(const std::string &s,
  194. bool convert_plus_to_space) {
  195. std::string result;
  196. for (size_t i = 0; i < s.size(); i++) {
  197. if (s[i] == '%' && i + 1 < s.size()) {
  198. if (s[i + 1] == 'u') {
  199. auto val = 0;
  200. if (from_hex_to_i(s, i + 2, 4, val)) {
  201. // 4 digits Unicode codes
  202. char buff[4];
  203. size_t len = to_utf8(val, buff);
  204. if (len > 0) { result.append(buff, len); }
  205. i += 5; // 'u0000'
  206. } else {
  207. result += s[i];
  208. }
  209. } else {
  210. auto val = 0;
  211. if (from_hex_to_i(s, i + 1, 2, val)) {
  212. // 2 digits hex codes
  213. result += static_cast<char>(val);
  214. i += 2; // '00'
  215. } else {
  216. result += s[i];
  217. }
  218. }
  219. } else if (convert_plus_to_space && s[i] == '+') {
  220. result += ' ';
  221. } else {
  222. result += s[i];
  223. }
  224. }
  225. return result;
  226. }
  227. std::string file_extension(const std::string &path) {
  228. std::smatch m;
  229. thread_local auto re = std::regex("\\.([a-zA-Z0-9]+)$");
  230. if (std::regex_search(path, m, re)) { return m[1].str(); }
  231. return std::string();
  232. }
  233. bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; }
  234. std::pair<size_t, size_t> trim(const char *b, const char *e, size_t left,
  235. size_t right) {
  236. while (b + left < e && is_space_or_tab(b[left])) {
  237. left++;
  238. }
  239. while (right > 0 && is_space_or_tab(b[right - 1])) {
  240. right--;
  241. }
  242. return std::make_pair(left, right);
  243. }
  244. std::string trim_copy(const std::string &s) {
  245. auto r = trim(s.data(), s.data() + s.size(), 0, s.size());
  246. return s.substr(r.first, r.second - r.first);
  247. }
  248. std::string trim_double_quotes_copy(const std::string &s) {
  249. if (s.length() >= 2 && s.front() == '"' && s.back() == '"') {
  250. return s.substr(1, s.size() - 2);
  251. }
  252. return s;
  253. }
  254. void
  255. divide(const char *data, std::size_t size, char d,
  256. std::function<void(const char *, std::size_t, const char *, std::size_t)>
  257. fn) {
  258. const auto it = std::find(data, data + size, d);
  259. const auto found = static_cast<std::size_t>(it != data + size);
  260. const auto lhs_data = data;
  261. const auto lhs_size = static_cast<std::size_t>(it - data);
  262. const auto rhs_data = it + found;
  263. const auto rhs_size = size - lhs_size - found;
  264. fn(lhs_data, lhs_size, rhs_data, rhs_size);
  265. }
  266. void
  267. divide(const std::string &str, char d,
  268. std::function<void(const char *, std::size_t, const char *, std::size_t)>
  269. fn) {
  270. divide(str.data(), str.size(), d, std::move(fn));
  271. }
  272. void split(const char *b, const char *e, char d,
  273. std::function<void(const char *, const char *)> fn) {
  274. return split(b, e, d, (std::numeric_limits<size_t>::max)(), std::move(fn));
  275. }
  276. void split(const char *b, const char *e, char d, size_t m,
  277. std::function<void(const char *, const char *)> fn) {
  278. size_t i = 0;
  279. size_t beg = 0;
  280. size_t count = 1;
  281. while (e ? (b + i < e) : (b[i] != '\0')) {
  282. if (b[i] == d && count < m) {
  283. auto r = trim(b, e, beg, i);
  284. if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  285. beg = i + 1;
  286. count++;
  287. }
  288. i++;
  289. }
  290. if (i) {
  291. auto r = trim(b, e, beg, i);
  292. if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  293. }
  294. }
  295. stream_line_reader::stream_line_reader(Stream &strm, char *fixed_buffer,
  296. size_t fixed_buffer_size)
  297. : strm_(strm), fixed_buffer_(fixed_buffer),
  298. fixed_buffer_size_(fixed_buffer_size) {}
  299. const char *stream_line_reader::ptr() const {
  300. if (growable_buffer_.empty()) {
  301. return fixed_buffer_;
  302. } else {
  303. return growable_buffer_.data();
  304. }
  305. }
  306. size_t stream_line_reader::size() const {
  307. if (growable_buffer_.empty()) {
  308. return fixed_buffer_used_size_;
  309. } else {
  310. return growable_buffer_.size();
  311. }
  312. }
  313. bool stream_line_reader::end_with_crlf() const {
  314. auto end = ptr() + size();
  315. return size() >= 2 && end[-2] == '\r' && end[-1] == '\n';
  316. }
  317. bool stream_line_reader::getline() {
  318. fixed_buffer_used_size_ = 0;
  319. growable_buffer_.clear();
  320. #ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
  321. char prev_byte = 0;
  322. #endif
  323. for (size_t i = 0;; i++) {
  324. if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
  325. // Treat exceptionally long lines as an error to
  326. // prevent infinite loops/memory exhaustion
  327. return false;
  328. }
  329. char byte;
  330. auto n = strm_.read(&byte, 1);
  331. if (n < 0) {
  332. return false;
  333. } else if (n == 0) {
  334. if (i == 0) {
  335. return false;
  336. } else {
  337. break;
  338. }
  339. }
  340. append(byte);
  341. #ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
  342. if (byte == '\n') { break; }
  343. #else
  344. if (prev_byte == '\r' && byte == '\n') { break; }
  345. prev_byte = byte;
  346. #endif
  347. }
  348. return true;
  349. }
  350. void stream_line_reader::append(char c) {
  351. if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) {
  352. fixed_buffer_[fixed_buffer_used_size_++] = c;
  353. fixed_buffer_[fixed_buffer_used_size_] = '\0';
  354. } else {
  355. if (growable_buffer_.empty()) {
  356. assert(fixed_buffer_[fixed_buffer_used_size_] == '\0');
  357. growable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
  358. }
  359. growable_buffer_ += c;
  360. }
  361. }
  362. mmap::mmap(const char *path) { open(path); }
  363. mmap::~mmap() { close(); }
  364. bool mmap::open(const char *path) {
  365. close();
  366. #if defined(_WIN32)
  367. auto wpath = u8string_to_wstring(path);
  368. if (wpath.empty()) { return false; }
  369. #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
  370. hFile_ = ::CreateFile2(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
  371. OPEN_EXISTING, NULL);
  372. #else
  373. hFile_ = ::CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
  374. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  375. #endif
  376. if (hFile_ == INVALID_HANDLE_VALUE) { return false; }
  377. LARGE_INTEGER size{};
  378. if (!::GetFileSizeEx(hFile_, &size)) { return false; }
  379. // If the following line doesn't compile due to QuadPart, update Windows SDK.
  380. // See:
  381. // https://github.com/yhirose/cpp-httplib/issues/1903#issuecomment-2316520721
  382. if (static_cast<ULONGLONG>(size.QuadPart) >
  383. (std::numeric_limits<decltype(size_)>::max)()) {
  384. // `size_t` might be 32-bits, on 32-bits Windows.
  385. return false;
  386. }
  387. size_ = static_cast<size_t>(size.QuadPart);
  388. #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
  389. hMapping_ =
  390. ::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL);
  391. #else
  392. hMapping_ = ::CreateFileMappingW(hFile_, NULL, PAGE_READONLY, 0, 0, NULL);
  393. #endif
  394. // Special treatment for an empty file...
  395. if (hMapping_ == NULL && size_ == 0) {
  396. close();
  397. is_open_empty_file = true;
  398. return true;
  399. }
  400. if (hMapping_ == NULL) {
  401. close();
  402. return false;
  403. }
  404. #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
  405. addr_ = ::MapViewOfFileFromApp(hMapping_, FILE_MAP_READ, 0, 0);
  406. #else
  407. addr_ = ::MapViewOfFile(hMapping_, FILE_MAP_READ, 0, 0, 0);
  408. #endif
  409. if (addr_ == nullptr) {
  410. close();
  411. return false;
  412. }
  413. #else
  414. fd_ = ::open(path, O_RDONLY);
  415. if (fd_ == -1) { return false; }
  416. struct stat sb;
  417. if (fstat(fd_, &sb) == -1) {
  418. close();
  419. return false;
  420. }
  421. size_ = static_cast<size_t>(sb.st_size);
  422. addr_ = ::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
  423. // Special treatment for an empty file...
  424. if (addr_ == MAP_FAILED && size_ == 0) {
  425. close();
  426. is_open_empty_file = true;
  427. return false;
  428. }
  429. #endif
  430. return true;
  431. }
  432. bool mmap::is_open() const {
  433. return is_open_empty_file ? true : addr_ != nullptr;
  434. }
  435. size_t mmap::size() const { return size_; }
  436. const char *mmap::data() const {
  437. return is_open_empty_file ? "" : static_cast<const char *>(addr_);
  438. }
  439. void mmap::close() {
  440. #if defined(_WIN32)
  441. if (addr_) {
  442. ::UnmapViewOfFile(addr_);
  443. addr_ = nullptr;
  444. }
  445. if (hMapping_) {
  446. ::CloseHandle(hMapping_);
  447. hMapping_ = NULL;
  448. }
  449. if (hFile_ != INVALID_HANDLE_VALUE) {
  450. ::CloseHandle(hFile_);
  451. hFile_ = INVALID_HANDLE_VALUE;
  452. }
  453. is_open_empty_file = false;
  454. #else
  455. if (addr_ != nullptr) {
  456. munmap(addr_, size_);
  457. addr_ = nullptr;
  458. }
  459. if (fd_ != -1) {
  460. ::close(fd_);
  461. fd_ = -1;
  462. }
  463. #endif
  464. size_ = 0;
  465. }
  466. int close_socket(socket_t sock) {
  467. #ifdef _WIN32
  468. return closesocket(sock);
  469. #else
  470. return close(sock);
  471. #endif
  472. }
  473. template <typename T> inline ssize_t handle_EINTR(T fn) {
  474. ssize_t res = 0;
  475. while (true) {
  476. res = fn();
  477. if (res < 0 && errno == EINTR) {
  478. std::this_thread::sleep_for(std::chrono::microseconds{1});
  479. continue;
  480. }
  481. break;
  482. }
  483. return res;
  484. }
  485. ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags) {
  486. return handle_EINTR([&]() {
  487. return recv(sock,
  488. #ifdef _WIN32
  489. static_cast<char *>(ptr), static_cast<int>(size),
  490. #else
  491. ptr, size,
  492. #endif
  493. flags);
  494. });
  495. }
  496. ssize_t send_socket(socket_t sock, const void *ptr, size_t size,
  497. int flags) {
  498. return handle_EINTR([&]() {
  499. return send(sock,
  500. #ifdef _WIN32
  501. static_cast<const char *>(ptr), static_cast<int>(size),
  502. #else
  503. ptr, size,
  504. #endif
  505. flags);
  506. });
  507. }
  508. int poll_wrapper(struct pollfd *fds, nfds_t nfds, int timeout) {
  509. #ifdef _WIN32
  510. return ::WSAPoll(fds, nfds, timeout);
  511. #else
  512. return ::poll(fds, nfds, timeout);
  513. #endif
  514. }
  515. template <bool Read>
  516. ssize_t select_impl(socket_t sock, time_t sec, time_t usec) {
  517. struct pollfd pfd;
  518. pfd.fd = sock;
  519. pfd.events = (Read ? POLLIN : POLLOUT);
  520. auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
  521. return handle_EINTR([&]() { return poll_wrapper(&pfd, 1, timeout); });
  522. }
  523. ssize_t select_read(socket_t sock, time_t sec, time_t usec) {
  524. return select_impl<true>(sock, sec, usec);
  525. }
  526. ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
  527. return select_impl<false>(sock, sec, usec);
  528. }
  529. Error wait_until_socket_is_ready(socket_t sock, time_t sec,
  530. time_t usec) {
  531. struct pollfd pfd_read;
  532. pfd_read.fd = sock;
  533. pfd_read.events = POLLIN | POLLOUT;
  534. auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
  535. auto poll_res =
  536. handle_EINTR([&]() { return poll_wrapper(&pfd_read, 1, timeout); });
  537. if (poll_res == 0) { return Error::ConnectionTimeout; }
  538. if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) {
  539. auto error = 0;
  540. socklen_t len = sizeof(error);
  541. auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR,
  542. reinterpret_cast<char *>(&error), &len);
  543. auto successful = res >= 0 && !error;
  544. return successful ? Error::Success : Error::Connection;
  545. }
  546. return Error::Connection;
  547. }
  548. bool is_socket_alive(socket_t sock) {
  549. const auto val = detail::select_read(sock, 0, 0);
  550. if (val == 0) {
  551. return true;
  552. } else if (val < 0 && errno == EBADF) {
  553. return false;
  554. }
  555. char buf[1];
  556. return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0;
  557. }
  558. class SocketStream final : public Stream {
  559. public:
  560. SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
  561. time_t write_timeout_sec, time_t write_timeout_usec,
  562. time_t max_timeout_msec = 0,
  563. std::chrono::time_point<std::chrono::steady_clock> start_time =
  564. (std::chrono::steady_clock::time_point::min)());
  565. ~SocketStream() override;
  566. bool is_readable() const override;
  567. bool wait_readable() const override;
  568. bool wait_writable() const override;
  569. ssize_t read(char *ptr, size_t size) override;
  570. ssize_t write(const char *ptr, size_t size) override;
  571. void get_remote_ip_and_port(std::string &ip, int &port) const override;
  572. void get_local_ip_and_port(std::string &ip, int &port) const override;
  573. socket_t socket() const override;
  574. time_t duration() const override;
  575. private:
  576. socket_t sock_;
  577. time_t read_timeout_sec_;
  578. time_t read_timeout_usec_;
  579. time_t write_timeout_sec_;
  580. time_t write_timeout_usec_;
  581. time_t max_timeout_msec_;
  582. const std::chrono::time_point<std::chrono::steady_clock> start_time_;
  583. std::vector<char> read_buff_;
  584. size_t read_buff_off_ = 0;
  585. size_t read_buff_content_size_ = 0;
  586. static const size_t read_buff_size_ = 1024l * 4;
  587. };
  588. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  589. class SSLSocketStream final : public Stream {
  590. public:
  591. SSLSocketStream(
  592. socket_t sock, SSL *ssl, time_t read_timeout_sec,
  593. time_t read_timeout_usec, time_t write_timeout_sec,
  594. time_t write_timeout_usec, time_t max_timeout_msec = 0,
  595. std::chrono::time_point<std::chrono::steady_clock> start_time =
  596. (std::chrono::steady_clock::time_point::min)());
  597. ~SSLSocketStream() override;
  598. bool is_readable() const override;
  599. bool wait_readable() const override;
  600. bool wait_writable() const override;
  601. ssize_t read(char *ptr, size_t size) override;
  602. ssize_t write(const char *ptr, size_t size) override;
  603. void get_remote_ip_and_port(std::string &ip, int &port) const override;
  604. void get_local_ip_and_port(std::string &ip, int &port) const override;
  605. socket_t socket() const override;
  606. time_t duration() const override;
  607. private:
  608. socket_t sock_;
  609. SSL *ssl_;
  610. time_t read_timeout_sec_;
  611. time_t read_timeout_usec_;
  612. time_t write_timeout_sec_;
  613. time_t write_timeout_usec_;
  614. time_t max_timeout_msec_;
  615. const std::chrono::time_point<std::chrono::steady_clock> start_time_;
  616. };
  617. #endif
  618. bool keep_alive(const std::atomic<socket_t> &svr_sock, socket_t sock,
  619. time_t keep_alive_timeout_sec) {
  620. using namespace std::chrono;
  621. const auto interval_usec =
  622. CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND;
  623. // Avoid expensive `steady_clock::now()` call for the first time
  624. if (select_read(sock, 0, interval_usec) > 0) { return true; }
  625. const auto start = steady_clock::now() - microseconds{interval_usec};
  626. const auto timeout = seconds{keep_alive_timeout_sec};
  627. while (true) {
  628. if (svr_sock == INVALID_SOCKET) {
  629. break; // Server socket is closed
  630. }
  631. auto val = select_read(sock, 0, interval_usec);
  632. if (val < 0) {
  633. break; // Ssocket error
  634. } else if (val == 0) {
  635. if (steady_clock::now() - start > timeout) {
  636. break; // Timeout
  637. }
  638. } else {
  639. return true; // Ready for read
  640. }
  641. }
  642. return false;
  643. }
  644. template <typename T>
  645. bool
  646. process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
  647. size_t keep_alive_max_count,
  648. time_t keep_alive_timeout_sec, T callback) {
  649. assert(keep_alive_max_count > 0);
  650. auto ret = false;
  651. auto count = keep_alive_max_count;
  652. while (count > 0 && keep_alive(svr_sock, sock, keep_alive_timeout_sec)) {
  653. auto close_connection = count == 1;
  654. auto connection_closed = false;
  655. ret = callback(close_connection, connection_closed);
  656. if (!ret || connection_closed) { break; }
  657. count--;
  658. }
  659. return ret;
  660. }
  661. template <typename T>
  662. bool
  663. process_server_socket(const std::atomic<socket_t> &svr_sock, socket_t sock,
  664. size_t keep_alive_max_count,
  665. time_t keep_alive_timeout_sec, time_t read_timeout_sec,
  666. time_t read_timeout_usec, time_t write_timeout_sec,
  667. time_t write_timeout_usec, T callback) {
  668. return process_server_socket_core(
  669. svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
  670. [&](bool close_connection, bool &connection_closed) {
  671. SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
  672. write_timeout_sec, write_timeout_usec);
  673. return callback(strm, close_connection, connection_closed);
  674. });
  675. }
  676. bool process_client_socket(
  677. socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
  678. time_t write_timeout_sec, time_t write_timeout_usec,
  679. time_t max_timeout_msec,
  680. std::chrono::time_point<std::chrono::steady_clock> start_time,
  681. std::function<bool(Stream &)> callback) {
  682. SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
  683. write_timeout_sec, write_timeout_usec, max_timeout_msec,
  684. start_time);
  685. return callback(strm);
  686. }
  687. int shutdown_socket(socket_t sock) {
  688. #ifdef _WIN32
  689. return shutdown(sock, SD_BOTH);
  690. #else
  691. return shutdown(sock, SHUT_RDWR);
  692. #endif
  693. }
  694. std::string escape_abstract_namespace_unix_domain(const std::string &s) {
  695. if (s.size() > 1 && s[0] == '\0') {
  696. auto ret = s;
  697. ret[0] = '@';
  698. return ret;
  699. }
  700. return s;
  701. }
  702. std::string
  703. unescape_abstract_namespace_unix_domain(const std::string &s) {
  704. if (s.size() > 1 && s[0] == '@') {
  705. auto ret = s;
  706. ret[0] = '\0';
  707. return ret;
  708. }
  709. return s;
  710. }
  711. template <typename BindOrConnect>
  712. socket_t create_socket(const std::string &host, const std::string &ip, int port,
  713. int address_family, int socket_flags, bool tcp_nodelay,
  714. bool ipv6_v6only, SocketOptions socket_options,
  715. BindOrConnect bind_or_connect) {
  716. // Get address info
  717. const char *node = nullptr;
  718. struct addrinfo hints;
  719. struct addrinfo *result;
  720. memset(&hints, 0, sizeof(struct addrinfo));
  721. hints.ai_socktype = SOCK_STREAM;
  722. hints.ai_protocol = IPPROTO_IP;
  723. if (!ip.empty()) {
  724. node = ip.c_str();
  725. // Ask getaddrinfo to convert IP in c-string to address
  726. hints.ai_family = AF_UNSPEC;
  727. hints.ai_flags = AI_NUMERICHOST;
  728. } else {
  729. if (!host.empty()) { node = host.c_str(); }
  730. hints.ai_family = address_family;
  731. hints.ai_flags = socket_flags;
  732. }
  733. if (hints.ai_family == AF_UNIX) {
  734. const auto addrlen = host.length();
  735. if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; }
  736. #ifdef SOCK_CLOEXEC
  737. auto sock = socket(hints.ai_family, hints.ai_socktype | SOCK_CLOEXEC,
  738. hints.ai_protocol);
  739. #else
  740. auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
  741. #endif
  742. if (sock != INVALID_SOCKET) {
  743. sockaddr_un addr{};
  744. addr.sun_family = AF_UNIX;
  745. auto unescaped_host = unescape_abstract_namespace_unix_domain(host);
  746. std::copy(unescaped_host.begin(), unescaped_host.end(), addr.sun_path);
  747. hints.ai_addr = reinterpret_cast<sockaddr *>(&addr);
  748. hints.ai_addrlen = static_cast<socklen_t>(
  749. sizeof(addr) - sizeof(addr.sun_path) + addrlen);
  750. #ifndef SOCK_CLOEXEC
  751. #ifndef _WIN32
  752. fcntl(sock, F_SETFD, FD_CLOEXEC);
  753. #endif
  754. #endif
  755. if (socket_options) { socket_options(sock); }
  756. #ifdef _WIN32
  757. // Setting SO_REUSEADDR seems not to work well with AF_UNIX on windows, so
  758. // remove the option.
  759. detail::set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 0);
  760. #endif
  761. bool dummy;
  762. if (!bind_or_connect(sock, hints, dummy)) {
  763. close_socket(sock);
  764. sock = INVALID_SOCKET;
  765. }
  766. }
  767. return sock;
  768. }
  769. auto service = std::to_string(port);
  770. if (getaddrinfo(node, service.c_str(), &hints, &result)) {
  771. #if defined __linux__ && !defined __ANDROID__
  772. res_init();
  773. #endif
  774. return INVALID_SOCKET;
  775. }
  776. auto se = detail::scope_exit([&] { freeaddrinfo(result); });
  777. for (auto rp = result; rp; rp = rp->ai_next) {
  778. // Create a socket
  779. #ifdef _WIN32
  780. auto sock =
  781. WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, nullptr, 0,
  782. WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
  783. /**
  784. * Since the WSA_FLAG_NO_HANDLE_INHERIT is only supported on Windows 7 SP1
  785. * and above the socket creation fails on older Windows Systems.
  786. *
  787. * Let's try to create a socket the old way in this case.
  788. *
  789. * Reference:
  790. * https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa
  791. *
  792. * WSA_FLAG_NO_HANDLE_INHERIT:
  793. * This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with
  794. * SP1, and later
  795. *
  796. */
  797. if (sock == INVALID_SOCKET) {
  798. sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  799. }
  800. #else
  801. #ifdef SOCK_CLOEXEC
  802. auto sock =
  803. socket(rp->ai_family, rp->ai_socktype | SOCK_CLOEXEC, rp->ai_protocol);
  804. #else
  805. auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  806. #endif
  807. #endif
  808. if (sock == INVALID_SOCKET) { continue; }
  809. #if !defined _WIN32 && !defined SOCK_CLOEXEC
  810. if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
  811. close_socket(sock);
  812. continue;
  813. }
  814. #endif
  815. if (tcp_nodelay) { set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); }
  816. if (rp->ai_family == AF_INET6) {
  817. set_socket_opt(sock, IPPROTO_IPV6, IPV6_V6ONLY, ipv6_v6only ? 1 : 0);
  818. }
  819. if (socket_options) { socket_options(sock); }
  820. // bind or connect
  821. auto quit = false;
  822. if (bind_or_connect(sock, *rp, quit)) { return sock; }
  823. close_socket(sock);
  824. if (quit) { break; }
  825. }
  826. return INVALID_SOCKET;
  827. }
  828. void set_nonblocking(socket_t sock, bool nonblocking) {
  829. #ifdef _WIN32
  830. auto flags = nonblocking ? 1UL : 0UL;
  831. ioctlsocket(sock, FIONBIO, &flags);
  832. #else
  833. auto flags = fcntl(sock, F_GETFL, 0);
  834. fcntl(sock, F_SETFL,
  835. nonblocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK)));
  836. #endif
  837. }
  838. bool is_connection_error() {
  839. #ifdef _WIN32
  840. return WSAGetLastError() != WSAEWOULDBLOCK;
  841. #else
  842. return errno != EINPROGRESS;
  843. #endif
  844. }
  845. bool bind_ip_address(socket_t sock, const std::string &host) {
  846. struct addrinfo hints;
  847. struct addrinfo *result;
  848. memset(&hints, 0, sizeof(struct addrinfo));
  849. hints.ai_family = AF_UNSPEC;
  850. hints.ai_socktype = SOCK_STREAM;
  851. hints.ai_protocol = 0;
  852. if (getaddrinfo(host.c_str(), "0", &hints, &result)) { return false; }
  853. auto se = detail::scope_exit([&] { freeaddrinfo(result); });
  854. auto ret = false;
  855. for (auto rp = result; rp; rp = rp->ai_next) {
  856. const auto &ai = *rp;
  857. if (!::bind(sock, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen))) {
  858. ret = true;
  859. break;
  860. }
  861. }
  862. return ret;
  863. }
  864. #if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__
  865. #define USE_IF2IP
  866. #endif
  867. #ifdef USE_IF2IP
  868. std::string if2ip(int address_family, const std::string &ifn) {
  869. struct ifaddrs *ifap;
  870. getifaddrs(&ifap);
  871. auto se = detail::scope_exit([&] { freeifaddrs(ifap); });
  872. std::string addr_candidate;
  873. for (auto ifa = ifap; ifa; ifa = ifa->ifa_next) {
  874. if (ifa->ifa_addr && ifn == ifa->ifa_name &&
  875. (AF_UNSPEC == address_family ||
  876. ifa->ifa_addr->sa_family == address_family)) {
  877. if (ifa->ifa_addr->sa_family == AF_INET) {
  878. auto sa = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr);
  879. char buf[INET_ADDRSTRLEN];
  880. if (inet_ntop(AF_INET, &sa->sin_addr, buf, INET_ADDRSTRLEN)) {
  881. return std::string(buf, INET_ADDRSTRLEN);
  882. }
  883. } else if (ifa->ifa_addr->sa_family == AF_INET6) {
  884. auto sa = reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_addr);
  885. if (!IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) {
  886. char buf[INET6_ADDRSTRLEN] = {};
  887. if (inet_ntop(AF_INET6, &sa->sin6_addr, buf, INET6_ADDRSTRLEN)) {
  888. // equivalent to mac's IN6_IS_ADDR_UNIQUE_LOCAL
  889. auto s6_addr_head = sa->sin6_addr.s6_addr[0];
  890. if (s6_addr_head == 0xfc || s6_addr_head == 0xfd) {
  891. addr_candidate = std::string(buf, INET6_ADDRSTRLEN);
  892. } else {
  893. return std::string(buf, INET6_ADDRSTRLEN);
  894. }
  895. }
  896. }
  897. }
  898. }
  899. }
  900. return addr_candidate;
  901. }
  902. #endif
  903. socket_t create_client_socket(
  904. const std::string &host, const std::string &ip, int port,
  905. int address_family, bool tcp_nodelay, bool ipv6_v6only,
  906. SocketOptions socket_options, time_t connection_timeout_sec,
  907. time_t connection_timeout_usec, time_t read_timeout_sec,
  908. time_t read_timeout_usec, time_t write_timeout_sec,
  909. time_t write_timeout_usec, const std::string &intf, Error &error) {
  910. auto sock = create_socket(
  911. host, ip, port, address_family, 0, tcp_nodelay, ipv6_v6only,
  912. std::move(socket_options),
  913. [&](socket_t sock2, struct addrinfo &ai, bool &quit) -> bool {
  914. if (!intf.empty()) {
  915. #ifdef USE_IF2IP
  916. auto ip_from_if = if2ip(address_family, intf);
  917. if (ip_from_if.empty()) { ip_from_if = intf; }
  918. if (!bind_ip_address(sock2, ip_from_if)) {
  919. error = Error::BindIPAddress;
  920. return false;
  921. }
  922. #endif
  923. }
  924. set_nonblocking(sock2, true);
  925. auto ret =
  926. ::connect(sock2, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen));
  927. if (ret < 0) {
  928. if (is_connection_error()) {
  929. error = Error::Connection;
  930. return false;
  931. }
  932. error = wait_until_socket_is_ready(sock2, connection_timeout_sec,
  933. connection_timeout_usec);
  934. if (error != Error::Success) {
  935. if (error == Error::ConnectionTimeout) { quit = true; }
  936. return false;
  937. }
  938. }
  939. set_nonblocking(sock2, false);
  940. set_socket_opt_time(sock2, SOL_SOCKET, SO_RCVTIMEO, read_timeout_sec,
  941. read_timeout_usec);
  942. set_socket_opt_time(sock2, SOL_SOCKET, SO_SNDTIMEO, write_timeout_sec,
  943. write_timeout_usec);
  944. error = Error::Success;
  945. return true;
  946. });
  947. if (sock != INVALID_SOCKET) {
  948. error = Error::Success;
  949. } else {
  950. if (error == Error::Success) { error = Error::Connection; }
  951. }
  952. return sock;
  953. }
  954. bool get_ip_and_port(const struct sockaddr_storage &addr,
  955. socklen_t addr_len, std::string &ip, int &port) {
  956. if (addr.ss_family == AF_INET) {
  957. port = ntohs(reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_port);
  958. } else if (addr.ss_family == AF_INET6) {
  959. port =
  960. ntohs(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_port);
  961. } else {
  962. return false;
  963. }
  964. std::array<char, NI_MAXHOST> ipstr{};
  965. if (getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
  966. ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
  967. 0, NI_NUMERICHOST)) {
  968. return false;
  969. }
  970. ip = ipstr.data();
  971. return true;
  972. }
  973. void get_local_ip_and_port(socket_t sock, std::string &ip, int &port) {
  974. struct sockaddr_storage addr;
  975. socklen_t addr_len = sizeof(addr);
  976. if (!getsockname(sock, reinterpret_cast<struct sockaddr *>(&addr),
  977. &addr_len)) {
  978. get_ip_and_port(addr, addr_len, ip, port);
  979. }
  980. }
  981. void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
  982. struct sockaddr_storage addr;
  983. socklen_t addr_len = sizeof(addr);
  984. if (!getpeername(sock, reinterpret_cast<struct sockaddr *>(&addr),
  985. &addr_len)) {
  986. #ifndef _WIN32
  987. if (addr.ss_family == AF_UNIX) {
  988. #if defined(__linux__)
  989. struct ucred ucred;
  990. socklen_t len = sizeof(ucred);
  991. if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) {
  992. port = ucred.pid;
  993. }
  994. #elif defined(SOL_LOCAL) && defined(SO_PEERPID) // __APPLE__
  995. pid_t pid;
  996. socklen_t len = sizeof(pid);
  997. if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) {
  998. port = pid;
  999. }
  1000. #endif
  1001. return;
  1002. }
  1003. #endif
  1004. get_ip_and_port(addr, addr_len, ip, port);
  1005. }
  1006. }
  1007. constexpr unsigned int str2tag_core(const char *s, size_t l,
  1008. unsigned int h) {
  1009. return (l == 0)
  1010. ? h
  1011. : str2tag_core(
  1012. s + 1, l - 1,
  1013. // Unsets the 6 high bits of h, therefore no overflow happens
  1014. (((std::numeric_limits<unsigned int>::max)() >> 6) &
  1015. h * 33) ^
  1016. static_cast<unsigned char>(*s));
  1017. }
  1018. unsigned int str2tag(const std::string &s) {
  1019. return str2tag_core(s.data(), s.size(), 0);
  1020. }
  1021. namespace udl {
  1022. constexpr unsigned int operator""_t(const char *s, size_t l) {
  1023. return str2tag_core(s, l, 0);
  1024. }
  1025. } // namespace udl
  1026. std::string
  1027. find_content_type(const std::string &path,
  1028. const std::map<std::string, std::string> &user_data,
  1029. const std::string &default_content_type) {
  1030. auto ext = file_extension(path);
  1031. auto it = user_data.find(ext);
  1032. if (it != user_data.end()) { return it->second; }
  1033. using udl::operator""_t;
  1034. switch (str2tag(ext)) {
  1035. default: return default_content_type;
  1036. case "css"_t: return "text/css";
  1037. case "csv"_t: return "text/csv";
  1038. case "htm"_t:
  1039. case "html"_t: return "text/html";
  1040. case "js"_t:
  1041. case "mjs"_t: return "text/javascript";
  1042. case "txt"_t: return "text/plain";
  1043. case "vtt"_t: return "text/vtt";
  1044. case "apng"_t: return "image/apng";
  1045. case "avif"_t: return "image/avif";
  1046. case "bmp"_t: return "image/bmp";
  1047. case "gif"_t: return "image/gif";
  1048. case "png"_t: return "image/png";
  1049. case "svg"_t: return "image/svg+xml";
  1050. case "webp"_t: return "image/webp";
  1051. case "ico"_t: return "image/x-icon";
  1052. case "tif"_t: return "image/tiff";
  1053. case "tiff"_t: return "image/tiff";
  1054. case "jpg"_t:
  1055. case "jpeg"_t: return "image/jpeg";
  1056. case "mp4"_t: return "video/mp4";
  1057. case "mpeg"_t: return "video/mpeg";
  1058. case "webm"_t: return "video/webm";
  1059. case "mp3"_t: return "audio/mp3";
  1060. case "mpga"_t: return "audio/mpeg";
  1061. case "weba"_t: return "audio/webm";
  1062. case "wav"_t: return "audio/wave";
  1063. case "otf"_t: return "font/otf";
  1064. case "ttf"_t: return "font/ttf";
  1065. case "woff"_t: return "font/woff";
  1066. case "woff2"_t: return "font/woff2";
  1067. case "7z"_t: return "application/x-7z-compressed";
  1068. case "atom"_t: return "application/atom+xml";
  1069. case "pdf"_t: return "application/pdf";
  1070. case "json"_t: return "application/json";
  1071. case "rss"_t: return "application/rss+xml";
  1072. case "tar"_t: return "application/x-tar";
  1073. case "xht"_t:
  1074. case "xhtml"_t: return "application/xhtml+xml";
  1075. case "xslt"_t: return "application/xslt+xml";
  1076. case "xml"_t: return "application/xml";
  1077. case "gz"_t: return "application/gzip";
  1078. case "zip"_t: return "application/zip";
  1079. case "wasm"_t: return "application/wasm";
  1080. }
  1081. }
  1082. bool can_compress_content_type(const std::string &content_type) {
  1083. using udl::operator""_t;
  1084. auto tag = str2tag(content_type);
  1085. switch (tag) {
  1086. case "image/svg+xml"_t:
  1087. case "application/javascript"_t:
  1088. case "application/json"_t:
  1089. case "application/xml"_t:
  1090. case "application/protobuf"_t:
  1091. case "application/xhtml+xml"_t: return true;
  1092. case "text/event-stream"_t: return false;
  1093. default: return !content_type.rfind("text/", 0);
  1094. }
  1095. }
  1096. EncodingType encoding_type(const Request &req, const Response &res) {
  1097. auto ret =
  1098. detail::can_compress_content_type(res.get_header_value("Content-Type"));
  1099. if (!ret) { return EncodingType::None; }
  1100. const auto &s = req.get_header_value("Accept-Encoding");
  1101. (void)(s);
  1102. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  1103. // TODO: 'Accept-Encoding' has br, not br;q=0
  1104. ret = s.find("br") != std::string::npos;
  1105. if (ret) { return EncodingType::Brotli; }
  1106. #endif
  1107. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  1108. // TODO: 'Accept-Encoding' has gzip, not gzip;q=0
  1109. ret = s.find("gzip") != std::string::npos;
  1110. if (ret) { return EncodingType::Gzip; }
  1111. #endif
  1112. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  1113. // TODO: 'Accept-Encoding' has zstd, not zstd;q=0
  1114. ret = s.find("zstd") != std::string::npos;
  1115. if (ret) { return EncodingType::Zstd; }
  1116. #endif
  1117. return EncodingType::None;
  1118. }
  1119. bool nocompressor::compress(const char *data, size_t data_length,
  1120. bool /*last*/, Callback callback) {
  1121. if (!data_length) { return true; }
  1122. return callback(data, data_length);
  1123. }
  1124. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  1125. gzip_compressor::gzip_compressor() {
  1126. std::memset(&strm_, 0, sizeof(strm_));
  1127. strm_.zalloc = Z_NULL;
  1128. strm_.zfree = Z_NULL;
  1129. strm_.opaque = Z_NULL;
  1130. is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8,
  1131. Z_DEFAULT_STRATEGY) == Z_OK;
  1132. }
  1133. gzip_compressor::~gzip_compressor() { deflateEnd(&strm_); }
  1134. bool gzip_compressor::compress(const char *data, size_t data_length,
  1135. bool last, Callback callback) {
  1136. assert(is_valid_);
  1137. do {
  1138. constexpr size_t max_avail_in =
  1139. (std::numeric_limits<decltype(strm_.avail_in)>::max)();
  1140. strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
  1141. (std::min)(data_length, max_avail_in));
  1142. strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
  1143. data_length -= strm_.avail_in;
  1144. data += strm_.avail_in;
  1145. auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH;
  1146. auto ret = Z_OK;
  1147. std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1148. do {
  1149. strm_.avail_out = static_cast<uInt>(buff.size());
  1150. strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
  1151. ret = deflate(&strm_, flush);
  1152. if (ret == Z_STREAM_ERROR) { return false; }
  1153. if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
  1154. return false;
  1155. }
  1156. } while (strm_.avail_out == 0);
  1157. assert((flush == Z_FINISH && ret == Z_STREAM_END) ||
  1158. (flush == Z_NO_FLUSH && ret == Z_OK));
  1159. assert(strm_.avail_in == 0);
  1160. } while (data_length > 0);
  1161. return true;
  1162. }
  1163. gzip_decompressor::gzip_decompressor() {
  1164. std::memset(&strm_, 0, sizeof(strm_));
  1165. strm_.zalloc = Z_NULL;
  1166. strm_.zfree = Z_NULL;
  1167. strm_.opaque = Z_NULL;
  1168. // 15 is the value of wbits, which should be at the maximum possible value
  1169. // to ensure that any gzip stream can be decoded. The offset of 32 specifies
  1170. // that the stream type should be automatically detected either gzip or
  1171. // deflate.
  1172. is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK;
  1173. }
  1174. gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); }
  1175. bool gzip_decompressor::is_valid() const { return is_valid_; }
  1176. bool gzip_decompressor::decompress(const char *data, size_t data_length,
  1177. Callback callback) {
  1178. assert(is_valid_);
  1179. auto ret = Z_OK;
  1180. do {
  1181. constexpr size_t max_avail_in =
  1182. (std::numeric_limits<decltype(strm_.avail_in)>::max)();
  1183. strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
  1184. (std::min)(data_length, max_avail_in));
  1185. strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
  1186. data_length -= strm_.avail_in;
  1187. data += strm_.avail_in;
  1188. std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1189. while (strm_.avail_in > 0 && ret == Z_OK) {
  1190. strm_.avail_out = static_cast<uInt>(buff.size());
  1191. strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
  1192. ret = inflate(&strm_, Z_NO_FLUSH);
  1193. assert(ret != Z_STREAM_ERROR);
  1194. switch (ret) {
  1195. case Z_NEED_DICT:
  1196. case Z_DATA_ERROR:
  1197. case Z_MEM_ERROR: inflateEnd(&strm_); return false;
  1198. }
  1199. if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
  1200. return false;
  1201. }
  1202. }
  1203. if (ret != Z_OK && ret != Z_STREAM_END) { return false; }
  1204. } while (data_length > 0);
  1205. return true;
  1206. }
  1207. #endif
  1208. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  1209. brotli_compressor::brotli_compressor() {
  1210. state_ = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
  1211. }
  1212. brotli_compressor::~brotli_compressor() {
  1213. BrotliEncoderDestroyInstance(state_);
  1214. }
  1215. bool brotli_compressor::compress(const char *data, size_t data_length,
  1216. bool last, Callback callback) {
  1217. std::array<uint8_t, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1218. auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS;
  1219. auto available_in = data_length;
  1220. auto next_in = reinterpret_cast<const uint8_t *>(data);
  1221. for (;;) {
  1222. if (last) {
  1223. if (BrotliEncoderIsFinished(state_)) { break; }
  1224. } else {
  1225. if (!available_in) { break; }
  1226. }
  1227. auto available_out = buff.size();
  1228. auto next_out = buff.data();
  1229. if (!BrotliEncoderCompressStream(state_, operation, &available_in, &next_in,
  1230. &available_out, &next_out, nullptr)) {
  1231. return false;
  1232. }
  1233. auto output_bytes = buff.size() - available_out;
  1234. if (output_bytes) {
  1235. callback(reinterpret_cast<const char *>(buff.data()), output_bytes);
  1236. }
  1237. }
  1238. return true;
  1239. }
  1240. brotli_decompressor::brotli_decompressor() {
  1241. decoder_s = BrotliDecoderCreateInstance(0, 0, 0);
  1242. decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT
  1243. : BROTLI_DECODER_RESULT_ERROR;
  1244. }
  1245. brotli_decompressor::~brotli_decompressor() {
  1246. if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); }
  1247. }
  1248. bool brotli_decompressor::is_valid() const { return decoder_s; }
  1249. bool brotli_decompressor::decompress(const char *data,
  1250. size_t data_length,
  1251. Callback callback) {
  1252. if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS ||
  1253. decoder_r == BROTLI_DECODER_RESULT_ERROR) {
  1254. return 0;
  1255. }
  1256. auto next_in = reinterpret_cast<const uint8_t *>(data);
  1257. size_t avail_in = data_length;
  1258. size_t total_out;
  1259. decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
  1260. std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1261. while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
  1262. char *next_out = buff.data();
  1263. size_t avail_out = buff.size();
  1264. decoder_r = BrotliDecoderDecompressStream(
  1265. decoder_s, &avail_in, &next_in, &avail_out,
  1266. reinterpret_cast<uint8_t **>(&next_out), &total_out);
  1267. if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false; }
  1268. if (!callback(buff.data(), buff.size() - avail_out)) { return false; }
  1269. }
  1270. return decoder_r == BROTLI_DECODER_RESULT_SUCCESS ||
  1271. decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
  1272. }
  1273. #endif
  1274. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  1275. zstd_compressor::zstd_compressor() {
  1276. ctx_ = ZSTD_createCCtx();
  1277. ZSTD_CCtx_setParameter(ctx_, ZSTD_c_compressionLevel, ZSTD_fast);
  1278. }
  1279. zstd_compressor::~zstd_compressor() { ZSTD_freeCCtx(ctx_); }
  1280. bool zstd_compressor::compress(const char *data, size_t data_length,
  1281. bool last, Callback callback) {
  1282. std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1283. ZSTD_EndDirective mode = last ? ZSTD_e_end : ZSTD_e_continue;
  1284. ZSTD_inBuffer input = {data, data_length, 0};
  1285. bool finished;
  1286. do {
  1287. ZSTD_outBuffer output = {buff.data(), CPPHTTPLIB_COMPRESSION_BUFSIZ, 0};
  1288. size_t const remaining = ZSTD_compressStream2(ctx_, &output, &input, mode);
  1289. if (ZSTD_isError(remaining)) { return false; }
  1290. if (!callback(buff.data(), output.pos)) { return false; }
  1291. finished = last ? (remaining == 0) : (input.pos == input.size);
  1292. } while (!finished);
  1293. return true;
  1294. }
  1295. zstd_decompressor::zstd_decompressor() { ctx_ = ZSTD_createDCtx(); }
  1296. zstd_decompressor::~zstd_decompressor() { ZSTD_freeDCtx(ctx_); }
  1297. bool zstd_decompressor::is_valid() const { return ctx_ != nullptr; }
  1298. bool zstd_decompressor::decompress(const char *data, size_t data_length,
  1299. Callback callback) {
  1300. std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
  1301. ZSTD_inBuffer input = {data, data_length, 0};
  1302. while (input.pos < input.size) {
  1303. ZSTD_outBuffer output = {buff.data(), CPPHTTPLIB_COMPRESSION_BUFSIZ, 0};
  1304. size_t const remaining = ZSTD_decompressStream(ctx_, &output, &input);
  1305. if (ZSTD_isError(remaining)) { return false; }
  1306. if (!callback(buff.data(), output.pos)) { return false; }
  1307. }
  1308. return true;
  1309. }
  1310. #endif
  1311. bool has_header(const Headers &headers, const std::string &key) {
  1312. return headers.find(key) != headers.end();
  1313. }
  1314. const char *get_header_value(const Headers &headers,
  1315. const std::string &key, const char *def,
  1316. size_t id) {
  1317. auto rng = headers.equal_range(key);
  1318. auto it = rng.first;
  1319. std::advance(it, static_cast<ssize_t>(id));
  1320. if (it != rng.second) { return it->second.c_str(); }
  1321. return def;
  1322. }
  1323. template <typename T>
  1324. bool parse_header(const char *beg, const char *end, T fn) {
  1325. // Skip trailing spaces and tabs.
  1326. while (beg < end && is_space_or_tab(end[-1])) {
  1327. end--;
  1328. }
  1329. auto p = beg;
  1330. while (p < end && *p != ':') {
  1331. p++;
  1332. }
  1333. auto name = std::string(beg, p);
  1334. if (!detail::fields::is_field_name(name)) { return false; }
  1335. if (p == end) { return false; }
  1336. auto key_end = p;
  1337. if (*p++ != ':') { return false; }
  1338. while (p < end && is_space_or_tab(*p)) {
  1339. p++;
  1340. }
  1341. if (p <= end) {
  1342. auto key_len = key_end - beg;
  1343. if (!key_len) { return false; }
  1344. auto key = std::string(beg, key_end);
  1345. auto val = std::string(p, end);
  1346. if (!detail::fields::is_field_value(val)) { return false; }
  1347. if (case_ignore::equal(key, "Location") ||
  1348. case_ignore::equal(key, "Referer")) {
  1349. fn(key, val);
  1350. } else {
  1351. fn(key, decode_url(val, false));
  1352. }
  1353. return true;
  1354. }
  1355. return false;
  1356. }
  1357. bool read_headers(Stream &strm, Headers &headers) {
  1358. const auto bufsiz = 2048;
  1359. char buf[bufsiz];
  1360. stream_line_reader line_reader(strm, buf, bufsiz);
  1361. for (;;) {
  1362. if (!line_reader.getline()) { return false; }
  1363. // Check if the line ends with CRLF.
  1364. auto line_terminator_len = 2;
  1365. if (line_reader.end_with_crlf()) {
  1366. // Blank line indicates end of headers.
  1367. if (line_reader.size() == 2) { break; }
  1368. } else {
  1369. #ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
  1370. // Blank line indicates end of headers.
  1371. if (line_reader.size() == 1) { break; }
  1372. line_terminator_len = 1;
  1373. #else
  1374. continue; // Skip invalid line.
  1375. #endif
  1376. }
  1377. if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  1378. // Exclude line terminator
  1379. auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
  1380. if (!parse_header(line_reader.ptr(), end,
  1381. [&](const std::string &key, const std::string &val) {
  1382. headers.emplace(key, val);
  1383. })) {
  1384. return false;
  1385. }
  1386. }
  1387. return true;
  1388. }
  1389. bool read_content_with_length(Stream &strm, uint64_t len,
  1390. Progress progress,
  1391. ContentReceiverWithProgress out) {
  1392. char buf[CPPHTTPLIB_RECV_BUFSIZ];
  1393. uint64_t r = 0;
  1394. while (r < len) {
  1395. auto read_len = static_cast<size_t>(len - r);
  1396. auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ));
  1397. if (n <= 0) { return false; }
  1398. if (!out(buf, static_cast<size_t>(n), r, len)) { return false; }
  1399. r += static_cast<uint64_t>(n);
  1400. if (progress) {
  1401. if (!progress(r, len)) { return false; }
  1402. }
  1403. }
  1404. return true;
  1405. }
  1406. void skip_content_with_length(Stream &strm, uint64_t len) {
  1407. char buf[CPPHTTPLIB_RECV_BUFSIZ];
  1408. uint64_t r = 0;
  1409. while (r < len) {
  1410. auto read_len = static_cast<size_t>(len - r);
  1411. auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ));
  1412. if (n <= 0) { return; }
  1413. r += static_cast<uint64_t>(n);
  1414. }
  1415. }
  1416. bool read_content_without_length(Stream &strm,
  1417. ContentReceiverWithProgress out) {
  1418. char buf[CPPHTTPLIB_RECV_BUFSIZ];
  1419. uint64_t r = 0;
  1420. for (;;) {
  1421. auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
  1422. if (n == 0) { return true; }
  1423. if (n < 0) { return false; }
  1424. if (!out(buf, static_cast<size_t>(n), r, 0)) { return false; }
  1425. r += static_cast<uint64_t>(n);
  1426. }
  1427. return true;
  1428. }
  1429. template <typename T>
  1430. bool read_content_chunked(Stream &strm, T &x,
  1431. ContentReceiverWithProgress out) {
  1432. const auto bufsiz = 16;
  1433. char buf[bufsiz];
  1434. stream_line_reader line_reader(strm, buf, bufsiz);
  1435. if (!line_reader.getline()) { return false; }
  1436. unsigned long chunk_len;
  1437. while (true) {
  1438. char *end_ptr;
  1439. chunk_len = std::strtoul(line_reader.ptr(), &end_ptr, 16);
  1440. if (end_ptr == line_reader.ptr()) { return false; }
  1441. if (chunk_len == ULONG_MAX) { return false; }
  1442. if (chunk_len == 0) { break; }
  1443. if (!read_content_with_length(strm, chunk_len, nullptr, out)) {
  1444. return false;
  1445. }
  1446. if (!line_reader.getline()) { return false; }
  1447. if (strcmp(line_reader.ptr(), "\r\n") != 0) { return false; }
  1448. if (!line_reader.getline()) { return false; }
  1449. }
  1450. assert(chunk_len == 0);
  1451. // NOTE: In RFC 9112, '7.1 Chunked Transfer Coding' mentions "The chunked
  1452. // transfer coding is complete when a chunk with a chunk-size of zero is
  1453. // received, possibly followed by a trailer section, and finally terminated by
  1454. // an empty line". https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1
  1455. //
  1456. // In '7.1.3. Decoding Chunked', however, the pseudo-code in the section
  1457. // does't care for the existence of the final CRLF. In other words, it seems
  1458. // to be ok whether the final CRLF exists or not in the chunked data.
  1459. // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1.3
  1460. //
  1461. // According to the reference code in RFC 9112, cpp-httplib now allows
  1462. // chunked transfer coding data without the final CRLF.
  1463. if (!line_reader.getline()) { return true; }
  1464. while (strcmp(line_reader.ptr(), "\r\n") != 0) {
  1465. if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  1466. // Exclude line terminator
  1467. constexpr auto line_terminator_len = 2;
  1468. auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
  1469. parse_header(line_reader.ptr(), end,
  1470. [&](const std::string &key, const std::string &val) {
  1471. x.headers.emplace(key, val);
  1472. });
  1473. if (!line_reader.getline()) { return false; }
  1474. }
  1475. return true;
  1476. }
  1477. bool is_chunked_transfer_encoding(const Headers &headers) {
  1478. return case_ignore::equal(
  1479. get_header_value(headers, "Transfer-Encoding", "", 0), "chunked");
  1480. }
  1481. template <typename T, typename U>
  1482. bool prepare_content_receiver(T &x, int &status,
  1483. ContentReceiverWithProgress receiver,
  1484. bool decompress, U callback) {
  1485. if (decompress) {
  1486. std::string encoding = x.get_header_value("Content-Encoding");
  1487. std::unique_ptr<decompressor> decompressor;
  1488. if (encoding == "gzip" || encoding == "deflate") {
  1489. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  1490. decompressor = detail::make_unique<gzip_decompressor>();
  1491. #else
  1492. status = StatusCode::UnsupportedMediaType_415;
  1493. return false;
  1494. #endif
  1495. } else if (encoding.find("br") != std::string::npos) {
  1496. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  1497. decompressor = detail::make_unique<brotli_decompressor>();
  1498. #else
  1499. status = StatusCode::UnsupportedMediaType_415;
  1500. return false;
  1501. #endif
  1502. } else if (encoding == "zstd") {
  1503. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  1504. decompressor = detail::make_unique<zstd_decompressor>();
  1505. #else
  1506. status = StatusCode::UnsupportedMediaType_415;
  1507. return false;
  1508. #endif
  1509. }
  1510. if (decompressor) {
  1511. if (decompressor->is_valid()) {
  1512. ContentReceiverWithProgress out = [&](const char *buf, size_t n,
  1513. uint64_t off, uint64_t len) {
  1514. return decompressor->decompress(buf, n,
  1515. [&](const char *buf2, size_t n2) {
  1516. return receiver(buf2, n2, off, len);
  1517. });
  1518. };
  1519. return callback(std::move(out));
  1520. } else {
  1521. status = StatusCode::InternalServerError_500;
  1522. return false;
  1523. }
  1524. }
  1525. }
  1526. ContentReceiverWithProgress out = [&](const char *buf, size_t n, uint64_t off,
  1527. uint64_t len) {
  1528. return receiver(buf, n, off, len);
  1529. };
  1530. return callback(std::move(out));
  1531. }
  1532. template <typename T>
  1533. bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status,
  1534. Progress progress, ContentReceiverWithProgress receiver,
  1535. bool decompress) {
  1536. return prepare_content_receiver(
  1537. x, status, std::move(receiver), decompress,
  1538. [&](const ContentReceiverWithProgress &out) {
  1539. auto ret = true;
  1540. auto exceed_payload_max_length = false;
  1541. if (is_chunked_transfer_encoding(x.headers)) {
  1542. ret = read_content_chunked(strm, x, out);
  1543. } else if (!has_header(x.headers, "Content-Length")) {
  1544. ret = read_content_without_length(strm, out);
  1545. } else {
  1546. auto is_invalid_value = false;
  1547. auto len = get_header_value_u64(
  1548. x.headers, "Content-Length",
  1549. (std::numeric_limits<uint64_t>::max)(), 0, is_invalid_value);
  1550. if (is_invalid_value) {
  1551. ret = false;
  1552. } else if (len > payload_max_length) {
  1553. exceed_payload_max_length = true;
  1554. skip_content_with_length(strm, len);
  1555. ret = false;
  1556. } else if (len > 0) {
  1557. ret = read_content_with_length(strm, len, std::move(progress), out);
  1558. }
  1559. }
  1560. if (!ret) {
  1561. status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
  1562. : StatusCode::BadRequest_400;
  1563. }
  1564. return ret;
  1565. });
  1566. }
  1567. ssize_t write_request_line(Stream &strm, const std::string &method,
  1568. const std::string &path) {
  1569. std::string s = method;
  1570. s += " ";
  1571. s += path;
  1572. s += " HTTP/1.1\r\n";
  1573. return strm.write(s.data(), s.size());
  1574. }
  1575. ssize_t write_response_line(Stream &strm, int status) {
  1576. std::string s = "HTTP/1.1 ";
  1577. s += std::to_string(status);
  1578. s += " ";
  1579. s += httplib::status_message(status);
  1580. s += "\r\n";
  1581. return strm.write(s.data(), s.size());
  1582. }
  1583. ssize_t write_headers(Stream &strm, const Headers &headers) {
  1584. ssize_t write_len = 0;
  1585. for (const auto &x : headers) {
  1586. std::string s;
  1587. s = x.first;
  1588. s += ": ";
  1589. s += x.second;
  1590. s += "\r\n";
  1591. auto len = strm.write(s.data(), s.size());
  1592. if (len < 0) { return len; }
  1593. write_len += len;
  1594. }
  1595. auto len = strm.write("\r\n");
  1596. if (len < 0) { return len; }
  1597. write_len += len;
  1598. return write_len;
  1599. }
  1600. bool write_data(Stream &strm, const char *d, size_t l) {
  1601. size_t offset = 0;
  1602. while (offset < l) {
  1603. auto length = strm.write(d + offset, l - offset);
  1604. if (length < 0) { return false; }
  1605. offset += static_cast<size_t>(length);
  1606. }
  1607. return true;
  1608. }
  1609. template <typename T>
  1610. bool write_content(Stream &strm, const ContentProvider &content_provider,
  1611. size_t offset, size_t length, T is_shutting_down,
  1612. Error &error) {
  1613. size_t end_offset = offset + length;
  1614. auto ok = true;
  1615. DataSink data_sink;
  1616. data_sink.write = [&](const char *d, size_t l) -> bool {
  1617. if (ok) {
  1618. if (write_data(strm, d, l)) {
  1619. offset += l;
  1620. } else {
  1621. ok = false;
  1622. }
  1623. }
  1624. return ok;
  1625. };
  1626. data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
  1627. while (offset < end_offset && !is_shutting_down()) {
  1628. if (!strm.wait_writable()) {
  1629. error = Error::Write;
  1630. return false;
  1631. } else if (!content_provider(offset, end_offset - offset, data_sink)) {
  1632. error = Error::Canceled;
  1633. return false;
  1634. } else if (!ok) {
  1635. error = Error::Write;
  1636. return false;
  1637. }
  1638. }
  1639. error = Error::Success;
  1640. return true;
  1641. }
  1642. template <typename T>
  1643. bool write_content(Stream &strm, const ContentProvider &content_provider,
  1644. size_t offset, size_t length,
  1645. const T &is_shutting_down) {
  1646. auto error = Error::Success;
  1647. return write_content(strm, content_provider, offset, length, is_shutting_down,
  1648. error);
  1649. }
  1650. template <typename T>
  1651. bool
  1652. write_content_without_length(Stream &strm,
  1653. const ContentProvider &content_provider,
  1654. const T &is_shutting_down) {
  1655. size_t offset = 0;
  1656. auto data_available = true;
  1657. auto ok = true;
  1658. DataSink data_sink;
  1659. data_sink.write = [&](const char *d, size_t l) -> bool {
  1660. if (ok) {
  1661. offset += l;
  1662. if (!write_data(strm, d, l)) { ok = false; }
  1663. }
  1664. return ok;
  1665. };
  1666. data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
  1667. data_sink.done = [&](void) { data_available = false; };
  1668. while (data_available && !is_shutting_down()) {
  1669. if (!strm.wait_writable()) {
  1670. return false;
  1671. } else if (!content_provider(offset, 0, data_sink)) {
  1672. return false;
  1673. } else if (!ok) {
  1674. return false;
  1675. }
  1676. }
  1677. return true;
  1678. }
  1679. template <typename T, typename U>
  1680. bool
  1681. write_content_chunked(Stream &strm, const ContentProvider &content_provider,
  1682. const T &is_shutting_down, U &compressor, Error &error) {
  1683. size_t offset = 0;
  1684. auto data_available = true;
  1685. auto ok = true;
  1686. DataSink data_sink;
  1687. data_sink.write = [&](const char *d, size_t l) -> bool {
  1688. if (ok) {
  1689. data_available = l > 0;
  1690. offset += l;
  1691. std::string payload;
  1692. if (compressor.compress(d, l, false,
  1693. [&](const char *data, size_t data_len) {
  1694. payload.append(data, data_len);
  1695. return true;
  1696. })) {
  1697. if (!payload.empty()) {
  1698. // Emit chunked response header and footer for each chunk
  1699. auto chunk =
  1700. from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
  1701. if (!write_data(strm, chunk.data(), chunk.size())) { ok = false; }
  1702. }
  1703. } else {
  1704. ok = false;
  1705. }
  1706. }
  1707. return ok;
  1708. };
  1709. data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
  1710. auto done_with_trailer = [&](const Headers *trailer) {
  1711. if (!ok) { return; }
  1712. data_available = false;
  1713. std::string payload;
  1714. if (!compressor.compress(nullptr, 0, true,
  1715. [&](const char *data, size_t data_len) {
  1716. payload.append(data, data_len);
  1717. return true;
  1718. })) {
  1719. ok = false;
  1720. return;
  1721. }
  1722. if (!payload.empty()) {
  1723. // Emit chunked response header and footer for each chunk
  1724. auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
  1725. if (!write_data(strm, chunk.data(), chunk.size())) {
  1726. ok = false;
  1727. return;
  1728. }
  1729. }
  1730. constexpr const char done_marker[] = "0\r\n";
  1731. if (!write_data(strm, done_marker, str_len(done_marker))) { ok = false; }
  1732. // Trailer
  1733. if (trailer) {
  1734. for (const auto &kv : *trailer) {
  1735. std::string field_line = kv.first + ": " + kv.second + "\r\n";
  1736. if (!write_data(strm, field_line.data(), field_line.size())) {
  1737. ok = false;
  1738. }
  1739. }
  1740. }
  1741. constexpr const char crlf[] = "\r\n";
  1742. if (!write_data(strm, crlf, str_len(crlf))) { ok = false; }
  1743. };
  1744. data_sink.done = [&](void) { done_with_trailer(nullptr); };
  1745. data_sink.done_with_trailer = [&](const Headers &trailer) {
  1746. done_with_trailer(&trailer);
  1747. };
  1748. while (data_available && !is_shutting_down()) {
  1749. if (!strm.wait_writable()) {
  1750. error = Error::Write;
  1751. return false;
  1752. } else if (!content_provider(offset, 0, data_sink)) {
  1753. error = Error::Canceled;
  1754. return false;
  1755. } else if (!ok) {
  1756. error = Error::Write;
  1757. return false;
  1758. }
  1759. }
  1760. error = Error::Success;
  1761. return true;
  1762. }
  1763. template <typename T, typename U>
  1764. bool write_content_chunked(Stream &strm,
  1765. const ContentProvider &content_provider,
  1766. const T &is_shutting_down, U &compressor) {
  1767. auto error = Error::Success;
  1768. return write_content_chunked(strm, content_provider, is_shutting_down,
  1769. compressor, error);
  1770. }
  1771. template <typename T>
  1772. bool redirect(T &cli, Request &req, Response &res,
  1773. const std::string &path, const std::string &location,
  1774. Error &error) {
  1775. Request new_req = req;
  1776. new_req.path = path;
  1777. new_req.redirect_count_ -= 1;
  1778. if (res.status == StatusCode::SeeOther_303 &&
  1779. (req.method != "GET" && req.method != "HEAD")) {
  1780. new_req.method = "GET";
  1781. new_req.body.clear();
  1782. new_req.headers.clear();
  1783. }
  1784. Response new_res;
  1785. auto ret = cli.send(new_req, new_res, error);
  1786. if (ret) {
  1787. req = new_req;
  1788. res = new_res;
  1789. if (res.location.empty()) { res.location = location; }
  1790. }
  1791. return ret;
  1792. }
  1793. std::string params_to_query_str(const Params &params) {
  1794. std::string query;
  1795. for (auto it = params.begin(); it != params.end(); ++it) {
  1796. if (it != params.begin()) { query += "&"; }
  1797. query += it->first;
  1798. query += "=";
  1799. query += encode_query_param(it->second);
  1800. }
  1801. return query;
  1802. }
  1803. void parse_query_text(const char *data, std::size_t size,
  1804. Params &params) {
  1805. std::set<std::string> cache;
  1806. split(data, data + size, '&', [&](const char *b, const char *e) {
  1807. std::string kv(b, e);
  1808. if (cache.find(kv) != cache.end()) { return; }
  1809. cache.insert(std::move(kv));
  1810. std::string key;
  1811. std::string val;
  1812. divide(b, static_cast<std::size_t>(e - b), '=',
  1813. [&](const char *lhs_data, std::size_t lhs_size, const char *rhs_data,
  1814. std::size_t rhs_size) {
  1815. key.assign(lhs_data, lhs_size);
  1816. val.assign(rhs_data, rhs_size);
  1817. });
  1818. if (!key.empty()) {
  1819. params.emplace(decode_url(key, true), decode_url(val, true));
  1820. }
  1821. });
  1822. }
  1823. void parse_query_text(const std::string &s, Params &params) {
  1824. parse_query_text(s.data(), s.size(), params);
  1825. }
  1826. bool parse_multipart_boundary(const std::string &content_type,
  1827. std::string &boundary) {
  1828. auto boundary_keyword = "boundary=";
  1829. auto pos = content_type.find(boundary_keyword);
  1830. if (pos == std::string::npos) { return false; }
  1831. auto end = content_type.find(';', pos);
  1832. auto beg = pos + strlen(boundary_keyword);
  1833. boundary = trim_double_quotes_copy(content_type.substr(beg, end - beg));
  1834. return !boundary.empty();
  1835. }
  1836. void parse_disposition_params(const std::string &s, Params &params) {
  1837. std::set<std::string> cache;
  1838. split(s.data(), s.data() + s.size(), ';', [&](const char *b, const char *e) {
  1839. std::string kv(b, e);
  1840. if (cache.find(kv) != cache.end()) { return; }
  1841. cache.insert(kv);
  1842. std::string key;
  1843. std::string val;
  1844. split(b, e, '=', [&](const char *b2, const char *e2) {
  1845. if (key.empty()) {
  1846. key.assign(b2, e2);
  1847. } else {
  1848. val.assign(b2, e2);
  1849. }
  1850. });
  1851. if (!key.empty()) {
  1852. params.emplace(trim_double_quotes_copy((key)),
  1853. trim_double_quotes_copy((val)));
  1854. }
  1855. });
  1856. }
  1857. #ifdef CPPHTTPLIB_NO_EXCEPTIONS
  1858. bool parse_range_header(const std::string &s, Ranges &ranges) {
  1859. #else
  1860. bool parse_range_header(const std::string &s, Ranges &ranges) try {
  1861. #endif
  1862. auto is_valid = [](const std::string &str) {
  1863. return std::all_of(str.cbegin(), str.cend(),
  1864. [](unsigned char c) { return std::isdigit(c); });
  1865. };
  1866. if (s.size() > 7 && s.compare(0, 6, "bytes=") == 0) {
  1867. const auto pos = static_cast<size_t>(6);
  1868. const auto len = static_cast<size_t>(s.size() - 6);
  1869. auto all_valid_ranges = true;
  1870. split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) {
  1871. if (!all_valid_ranges) { return; }
  1872. const auto it = std::find(b, e, '-');
  1873. if (it == e) {
  1874. all_valid_ranges = false;
  1875. return;
  1876. }
  1877. const auto lhs = std::string(b, it);
  1878. const auto rhs = std::string(it + 1, e);
  1879. if (!is_valid(lhs) || !is_valid(rhs)) {
  1880. all_valid_ranges = false;
  1881. return;
  1882. }
  1883. const auto first =
  1884. static_cast<ssize_t>(lhs.empty() ? -1 : std::stoll(lhs));
  1885. const auto last =
  1886. static_cast<ssize_t>(rhs.empty() ? -1 : std::stoll(rhs));
  1887. if ((first == -1 && last == -1) ||
  1888. (first != -1 && last != -1 && first > last)) {
  1889. all_valid_ranges = false;
  1890. return;
  1891. }
  1892. ranges.emplace_back(first, last);
  1893. });
  1894. return all_valid_ranges && !ranges.empty();
  1895. }
  1896. return false;
  1897. #ifdef CPPHTTPLIB_NO_EXCEPTIONS
  1898. }
  1899. #else
  1900. } catch (...) { return false; }
  1901. #endif
  1902. class MultipartFormDataParser {
  1903. public:
  1904. MultipartFormDataParser() = default;
  1905. void set_boundary(std::string &&boundary) {
  1906. boundary_ = boundary;
  1907. dash_boundary_crlf_ = dash_ + boundary_ + crlf_;
  1908. crlf_dash_boundary_ = crlf_ + dash_ + boundary_;
  1909. }
  1910. bool is_valid() const { return is_valid_; }
  1911. bool parse(const char *buf, size_t n, const ContentReceiver &content_callback,
  1912. const MultipartContentHeader &header_callback) {
  1913. buf_append(buf, n);
  1914. while (buf_size() > 0) {
  1915. switch (state_) {
  1916. case 0: { // Initial boundary
  1917. buf_erase(buf_find(dash_boundary_crlf_));
  1918. if (dash_boundary_crlf_.size() > buf_size()) { return true; }
  1919. if (!buf_start_with(dash_boundary_crlf_)) { return false; }
  1920. buf_erase(dash_boundary_crlf_.size());
  1921. state_ = 1;
  1922. break;
  1923. }
  1924. case 1: { // New entry
  1925. clear_file_info();
  1926. state_ = 2;
  1927. break;
  1928. }
  1929. case 2: { // Headers
  1930. auto pos = buf_find(crlf_);
  1931. if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  1932. while (pos < buf_size()) {
  1933. // Empty line
  1934. if (pos == 0) {
  1935. if (!header_callback(file_)) {
  1936. is_valid_ = false;
  1937. return false;
  1938. }
  1939. buf_erase(crlf_.size());
  1940. state_ = 3;
  1941. break;
  1942. }
  1943. const auto header = buf_head(pos);
  1944. if (!parse_header(header.data(), header.data() + header.size(),
  1945. [&](const std::string &, const std::string &) {})) {
  1946. is_valid_ = false;
  1947. return false;
  1948. }
  1949. constexpr const char header_content_type[] = "Content-Type:";
  1950. if (start_with_case_ignore(header, header_content_type)) {
  1951. file_.content_type =
  1952. trim_copy(header.substr(str_len(header_content_type)));
  1953. } else {
  1954. thread_local const std::regex re_content_disposition(
  1955. R"~(^Content-Disposition:\s*form-data;\s*(.*)$)~",
  1956. std::regex_constants::icase);
  1957. std::smatch m;
  1958. if (std::regex_match(header, m, re_content_disposition)) {
  1959. Params params;
  1960. parse_disposition_params(m[1], params);
  1961. auto it = params.find("name");
  1962. if (it != params.end()) {
  1963. file_.name = it->second;
  1964. } else {
  1965. is_valid_ = false;
  1966. return false;
  1967. }
  1968. it = params.find("filename");
  1969. if (it != params.end()) { file_.filename = it->second; }
  1970. it = params.find("filename*");
  1971. if (it != params.end()) {
  1972. // Only allow UTF-8 encoding...
  1973. thread_local const std::regex re_rfc5987_encoding(
  1974. R"~(^UTF-8''(.+?)$)~", std::regex_constants::icase);
  1975. std::smatch m2;
  1976. if (std::regex_match(it->second, m2, re_rfc5987_encoding)) {
  1977. file_.filename = decode_url(m2[1], false); // override...
  1978. } else {
  1979. is_valid_ = false;
  1980. return false;
  1981. }
  1982. }
  1983. }
  1984. }
  1985. buf_erase(pos + crlf_.size());
  1986. pos = buf_find(crlf_);
  1987. }
  1988. if (state_ != 3) { return true; }
  1989. break;
  1990. }
  1991. case 3: { // Body
  1992. if (crlf_dash_boundary_.size() > buf_size()) { return true; }
  1993. auto pos = buf_find(crlf_dash_boundary_);
  1994. if (pos < buf_size()) {
  1995. if (!content_callback(buf_data(), pos)) {
  1996. is_valid_ = false;
  1997. return false;
  1998. }
  1999. buf_erase(pos + crlf_dash_boundary_.size());
  2000. state_ = 4;
  2001. } else {
  2002. auto len = buf_size() - crlf_dash_boundary_.size();
  2003. if (len > 0) {
  2004. if (!content_callback(buf_data(), len)) {
  2005. is_valid_ = false;
  2006. return false;
  2007. }
  2008. buf_erase(len);
  2009. }
  2010. return true;
  2011. }
  2012. break;
  2013. }
  2014. case 4: { // Boundary
  2015. if (crlf_.size() > buf_size()) { return true; }
  2016. if (buf_start_with(crlf_)) {
  2017. buf_erase(crlf_.size());
  2018. state_ = 1;
  2019. } else {
  2020. if (dash_.size() > buf_size()) { return true; }
  2021. if (buf_start_with(dash_)) {
  2022. buf_erase(dash_.size());
  2023. is_valid_ = true;
  2024. buf_erase(buf_size()); // Remove epilogue
  2025. } else {
  2026. return true;
  2027. }
  2028. }
  2029. break;
  2030. }
  2031. }
  2032. }
  2033. return true;
  2034. }
  2035. private:
  2036. void clear_file_info() {
  2037. file_.name.clear();
  2038. file_.filename.clear();
  2039. file_.content_type.clear();
  2040. }
  2041. bool start_with_case_ignore(const std::string &a, const char *b) const {
  2042. const auto b_len = strlen(b);
  2043. if (a.size() < b_len) { return false; }
  2044. for (size_t i = 0; i < b_len; i++) {
  2045. if (case_ignore::to_lower(a[i]) != case_ignore::to_lower(b[i])) {
  2046. return false;
  2047. }
  2048. }
  2049. return true;
  2050. }
  2051. const std::string dash_ = "--";
  2052. const std::string crlf_ = "\r\n";
  2053. std::string boundary_;
  2054. std::string dash_boundary_crlf_;
  2055. std::string crlf_dash_boundary_;
  2056. size_t state_ = 0;
  2057. bool is_valid_ = false;
  2058. MultipartFormData file_;
  2059. // Buffer
  2060. bool start_with(const std::string &a, size_t spos, size_t epos,
  2061. const std::string &b) const {
  2062. if (epos - spos < b.size()) { return false; }
  2063. for (size_t i = 0; i < b.size(); i++) {
  2064. if (a[i + spos] != b[i]) { return false; }
  2065. }
  2066. return true;
  2067. }
  2068. size_t buf_size() const { return buf_epos_ - buf_spos_; }
  2069. const char *buf_data() const { return &buf_[buf_spos_]; }
  2070. std::string buf_head(size_t l) const { return buf_.substr(buf_spos_, l); }
  2071. bool buf_start_with(const std::string &s) const {
  2072. return start_with(buf_, buf_spos_, buf_epos_, s);
  2073. }
  2074. size_t buf_find(const std::string &s) const {
  2075. auto c = s.front();
  2076. size_t off = buf_spos_;
  2077. while (off < buf_epos_) {
  2078. auto pos = off;
  2079. while (true) {
  2080. if (pos == buf_epos_) { return buf_size(); }
  2081. if (buf_[pos] == c) { break; }
  2082. pos++;
  2083. }
  2084. auto remaining_size = buf_epos_ - pos;
  2085. if (s.size() > remaining_size) { return buf_size(); }
  2086. if (start_with(buf_, pos, buf_epos_, s)) { return pos - buf_spos_; }
  2087. off = pos + 1;
  2088. }
  2089. return buf_size();
  2090. }
  2091. void buf_append(const char *data, size_t n) {
  2092. auto remaining_size = buf_size();
  2093. if (remaining_size > 0 && buf_spos_ > 0) {
  2094. for (size_t i = 0; i < remaining_size; i++) {
  2095. buf_[i] = buf_[buf_spos_ + i];
  2096. }
  2097. }
  2098. buf_spos_ = 0;
  2099. buf_epos_ = remaining_size;
  2100. if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); }
  2101. for (size_t i = 0; i < n; i++) {
  2102. buf_[buf_epos_ + i] = data[i];
  2103. }
  2104. buf_epos_ += n;
  2105. }
  2106. void buf_erase(size_t size) { buf_spos_ += size; }
  2107. std::string buf_;
  2108. size_t buf_spos_ = 0;
  2109. size_t buf_epos_ = 0;
  2110. };
  2111. std::string random_string(size_t length) {
  2112. constexpr const char data[] =
  2113. "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  2114. thread_local auto engine([]() {
  2115. // std::random_device might actually be deterministic on some
  2116. // platforms, but due to lack of support in the c++ standard library,
  2117. // doing better requires either some ugly hacks or breaking portability.
  2118. std::random_device seed_gen;
  2119. // Request 128 bits of entropy for initialization
  2120. std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()};
  2121. return std::mt19937(seed_sequence);
  2122. }());
  2123. std::string result;
  2124. for (size_t i = 0; i < length; i++) {
  2125. result += data[engine() % (sizeof(data) - 1)];
  2126. }
  2127. return result;
  2128. }
  2129. std::string make_multipart_data_boundary() {
  2130. return "--cpp-httplib-multipart-data-" + detail::random_string(16);
  2131. }
  2132. bool is_multipart_boundary_chars_valid(const std::string &boundary) {
  2133. auto valid = true;
  2134. for (size_t i = 0; i < boundary.size(); i++) {
  2135. auto c = boundary[i];
  2136. if (!std::isalnum(c) && c != '-' && c != '_') {
  2137. valid = false;
  2138. break;
  2139. }
  2140. }
  2141. return valid;
  2142. }
  2143. template <typename T>
  2144. std::string
  2145. serialize_multipart_formdata_item_begin(const T &item,
  2146. const std::string &boundary) {
  2147. std::string body = "--" + boundary + "\r\n";
  2148. body += "Content-Disposition: form-data; name=\"" + item.name + "\"";
  2149. if (!item.filename.empty()) {
  2150. body += "; filename=\"" + item.filename + "\"";
  2151. }
  2152. body += "\r\n";
  2153. if (!item.content_type.empty()) {
  2154. body += "Content-Type: " + item.content_type + "\r\n";
  2155. }
  2156. body += "\r\n";
  2157. return body;
  2158. }
  2159. std::string serialize_multipart_formdata_item_end() { return "\r\n"; }
  2160. std::string
  2161. serialize_multipart_formdata_finish(const std::string &boundary) {
  2162. return "--" + boundary + "--\r\n";
  2163. }
  2164. std::string
  2165. serialize_multipart_formdata_get_content_type(const std::string &boundary) {
  2166. return "multipart/form-data; boundary=" + boundary;
  2167. }
  2168. std::string
  2169. serialize_multipart_formdata(const MultipartFormDataItems &items,
  2170. const std::string &boundary, bool finish = true) {
  2171. std::string body;
  2172. for (const auto &item : items) {
  2173. body += serialize_multipart_formdata_item_begin(item, boundary);
  2174. body += item.content + serialize_multipart_formdata_item_end();
  2175. }
  2176. if (finish) { body += serialize_multipart_formdata_finish(boundary); }
  2177. return body;
  2178. }
  2179. bool range_error(Request &req, Response &res) {
  2180. if (!req.ranges.empty() && 200 <= res.status && res.status < 300) {
  2181. ssize_t content_len = static_cast<ssize_t>(
  2182. res.content_length_ ? res.content_length_ : res.body.size());
  2183. ssize_t prev_first_pos = -1;
  2184. ssize_t prev_last_pos = -1;
  2185. size_t overwrapping_count = 0;
  2186. // NOTE: The following Range check is based on '14.2. Range' in RFC 9110
  2187. // 'HTTP Semantics' to avoid potential denial-of-service attacks.
  2188. // https://www.rfc-editor.org/rfc/rfc9110#section-14.2
  2189. // Too many ranges
  2190. if (req.ranges.size() > CPPHTTPLIB_RANGE_MAX_COUNT) { return true; }
  2191. for (auto &r : req.ranges) {
  2192. auto &first_pos = r.first;
  2193. auto &last_pos = r.second;
  2194. if (first_pos == -1 && last_pos == -1) {
  2195. first_pos = 0;
  2196. last_pos = content_len;
  2197. }
  2198. if (first_pos == -1) {
  2199. first_pos = content_len - last_pos;
  2200. last_pos = content_len - 1;
  2201. }
  2202. // NOTE: RFC-9110 '14.1.2. Byte Ranges':
  2203. // A client can limit the number of bytes requested without knowing the
  2204. // size of the selected representation. If the last-pos value is absent,
  2205. // or if the value is greater than or equal to the current length of the
  2206. // representation data, the byte range is interpreted as the remainder of
  2207. // the representation (i.e., the server replaces the value of last-pos
  2208. // with a value that is one less than the current length of the selected
  2209. // representation).
  2210. // https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
  2211. if (last_pos == -1 || last_pos >= content_len) {
  2212. last_pos = content_len - 1;
  2213. }
  2214. // Range must be within content length
  2215. if (!(0 <= first_pos && first_pos <= last_pos &&
  2216. last_pos <= content_len - 1)) {
  2217. return true;
  2218. }
  2219. // Ranges must be in ascending order
  2220. if (first_pos <= prev_first_pos) { return true; }
  2221. // Request must not have more than two overlapping ranges
  2222. if (first_pos <= prev_last_pos) {
  2223. overwrapping_count++;
  2224. if (overwrapping_count > 2) { return true; }
  2225. }
  2226. prev_first_pos = (std::max)(prev_first_pos, first_pos);
  2227. prev_last_pos = (std::max)(prev_last_pos, last_pos);
  2228. }
  2229. }
  2230. return false;
  2231. }
  2232. std::pair<size_t, size_t>
  2233. get_range_offset_and_length(Range r, size_t content_length) {
  2234. assert(r.first != -1 && r.second != -1);
  2235. assert(0 <= r.first && r.first < static_cast<ssize_t>(content_length));
  2236. assert(r.first <= r.second &&
  2237. r.second < static_cast<ssize_t>(content_length));
  2238. (void)(content_length);
  2239. return std::make_pair(r.first, static_cast<size_t>(r.second - r.first) + 1);
  2240. }
  2241. std::string make_content_range_header_field(
  2242. const std::pair<size_t, size_t> &offset_and_length, size_t content_length) {
  2243. auto st = offset_and_length.first;
  2244. auto ed = st + offset_and_length.second - 1;
  2245. std::string field = "bytes ";
  2246. field += std::to_string(st);
  2247. field += "-";
  2248. field += std::to_string(ed);
  2249. field += "/";
  2250. field += std::to_string(content_length);
  2251. return field;
  2252. }
  2253. template <typename SToken, typename CToken, typename Content>
  2254. bool process_multipart_ranges_data(const Request &req,
  2255. const std::string &boundary,
  2256. const std::string &content_type,
  2257. size_t content_length, SToken stoken,
  2258. CToken ctoken, Content content) {
  2259. for (size_t i = 0; i < req.ranges.size(); i++) {
  2260. ctoken("--");
  2261. stoken(boundary);
  2262. ctoken("\r\n");
  2263. if (!content_type.empty()) {
  2264. ctoken("Content-Type: ");
  2265. stoken(content_type);
  2266. ctoken("\r\n");
  2267. }
  2268. auto offset_and_length =
  2269. get_range_offset_and_length(req.ranges[i], content_length);
  2270. ctoken("Content-Range: ");
  2271. stoken(make_content_range_header_field(offset_and_length, content_length));
  2272. ctoken("\r\n");
  2273. ctoken("\r\n");
  2274. if (!content(offset_and_length.first, offset_and_length.second)) {
  2275. return false;
  2276. }
  2277. ctoken("\r\n");
  2278. }
  2279. ctoken("--");
  2280. stoken(boundary);
  2281. ctoken("--");
  2282. return true;
  2283. }
  2284. void make_multipart_ranges_data(const Request &req, Response &res,
  2285. const std::string &boundary,
  2286. const std::string &content_type,
  2287. size_t content_length,
  2288. std::string &data) {
  2289. process_multipart_ranges_data(
  2290. req, boundary, content_type, content_length,
  2291. [&](const std::string &token) { data += token; },
  2292. [&](const std::string &token) { data += token; },
  2293. [&](size_t offset, size_t length) {
  2294. assert(offset + length <= content_length);
  2295. data += res.body.substr(offset, length);
  2296. return true;
  2297. });
  2298. }
  2299. size_t get_multipart_ranges_data_length(const Request &req,
  2300. const std::string &boundary,
  2301. const std::string &content_type,
  2302. size_t content_length) {
  2303. size_t data_length = 0;
  2304. process_multipart_ranges_data(
  2305. req, boundary, content_type, content_length,
  2306. [&](const std::string &token) { data_length += token.size(); },
  2307. [&](const std::string &token) { data_length += token.size(); },
  2308. [&](size_t /*offset*/, size_t length) {
  2309. data_length += length;
  2310. return true;
  2311. });
  2312. return data_length;
  2313. }
  2314. template <typename T>
  2315. bool
  2316. write_multipart_ranges_data(Stream &strm, const Request &req, Response &res,
  2317. const std::string &boundary,
  2318. const std::string &content_type,
  2319. size_t content_length, const T &is_shutting_down) {
  2320. return process_multipart_ranges_data(
  2321. req, boundary, content_type, content_length,
  2322. [&](const std::string &token) { strm.write(token); },
  2323. [&](const std::string &token) { strm.write(token); },
  2324. [&](size_t offset, size_t length) {
  2325. return write_content(strm, res.content_provider_, offset, length,
  2326. is_shutting_down);
  2327. });
  2328. }
  2329. bool expect_content(const Request &req) {
  2330. if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" ||
  2331. req.method == "DELETE") {
  2332. return true;
  2333. }
  2334. if (req.has_header("Content-Length") &&
  2335. req.get_header_value_u64("Content-Length") > 0) {
  2336. return true;
  2337. }
  2338. if (is_chunked_transfer_encoding(req.headers)) { return true; }
  2339. return false;
  2340. }
  2341. bool has_crlf(const std::string &s) {
  2342. auto p = s.c_str();
  2343. while (*p) {
  2344. if (*p == '\r' || *p == '\n') { return true; }
  2345. p++;
  2346. }
  2347. return false;
  2348. }
  2349. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  2350. std::string message_digest(const std::string &s, const EVP_MD *algo) {
  2351. auto context = std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(
  2352. EVP_MD_CTX_new(), EVP_MD_CTX_free);
  2353. unsigned int hash_length = 0;
  2354. unsigned char hash[EVP_MAX_MD_SIZE];
  2355. EVP_DigestInit_ex(context.get(), algo, nullptr);
  2356. EVP_DigestUpdate(context.get(), s.c_str(), s.size());
  2357. EVP_DigestFinal_ex(context.get(), hash, &hash_length);
  2358. std::stringstream ss;
  2359. for (auto i = 0u; i < hash_length; ++i) {
  2360. ss << std::hex << std::setw(2) << std::setfill('0')
  2361. << static_cast<unsigned int>(hash[i]);
  2362. }
  2363. return ss.str();
  2364. }
  2365. std::string MD5(const std::string &s) {
  2366. return message_digest(s, EVP_md5());
  2367. }
  2368. std::string SHA_256(const std::string &s) {
  2369. return message_digest(s, EVP_sha256());
  2370. }
  2371. std::string SHA_512(const std::string &s) {
  2372. return message_digest(s, EVP_sha512());
  2373. }
  2374. std::pair<std::string, std::string> make_digest_authentication_header(
  2375. const Request &req, const std::map<std::string, std::string> &auth,
  2376. size_t cnonce_count, const std::string &cnonce, const std::string &username,
  2377. const std::string &password, bool is_proxy = false) {
  2378. std::string nc;
  2379. {
  2380. std::stringstream ss;
  2381. ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count;
  2382. nc = ss.str();
  2383. }
  2384. std::string qop;
  2385. if (auth.find("qop") != auth.end()) {
  2386. qop = auth.at("qop");
  2387. if (qop.find("auth-int") != std::string::npos) {
  2388. qop = "auth-int";
  2389. } else if (qop.find("auth") != std::string::npos) {
  2390. qop = "auth";
  2391. } else {
  2392. qop.clear();
  2393. }
  2394. }
  2395. std::string algo = "MD5";
  2396. if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); }
  2397. std::string response;
  2398. {
  2399. auto H = algo == "SHA-256" ? detail::SHA_256
  2400. : algo == "SHA-512" ? detail::SHA_512
  2401. : detail::MD5;
  2402. auto A1 = username + ":" + auth.at("realm") + ":" + password;
  2403. auto A2 = req.method + ":" + req.path;
  2404. if (qop == "auth-int") { A2 += ":" + H(req.body); }
  2405. if (qop.empty()) {
  2406. response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2));
  2407. } else {
  2408. response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce +
  2409. ":" + qop + ":" + H(A2));
  2410. }
  2411. }
  2412. auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : "";
  2413. auto field = "Digest username=\"" + username + "\", realm=\"" +
  2414. auth.at("realm") + "\", nonce=\"" + auth.at("nonce") +
  2415. "\", uri=\"" + req.path + "\", algorithm=" + algo +
  2416. (qop.empty() ? ", response=\""
  2417. : ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" +
  2418. cnonce + "\", response=\"") +
  2419. response + "\"" +
  2420. (opaque.empty() ? "" : ", opaque=\"" + opaque + "\"");
  2421. auto key = is_proxy ? "Proxy-Authorization" : "Authorization";
  2422. return std::make_pair(key, field);
  2423. }
  2424. bool is_ssl_peer_could_be_closed(SSL *ssl, socket_t sock) {
  2425. detail::set_nonblocking(sock, true);
  2426. auto se = detail::scope_exit([&]() { detail::set_nonblocking(sock, false); });
  2427. char buf[1];
  2428. return !SSL_peek(ssl, buf, 1) &&
  2429. SSL_get_error(ssl, 0) == SSL_ERROR_ZERO_RETURN;
  2430. }
  2431. #ifdef _WIN32
  2432. // NOTE: This code came up with the following stackoverflow post:
  2433. // https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store
  2434. bool load_system_certs_on_windows(X509_STORE *store) {
  2435. auto hStore = CertOpenSystemStoreW((HCRYPTPROV_LEGACY)NULL, L"ROOT");
  2436. if (!hStore) { return false; }
  2437. auto result = false;
  2438. PCCERT_CONTEXT pContext = NULL;
  2439. while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) !=
  2440. nullptr) {
  2441. auto encoded_cert =
  2442. static_cast<const unsigned char *>(pContext->pbCertEncoded);
  2443. auto x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
  2444. if (x509) {
  2445. X509_STORE_add_cert(store, x509);
  2446. X509_free(x509);
  2447. result = true;
  2448. }
  2449. }
  2450. CertFreeCertificateContext(pContext);
  2451. CertCloseStore(hStore, 0);
  2452. return result;
  2453. }
  2454. #elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
  2455. #if TARGET_OS_OSX
  2456. template <typename T>
  2457. using CFObjectPtr =
  2458. std::unique_ptr<typename std::remove_pointer<T>::type, void (*)(CFTypeRef)>;
  2459. void cf_object_ptr_deleter(CFTypeRef obj) {
  2460. if (obj) { CFRelease(obj); }
  2461. }
  2462. bool retrieve_certs_from_keychain(CFObjectPtr<CFArrayRef> &certs) {
  2463. CFStringRef keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef};
  2464. CFTypeRef values[] = {kSecClassCertificate, kSecMatchLimitAll,
  2465. kCFBooleanTrue};
  2466. CFObjectPtr<CFDictionaryRef> query(
  2467. CFDictionaryCreate(nullptr, reinterpret_cast<const void **>(keys), values,
  2468. sizeof(keys) / sizeof(keys[0]),
  2469. &kCFTypeDictionaryKeyCallBacks,
  2470. &kCFTypeDictionaryValueCallBacks),
  2471. cf_object_ptr_deleter);
  2472. if (!query) { return false; }
  2473. CFTypeRef security_items = nullptr;
  2474. if (SecItemCopyMatching(query.get(), &security_items) != errSecSuccess ||
  2475. CFArrayGetTypeID() != CFGetTypeID(security_items)) {
  2476. return false;
  2477. }
  2478. certs.reset(reinterpret_cast<CFArrayRef>(security_items));
  2479. return true;
  2480. }
  2481. bool retrieve_root_certs_from_keychain(CFObjectPtr<CFArrayRef> &certs) {
  2482. CFArrayRef root_security_items = nullptr;
  2483. if (SecTrustCopyAnchorCertificates(&root_security_items) != errSecSuccess) {
  2484. return false;
  2485. }
  2486. certs.reset(root_security_items);
  2487. return true;
  2488. }
  2489. bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) {
  2490. auto result = false;
  2491. for (auto i = 0; i < CFArrayGetCount(certs); ++i) {
  2492. const auto cert = reinterpret_cast<const __SecCertificate *>(
  2493. CFArrayGetValueAtIndex(certs, i));
  2494. if (SecCertificateGetTypeID() != CFGetTypeID(cert)) { continue; }
  2495. CFDataRef cert_data = nullptr;
  2496. if (SecItemExport(cert, kSecFormatX509Cert, 0, nullptr, &cert_data) !=
  2497. errSecSuccess) {
  2498. continue;
  2499. }
  2500. CFObjectPtr<CFDataRef> cert_data_ptr(cert_data, cf_object_ptr_deleter);
  2501. auto encoded_cert = static_cast<const unsigned char *>(
  2502. CFDataGetBytePtr(cert_data_ptr.get()));
  2503. auto x509 =
  2504. d2i_X509(NULL, &encoded_cert, CFDataGetLength(cert_data_ptr.get()));
  2505. if (x509) {
  2506. X509_STORE_add_cert(store, x509);
  2507. X509_free(x509);
  2508. result = true;
  2509. }
  2510. }
  2511. return result;
  2512. }
  2513. bool load_system_certs_on_macos(X509_STORE *store) {
  2514. auto result = false;
  2515. CFObjectPtr<CFArrayRef> certs(nullptr, cf_object_ptr_deleter);
  2516. if (retrieve_certs_from_keychain(certs) && certs) {
  2517. result = add_certs_to_x509_store(certs.get(), store);
  2518. }
  2519. if (retrieve_root_certs_from_keychain(certs) && certs) {
  2520. result = add_certs_to_x509_store(certs.get(), store) || result;
  2521. }
  2522. return result;
  2523. }
  2524. #endif // TARGET_OS_OSX
  2525. #endif // _WIN32
  2526. #endif // CPPHTTPLIB_OPENSSL_SUPPORT
  2527. #ifdef _WIN32
  2528. class WSInit {
  2529. public:
  2530. WSInit() {
  2531. WSADATA wsaData;
  2532. if (WSAStartup(0x0002, &wsaData) == 0) is_valid_ = true;
  2533. }
  2534. ~WSInit() {
  2535. if (is_valid_) WSACleanup();
  2536. }
  2537. bool is_valid_ = false;
  2538. };
  2539. static WSInit wsinit_;
  2540. #endif
  2541. bool parse_www_authenticate(const Response &res,
  2542. std::map<std::string, std::string> &auth,
  2543. bool is_proxy) {
  2544. auto auth_key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
  2545. if (res.has_header(auth_key)) {
  2546. thread_local auto re =
  2547. std::regex(R"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~");
  2548. auto s = res.get_header_value(auth_key);
  2549. auto pos = s.find(' ');
  2550. if (pos != std::string::npos) {
  2551. auto type = s.substr(0, pos);
  2552. if (type == "Basic") {
  2553. return false;
  2554. } else if (type == "Digest") {
  2555. s = s.substr(pos + 1);
  2556. auto beg = std::sregex_iterator(s.begin(), s.end(), re);
  2557. for (auto i = beg; i != std::sregex_iterator(); ++i) {
  2558. const auto &m = *i;
  2559. auto key = s.substr(static_cast<size_t>(m.position(1)),
  2560. static_cast<size_t>(m.length(1)));
  2561. auto val = m.length(2) > 0
  2562. ? s.substr(static_cast<size_t>(m.position(2)),
  2563. static_cast<size_t>(m.length(2)))
  2564. : s.substr(static_cast<size_t>(m.position(3)),
  2565. static_cast<size_t>(m.length(3)));
  2566. auth[key] = val;
  2567. }
  2568. return true;
  2569. }
  2570. }
  2571. }
  2572. return false;
  2573. }
  2574. class ContentProviderAdapter {
  2575. public:
  2576. explicit ContentProviderAdapter(
  2577. ContentProviderWithoutLength &&content_provider)
  2578. : content_provider_(content_provider) {}
  2579. bool operator()(size_t offset, size_t, DataSink &sink) {
  2580. return content_provider_(offset, sink);
  2581. }
  2582. private:
  2583. ContentProviderWithoutLength content_provider_;
  2584. };
  2585. } // namespace detail
  2586. std::string hosted_at(const std::string &hostname) {
  2587. std::vector<std::string> addrs;
  2588. hosted_at(hostname, addrs);
  2589. if (addrs.empty()) { return std::string(); }
  2590. return addrs[0];
  2591. }
  2592. void hosted_at(const std::string &hostname,
  2593. std::vector<std::string> &addrs) {
  2594. struct addrinfo hints;
  2595. struct addrinfo *result;
  2596. memset(&hints, 0, sizeof(struct addrinfo));
  2597. hints.ai_family = AF_UNSPEC;
  2598. hints.ai_socktype = SOCK_STREAM;
  2599. hints.ai_protocol = 0;
  2600. if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result)) {
  2601. #if defined __linux__ && !defined __ANDROID__
  2602. res_init();
  2603. #endif
  2604. return;
  2605. }
  2606. auto se = detail::scope_exit([&] { freeaddrinfo(result); });
  2607. for (auto rp = result; rp; rp = rp->ai_next) {
  2608. const auto &addr =
  2609. *reinterpret_cast<struct sockaddr_storage *>(rp->ai_addr);
  2610. std::string ip;
  2611. auto dummy = -1;
  2612. if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), ip,
  2613. dummy)) {
  2614. addrs.push_back(ip);
  2615. }
  2616. }
  2617. }
  2618. std::string append_query_params(const std::string &path,
  2619. const Params &params) {
  2620. std::string path_with_query = path;
  2621. thread_local const std::regex re("[^?]+\\?.*");
  2622. auto delm = std::regex_match(path, re) ? '&' : '?';
  2623. path_with_query += delm + detail::params_to_query_str(params);
  2624. return path_with_query;
  2625. }
  2626. // Header utilities
  2627. std::pair<std::string, std::string>
  2628. make_range_header(const Ranges &ranges) {
  2629. std::string field = "bytes=";
  2630. auto i = 0;
  2631. for (const auto &r : ranges) {
  2632. if (i != 0) { field += ", "; }
  2633. if (r.first != -1) { field += std::to_string(r.first); }
  2634. field += '-';
  2635. if (r.second != -1) { field += std::to_string(r.second); }
  2636. i++;
  2637. }
  2638. return std::make_pair("Range", std::move(field));
  2639. }
  2640. std::pair<std::string, std::string>
  2641. make_basic_authentication_header(const std::string &username,
  2642. const std::string &password, bool is_proxy) {
  2643. auto field = "Basic " + detail::base64_encode(username + ":" + password);
  2644. auto key = is_proxy ? "Proxy-Authorization" : "Authorization";
  2645. return std::make_pair(key, std::move(field));
  2646. }
  2647. std::pair<std::string, std::string>
  2648. make_bearer_token_authentication_header(const std::string &token,
  2649. bool is_proxy = false) {
  2650. auto field = "Bearer " + token;
  2651. auto key = is_proxy ? "Proxy-Authorization" : "Authorization";
  2652. return std::make_pair(key, std::move(field));
  2653. }
  2654. // Request implementation
  2655. bool Request::has_header(const std::string &key) const {
  2656. return detail::has_header(headers, key);
  2657. }
  2658. std::string Request::get_header_value(const std::string &key,
  2659. const char *def, size_t id) const {
  2660. return detail::get_header_value(headers, key, def, id);
  2661. }
  2662. size_t Request::get_header_value_count(const std::string &key) const {
  2663. auto r = headers.equal_range(key);
  2664. return static_cast<size_t>(std::distance(r.first, r.second));
  2665. }
  2666. void Request::set_header(const std::string &key,
  2667. const std::string &val) {
  2668. if (detail::fields::is_field_name(key) &&
  2669. detail::fields::is_field_value(val)) {
  2670. headers.emplace(key, val);
  2671. }
  2672. }
  2673. bool Request::has_param(const std::string &key) const {
  2674. return params.find(key) != params.end();
  2675. }
  2676. std::string Request::get_param_value(const std::string &key,
  2677. size_t id) const {
  2678. auto rng = params.equal_range(key);
  2679. auto it = rng.first;
  2680. std::advance(it, static_cast<ssize_t>(id));
  2681. if (it != rng.second) { return it->second; }
  2682. return std::string();
  2683. }
  2684. size_t Request::get_param_value_count(const std::string &key) const {
  2685. auto r = params.equal_range(key);
  2686. return static_cast<size_t>(std::distance(r.first, r.second));
  2687. }
  2688. bool Request::is_multipart_form_data() const {
  2689. const auto &content_type = get_header_value("Content-Type");
  2690. return !content_type.rfind("multipart/form-data", 0);
  2691. }
  2692. bool Request::has_file(const std::string &key) const {
  2693. return files.find(key) != files.end();
  2694. }
  2695. MultipartFormData Request::get_file_value(const std::string &key) const {
  2696. auto it = files.find(key);
  2697. if (it != files.end()) { return it->second; }
  2698. return MultipartFormData();
  2699. }
  2700. std::vector<MultipartFormData>
  2701. Request::get_file_values(const std::string &key) const {
  2702. std::vector<MultipartFormData> values;
  2703. auto rng = files.equal_range(key);
  2704. for (auto it = rng.first; it != rng.second; it++) {
  2705. values.push_back(it->second);
  2706. }
  2707. return values;
  2708. }
  2709. // Response implementation
  2710. bool Response::has_header(const std::string &key) const {
  2711. return headers.find(key) != headers.end();
  2712. }
  2713. std::string Response::get_header_value(const std::string &key,
  2714. const char *def,
  2715. size_t id) const {
  2716. return detail::get_header_value(headers, key, def, id);
  2717. }
  2718. size_t Response::get_header_value_count(const std::string &key) const {
  2719. auto r = headers.equal_range(key);
  2720. return static_cast<size_t>(std::distance(r.first, r.second));
  2721. }
  2722. void Response::set_header(const std::string &key,
  2723. const std::string &val) {
  2724. if (detail::fields::is_field_name(key) &&
  2725. detail::fields::is_field_value(val)) {
  2726. headers.emplace(key, val);
  2727. }
  2728. }
  2729. void Response::set_redirect(const std::string &url, int stat) {
  2730. if (detail::fields::is_field_value(url)) {
  2731. set_header("Location", url);
  2732. if (300 <= stat && stat < 400) {
  2733. this->status = stat;
  2734. } else {
  2735. this->status = StatusCode::Found_302;
  2736. }
  2737. }
  2738. }
  2739. void Response::set_content(const char *s, size_t n,
  2740. const std::string &content_type) {
  2741. body.assign(s, n);
  2742. auto rng = headers.equal_range("Content-Type");
  2743. headers.erase(rng.first, rng.second);
  2744. set_header("Content-Type", content_type);
  2745. }
  2746. void Response::set_content(const std::string &s,
  2747. const std::string &content_type) {
  2748. set_content(s.data(), s.size(), content_type);
  2749. }
  2750. void Response::set_content(std::string &&s,
  2751. const std::string &content_type) {
  2752. body = std::move(s);
  2753. auto rng = headers.equal_range("Content-Type");
  2754. headers.erase(rng.first, rng.second);
  2755. set_header("Content-Type", content_type);
  2756. }
  2757. void Response::set_content_provider(
  2758. size_t in_length, const std::string &content_type, ContentProvider provider,
  2759. ContentProviderResourceReleaser resource_releaser) {
  2760. set_header("Content-Type", content_type);
  2761. content_length_ = in_length;
  2762. if (in_length > 0) { content_provider_ = std::move(provider); }
  2763. content_provider_resource_releaser_ = std::move(resource_releaser);
  2764. is_chunked_content_provider_ = false;
  2765. }
  2766. void Response::set_content_provider(
  2767. const std::string &content_type, ContentProviderWithoutLength provider,
  2768. ContentProviderResourceReleaser resource_releaser) {
  2769. set_header("Content-Type", content_type);
  2770. content_length_ = 0;
  2771. content_provider_ = detail::ContentProviderAdapter(std::move(provider));
  2772. content_provider_resource_releaser_ = std::move(resource_releaser);
  2773. is_chunked_content_provider_ = false;
  2774. }
  2775. void Response::set_chunked_content_provider(
  2776. const std::string &content_type, ContentProviderWithoutLength provider,
  2777. ContentProviderResourceReleaser resource_releaser) {
  2778. set_header("Content-Type", content_type);
  2779. content_length_ = 0;
  2780. content_provider_ = detail::ContentProviderAdapter(std::move(provider));
  2781. content_provider_resource_releaser_ = std::move(resource_releaser);
  2782. is_chunked_content_provider_ = true;
  2783. }
  2784. void Response::set_file_content(const std::string &path,
  2785. const std::string &content_type) {
  2786. file_content_path_ = path;
  2787. file_content_content_type_ = content_type;
  2788. }
  2789. void Response::set_file_content(const std::string &path) {
  2790. file_content_path_ = path;
  2791. }
  2792. // Result implementation
  2793. bool Result::has_request_header(const std::string &key) const {
  2794. return request_headers_.find(key) != request_headers_.end();
  2795. }
  2796. std::string Result::get_request_header_value(const std::string &key,
  2797. const char *def,
  2798. size_t id) const {
  2799. return detail::get_header_value(request_headers_, key, def, id);
  2800. }
  2801. size_t
  2802. Result::get_request_header_value_count(const std::string &key) const {
  2803. auto r = request_headers_.equal_range(key);
  2804. return static_cast<size_t>(std::distance(r.first, r.second));
  2805. }
  2806. // Stream implementation
  2807. ssize_t Stream::write(const char *ptr) {
  2808. return write(ptr, strlen(ptr));
  2809. }
  2810. ssize_t Stream::write(const std::string &s) {
  2811. return write(s.data(), s.size());
  2812. }
  2813. namespace detail {
  2814. void calc_actual_timeout(time_t max_timeout_msec, time_t duration_msec,
  2815. time_t timeout_sec, time_t timeout_usec,
  2816. time_t &actual_timeout_sec,
  2817. time_t &actual_timeout_usec) {
  2818. auto timeout_msec = (timeout_sec * 1000) + (timeout_usec / 1000);
  2819. auto actual_timeout_msec =
  2820. (std::min)(max_timeout_msec - duration_msec, timeout_msec);
  2821. if (actual_timeout_msec < 0) { actual_timeout_msec = 0; }
  2822. actual_timeout_sec = actual_timeout_msec / 1000;
  2823. actual_timeout_usec = (actual_timeout_msec % 1000) * 1000;
  2824. }
  2825. // Socket stream implementation
  2826. SocketStream::SocketStream(
  2827. socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
  2828. time_t write_timeout_sec, time_t write_timeout_usec,
  2829. time_t max_timeout_msec,
  2830. std::chrono::time_point<std::chrono::steady_clock> start_time)
  2831. : sock_(sock), read_timeout_sec_(read_timeout_sec),
  2832. read_timeout_usec_(read_timeout_usec),
  2833. write_timeout_sec_(write_timeout_sec),
  2834. write_timeout_usec_(write_timeout_usec),
  2835. max_timeout_msec_(max_timeout_msec), start_time_(start_time),
  2836. read_buff_(read_buff_size_, 0) {}
  2837. SocketStream::~SocketStream() = default;
  2838. bool SocketStream::is_readable() const {
  2839. return read_buff_off_ < read_buff_content_size_;
  2840. }
  2841. bool SocketStream::wait_readable() const {
  2842. if (max_timeout_msec_ <= 0) {
  2843. return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
  2844. }
  2845. time_t read_timeout_sec;
  2846. time_t read_timeout_usec;
  2847. calc_actual_timeout(max_timeout_msec_, duration(), read_timeout_sec_,
  2848. read_timeout_usec_, read_timeout_sec, read_timeout_usec);
  2849. return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
  2850. }
  2851. bool SocketStream::wait_writable() const {
  2852. return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
  2853. is_socket_alive(sock_);
  2854. }
  2855. ssize_t SocketStream::read(char *ptr, size_t size) {
  2856. #ifdef _WIN32
  2857. size =
  2858. (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
  2859. #else
  2860. size = (std::min)(size,
  2861. static_cast<size_t>((std::numeric_limits<ssize_t>::max)()));
  2862. #endif
  2863. if (read_buff_off_ < read_buff_content_size_) {
  2864. auto remaining_size = read_buff_content_size_ - read_buff_off_;
  2865. if (size <= remaining_size) {
  2866. memcpy(ptr, read_buff_.data() + read_buff_off_, size);
  2867. read_buff_off_ += size;
  2868. return static_cast<ssize_t>(size);
  2869. } else {
  2870. memcpy(ptr, read_buff_.data() + read_buff_off_, remaining_size);
  2871. read_buff_off_ += remaining_size;
  2872. return static_cast<ssize_t>(remaining_size);
  2873. }
  2874. }
  2875. if (!wait_readable()) { return -1; }
  2876. read_buff_off_ = 0;
  2877. read_buff_content_size_ = 0;
  2878. if (size < read_buff_size_) {
  2879. auto n = read_socket(sock_, read_buff_.data(), read_buff_size_,
  2880. CPPHTTPLIB_RECV_FLAGS);
  2881. if (n <= 0) {
  2882. return n;
  2883. } else if (n <= static_cast<ssize_t>(size)) {
  2884. memcpy(ptr, read_buff_.data(), static_cast<size_t>(n));
  2885. return n;
  2886. } else {
  2887. memcpy(ptr, read_buff_.data(), size);
  2888. read_buff_off_ = size;
  2889. read_buff_content_size_ = static_cast<size_t>(n);
  2890. return static_cast<ssize_t>(size);
  2891. }
  2892. } else {
  2893. return read_socket(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS);
  2894. }
  2895. }
  2896. ssize_t SocketStream::write(const char *ptr, size_t size) {
  2897. if (!wait_writable()) { return -1; }
  2898. #if defined(_WIN32) && !defined(_WIN64)
  2899. size =
  2900. (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
  2901. #endif
  2902. return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS);
  2903. }
  2904. void SocketStream::get_remote_ip_and_port(std::string &ip,
  2905. int &port) const {
  2906. return detail::get_remote_ip_and_port(sock_, ip, port);
  2907. }
  2908. void SocketStream::get_local_ip_and_port(std::string &ip,
  2909. int &port) const {
  2910. return detail::get_local_ip_and_port(sock_, ip, port);
  2911. }
  2912. socket_t SocketStream::socket() const { return sock_; }
  2913. time_t SocketStream::duration() const {
  2914. return std::chrono::duration_cast<std::chrono::milliseconds>(
  2915. std::chrono::steady_clock::now() - start_time_)
  2916. .count();
  2917. }
  2918. // Buffer stream implementation
  2919. bool BufferStream::is_readable() const { return true; }
  2920. bool BufferStream::wait_readable() const { return true; }
  2921. bool BufferStream::wait_writable() const { return true; }
  2922. ssize_t BufferStream::read(char *ptr, size_t size) {
  2923. #if defined(_MSC_VER) && _MSC_VER < 1910
  2924. auto len_read = buffer._Copy_s(ptr, size, size, position);
  2925. #else
  2926. auto len_read = buffer.copy(ptr, size, position);
  2927. #endif
  2928. position += static_cast<size_t>(len_read);
  2929. return static_cast<ssize_t>(len_read);
  2930. }
  2931. ssize_t BufferStream::write(const char *ptr, size_t size) {
  2932. buffer.append(ptr, size);
  2933. return static_cast<ssize_t>(size);
  2934. }
  2935. void BufferStream::get_remote_ip_and_port(std::string & /*ip*/,
  2936. int & /*port*/) const {}
  2937. void BufferStream::get_local_ip_and_port(std::string & /*ip*/,
  2938. int & /*port*/) const {}
  2939. socket_t BufferStream::socket() const { return 0; }
  2940. time_t BufferStream::duration() const { return 0; }
  2941. const std::string &BufferStream::get_buffer() const { return buffer; }
  2942. PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
  2943. constexpr const char marker[] = "/:";
  2944. // One past the last ending position of a path param substring
  2945. std::size_t last_param_end = 0;
  2946. #ifndef CPPHTTPLIB_NO_EXCEPTIONS
  2947. // Needed to ensure that parameter names are unique during matcher
  2948. // construction
  2949. // If exceptions are disabled, only last duplicate path
  2950. // parameter will be set
  2951. std::unordered_set<std::string> param_name_set;
  2952. #endif
  2953. while (true) {
  2954. const auto marker_pos = pattern.find(
  2955. marker, last_param_end == 0 ? last_param_end : last_param_end - 1);
  2956. if (marker_pos == std::string::npos) { break; }
  2957. static_fragments_.push_back(
  2958. pattern.substr(last_param_end, marker_pos - last_param_end + 1));
  2959. const auto param_name_start = marker_pos + str_len(marker);
  2960. auto sep_pos = pattern.find(separator, param_name_start);
  2961. if (sep_pos == std::string::npos) { sep_pos = pattern.length(); }
  2962. auto param_name =
  2963. pattern.substr(param_name_start, sep_pos - param_name_start);
  2964. #ifndef CPPHTTPLIB_NO_EXCEPTIONS
  2965. if (param_name_set.find(param_name) != param_name_set.cend()) {
  2966. std::string msg = "Encountered path parameter '" + param_name +
  2967. "' multiple times in route pattern '" + pattern + "'.";
  2968. throw std::invalid_argument(msg);
  2969. }
  2970. #endif
  2971. param_names_.push_back(std::move(param_name));
  2972. last_param_end = sep_pos + 1;
  2973. }
  2974. if (last_param_end < pattern.length()) {
  2975. static_fragments_.push_back(pattern.substr(last_param_end));
  2976. }
  2977. }
  2978. bool PathParamsMatcher::match(Request &request) const {
  2979. request.matches = std::smatch();
  2980. request.path_params.clear();
  2981. request.path_params.reserve(param_names_.size());
  2982. // One past the position at which the path matched the pattern last time
  2983. std::size_t starting_pos = 0;
  2984. for (size_t i = 0; i < static_fragments_.size(); ++i) {
  2985. const auto &fragment = static_fragments_[i];
  2986. if (starting_pos + fragment.length() > request.path.length()) {
  2987. return false;
  2988. }
  2989. // Avoid unnecessary allocation by using strncmp instead of substr +
  2990. // comparison
  2991. if (std::strncmp(request.path.c_str() + starting_pos, fragment.c_str(),
  2992. fragment.length()) != 0) {
  2993. return false;
  2994. }
  2995. starting_pos += fragment.length();
  2996. // Should only happen when we have a static fragment after a param
  2997. // Example: '/users/:id/subscriptions'
  2998. // The 'subscriptions' fragment here does not have a corresponding param
  2999. if (i >= param_names_.size()) { continue; }
  3000. auto sep_pos = request.path.find(separator, starting_pos);
  3001. if (sep_pos == std::string::npos) { sep_pos = request.path.length(); }
  3002. const auto &param_name = param_names_[i];
  3003. request.path_params.emplace(
  3004. param_name, request.path.substr(starting_pos, sep_pos - starting_pos));
  3005. // Mark everything up to '/' as matched
  3006. starting_pos = sep_pos + 1;
  3007. }
  3008. // Returns false if the path is longer than the pattern
  3009. return starting_pos >= request.path.length();
  3010. }
  3011. bool RegexMatcher::match(Request &request) const {
  3012. request.path_params.clear();
  3013. return std::regex_match(request.path, request.matches, regex_);
  3014. }
  3015. } // namespace detail
  3016. // HTTP server implementation
  3017. Server::Server()
  3018. : new_task_queue(
  3019. [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) {
  3020. #ifndef _WIN32
  3021. signal(SIGPIPE, SIG_IGN);
  3022. #endif
  3023. }
  3024. Server::~Server() = default;
  3025. std::unique_ptr<detail::MatcherBase>
  3026. Server::make_matcher(const std::string &pattern) {
  3027. if (pattern.find("/:") != std::string::npos) {
  3028. return detail::make_unique<detail::PathParamsMatcher>(pattern);
  3029. } else {
  3030. return detail::make_unique<detail::RegexMatcher>(pattern);
  3031. }
  3032. }
  3033. Server &Server::Get(const std::string &pattern, Handler handler) {
  3034. get_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3035. return *this;
  3036. }
  3037. Server &Server::Post(const std::string &pattern, Handler handler) {
  3038. post_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3039. return *this;
  3040. }
  3041. Server &Server::Post(const std::string &pattern,
  3042. HandlerWithContentReader handler) {
  3043. post_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
  3044. std::move(handler));
  3045. return *this;
  3046. }
  3047. Server &Server::Put(const std::string &pattern, Handler handler) {
  3048. put_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3049. return *this;
  3050. }
  3051. Server &Server::Put(const std::string &pattern,
  3052. HandlerWithContentReader handler) {
  3053. put_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
  3054. std::move(handler));
  3055. return *this;
  3056. }
  3057. Server &Server::Patch(const std::string &pattern, Handler handler) {
  3058. patch_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3059. return *this;
  3060. }
  3061. Server &Server::Patch(const std::string &pattern,
  3062. HandlerWithContentReader handler) {
  3063. patch_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
  3064. std::move(handler));
  3065. return *this;
  3066. }
  3067. Server &Server::Delete(const std::string &pattern, Handler handler) {
  3068. delete_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3069. return *this;
  3070. }
  3071. Server &Server::Delete(const std::string &pattern,
  3072. HandlerWithContentReader handler) {
  3073. delete_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
  3074. std::move(handler));
  3075. return *this;
  3076. }
  3077. Server &Server::Options(const std::string &pattern, Handler handler) {
  3078. options_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
  3079. return *this;
  3080. }
  3081. bool Server::set_base_dir(const std::string &dir,
  3082. const std::string &mount_point) {
  3083. return set_mount_point(mount_point, dir);
  3084. }
  3085. bool Server::set_mount_point(const std::string &mount_point,
  3086. const std::string &dir, Headers headers) {
  3087. detail::FileStat stat(dir);
  3088. if (stat.is_dir()) {
  3089. std::string mnt = !mount_point.empty() ? mount_point : "/";
  3090. if (!mnt.empty() && mnt[0] == '/') {
  3091. base_dirs_.push_back({mnt, dir, std::move(headers)});
  3092. return true;
  3093. }
  3094. }
  3095. return false;
  3096. }
  3097. bool Server::remove_mount_point(const std::string &mount_point) {
  3098. for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) {
  3099. if (it->mount_point == mount_point) {
  3100. base_dirs_.erase(it);
  3101. return true;
  3102. }
  3103. }
  3104. return false;
  3105. }
  3106. Server &
  3107. Server::set_file_extension_and_mimetype_mapping(const std::string &ext,
  3108. const std::string &mime) {
  3109. file_extension_and_mimetype_map_[ext] = mime;
  3110. return *this;
  3111. }
  3112. Server &Server::set_default_file_mimetype(const std::string &mime) {
  3113. default_file_mimetype_ = mime;
  3114. return *this;
  3115. }
  3116. Server &Server::set_file_request_handler(Handler handler) {
  3117. file_request_handler_ = std::move(handler);
  3118. return *this;
  3119. }
  3120. Server &Server::set_error_handler_core(HandlerWithResponse handler,
  3121. std::true_type) {
  3122. error_handler_ = std::move(handler);
  3123. return *this;
  3124. }
  3125. Server &Server::set_error_handler_core(Handler handler,
  3126. std::false_type) {
  3127. error_handler_ = [handler](const Request &req, Response &res) {
  3128. handler(req, res);
  3129. return HandlerResponse::Handled;
  3130. };
  3131. return *this;
  3132. }
  3133. Server &Server::set_exception_handler(ExceptionHandler handler) {
  3134. exception_handler_ = std::move(handler);
  3135. return *this;
  3136. }
  3137. Server &Server::set_pre_routing_handler(HandlerWithResponse handler) {
  3138. pre_routing_handler_ = std::move(handler);
  3139. return *this;
  3140. }
  3141. Server &Server::set_post_routing_handler(Handler handler) {
  3142. post_routing_handler_ = std::move(handler);
  3143. return *this;
  3144. }
  3145. Server &Server::set_logger(Logger logger) {
  3146. logger_ = std::move(logger);
  3147. return *this;
  3148. }
  3149. Server &
  3150. Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) {
  3151. expect_100_continue_handler_ = std::move(handler);
  3152. return *this;
  3153. }
  3154. Server &Server::set_address_family(int family) {
  3155. address_family_ = family;
  3156. return *this;
  3157. }
  3158. Server &Server::set_tcp_nodelay(bool on) {
  3159. tcp_nodelay_ = on;
  3160. return *this;
  3161. }
  3162. Server &Server::set_ipv6_v6only(bool on) {
  3163. ipv6_v6only_ = on;
  3164. return *this;
  3165. }
  3166. Server &Server::set_socket_options(SocketOptions socket_options) {
  3167. socket_options_ = std::move(socket_options);
  3168. return *this;
  3169. }
  3170. Server &Server::set_default_headers(Headers headers) {
  3171. default_headers_ = std::move(headers);
  3172. return *this;
  3173. }
  3174. Server &Server::set_header_writer(
  3175. std::function<ssize_t(Stream &, Headers &)> const &writer) {
  3176. header_writer_ = writer;
  3177. return *this;
  3178. }
  3179. Server &Server::set_keep_alive_max_count(size_t count) {
  3180. keep_alive_max_count_ = count;
  3181. return *this;
  3182. }
  3183. Server &Server::set_keep_alive_timeout(time_t sec) {
  3184. keep_alive_timeout_sec_ = sec;
  3185. return *this;
  3186. }
  3187. Server &Server::set_read_timeout(time_t sec, time_t usec) {
  3188. read_timeout_sec_ = sec;
  3189. read_timeout_usec_ = usec;
  3190. return *this;
  3191. }
  3192. Server &Server::set_write_timeout(time_t sec, time_t usec) {
  3193. write_timeout_sec_ = sec;
  3194. write_timeout_usec_ = usec;
  3195. return *this;
  3196. }
  3197. Server &Server::set_idle_interval(time_t sec, time_t usec) {
  3198. idle_interval_sec_ = sec;
  3199. idle_interval_usec_ = usec;
  3200. return *this;
  3201. }
  3202. Server &Server::set_payload_max_length(size_t length) {
  3203. payload_max_length_ = length;
  3204. return *this;
  3205. }
  3206. bool Server::bind_to_port(const std::string &host, int port,
  3207. int socket_flags) {
  3208. auto ret = bind_internal(host, port, socket_flags);
  3209. if (ret == -1) { is_decommissioned = true; }
  3210. return ret >= 0;
  3211. }
  3212. int Server::bind_to_any_port(const std::string &host, int socket_flags) {
  3213. auto ret = bind_internal(host, 0, socket_flags);
  3214. if (ret == -1) { is_decommissioned = true; }
  3215. return ret;
  3216. }
  3217. bool Server::listen_after_bind() { return listen_internal(); }
  3218. bool Server::listen(const std::string &host, int port,
  3219. int socket_flags) {
  3220. return bind_to_port(host, port, socket_flags) && listen_internal();
  3221. }
  3222. bool Server::is_running() const { return is_running_; }
  3223. void Server::wait_until_ready() const {
  3224. while (!is_running_ && !is_decommissioned) {
  3225. std::this_thread::sleep_for(std::chrono::milliseconds{1});
  3226. }
  3227. }
  3228. void Server::stop() {
  3229. if (is_running_) {
  3230. assert(svr_sock_ != INVALID_SOCKET);
  3231. std::atomic<socket_t> sock(svr_sock_.exchange(INVALID_SOCKET));
  3232. detail::shutdown_socket(sock);
  3233. detail::close_socket(sock);
  3234. }
  3235. is_decommissioned = false;
  3236. }
  3237. void Server::decommission() { is_decommissioned = true; }
  3238. bool Server::parse_request_line(const char *s, Request &req) const {
  3239. auto len = strlen(s);
  3240. if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; }
  3241. len -= 2;
  3242. {
  3243. size_t count = 0;
  3244. detail::split(s, s + len, ' ', [&](const char *b, const char *e) {
  3245. switch (count) {
  3246. case 0: req.method = std::string(b, e); break;
  3247. case 1: req.target = std::string(b, e); break;
  3248. case 2: req.version = std::string(b, e); break;
  3249. default: break;
  3250. }
  3251. count++;
  3252. });
  3253. if (count != 3) { return false; }
  3254. }
  3255. thread_local const std::set<std::string> methods{
  3256. "GET", "HEAD", "POST", "PUT", "DELETE",
  3257. "CONNECT", "OPTIONS", "TRACE", "PATCH", "PRI"};
  3258. if (methods.find(req.method) == methods.end()) { return false; }
  3259. if (req.version != "HTTP/1.1" && req.version != "HTTP/1.0") { return false; }
  3260. {
  3261. // Skip URL fragment
  3262. for (size_t i = 0; i < req.target.size(); i++) {
  3263. if (req.target[i] == '#') {
  3264. req.target.erase(i);
  3265. break;
  3266. }
  3267. }
  3268. detail::divide(req.target, '?',
  3269. [&](const char *lhs_data, std::size_t lhs_size,
  3270. const char *rhs_data, std::size_t rhs_size) {
  3271. req.path = detail::decode_url(
  3272. std::string(lhs_data, lhs_size), false);
  3273. detail::parse_query_text(rhs_data, rhs_size, req.params);
  3274. });
  3275. }
  3276. return true;
  3277. }
  3278. bool Server::write_response(Stream &strm, bool close_connection,
  3279. Request &req, Response &res) {
  3280. // NOTE: `req.ranges` should be empty, otherwise it will be applied
  3281. // incorrectly to the error content.
  3282. req.ranges.clear();
  3283. return write_response_core(strm, close_connection, req, res, false);
  3284. }
  3285. bool Server::write_response_with_content(Stream &strm,
  3286. bool close_connection,
  3287. const Request &req,
  3288. Response &res) {
  3289. return write_response_core(strm, close_connection, req, res, true);
  3290. }
  3291. bool Server::write_response_core(Stream &strm, bool close_connection,
  3292. const Request &req, Response &res,
  3293. bool need_apply_ranges) {
  3294. assert(res.status != -1);
  3295. if (400 <= res.status && error_handler_ &&
  3296. error_handler_(req, res) == HandlerResponse::Handled) {
  3297. need_apply_ranges = true;
  3298. }
  3299. std::string content_type;
  3300. std::string boundary;
  3301. if (need_apply_ranges) { apply_ranges(req, res, content_type, boundary); }
  3302. // Prepare additional headers
  3303. if (close_connection || req.get_header_value("Connection") == "close") {
  3304. res.set_header("Connection", "close");
  3305. } else {
  3306. std::string s = "timeout=";
  3307. s += std::to_string(keep_alive_timeout_sec_);
  3308. s += ", max=";
  3309. s += std::to_string(keep_alive_max_count_);
  3310. res.set_header("Keep-Alive", s);
  3311. }
  3312. if ((!res.body.empty() || res.content_length_ > 0 || res.content_provider_) &&
  3313. !res.has_header("Content-Type")) {
  3314. res.set_header("Content-Type", "text/plain");
  3315. }
  3316. if (res.body.empty() && !res.content_length_ && !res.content_provider_ &&
  3317. !res.has_header("Content-Length")) {
  3318. res.set_header("Content-Length", "0");
  3319. }
  3320. if (req.method == "HEAD" && !res.has_header("Accept-Ranges")) {
  3321. res.set_header("Accept-Ranges", "bytes");
  3322. }
  3323. if (post_routing_handler_) { post_routing_handler_(req, res); }
  3324. // Response line and headers
  3325. {
  3326. detail::BufferStream bstrm;
  3327. if (!detail::write_response_line(bstrm, res.status)) { return false; }
  3328. if (!header_writer_(bstrm, res.headers)) { return false; }
  3329. // Flush buffer
  3330. auto &data = bstrm.get_buffer();
  3331. detail::write_data(strm, data.data(), data.size());
  3332. }
  3333. // Body
  3334. auto ret = true;
  3335. if (req.method != "HEAD") {
  3336. if (!res.body.empty()) {
  3337. if (!detail::write_data(strm, res.body.data(), res.body.size())) {
  3338. ret = false;
  3339. }
  3340. } else if (res.content_provider_) {
  3341. if (write_content_with_provider(strm, req, res, boundary, content_type)) {
  3342. res.content_provider_success_ = true;
  3343. } else {
  3344. ret = false;
  3345. }
  3346. }
  3347. }
  3348. // Log
  3349. if (logger_) { logger_(req, res); }
  3350. return ret;
  3351. }
  3352. bool
  3353. Server::write_content_with_provider(Stream &strm, const Request &req,
  3354. Response &res, const std::string &boundary,
  3355. const std::string &content_type) {
  3356. auto is_shutting_down = [this]() {
  3357. return this->svr_sock_ == INVALID_SOCKET;
  3358. };
  3359. if (res.content_length_ > 0) {
  3360. if (req.ranges.empty()) {
  3361. return detail::write_content(strm, res.content_provider_, 0,
  3362. res.content_length_, is_shutting_down);
  3363. } else if (req.ranges.size() == 1) {
  3364. auto offset_and_length = detail::get_range_offset_and_length(
  3365. req.ranges[0], res.content_length_);
  3366. return detail::write_content(strm, res.content_provider_,
  3367. offset_and_length.first,
  3368. offset_and_length.second, is_shutting_down);
  3369. } else {
  3370. return detail::write_multipart_ranges_data(
  3371. strm, req, res, boundary, content_type, res.content_length_,
  3372. is_shutting_down);
  3373. }
  3374. } else {
  3375. if (res.is_chunked_content_provider_) {
  3376. auto type = detail::encoding_type(req, res);
  3377. std::unique_ptr<detail::compressor> compressor;
  3378. if (type == detail::EncodingType::Gzip) {
  3379. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  3380. compressor = detail::make_unique<detail::gzip_compressor>();
  3381. #endif
  3382. } else if (type == detail::EncodingType::Brotli) {
  3383. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  3384. compressor = detail::make_unique<detail::brotli_compressor>();
  3385. #endif
  3386. } else if (type == detail::EncodingType::Zstd) {
  3387. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  3388. compressor = detail::make_unique<detail::zstd_compressor>();
  3389. #endif
  3390. } else {
  3391. compressor = detail::make_unique<detail::nocompressor>();
  3392. }
  3393. assert(compressor != nullptr);
  3394. return detail::write_content_chunked(strm, res.content_provider_,
  3395. is_shutting_down, *compressor);
  3396. } else {
  3397. return detail::write_content_without_length(strm, res.content_provider_,
  3398. is_shutting_down);
  3399. }
  3400. }
  3401. }
  3402. bool Server::read_content(Stream &strm, Request &req, Response &res) {
  3403. MultipartFormDataMap::iterator cur;
  3404. auto file_count = 0;
  3405. if (read_content_core(
  3406. strm, req, res,
  3407. // Regular
  3408. [&](const char *buf, size_t n) {
  3409. if (req.body.size() + n > req.body.max_size()) { return false; }
  3410. req.body.append(buf, n);
  3411. return true;
  3412. },
  3413. // Multipart
  3414. [&](const MultipartFormData &file) {
  3415. if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) {
  3416. return false;
  3417. }
  3418. cur = req.files.emplace(file.name, file);
  3419. return true;
  3420. },
  3421. [&](const char *buf, size_t n) {
  3422. auto &content = cur->second.content;
  3423. if (content.size() + n > content.max_size()) { return false; }
  3424. content.append(buf, n);
  3425. return true;
  3426. })) {
  3427. const auto &content_type = req.get_header_value("Content-Type");
  3428. if (!content_type.find("application/x-www-form-urlencoded")) {
  3429. if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) {
  3430. res.status = StatusCode::PayloadTooLarge_413; // NOTE: should be 414?
  3431. return false;
  3432. }
  3433. detail::parse_query_text(req.body, req.params);
  3434. }
  3435. return true;
  3436. }
  3437. return false;
  3438. }
  3439. bool Server::read_content_with_content_receiver(
  3440. Stream &strm, Request &req, Response &res, ContentReceiver receiver,
  3441. MultipartContentHeader multipart_header,
  3442. ContentReceiver multipart_receiver) {
  3443. return read_content_core(strm, req, res, std::move(receiver),
  3444. std::move(multipart_header),
  3445. std::move(multipart_receiver));
  3446. }
  3447. bool
  3448. Server::read_content_core(Stream &strm, Request &req, Response &res,
  3449. ContentReceiver receiver,
  3450. MultipartContentHeader multipart_header,
  3451. ContentReceiver multipart_receiver) const {
  3452. detail::MultipartFormDataParser multipart_form_data_parser;
  3453. ContentReceiverWithProgress out;
  3454. if (req.is_multipart_form_data()) {
  3455. const auto &content_type = req.get_header_value("Content-Type");
  3456. std::string boundary;
  3457. if (!detail::parse_multipart_boundary(content_type, boundary)) {
  3458. res.status = StatusCode::BadRequest_400;
  3459. return false;
  3460. }
  3461. multipart_form_data_parser.set_boundary(std::move(boundary));
  3462. out = [&](const char *buf, size_t n, uint64_t /*off*/, uint64_t /*len*/) {
  3463. /* For debug
  3464. size_t pos = 0;
  3465. while (pos < n) {
  3466. auto read_size = (std::min)<size_t>(1, n - pos);
  3467. auto ret = multipart_form_data_parser.parse(
  3468. buf + pos, read_size, multipart_receiver, multipart_header);
  3469. if (!ret) { return false; }
  3470. pos += read_size;
  3471. }
  3472. return true;
  3473. */
  3474. return multipart_form_data_parser.parse(buf, n, multipart_receiver,
  3475. multipart_header);
  3476. };
  3477. } else {
  3478. out = [receiver](const char *buf, size_t n, uint64_t /*off*/,
  3479. uint64_t /*len*/) { return receiver(buf, n); };
  3480. }
  3481. if (req.method == "DELETE" && !req.has_header("Content-Length")) {
  3482. return true;
  3483. }
  3484. if (!detail::read_content(strm, req, payload_max_length_, res.status, nullptr,
  3485. out, true)) {
  3486. return false;
  3487. }
  3488. if (req.is_multipart_form_data()) {
  3489. if (!multipart_form_data_parser.is_valid()) {
  3490. res.status = StatusCode::BadRequest_400;
  3491. return false;
  3492. }
  3493. }
  3494. return true;
  3495. }
  3496. bool Server::handle_file_request(const Request &req, Response &res,
  3497. bool head) {
  3498. for (const auto &entry : base_dirs_) {
  3499. // Prefix match
  3500. if (!req.path.compare(0, entry.mount_point.size(), entry.mount_point)) {
  3501. std::string sub_path = "/" + req.path.substr(entry.mount_point.size());
  3502. if (detail::is_valid_path(sub_path)) {
  3503. auto path = entry.base_dir + sub_path;
  3504. if (path.back() == '/') { path += "index.html"; }
  3505. detail::FileStat stat(path);
  3506. if (stat.is_dir()) {
  3507. res.set_redirect(sub_path + "/", StatusCode::MovedPermanently_301);
  3508. return true;
  3509. }
  3510. if (stat.is_file()) {
  3511. for (const auto &kv : entry.headers) {
  3512. res.set_header(kv.first, kv.second);
  3513. }
  3514. auto mm = std::make_shared<detail::mmap>(path.c_str());
  3515. if (!mm->is_open()) { return false; }
  3516. res.set_content_provider(
  3517. mm->size(),
  3518. detail::find_content_type(path, file_extension_and_mimetype_map_,
  3519. default_file_mimetype_),
  3520. [mm](size_t offset, size_t length, DataSink &sink) -> bool {
  3521. sink.write(mm->data() + offset, length);
  3522. return true;
  3523. });
  3524. if (!head && file_request_handler_) {
  3525. file_request_handler_(req, res);
  3526. }
  3527. return true;
  3528. }
  3529. }
  3530. }
  3531. }
  3532. return false;
  3533. }
  3534. socket_t
  3535. Server::create_server_socket(const std::string &host, int port,
  3536. int socket_flags,
  3537. SocketOptions socket_options) const {
  3538. return detail::create_socket(
  3539. host, std::string(), port, address_family_, socket_flags, tcp_nodelay_,
  3540. ipv6_v6only_, std::move(socket_options),
  3541. [](socket_t sock, struct addrinfo &ai, bool & /*quit*/) -> bool {
  3542. if (::bind(sock, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen))) {
  3543. return false;
  3544. }
  3545. if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false; }
  3546. return true;
  3547. });
  3548. }
  3549. int Server::bind_internal(const std::string &host, int port,
  3550. int socket_flags) {
  3551. if (is_decommissioned) { return -1; }
  3552. if (!is_valid()) { return -1; }
  3553. svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_);
  3554. if (svr_sock_ == INVALID_SOCKET) { return -1; }
  3555. if (port == 0) {
  3556. struct sockaddr_storage addr;
  3557. socklen_t addr_len = sizeof(addr);
  3558. if (getsockname(svr_sock_, reinterpret_cast<struct sockaddr *>(&addr),
  3559. &addr_len) == -1) {
  3560. return -1;
  3561. }
  3562. if (addr.ss_family == AF_INET) {
  3563. return ntohs(reinterpret_cast<struct sockaddr_in *>(&addr)->sin_port);
  3564. } else if (addr.ss_family == AF_INET6) {
  3565. return ntohs(reinterpret_cast<struct sockaddr_in6 *>(&addr)->sin6_port);
  3566. } else {
  3567. return -1;
  3568. }
  3569. } else {
  3570. return port;
  3571. }
  3572. }
  3573. bool Server::listen_internal() {
  3574. if (is_decommissioned) { return false; }
  3575. auto ret = true;
  3576. is_running_ = true;
  3577. auto se = detail::scope_exit([&]() { is_running_ = false; });
  3578. {
  3579. std::unique_ptr<TaskQueue> task_queue(new_task_queue());
  3580. while (svr_sock_ != INVALID_SOCKET) {
  3581. #ifndef _WIN32
  3582. if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) {
  3583. #endif
  3584. auto val = detail::select_read(svr_sock_, idle_interval_sec_,
  3585. idle_interval_usec_);
  3586. if (val == 0) { // Timeout
  3587. task_queue->on_idle();
  3588. continue;
  3589. }
  3590. #ifndef _WIN32
  3591. }
  3592. #endif
  3593. #if defined _WIN32
  3594. // sockets connected via WASAccept inherit flags NO_HANDLE_INHERIT,
  3595. // OVERLAPPED
  3596. socket_t sock = WSAAccept(svr_sock_, nullptr, nullptr, nullptr, 0);
  3597. #elif defined SOCK_CLOEXEC
  3598. socket_t sock = accept4(svr_sock_, nullptr, nullptr, SOCK_CLOEXEC);
  3599. #else
  3600. socket_t sock = accept(svr_sock_, nullptr, nullptr);
  3601. #endif
  3602. if (sock == INVALID_SOCKET) {
  3603. if (errno == EMFILE) {
  3604. // The per-process limit of open file descriptors has been reached.
  3605. // Try to accept new connections after a short sleep.
  3606. std::this_thread::sleep_for(std::chrono::microseconds{1});
  3607. continue;
  3608. } else if (errno == EINTR || errno == EAGAIN) {
  3609. continue;
  3610. }
  3611. if (svr_sock_ != INVALID_SOCKET) {
  3612. detail::close_socket(svr_sock_);
  3613. ret = false;
  3614. } else {
  3615. ; // The server socket was closed by user.
  3616. }
  3617. break;
  3618. }
  3619. detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO,
  3620. read_timeout_sec_, read_timeout_usec_);
  3621. detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
  3622. write_timeout_sec_, write_timeout_usec_);
  3623. if (!task_queue->enqueue(
  3624. [this, sock]() { process_and_close_socket(sock); })) {
  3625. detail::shutdown_socket(sock);
  3626. detail::close_socket(sock);
  3627. }
  3628. }
  3629. task_queue->shutdown();
  3630. }
  3631. is_decommissioned = !ret;
  3632. return ret;
  3633. }
  3634. bool Server::routing(Request &req, Response &res, Stream &strm) {
  3635. if (pre_routing_handler_ &&
  3636. pre_routing_handler_(req, res) == HandlerResponse::Handled) {
  3637. return true;
  3638. }
  3639. // File handler
  3640. auto is_head_request = req.method == "HEAD";
  3641. if ((req.method == "GET" || is_head_request) &&
  3642. handle_file_request(req, res, is_head_request)) {
  3643. return true;
  3644. }
  3645. if (detail::expect_content(req)) {
  3646. // Content reader handler
  3647. {
  3648. ContentReader reader(
  3649. [&](ContentReceiver receiver) {
  3650. return read_content_with_content_receiver(
  3651. strm, req, res, std::move(receiver), nullptr, nullptr);
  3652. },
  3653. [&](MultipartContentHeader header, ContentReceiver receiver) {
  3654. return read_content_with_content_receiver(strm, req, res, nullptr,
  3655. std::move(header),
  3656. std::move(receiver));
  3657. });
  3658. if (req.method == "POST") {
  3659. if (dispatch_request_for_content_reader(
  3660. req, res, std::move(reader),
  3661. post_handlers_for_content_reader_)) {
  3662. return true;
  3663. }
  3664. } else if (req.method == "PUT") {
  3665. if (dispatch_request_for_content_reader(
  3666. req, res, std::move(reader),
  3667. put_handlers_for_content_reader_)) {
  3668. return true;
  3669. }
  3670. } else if (req.method == "PATCH") {
  3671. if (dispatch_request_for_content_reader(
  3672. req, res, std::move(reader),
  3673. patch_handlers_for_content_reader_)) {
  3674. return true;
  3675. }
  3676. } else if (req.method == "DELETE") {
  3677. if (dispatch_request_for_content_reader(
  3678. req, res, std::move(reader),
  3679. delete_handlers_for_content_reader_)) {
  3680. return true;
  3681. }
  3682. }
  3683. }
  3684. // Read content into `req.body`
  3685. if (!read_content(strm, req, res)) { return false; }
  3686. }
  3687. // Regular handler
  3688. if (req.method == "GET" || req.method == "HEAD") {
  3689. return dispatch_request(req, res, get_handlers_);
  3690. } else if (req.method == "POST") {
  3691. return dispatch_request(req, res, post_handlers_);
  3692. } else if (req.method == "PUT") {
  3693. return dispatch_request(req, res, put_handlers_);
  3694. } else if (req.method == "DELETE") {
  3695. return dispatch_request(req, res, delete_handlers_);
  3696. } else if (req.method == "OPTIONS") {
  3697. return dispatch_request(req, res, options_handlers_);
  3698. } else if (req.method == "PATCH") {
  3699. return dispatch_request(req, res, patch_handlers_);
  3700. }
  3701. res.status = StatusCode::BadRequest_400;
  3702. return false;
  3703. }
  3704. bool Server::dispatch_request(Request &req, Response &res,
  3705. const Handlers &handlers) const {
  3706. for (const auto &x : handlers) {
  3707. const auto &matcher = x.first;
  3708. const auto &handler = x.second;
  3709. if (matcher->match(req)) {
  3710. handler(req, res);
  3711. return true;
  3712. }
  3713. }
  3714. return false;
  3715. }
  3716. void Server::apply_ranges(const Request &req, Response &res,
  3717. std::string &content_type,
  3718. std::string &boundary) const {
  3719. if (req.ranges.size() > 1 && res.status == StatusCode::PartialContent_206) {
  3720. auto it = res.headers.find("Content-Type");
  3721. if (it != res.headers.end()) {
  3722. content_type = it->second;
  3723. res.headers.erase(it);
  3724. }
  3725. boundary = detail::make_multipart_data_boundary();
  3726. res.set_header("Content-Type",
  3727. "multipart/byteranges; boundary=" + boundary);
  3728. }
  3729. auto type = detail::encoding_type(req, res);
  3730. if (res.body.empty()) {
  3731. if (res.content_length_ > 0) {
  3732. size_t length = 0;
  3733. if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) {
  3734. length = res.content_length_;
  3735. } else if (req.ranges.size() == 1) {
  3736. auto offset_and_length = detail::get_range_offset_and_length(
  3737. req.ranges[0], res.content_length_);
  3738. length = offset_and_length.second;
  3739. auto content_range = detail::make_content_range_header_field(
  3740. offset_and_length, res.content_length_);
  3741. res.set_header("Content-Range", content_range);
  3742. } else {
  3743. length = detail::get_multipart_ranges_data_length(
  3744. req, boundary, content_type, res.content_length_);
  3745. }
  3746. res.set_header("Content-Length", std::to_string(length));
  3747. } else {
  3748. if (res.content_provider_) {
  3749. if (res.is_chunked_content_provider_) {
  3750. res.set_header("Transfer-Encoding", "chunked");
  3751. if (type == detail::EncodingType::Gzip) {
  3752. res.set_header("Content-Encoding", "gzip");
  3753. } else if (type == detail::EncodingType::Brotli) {
  3754. res.set_header("Content-Encoding", "br");
  3755. } else if (type == detail::EncodingType::Zstd) {
  3756. res.set_header("Content-Encoding", "zstd");
  3757. }
  3758. }
  3759. }
  3760. }
  3761. } else {
  3762. if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) {
  3763. ;
  3764. } else if (req.ranges.size() == 1) {
  3765. auto offset_and_length =
  3766. detail::get_range_offset_and_length(req.ranges[0], res.body.size());
  3767. auto offset = offset_and_length.first;
  3768. auto length = offset_and_length.second;
  3769. auto content_range = detail::make_content_range_header_field(
  3770. offset_and_length, res.body.size());
  3771. res.set_header("Content-Range", content_range);
  3772. assert(offset + length <= res.body.size());
  3773. res.body = res.body.substr(offset, length);
  3774. } else {
  3775. std::string data;
  3776. detail::make_multipart_ranges_data(req, res, boundary, content_type,
  3777. res.body.size(), data);
  3778. res.body.swap(data);
  3779. }
  3780. if (type != detail::EncodingType::None) {
  3781. std::unique_ptr<detail::compressor> compressor;
  3782. std::string content_encoding;
  3783. if (type == detail::EncodingType::Gzip) {
  3784. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  3785. compressor = detail::make_unique<detail::gzip_compressor>();
  3786. content_encoding = "gzip";
  3787. #endif
  3788. } else if (type == detail::EncodingType::Brotli) {
  3789. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  3790. compressor = detail::make_unique<detail::brotli_compressor>();
  3791. content_encoding = "br";
  3792. #endif
  3793. } else if (type == detail::EncodingType::Zstd) {
  3794. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  3795. compressor = detail::make_unique<detail::zstd_compressor>();
  3796. content_encoding = "zstd";
  3797. #endif
  3798. }
  3799. if (compressor) {
  3800. std::string compressed;
  3801. if (compressor->compress(res.body.data(), res.body.size(), true,
  3802. [&](const char *data, size_t data_len) {
  3803. compressed.append(data, data_len);
  3804. return true;
  3805. })) {
  3806. res.body.swap(compressed);
  3807. res.set_header("Content-Encoding", content_encoding);
  3808. }
  3809. }
  3810. }
  3811. auto length = std::to_string(res.body.size());
  3812. res.set_header("Content-Length", length);
  3813. }
  3814. }
  3815. bool Server::dispatch_request_for_content_reader(
  3816. Request &req, Response &res, ContentReader content_reader,
  3817. const HandlersForContentReader &handlers) const {
  3818. for (const auto &x : handlers) {
  3819. const auto &matcher = x.first;
  3820. const auto &handler = x.second;
  3821. if (matcher->match(req)) {
  3822. handler(req, res, content_reader);
  3823. return true;
  3824. }
  3825. }
  3826. return false;
  3827. }
  3828. bool
  3829. Server::process_request(Stream &strm, const std::string &remote_addr,
  3830. int remote_port, const std::string &local_addr,
  3831. int local_port, bool close_connection,
  3832. bool &connection_closed,
  3833. const std::function<void(Request &)> &setup_request) {
  3834. std::array<char, 2048> buf{};
  3835. detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
  3836. // Connection has been closed on client
  3837. if (!line_reader.getline()) { return false; }
  3838. Request req;
  3839. Response res;
  3840. res.version = "HTTP/1.1";
  3841. res.headers = default_headers_;
  3842. // Request line and headers
  3843. if (!parse_request_line(line_reader.ptr(), req) ||
  3844. !detail::read_headers(strm, req.headers)) {
  3845. res.status = StatusCode::BadRequest_400;
  3846. return write_response(strm, close_connection, req, res);
  3847. }
  3848. // Check if the request URI doesn't exceed the limit
  3849. if (req.target.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
  3850. Headers dummy;
  3851. detail::read_headers(strm, dummy);
  3852. res.status = StatusCode::UriTooLong_414;
  3853. return write_response(strm, close_connection, req, res);
  3854. }
  3855. if (req.get_header_value("Connection") == "close") {
  3856. connection_closed = true;
  3857. }
  3858. if (req.version == "HTTP/1.0" &&
  3859. req.get_header_value("Connection") != "Keep-Alive") {
  3860. connection_closed = true;
  3861. }
  3862. req.remote_addr = remote_addr;
  3863. req.remote_port = remote_port;
  3864. req.set_header("REMOTE_ADDR", req.remote_addr);
  3865. req.set_header("REMOTE_PORT", std::to_string(req.remote_port));
  3866. req.local_addr = local_addr;
  3867. req.local_port = local_port;
  3868. req.set_header("LOCAL_ADDR", req.local_addr);
  3869. req.set_header("LOCAL_PORT", std::to_string(req.local_port));
  3870. if (req.has_header("Range")) {
  3871. const auto &range_header_value = req.get_header_value("Range");
  3872. if (!detail::parse_range_header(range_header_value, req.ranges)) {
  3873. res.status = StatusCode::RangeNotSatisfiable_416;
  3874. return write_response(strm, close_connection, req, res);
  3875. }
  3876. }
  3877. if (setup_request) { setup_request(req); }
  3878. if (req.get_header_value("Expect") == "100-continue") {
  3879. int status = StatusCode::Continue_100;
  3880. if (expect_100_continue_handler_) {
  3881. status = expect_100_continue_handler_(req, res);
  3882. }
  3883. switch (status) {
  3884. case StatusCode::Continue_100:
  3885. case StatusCode::ExpectationFailed_417:
  3886. detail::write_response_line(strm, status);
  3887. strm.write("\r\n");
  3888. break;
  3889. default:
  3890. connection_closed = true;
  3891. return write_response(strm, true, req, res);
  3892. }
  3893. }
  3894. // Setup `is_connection_closed` method
  3895. auto sock = strm.socket();
  3896. req.is_connection_closed = [sock]() {
  3897. return !detail::is_socket_alive(sock);
  3898. };
  3899. // Routing
  3900. auto routed = false;
  3901. #ifdef CPPHTTPLIB_NO_EXCEPTIONS
  3902. routed = routing(req, res, strm);
  3903. #else
  3904. try {
  3905. routed = routing(req, res, strm);
  3906. } catch (std::exception &e) {
  3907. if (exception_handler_) {
  3908. auto ep = std::current_exception();
  3909. exception_handler_(req, res, ep);
  3910. routed = true;
  3911. } else {
  3912. res.status = StatusCode::InternalServerError_500;
  3913. std::string val;
  3914. auto s = e.what();
  3915. for (size_t i = 0; s[i]; i++) {
  3916. switch (s[i]) {
  3917. case '\r': val += "\\r"; break;
  3918. case '\n': val += "\\n"; break;
  3919. default: val += s[i]; break;
  3920. }
  3921. }
  3922. res.set_header("EXCEPTION_WHAT", val);
  3923. }
  3924. } catch (...) {
  3925. if (exception_handler_) {
  3926. auto ep = std::current_exception();
  3927. exception_handler_(req, res, ep);
  3928. routed = true;
  3929. } else {
  3930. res.status = StatusCode::InternalServerError_500;
  3931. res.set_header("EXCEPTION_WHAT", "UNKNOWN");
  3932. }
  3933. }
  3934. #endif
  3935. if (routed) {
  3936. if (res.status == -1) {
  3937. res.status = req.ranges.empty() ? StatusCode::OK_200
  3938. : StatusCode::PartialContent_206;
  3939. }
  3940. // Serve file content by using a content provider
  3941. if (!res.file_content_path_.empty()) {
  3942. const auto &path = res.file_content_path_;
  3943. auto mm = std::make_shared<detail::mmap>(path.c_str());
  3944. if (!mm->is_open()) {
  3945. res.body.clear();
  3946. res.content_length_ = 0;
  3947. res.content_provider_ = nullptr;
  3948. res.status = StatusCode::NotFound_404;
  3949. return write_response(strm, close_connection, req, res);
  3950. }
  3951. auto content_type = res.file_content_content_type_;
  3952. if (content_type.empty()) {
  3953. content_type = detail::find_content_type(
  3954. path, file_extension_and_mimetype_map_, default_file_mimetype_);
  3955. }
  3956. res.set_content_provider(
  3957. mm->size(), content_type,
  3958. [mm](size_t offset, size_t length, DataSink &sink) -> bool {
  3959. sink.write(mm->data() + offset, length);
  3960. return true;
  3961. });
  3962. }
  3963. if (detail::range_error(req, res)) {
  3964. res.body.clear();
  3965. res.content_length_ = 0;
  3966. res.content_provider_ = nullptr;
  3967. res.status = StatusCode::RangeNotSatisfiable_416;
  3968. return write_response(strm, close_connection, req, res);
  3969. }
  3970. return write_response_with_content(strm, close_connection, req, res);
  3971. } else {
  3972. if (res.status == -1) { res.status = StatusCode::NotFound_404; }
  3973. return write_response(strm, close_connection, req, res);
  3974. }
  3975. }
  3976. bool Server::is_valid() const { return true; }
  3977. bool Server::process_and_close_socket(socket_t sock) {
  3978. std::string remote_addr;
  3979. int remote_port = 0;
  3980. detail::get_remote_ip_and_port(sock, remote_addr, remote_port);
  3981. std::string local_addr;
  3982. int local_port = 0;
  3983. detail::get_local_ip_and_port(sock, local_addr, local_port);
  3984. auto ret = detail::process_server_socket(
  3985. svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
  3986. read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
  3987. write_timeout_usec_,
  3988. [&](Stream &strm, bool close_connection, bool &connection_closed) {
  3989. return process_request(strm, remote_addr, remote_port, local_addr,
  3990. local_port, close_connection, connection_closed,
  3991. nullptr);
  3992. });
  3993. detail::shutdown_socket(sock);
  3994. detail::close_socket(sock);
  3995. return ret;
  3996. }
  3997. // HTTP client implementation
  3998. ClientImpl::ClientImpl(const std::string &host)
  3999. : ClientImpl(host, 80, std::string(), std::string()) {}
  4000. ClientImpl::ClientImpl(const std::string &host, int port)
  4001. : ClientImpl(host, port, std::string(), std::string()) {}
  4002. ClientImpl::ClientImpl(const std::string &host, int port,
  4003. const std::string &client_cert_path,
  4004. const std::string &client_key_path)
  4005. : host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
  4006. host_and_port_(adjust_host_string(host_) + ":" + std::to_string(port)),
  4007. client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
  4008. ClientImpl::~ClientImpl() {
  4009. // Wait until all the requests in flight are handled.
  4010. size_t retry_count = 10;
  4011. while (retry_count-- > 0) {
  4012. {
  4013. std::lock_guard<std::mutex> guard(socket_mutex_);
  4014. if (socket_requests_in_flight_ == 0) { break; }
  4015. }
  4016. std::this_thread::sleep_for(std::chrono::milliseconds{1});
  4017. }
  4018. std::lock_guard<std::mutex> guard(socket_mutex_);
  4019. shutdown_socket(socket_);
  4020. close_socket(socket_);
  4021. }
  4022. bool ClientImpl::is_valid() const { return true; }
  4023. void ClientImpl::copy_settings(const ClientImpl &rhs) {
  4024. client_cert_path_ = rhs.client_cert_path_;
  4025. client_key_path_ = rhs.client_key_path_;
  4026. connection_timeout_sec_ = rhs.connection_timeout_sec_;
  4027. read_timeout_sec_ = rhs.read_timeout_sec_;
  4028. read_timeout_usec_ = rhs.read_timeout_usec_;
  4029. write_timeout_sec_ = rhs.write_timeout_sec_;
  4030. write_timeout_usec_ = rhs.write_timeout_usec_;
  4031. max_timeout_msec_ = rhs.max_timeout_msec_;
  4032. basic_auth_username_ = rhs.basic_auth_username_;
  4033. basic_auth_password_ = rhs.basic_auth_password_;
  4034. bearer_token_auth_token_ = rhs.bearer_token_auth_token_;
  4035. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4036. digest_auth_username_ = rhs.digest_auth_username_;
  4037. digest_auth_password_ = rhs.digest_auth_password_;
  4038. #endif
  4039. keep_alive_ = rhs.keep_alive_;
  4040. follow_location_ = rhs.follow_location_;
  4041. url_encode_ = rhs.url_encode_;
  4042. address_family_ = rhs.address_family_;
  4043. tcp_nodelay_ = rhs.tcp_nodelay_;
  4044. ipv6_v6only_ = rhs.ipv6_v6only_;
  4045. socket_options_ = rhs.socket_options_;
  4046. compress_ = rhs.compress_;
  4047. decompress_ = rhs.decompress_;
  4048. interface_ = rhs.interface_;
  4049. proxy_host_ = rhs.proxy_host_;
  4050. proxy_port_ = rhs.proxy_port_;
  4051. proxy_basic_auth_username_ = rhs.proxy_basic_auth_username_;
  4052. proxy_basic_auth_password_ = rhs.proxy_basic_auth_password_;
  4053. proxy_bearer_token_auth_token_ = rhs.proxy_bearer_token_auth_token_;
  4054. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4055. proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_;
  4056. proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_;
  4057. #endif
  4058. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4059. ca_cert_file_path_ = rhs.ca_cert_file_path_;
  4060. ca_cert_dir_path_ = rhs.ca_cert_dir_path_;
  4061. ca_cert_store_ = rhs.ca_cert_store_;
  4062. #endif
  4063. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4064. server_certificate_verification_ = rhs.server_certificate_verification_;
  4065. server_hostname_verification_ = rhs.server_hostname_verification_;
  4066. server_certificate_verifier_ = rhs.server_certificate_verifier_;
  4067. #endif
  4068. logger_ = rhs.logger_;
  4069. }
  4070. socket_t ClientImpl::create_client_socket(Error &error) const {
  4071. if (!proxy_host_.empty() && proxy_port_ != -1) {
  4072. return detail::create_client_socket(
  4073. proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_,
  4074. ipv6_v6only_, socket_options_, connection_timeout_sec_,
  4075. connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_,
  4076. write_timeout_sec_, write_timeout_usec_, interface_, error);
  4077. }
  4078. // Check is custom IP specified for host_
  4079. std::string ip;
  4080. auto it = addr_map_.find(host_);
  4081. if (it != addr_map_.end()) { ip = it->second; }
  4082. return detail::create_client_socket(
  4083. host_, ip, port_, address_family_, tcp_nodelay_, ipv6_v6only_,
  4084. socket_options_, connection_timeout_sec_, connection_timeout_usec_,
  4085. read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
  4086. write_timeout_usec_, interface_, error);
  4087. }
  4088. bool ClientImpl::create_and_connect_socket(Socket &socket,
  4089. Error &error) {
  4090. auto sock = create_client_socket(error);
  4091. if (sock == INVALID_SOCKET) { return false; }
  4092. socket.sock = sock;
  4093. return true;
  4094. }
  4095. void ClientImpl::shutdown_ssl(Socket & /*socket*/,
  4096. bool /*shutdown_gracefully*/) {
  4097. // If there are any requests in flight from threads other than us, then it's
  4098. // a thread-unsafe race because individual ssl* objects are not thread-safe.
  4099. assert(socket_requests_in_flight_ == 0 ||
  4100. socket_requests_are_from_thread_ == std::this_thread::get_id());
  4101. }
  4102. void ClientImpl::shutdown_socket(Socket &socket) const {
  4103. if (socket.sock == INVALID_SOCKET) { return; }
  4104. detail::shutdown_socket(socket.sock);
  4105. }
  4106. void ClientImpl::close_socket(Socket &socket) {
  4107. // If there are requests in flight in another thread, usually closing
  4108. // the socket will be fine and they will simply receive an error when
  4109. // using the closed socket, but it is still a bug since rarely the OS
  4110. // may reassign the socket id to be used for a new socket, and then
  4111. // suddenly they will be operating on a live socket that is different
  4112. // than the one they intended!
  4113. assert(socket_requests_in_flight_ == 0 ||
  4114. socket_requests_are_from_thread_ == std::this_thread::get_id());
  4115. // It is also a bug if this happens while SSL is still active
  4116. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4117. assert(socket.ssl == nullptr);
  4118. #endif
  4119. if (socket.sock == INVALID_SOCKET) { return; }
  4120. detail::close_socket(socket.sock);
  4121. socket.sock = INVALID_SOCKET;
  4122. }
  4123. bool ClientImpl::read_response_line(Stream &strm, const Request &req,
  4124. Response &res) const {
  4125. std::array<char, 2048> buf{};
  4126. detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
  4127. if (!line_reader.getline()) { return false; }
  4128. #ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
  4129. thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n");
  4130. #else
  4131. thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n");
  4132. #endif
  4133. std::cmatch m;
  4134. if (!std::regex_match(line_reader.ptr(), m, re)) {
  4135. return req.method == "CONNECT";
  4136. }
  4137. res.version = std::string(m[1]);
  4138. res.status = std::stoi(std::string(m[2]));
  4139. res.reason = std::string(m[3]);
  4140. // Ignore '100 Continue'
  4141. while (res.status == StatusCode::Continue_100) {
  4142. if (!line_reader.getline()) { return false; } // CRLF
  4143. if (!line_reader.getline()) { return false; } // next response line
  4144. if (!std::regex_match(line_reader.ptr(), m, re)) { return false; }
  4145. res.version = std::string(m[1]);
  4146. res.status = std::stoi(std::string(m[2]));
  4147. res.reason = std::string(m[3]);
  4148. }
  4149. return true;
  4150. }
  4151. bool ClientImpl::send(Request &req, Response &res, Error &error) {
  4152. std::lock_guard<std::recursive_mutex> request_mutex_guard(request_mutex_);
  4153. auto ret = send_(req, res, error);
  4154. if (error == Error::SSLPeerCouldBeClosed_) {
  4155. assert(!ret);
  4156. ret = send_(req, res, error);
  4157. }
  4158. return ret;
  4159. }
  4160. bool ClientImpl::send_(Request &req, Response &res, Error &error) {
  4161. {
  4162. std::lock_guard<std::mutex> guard(socket_mutex_);
  4163. // Set this to false immediately - if it ever gets set to true by the end of
  4164. // the request, we know another thread instructed us to close the socket.
  4165. socket_should_be_closed_when_request_is_done_ = false;
  4166. auto is_alive = false;
  4167. if (socket_.is_open()) {
  4168. is_alive = detail::is_socket_alive(socket_.sock);
  4169. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4170. if (is_alive && is_ssl()) {
  4171. if (detail::is_ssl_peer_could_be_closed(socket_.ssl, socket_.sock)) {
  4172. is_alive = false;
  4173. }
  4174. }
  4175. #endif
  4176. if (!is_alive) {
  4177. // Attempt to avoid sigpipe by shutting down non-gracefully if it seems
  4178. // like the other side has already closed the connection Also, there
  4179. // cannot be any requests in flight from other threads since we locked
  4180. // request_mutex_, so safe to close everything immediately
  4181. const bool shutdown_gracefully = false;
  4182. shutdown_ssl(socket_, shutdown_gracefully);
  4183. shutdown_socket(socket_);
  4184. close_socket(socket_);
  4185. }
  4186. }
  4187. if (!is_alive) {
  4188. if (!create_and_connect_socket(socket_, error)) { return false; }
  4189. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4190. // TODO: refactoring
  4191. if (is_ssl()) {
  4192. auto &scli = static_cast<SSLClient &>(*this);
  4193. if (!proxy_host_.empty() && proxy_port_ != -1) {
  4194. auto success = false;
  4195. if (!scli.connect_with_proxy(socket_, req.start_time_, res, success,
  4196. error)) {
  4197. return success;
  4198. }
  4199. }
  4200. if (!scli.initialize_ssl(socket_, error)) { return false; }
  4201. }
  4202. #endif
  4203. }
  4204. // Mark the current socket as being in use so that it cannot be closed by
  4205. // anyone else while this request is ongoing, even though we will be
  4206. // releasing the mutex.
  4207. if (socket_requests_in_flight_ > 1) {
  4208. assert(socket_requests_are_from_thread_ == std::this_thread::get_id());
  4209. }
  4210. socket_requests_in_flight_ += 1;
  4211. socket_requests_are_from_thread_ = std::this_thread::get_id();
  4212. }
  4213. for (const auto &header : default_headers_) {
  4214. if (req.headers.find(header.first) == req.headers.end()) {
  4215. req.headers.insert(header);
  4216. }
  4217. }
  4218. auto ret = false;
  4219. auto close_connection = !keep_alive_;
  4220. auto se = detail::scope_exit([&]() {
  4221. // Briefly lock mutex in order to mark that a request is no longer ongoing
  4222. std::lock_guard<std::mutex> guard(socket_mutex_);
  4223. socket_requests_in_flight_ -= 1;
  4224. if (socket_requests_in_flight_ <= 0) {
  4225. assert(socket_requests_in_flight_ == 0);
  4226. socket_requests_are_from_thread_ = std::thread::id();
  4227. }
  4228. if (socket_should_be_closed_when_request_is_done_ || close_connection ||
  4229. !ret) {
  4230. shutdown_ssl(socket_, true);
  4231. shutdown_socket(socket_);
  4232. close_socket(socket_);
  4233. }
  4234. });
  4235. ret = process_socket(socket_, req.start_time_, [&](Stream &strm) {
  4236. return handle_request(strm, req, res, close_connection, error);
  4237. });
  4238. if (!ret) {
  4239. if (error == Error::Success) { error = Error::Unknown; }
  4240. }
  4241. return ret;
  4242. }
  4243. Result ClientImpl::send(const Request &req) {
  4244. auto req2 = req;
  4245. return send_(std::move(req2));
  4246. }
  4247. Result ClientImpl::send_(Request &&req) {
  4248. auto res = detail::make_unique<Response>();
  4249. auto error = Error::Success;
  4250. auto ret = send(req, *res, error);
  4251. return Result{ret ? std::move(res) : nullptr, error, std::move(req.headers)};
  4252. }
  4253. bool ClientImpl::handle_request(Stream &strm, Request &req,
  4254. Response &res, bool close_connection,
  4255. Error &error) {
  4256. if (req.path.empty()) {
  4257. error = Error::Connection;
  4258. return false;
  4259. }
  4260. auto req_save = req;
  4261. bool ret;
  4262. if (!is_ssl() && !proxy_host_.empty() && proxy_port_ != -1) {
  4263. auto req2 = req;
  4264. req2.path = "http://" + host_and_port_ + req.path;
  4265. ret = process_request(strm, req2, res, close_connection, error);
  4266. req = req2;
  4267. req.path = req_save.path;
  4268. } else {
  4269. ret = process_request(strm, req, res, close_connection, error);
  4270. }
  4271. if (!ret) { return false; }
  4272. if (res.get_header_value("Connection") == "close" ||
  4273. (res.version == "HTTP/1.0" && res.reason != "Connection established")) {
  4274. // TODO this requires a not-entirely-obvious chain of calls to be correct
  4275. // for this to be safe.
  4276. // This is safe to call because handle_request is only called by send_
  4277. // which locks the request mutex during the process. It would be a bug
  4278. // to call it from a different thread since it's a thread-safety issue
  4279. // to do these things to the socket if another thread is using the socket.
  4280. std::lock_guard<std::mutex> guard(socket_mutex_);
  4281. shutdown_ssl(socket_, true);
  4282. shutdown_socket(socket_);
  4283. close_socket(socket_);
  4284. }
  4285. if (300 < res.status && res.status < 400 && follow_location_) {
  4286. req = req_save;
  4287. ret = redirect(req, res, error);
  4288. }
  4289. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4290. if ((res.status == StatusCode::Unauthorized_401 ||
  4291. res.status == StatusCode::ProxyAuthenticationRequired_407) &&
  4292. req.authorization_count_ < 5) {
  4293. auto is_proxy = res.status == StatusCode::ProxyAuthenticationRequired_407;
  4294. const auto &username =
  4295. is_proxy ? proxy_digest_auth_username_ : digest_auth_username_;
  4296. const auto &password =
  4297. is_proxy ? proxy_digest_auth_password_ : digest_auth_password_;
  4298. if (!username.empty() && !password.empty()) {
  4299. std::map<std::string, std::string> auth;
  4300. if (detail::parse_www_authenticate(res, auth, is_proxy)) {
  4301. Request new_req = req;
  4302. new_req.authorization_count_ += 1;
  4303. new_req.headers.erase(is_proxy ? "Proxy-Authorization"
  4304. : "Authorization");
  4305. new_req.headers.insert(detail::make_digest_authentication_header(
  4306. req, auth, new_req.authorization_count_, detail::random_string(10),
  4307. username, password, is_proxy));
  4308. Response new_res;
  4309. ret = send(new_req, new_res, error);
  4310. if (ret) { res = new_res; }
  4311. }
  4312. }
  4313. }
  4314. #endif
  4315. return ret;
  4316. }
  4317. bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
  4318. if (req.redirect_count_ == 0) {
  4319. error = Error::ExceedRedirectCount;
  4320. return false;
  4321. }
  4322. auto location = res.get_header_value("location");
  4323. if (location.empty()) { return false; }
  4324. thread_local const std::regex re(
  4325. R"((?:(https?):)?(?://(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)");
  4326. std::smatch m;
  4327. if (!std::regex_match(location, m, re)) { return false; }
  4328. auto scheme = is_ssl() ? "https" : "http";
  4329. auto next_scheme = m[1].str();
  4330. auto next_host = m[2].str();
  4331. if (next_host.empty()) { next_host = m[3].str(); }
  4332. auto port_str = m[4].str();
  4333. auto next_path = m[5].str();
  4334. auto next_query = m[6].str();
  4335. auto next_port = port_;
  4336. if (!port_str.empty()) {
  4337. next_port = std::stoi(port_str);
  4338. } else if (!next_scheme.empty()) {
  4339. next_port = next_scheme == "https" ? 443 : 80;
  4340. }
  4341. if (next_scheme.empty()) { next_scheme = scheme; }
  4342. if (next_host.empty()) { next_host = host_; }
  4343. if (next_path.empty()) { next_path = "/"; }
  4344. auto path = detail::decode_url(next_path, true) + next_query;
  4345. if (next_scheme == scheme && next_host == host_ && next_port == port_) {
  4346. return detail::redirect(*this, req, res, path, location, error);
  4347. } else {
  4348. if (next_scheme == "https") {
  4349. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4350. SSLClient cli(next_host, next_port);
  4351. cli.copy_settings(*this);
  4352. if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); }
  4353. return detail::redirect(cli, req, res, path, location, error);
  4354. #else
  4355. return false;
  4356. #endif
  4357. } else {
  4358. ClientImpl cli(next_host, next_port);
  4359. cli.copy_settings(*this);
  4360. return detail::redirect(cli, req, res, path, location, error);
  4361. }
  4362. }
  4363. }
  4364. bool ClientImpl::write_content_with_provider(Stream &strm,
  4365. const Request &req,
  4366. Error &error) const {
  4367. auto is_shutting_down = []() { return false; };
  4368. if (req.is_chunked_content_provider_) {
  4369. // TODO: Brotli support
  4370. std::unique_ptr<detail::compressor> compressor;
  4371. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  4372. if (compress_) {
  4373. compressor = detail::make_unique<detail::gzip_compressor>();
  4374. } else
  4375. #endif
  4376. {
  4377. compressor = detail::make_unique<detail::nocompressor>();
  4378. }
  4379. return detail::write_content_chunked(strm, req.content_provider_,
  4380. is_shutting_down, *compressor, error);
  4381. } else {
  4382. return detail::write_content(strm, req.content_provider_, 0,
  4383. req.content_length_, is_shutting_down, error);
  4384. }
  4385. }
  4386. bool ClientImpl::write_request(Stream &strm, Request &req,
  4387. bool close_connection, Error &error) {
  4388. // Prepare additional headers
  4389. if (close_connection) {
  4390. if (!req.has_header("Connection")) {
  4391. req.set_header("Connection", "close");
  4392. }
  4393. }
  4394. if (!req.has_header("Host")) {
  4395. if (is_ssl()) {
  4396. if (port_ == 443) {
  4397. req.set_header("Host", host_);
  4398. } else {
  4399. req.set_header("Host", host_and_port_);
  4400. }
  4401. } else {
  4402. if (port_ == 80) {
  4403. req.set_header("Host", host_);
  4404. } else {
  4405. req.set_header("Host", host_and_port_);
  4406. }
  4407. }
  4408. }
  4409. if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); }
  4410. if (!req.content_receiver) {
  4411. if (!req.has_header("Accept-Encoding")) {
  4412. std::string accept_encoding;
  4413. #ifdef CPPHTTPLIB_BROTLI_SUPPORT
  4414. accept_encoding = "br";
  4415. #endif
  4416. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  4417. if (!accept_encoding.empty()) { accept_encoding += ", "; }
  4418. accept_encoding += "gzip, deflate";
  4419. #endif
  4420. #ifdef CPPHTTPLIB_ZSTD_SUPPORT
  4421. if (!accept_encoding.empty()) { accept_encoding += ", "; }
  4422. accept_encoding += "zstd";
  4423. #endif
  4424. req.set_header("Accept-Encoding", accept_encoding);
  4425. }
  4426. #ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
  4427. if (!req.has_header("User-Agent")) {
  4428. auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION;
  4429. req.set_header("User-Agent", agent);
  4430. }
  4431. #endif
  4432. };
  4433. if (req.body.empty()) {
  4434. if (req.content_provider_) {
  4435. if (!req.is_chunked_content_provider_) {
  4436. if (!req.has_header("Content-Length")) {
  4437. auto length = std::to_string(req.content_length_);
  4438. req.set_header("Content-Length", length);
  4439. }
  4440. }
  4441. } else {
  4442. if (req.method == "POST" || req.method == "PUT" ||
  4443. req.method == "PATCH") {
  4444. req.set_header("Content-Length", "0");
  4445. }
  4446. }
  4447. } else {
  4448. if (!req.has_header("Content-Type")) {
  4449. req.set_header("Content-Type", "text/plain");
  4450. }
  4451. if (!req.has_header("Content-Length")) {
  4452. auto length = std::to_string(req.body.size());
  4453. req.set_header("Content-Length", length);
  4454. }
  4455. }
  4456. if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) {
  4457. if (!req.has_header("Authorization")) {
  4458. req.headers.insert(make_basic_authentication_header(
  4459. basic_auth_username_, basic_auth_password_, false));
  4460. }
  4461. }
  4462. if (!proxy_basic_auth_username_.empty() &&
  4463. !proxy_basic_auth_password_.empty()) {
  4464. if (!req.has_header("Proxy-Authorization")) {
  4465. req.headers.insert(make_basic_authentication_header(
  4466. proxy_basic_auth_username_, proxy_basic_auth_password_, true));
  4467. }
  4468. }
  4469. if (!bearer_token_auth_token_.empty()) {
  4470. if (!req.has_header("Authorization")) {
  4471. req.headers.insert(make_bearer_token_authentication_header(
  4472. bearer_token_auth_token_, false));
  4473. }
  4474. }
  4475. if (!proxy_bearer_token_auth_token_.empty()) {
  4476. if (!req.has_header("Proxy-Authorization")) {
  4477. req.headers.insert(make_bearer_token_authentication_header(
  4478. proxy_bearer_token_auth_token_, true));
  4479. }
  4480. }
  4481. // Request line and headers
  4482. {
  4483. detail::BufferStream bstrm;
  4484. const auto &path_with_query =
  4485. req.params.empty() ? req.path
  4486. : append_query_params(req.path, req.params);
  4487. const auto &path =
  4488. url_encode_ ? detail::encode_url(path_with_query) : path_with_query;
  4489. detail::write_request_line(bstrm, req.method, path);
  4490. header_writer_(bstrm, req.headers);
  4491. // Flush buffer
  4492. auto &data = bstrm.get_buffer();
  4493. if (!detail::write_data(strm, data.data(), data.size())) {
  4494. error = Error::Write;
  4495. return false;
  4496. }
  4497. }
  4498. // Body
  4499. if (req.body.empty()) {
  4500. return write_content_with_provider(strm, req, error);
  4501. }
  4502. if (!detail::write_data(strm, req.body.data(), req.body.size())) {
  4503. error = Error::Write;
  4504. return false;
  4505. }
  4506. return true;
  4507. }
  4508. std::unique_ptr<Response> ClientImpl::send_with_content_provider(
  4509. Request &req, const char *body, size_t content_length,
  4510. ContentProvider content_provider,
  4511. ContentProviderWithoutLength content_provider_without_length,
  4512. const std::string &content_type, Error &error) {
  4513. if (!content_type.empty()) { req.set_header("Content-Type", content_type); }
  4514. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  4515. if (compress_) { req.set_header("Content-Encoding", "gzip"); }
  4516. #endif
  4517. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  4518. if (compress_ && !content_provider_without_length) {
  4519. // TODO: Brotli support
  4520. detail::gzip_compressor compressor;
  4521. if (content_provider) {
  4522. auto ok = true;
  4523. size_t offset = 0;
  4524. DataSink data_sink;
  4525. data_sink.write = [&](const char *data, size_t data_len) -> bool {
  4526. if (ok) {
  4527. auto last = offset + data_len == content_length;
  4528. auto ret = compressor.compress(
  4529. data, data_len, last,
  4530. [&](const char *compressed_data, size_t compressed_data_len) {
  4531. req.body.append(compressed_data, compressed_data_len);
  4532. return true;
  4533. });
  4534. if (ret) {
  4535. offset += data_len;
  4536. } else {
  4537. ok = false;
  4538. }
  4539. }
  4540. return ok;
  4541. };
  4542. while (ok && offset < content_length) {
  4543. if (!content_provider(offset, content_length - offset, data_sink)) {
  4544. error = Error::Canceled;
  4545. return nullptr;
  4546. }
  4547. }
  4548. } else {
  4549. if (!compressor.compress(body, content_length, true,
  4550. [&](const char *data, size_t data_len) {
  4551. req.body.append(data, data_len);
  4552. return true;
  4553. })) {
  4554. error = Error::Compression;
  4555. return nullptr;
  4556. }
  4557. }
  4558. } else
  4559. #endif
  4560. {
  4561. if (content_provider) {
  4562. req.content_length_ = content_length;
  4563. req.content_provider_ = std::move(content_provider);
  4564. req.is_chunked_content_provider_ = false;
  4565. } else if (content_provider_without_length) {
  4566. req.content_length_ = 0;
  4567. req.content_provider_ = detail::ContentProviderAdapter(
  4568. std::move(content_provider_without_length));
  4569. req.is_chunked_content_provider_ = true;
  4570. req.set_header("Transfer-Encoding", "chunked");
  4571. } else {
  4572. req.body.assign(body, content_length);
  4573. }
  4574. }
  4575. auto res = detail::make_unique<Response>();
  4576. return send(req, *res, error) ? std::move(res) : nullptr;
  4577. }
  4578. Result ClientImpl::send_with_content_provider(
  4579. const std::string &method, const std::string &path, const Headers &headers,
  4580. const char *body, size_t content_length, ContentProvider content_provider,
  4581. ContentProviderWithoutLength content_provider_without_length,
  4582. const std::string &content_type, Progress progress) {
  4583. Request req;
  4584. req.method = method;
  4585. req.headers = headers;
  4586. req.path = path;
  4587. req.progress = progress;
  4588. if (max_timeout_msec_ > 0) {
  4589. req.start_time_ = std::chrono::steady_clock::now();
  4590. }
  4591. auto error = Error::Success;
  4592. auto res = send_with_content_provider(
  4593. req, body, content_length, std::move(content_provider),
  4594. std::move(content_provider_without_length), content_type, error);
  4595. return Result{std::move(res), error, std::move(req.headers)};
  4596. }
  4597. std::string
  4598. ClientImpl::adjust_host_string(const std::string &host) const {
  4599. if (host.find(':') != std::string::npos) { return "[" + host + "]"; }
  4600. return host;
  4601. }
  4602. bool ClientImpl::process_request(Stream &strm, Request &req,
  4603. Response &res, bool close_connection,
  4604. Error &error) {
  4605. // Send request
  4606. if (!write_request(strm, req, close_connection, error)) { return false; }
  4607. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  4608. if (is_ssl()) {
  4609. auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1;
  4610. if (!is_proxy_enabled) {
  4611. if (detail::is_ssl_peer_could_be_closed(socket_.ssl, socket_.sock)) {
  4612. error = Error::SSLPeerCouldBeClosed_;
  4613. return false;
  4614. }
  4615. }
  4616. }
  4617. #endif
  4618. // Receive response and headers
  4619. if (!read_response_line(strm, req, res) ||
  4620. !detail::read_headers(strm, res.headers)) {
  4621. error = Error::Read;
  4622. return false;
  4623. }
  4624. // Body
  4625. if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
  4626. req.method != "CONNECT") {
  4627. auto redirect = 300 < res.status && res.status < 400 &&
  4628. res.status != StatusCode::NotModified_304 &&
  4629. follow_location_;
  4630. if (req.response_handler && !redirect) {
  4631. if (!req.response_handler(res)) {
  4632. error = Error::Canceled;
  4633. return false;
  4634. }
  4635. }
  4636. auto out =
  4637. req.content_receiver
  4638. ? static_cast<ContentReceiverWithProgress>(
  4639. [&](const char *buf, size_t n, uint64_t off, uint64_t len) {
  4640. if (redirect) { return true; }
  4641. auto ret = req.content_receiver(buf, n, off, len);
  4642. if (!ret) { error = Error::Canceled; }
  4643. return ret;
  4644. })
  4645. : static_cast<ContentReceiverWithProgress>(
  4646. [&](const char *buf, size_t n, uint64_t /*off*/,
  4647. uint64_t /*len*/) {
  4648. assert(res.body.size() + n <= res.body.max_size());
  4649. res.body.append(buf, n);
  4650. return true;
  4651. });
  4652. auto progress = [&](uint64_t current, uint64_t total) {
  4653. if (!req.progress || redirect) { return true; }
  4654. auto ret = req.progress(current, total);
  4655. if (!ret) { error = Error::Canceled; }
  4656. return ret;
  4657. };
  4658. if (res.has_header("Content-Length")) {
  4659. if (!req.content_receiver) {
  4660. auto len = res.get_header_value_u64("Content-Length");
  4661. if (len > res.body.max_size()) {
  4662. error = Error::Read;
  4663. return false;
  4664. }
  4665. res.body.reserve(static_cast<size_t>(len));
  4666. }
  4667. }
  4668. if (res.status != StatusCode::NotModified_304) {
  4669. int dummy_status;
  4670. if (!detail::read_content(strm, res, (std::numeric_limits<size_t>::max)(),
  4671. dummy_status, std::move(progress),
  4672. std::move(out), decompress_)) {
  4673. if (error != Error::Canceled) { error = Error::Read; }
  4674. return false;
  4675. }
  4676. }
  4677. }
  4678. // Log
  4679. if (logger_) { logger_(req, res); }
  4680. return true;
  4681. }
  4682. ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
  4683. const std::string &boundary, const MultipartFormDataItems &items,
  4684. const MultipartFormDataProviderItems &provider_items) const {
  4685. size_t cur_item = 0;
  4686. size_t cur_start = 0;
  4687. // cur_item and cur_start are copied to within the std::function and maintain
  4688. // state between successive calls
  4689. return [&, cur_item, cur_start](size_t offset,
  4690. DataSink &sink) mutable -> bool {
  4691. if (!offset && !items.empty()) {
  4692. sink.os << detail::serialize_multipart_formdata(items, boundary, false);
  4693. return true;
  4694. } else if (cur_item < provider_items.size()) {
  4695. if (!cur_start) {
  4696. const auto &begin = detail::serialize_multipart_formdata_item_begin(
  4697. provider_items[cur_item], boundary);
  4698. offset += begin.size();
  4699. cur_start = offset;
  4700. sink.os << begin;
  4701. }
  4702. DataSink cur_sink;
  4703. auto has_data = true;
  4704. cur_sink.write = sink.write;
  4705. cur_sink.done = [&]() { has_data = false; };
  4706. if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) {
  4707. return false;
  4708. }
  4709. if (!has_data) {
  4710. sink.os << detail::serialize_multipart_formdata_item_end();
  4711. cur_item++;
  4712. cur_start = 0;
  4713. }
  4714. return true;
  4715. } else {
  4716. sink.os << detail::serialize_multipart_formdata_finish(boundary);
  4717. sink.done();
  4718. return true;
  4719. }
  4720. };
  4721. }
  4722. bool ClientImpl::process_socket(
  4723. const Socket &socket,
  4724. std::chrono::time_point<std::chrono::steady_clock> start_time,
  4725. std::function<bool(Stream &strm)> callback) {
  4726. return detail::process_client_socket(
  4727. socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
  4728. write_timeout_usec_, max_timeout_msec_, start_time, std::move(callback));
  4729. }
  4730. bool ClientImpl::is_ssl() const { return false; }
  4731. Result ClientImpl::Get(const std::string &path) {
  4732. return Get(path, Headers(), Progress());
  4733. }
  4734. Result ClientImpl::Get(const std::string &path, Progress progress) {
  4735. return Get(path, Headers(), std::move(progress));
  4736. }
  4737. Result ClientImpl::Get(const std::string &path, const Headers &headers) {
  4738. return Get(path, headers, Progress());
  4739. }
  4740. Result ClientImpl::Get(const std::string &path, const Headers &headers,
  4741. Progress progress) {
  4742. Request req;
  4743. req.method = "GET";
  4744. req.path = path;
  4745. req.headers = headers;
  4746. req.progress = std::move(progress);
  4747. if (max_timeout_msec_ > 0) {
  4748. req.start_time_ = std::chrono::steady_clock::now();
  4749. }
  4750. return send_(std::move(req));
  4751. }
  4752. Result ClientImpl::Get(const std::string &path,
  4753. ContentReceiver content_receiver) {
  4754. return Get(path, Headers(), nullptr, std::move(content_receiver), nullptr);
  4755. }
  4756. Result ClientImpl::Get(const std::string &path,
  4757. ContentReceiver content_receiver,
  4758. Progress progress) {
  4759. return Get(path, Headers(), nullptr, std::move(content_receiver),
  4760. std::move(progress));
  4761. }
  4762. Result ClientImpl::Get(const std::string &path, const Headers &headers,
  4763. ContentReceiver content_receiver) {
  4764. return Get(path, headers, nullptr, std::move(content_receiver), nullptr);
  4765. }
  4766. Result ClientImpl::Get(const std::string &path, const Headers &headers,
  4767. ContentReceiver content_receiver,
  4768. Progress progress) {
  4769. return Get(path, headers, nullptr, std::move(content_receiver),
  4770. std::move(progress));
  4771. }
  4772. Result ClientImpl::Get(const std::string &path,
  4773. ResponseHandler response_handler,
  4774. ContentReceiver content_receiver) {
  4775. return Get(path, Headers(), std::move(response_handler),
  4776. std::move(content_receiver), nullptr);
  4777. }
  4778. Result ClientImpl::Get(const std::string &path, const Headers &headers,
  4779. ResponseHandler response_handler,
  4780. ContentReceiver content_receiver) {
  4781. return Get(path, headers, std::move(response_handler),
  4782. std::move(content_receiver), nullptr);
  4783. }
  4784. Result ClientImpl::Get(const std::string &path,
  4785. ResponseHandler response_handler,
  4786. ContentReceiver content_receiver,
  4787. Progress progress) {
  4788. return Get(path, Headers(), std::move(response_handler),
  4789. std::move(content_receiver), std::move(progress));
  4790. }
  4791. Result ClientImpl::Get(const std::string &path, const Headers &headers,
  4792. ResponseHandler response_handler,
  4793. ContentReceiver content_receiver,
  4794. Progress progress) {
  4795. Request req;
  4796. req.method = "GET";
  4797. req.path = path;
  4798. req.headers = headers;
  4799. req.response_handler = std::move(response_handler);
  4800. req.content_receiver =
  4801. [content_receiver](const char *data, size_t data_length,
  4802. uint64_t /*offset*/, uint64_t /*total_length*/) {
  4803. return content_receiver(data, data_length);
  4804. };
  4805. req.progress = std::move(progress);
  4806. if (max_timeout_msec_ > 0) {
  4807. req.start_time_ = std::chrono::steady_clock::now();
  4808. }
  4809. return send_(std::move(req));
  4810. }
  4811. Result ClientImpl::Get(const std::string &path, const Params &params,
  4812. const Headers &headers, Progress progress) {
  4813. if (params.empty()) { return Get(path, headers); }
  4814. std::string path_with_query = append_query_params(path, params);
  4815. return Get(path_with_query, headers, std::move(progress));
  4816. }
  4817. Result ClientImpl::Get(const std::string &path, const Params &params,
  4818. const Headers &headers,
  4819. ContentReceiver content_receiver,
  4820. Progress progress) {
  4821. return Get(path, params, headers, nullptr, std::move(content_receiver),
  4822. std::move(progress));
  4823. }
  4824. Result ClientImpl::Get(const std::string &path, const Params &params,
  4825. const Headers &headers,
  4826. ResponseHandler response_handler,
  4827. ContentReceiver content_receiver,
  4828. Progress progress) {
  4829. if (params.empty()) {
  4830. return Get(path, headers, std::move(response_handler),
  4831. std::move(content_receiver), std::move(progress));
  4832. }
  4833. std::string path_with_query = append_query_params(path, params);
  4834. return Get(path_with_query, headers, std::move(response_handler),
  4835. std::move(content_receiver), std::move(progress));
  4836. }
  4837. Result ClientImpl::Head(const std::string &path) {
  4838. return Head(path, Headers());
  4839. }
  4840. Result ClientImpl::Head(const std::string &path,
  4841. const Headers &headers) {
  4842. Request req;
  4843. req.method = "HEAD";
  4844. req.headers = headers;
  4845. req.path = path;
  4846. if (max_timeout_msec_ > 0) {
  4847. req.start_time_ = std::chrono::steady_clock::now();
  4848. }
  4849. return send_(std::move(req));
  4850. }
  4851. Result ClientImpl::Post(const std::string &path) {
  4852. return Post(path, std::string(), std::string());
  4853. }
  4854. Result ClientImpl::Post(const std::string &path,
  4855. const Headers &headers) {
  4856. return Post(path, headers, nullptr, 0, std::string());
  4857. }
  4858. Result ClientImpl::Post(const std::string &path, const char *body,
  4859. size_t content_length,
  4860. const std::string &content_type) {
  4861. return Post(path, Headers(), body, content_length, content_type, nullptr);
  4862. }
  4863. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4864. const char *body, size_t content_length,
  4865. const std::string &content_type) {
  4866. return send_with_content_provider("POST", path, headers, body, content_length,
  4867. nullptr, nullptr, content_type, nullptr);
  4868. }
  4869. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4870. const char *body, size_t content_length,
  4871. const std::string &content_type,
  4872. Progress progress) {
  4873. return send_with_content_provider("POST", path, headers, body, content_length,
  4874. nullptr, nullptr, content_type, progress);
  4875. }
  4876. Result ClientImpl::Post(const std::string &path, const std::string &body,
  4877. const std::string &content_type) {
  4878. return Post(path, Headers(), body, content_type);
  4879. }
  4880. Result ClientImpl::Post(const std::string &path, const std::string &body,
  4881. const std::string &content_type,
  4882. Progress progress) {
  4883. return Post(path, Headers(), body, content_type, progress);
  4884. }
  4885. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4886. const std::string &body,
  4887. const std::string &content_type) {
  4888. return send_with_content_provider("POST", path, headers, body.data(),
  4889. body.size(), nullptr, nullptr, content_type,
  4890. nullptr);
  4891. }
  4892. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4893. const std::string &body,
  4894. const std::string &content_type,
  4895. Progress progress) {
  4896. return send_with_content_provider("POST", path, headers, body.data(),
  4897. body.size(), nullptr, nullptr, content_type,
  4898. progress);
  4899. }
  4900. Result ClientImpl::Post(const std::string &path, const Params &params) {
  4901. return Post(path, Headers(), params);
  4902. }
  4903. Result ClientImpl::Post(const std::string &path, size_t content_length,
  4904. ContentProvider content_provider,
  4905. const std::string &content_type) {
  4906. return Post(path, Headers(), content_length, std::move(content_provider),
  4907. content_type);
  4908. }
  4909. Result ClientImpl::Post(const std::string &path,
  4910. ContentProviderWithoutLength content_provider,
  4911. const std::string &content_type) {
  4912. return Post(path, Headers(), std::move(content_provider), content_type);
  4913. }
  4914. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4915. size_t content_length,
  4916. ContentProvider content_provider,
  4917. const std::string &content_type) {
  4918. return send_with_content_provider("POST", path, headers, nullptr,
  4919. content_length, std::move(content_provider),
  4920. nullptr, content_type, nullptr);
  4921. }
  4922. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4923. ContentProviderWithoutLength content_provider,
  4924. const std::string &content_type) {
  4925. return send_with_content_provider("POST", path, headers, nullptr, 0, nullptr,
  4926. std::move(content_provider), content_type,
  4927. nullptr);
  4928. }
  4929. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4930. const Params &params) {
  4931. auto query = detail::params_to_query_str(params);
  4932. return Post(path, headers, query, "application/x-www-form-urlencoded");
  4933. }
  4934. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4935. const Params &params, Progress progress) {
  4936. auto query = detail::params_to_query_str(params);
  4937. return Post(path, headers, query, "application/x-www-form-urlencoded",
  4938. progress);
  4939. }
  4940. Result ClientImpl::Post(const std::string &path,
  4941. const MultipartFormDataItems &items) {
  4942. return Post(path, Headers(), items);
  4943. }
  4944. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4945. const MultipartFormDataItems &items) {
  4946. const auto &boundary = detail::make_multipart_data_boundary();
  4947. const auto &content_type =
  4948. detail::serialize_multipart_formdata_get_content_type(boundary);
  4949. const auto &body = detail::serialize_multipart_formdata(items, boundary);
  4950. return Post(path, headers, body, content_type);
  4951. }
  4952. Result ClientImpl::Post(const std::string &path, const Headers &headers,
  4953. const MultipartFormDataItems &items,
  4954. const std::string &boundary) {
  4955. if (!detail::is_multipart_boundary_chars_valid(boundary)) {
  4956. return Result{nullptr, Error::UnsupportedMultipartBoundaryChars};
  4957. }
  4958. const auto &content_type =
  4959. detail::serialize_multipart_formdata_get_content_type(boundary);
  4960. const auto &body = detail::serialize_multipart_formdata(items, boundary);
  4961. return Post(path, headers, body, content_type);
  4962. }
  4963. Result
  4964. ClientImpl::Post(const std::string &path, const Headers &headers,
  4965. const MultipartFormDataItems &items,
  4966. const MultipartFormDataProviderItems &provider_items) {
  4967. const auto &boundary = detail::make_multipart_data_boundary();
  4968. const auto &content_type =
  4969. detail::serialize_multipart_formdata_get_content_type(boundary);
  4970. return send_with_content_provider(
  4971. "POST", path, headers, nullptr, 0, nullptr,
  4972. get_multipart_content_provider(boundary, items, provider_items),
  4973. content_type, nullptr);
  4974. }
  4975. Result ClientImpl::Put(const std::string &path) {
  4976. return Put(path, std::string(), std::string());
  4977. }
  4978. Result ClientImpl::Put(const std::string &path, const char *body,
  4979. size_t content_length,
  4980. const std::string &content_type) {
  4981. return Put(path, Headers(), body, content_length, content_type);
  4982. }
  4983. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  4984. const char *body, size_t content_length,
  4985. const std::string &content_type) {
  4986. return send_with_content_provider("PUT", path, headers, body, content_length,
  4987. nullptr, nullptr, content_type, nullptr);
  4988. }
  4989. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  4990. const char *body, size_t content_length,
  4991. const std::string &content_type,
  4992. Progress progress) {
  4993. return send_with_content_provider("PUT", path, headers, body, content_length,
  4994. nullptr, nullptr, content_type, progress);
  4995. }
  4996. Result ClientImpl::Put(const std::string &path, const std::string &body,
  4997. const std::string &content_type) {
  4998. return Put(path, Headers(), body, content_type);
  4999. }
  5000. Result ClientImpl::Put(const std::string &path, const std::string &body,
  5001. const std::string &content_type,
  5002. Progress progress) {
  5003. return Put(path, Headers(), body, content_type, progress);
  5004. }
  5005. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5006. const std::string &body,
  5007. const std::string &content_type) {
  5008. return send_with_content_provider("PUT", path, headers, body.data(),
  5009. body.size(), nullptr, nullptr, content_type,
  5010. nullptr);
  5011. }
  5012. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5013. const std::string &body,
  5014. const std::string &content_type,
  5015. Progress progress) {
  5016. return send_with_content_provider("PUT", path, headers, body.data(),
  5017. body.size(), nullptr, nullptr, content_type,
  5018. progress);
  5019. }
  5020. Result ClientImpl::Put(const std::string &path, size_t content_length,
  5021. ContentProvider content_provider,
  5022. const std::string &content_type) {
  5023. return Put(path, Headers(), content_length, std::move(content_provider),
  5024. content_type);
  5025. }
  5026. Result ClientImpl::Put(const std::string &path,
  5027. ContentProviderWithoutLength content_provider,
  5028. const std::string &content_type) {
  5029. return Put(path, Headers(), std::move(content_provider), content_type);
  5030. }
  5031. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5032. size_t content_length,
  5033. ContentProvider content_provider,
  5034. const std::string &content_type) {
  5035. return send_with_content_provider("PUT", path, headers, nullptr,
  5036. content_length, std::move(content_provider),
  5037. nullptr, content_type, nullptr);
  5038. }
  5039. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5040. ContentProviderWithoutLength content_provider,
  5041. const std::string &content_type) {
  5042. return send_with_content_provider("PUT", path, headers, nullptr, 0, nullptr,
  5043. std::move(content_provider), content_type,
  5044. nullptr);
  5045. }
  5046. Result ClientImpl::Put(const std::string &path, const Params &params) {
  5047. return Put(path, Headers(), params);
  5048. }
  5049. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5050. const Params &params) {
  5051. auto query = detail::params_to_query_str(params);
  5052. return Put(path, headers, query, "application/x-www-form-urlencoded");
  5053. }
  5054. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5055. const Params &params, Progress progress) {
  5056. auto query = detail::params_to_query_str(params);
  5057. return Put(path, headers, query, "application/x-www-form-urlencoded",
  5058. progress);
  5059. }
  5060. Result ClientImpl::Put(const std::string &path,
  5061. const MultipartFormDataItems &items) {
  5062. return Put(path, Headers(), items);
  5063. }
  5064. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5065. const MultipartFormDataItems &items) {
  5066. const auto &boundary = detail::make_multipart_data_boundary();
  5067. const auto &content_type =
  5068. detail::serialize_multipart_formdata_get_content_type(boundary);
  5069. const auto &body = detail::serialize_multipart_formdata(items, boundary);
  5070. return Put(path, headers, body, content_type);
  5071. }
  5072. Result ClientImpl::Put(const std::string &path, const Headers &headers,
  5073. const MultipartFormDataItems &items,
  5074. const std::string &boundary) {
  5075. if (!detail::is_multipart_boundary_chars_valid(boundary)) {
  5076. return Result{nullptr, Error::UnsupportedMultipartBoundaryChars};
  5077. }
  5078. const auto &content_type =
  5079. detail::serialize_multipart_formdata_get_content_type(boundary);
  5080. const auto &body = detail::serialize_multipart_formdata(items, boundary);
  5081. return Put(path, headers, body, content_type);
  5082. }
  5083. Result
  5084. ClientImpl::Put(const std::string &path, const Headers &headers,
  5085. const MultipartFormDataItems &items,
  5086. const MultipartFormDataProviderItems &provider_items) {
  5087. const auto &boundary = detail::make_multipart_data_boundary();
  5088. const auto &content_type =
  5089. detail::serialize_multipart_formdata_get_content_type(boundary);
  5090. return send_with_content_provider(
  5091. "PUT", path, headers, nullptr, 0, nullptr,
  5092. get_multipart_content_provider(boundary, items, provider_items),
  5093. content_type, nullptr);
  5094. }
  5095. Result ClientImpl::Patch(const std::string &path) {
  5096. return Patch(path, std::string(), std::string());
  5097. }
  5098. Result ClientImpl::Patch(const std::string &path, const char *body,
  5099. size_t content_length,
  5100. const std::string &content_type) {
  5101. return Patch(path, Headers(), body, content_length, content_type);
  5102. }
  5103. Result ClientImpl::Patch(const std::string &path, const char *body,
  5104. size_t content_length,
  5105. const std::string &content_type,
  5106. Progress progress) {
  5107. return Patch(path, Headers(), body, content_length, content_type, progress);
  5108. }
  5109. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5110. const char *body, size_t content_length,
  5111. const std::string &content_type) {
  5112. return Patch(path, headers, body, content_length, content_type, nullptr);
  5113. }
  5114. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5115. const char *body, size_t content_length,
  5116. const std::string &content_type,
  5117. Progress progress) {
  5118. return send_with_content_provider("PATCH", path, headers, body,
  5119. content_length, nullptr, nullptr,
  5120. content_type, progress);
  5121. }
  5122. Result ClientImpl::Patch(const std::string &path,
  5123. const std::string &body,
  5124. const std::string &content_type) {
  5125. return Patch(path, Headers(), body, content_type);
  5126. }
  5127. Result ClientImpl::Patch(const std::string &path,
  5128. const std::string &body,
  5129. const std::string &content_type,
  5130. Progress progress) {
  5131. return Patch(path, Headers(), body, content_type, progress);
  5132. }
  5133. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5134. const std::string &body,
  5135. const std::string &content_type) {
  5136. return Patch(path, headers, body, content_type, nullptr);
  5137. }
  5138. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5139. const std::string &body,
  5140. const std::string &content_type,
  5141. Progress progress) {
  5142. return send_with_content_provider("PATCH", path, headers, body.data(),
  5143. body.size(), nullptr, nullptr, content_type,
  5144. progress);
  5145. }
  5146. Result ClientImpl::Patch(const std::string &path, size_t content_length,
  5147. ContentProvider content_provider,
  5148. const std::string &content_type) {
  5149. return Patch(path, Headers(), content_length, std::move(content_provider),
  5150. content_type);
  5151. }
  5152. Result ClientImpl::Patch(const std::string &path,
  5153. ContentProviderWithoutLength content_provider,
  5154. const std::string &content_type) {
  5155. return Patch(path, Headers(), std::move(content_provider), content_type);
  5156. }
  5157. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5158. size_t content_length,
  5159. ContentProvider content_provider,
  5160. const std::string &content_type) {
  5161. return send_with_content_provider("PATCH", path, headers, nullptr,
  5162. content_length, std::move(content_provider),
  5163. nullptr, content_type, nullptr);
  5164. }
  5165. Result ClientImpl::Patch(const std::string &path, const Headers &headers,
  5166. ContentProviderWithoutLength content_provider,
  5167. const std::string &content_type) {
  5168. return send_with_content_provider("PATCH", path, headers, nullptr, 0, nullptr,
  5169. std::move(content_provider), content_type,
  5170. nullptr);
  5171. }
  5172. Result ClientImpl::Delete(const std::string &path) {
  5173. return Delete(path, Headers(), std::string(), std::string());
  5174. }
  5175. Result ClientImpl::Delete(const std::string &path,
  5176. const Headers &headers) {
  5177. return Delete(path, headers, std::string(), std::string());
  5178. }
  5179. Result ClientImpl::Delete(const std::string &path, const char *body,
  5180. size_t content_length,
  5181. const std::string &content_type) {
  5182. return Delete(path, Headers(), body, content_length, content_type);
  5183. }
  5184. Result ClientImpl::Delete(const std::string &path, const char *body,
  5185. size_t content_length,
  5186. const std::string &content_type,
  5187. Progress progress) {
  5188. return Delete(path, Headers(), body, content_length, content_type, progress);
  5189. }
  5190. Result ClientImpl::Delete(const std::string &path,
  5191. const Headers &headers, const char *body,
  5192. size_t content_length,
  5193. const std::string &content_type) {
  5194. return Delete(path, headers, body, content_length, content_type, nullptr);
  5195. }
  5196. Result ClientImpl::Delete(const std::string &path,
  5197. const Headers &headers, const char *body,
  5198. size_t content_length,
  5199. const std::string &content_type,
  5200. Progress progress) {
  5201. Request req;
  5202. req.method = "DELETE";
  5203. req.headers = headers;
  5204. req.path = path;
  5205. req.progress = progress;
  5206. if (max_timeout_msec_ > 0) {
  5207. req.start_time_ = std::chrono::steady_clock::now();
  5208. }
  5209. if (!content_type.empty()) { req.set_header("Content-Type", content_type); }
  5210. req.body.assign(body, content_length);
  5211. return send_(std::move(req));
  5212. }
  5213. Result ClientImpl::Delete(const std::string &path,
  5214. const std::string &body,
  5215. const std::string &content_type) {
  5216. return Delete(path, Headers(), body.data(), body.size(), content_type);
  5217. }
  5218. Result ClientImpl::Delete(const std::string &path,
  5219. const std::string &body,
  5220. const std::string &content_type,
  5221. Progress progress) {
  5222. return Delete(path, Headers(), body.data(), body.size(), content_type,
  5223. progress);
  5224. }
  5225. Result ClientImpl::Delete(const std::string &path,
  5226. const Headers &headers,
  5227. const std::string &body,
  5228. const std::string &content_type) {
  5229. return Delete(path, headers, body.data(), body.size(), content_type);
  5230. }
  5231. Result ClientImpl::Delete(const std::string &path,
  5232. const Headers &headers,
  5233. const std::string &body,
  5234. const std::string &content_type,
  5235. Progress progress) {
  5236. return Delete(path, headers, body.data(), body.size(), content_type,
  5237. progress);
  5238. }
  5239. Result ClientImpl::Options(const std::string &path) {
  5240. return Options(path, Headers());
  5241. }
  5242. Result ClientImpl::Options(const std::string &path,
  5243. const Headers &headers) {
  5244. Request req;
  5245. req.method = "OPTIONS";
  5246. req.headers = headers;
  5247. req.path = path;
  5248. if (max_timeout_msec_ > 0) {
  5249. req.start_time_ = std::chrono::steady_clock::now();
  5250. }
  5251. return send_(std::move(req));
  5252. }
  5253. void ClientImpl::stop() {
  5254. std::lock_guard<std::mutex> guard(socket_mutex_);
  5255. // If there is anything ongoing right now, the ONLY thread-safe thing we can
  5256. // do is to shutdown_socket, so that threads using this socket suddenly
  5257. // discover they can't read/write any more and error out. Everything else
  5258. // (closing the socket, shutting ssl down) is unsafe because these actions are
  5259. // not thread-safe.
  5260. if (socket_requests_in_flight_ > 0) {
  5261. shutdown_socket(socket_);
  5262. // Aside from that, we set a flag for the socket to be closed when we're
  5263. // done.
  5264. socket_should_be_closed_when_request_is_done_ = true;
  5265. return;
  5266. }
  5267. // Otherwise, still holding the mutex, we can shut everything down ourselves
  5268. shutdown_ssl(socket_, true);
  5269. shutdown_socket(socket_);
  5270. close_socket(socket_);
  5271. }
  5272. std::string ClientImpl::host() const { return host_; }
  5273. int ClientImpl::port() const { return port_; }
  5274. size_t ClientImpl::is_socket_open() const {
  5275. std::lock_guard<std::mutex> guard(socket_mutex_);
  5276. return socket_.is_open();
  5277. }
  5278. socket_t ClientImpl::socket() const { return socket_.sock; }
  5279. void ClientImpl::set_connection_timeout(time_t sec, time_t usec) {
  5280. connection_timeout_sec_ = sec;
  5281. connection_timeout_usec_ = usec;
  5282. }
  5283. void ClientImpl::set_read_timeout(time_t sec, time_t usec) {
  5284. read_timeout_sec_ = sec;
  5285. read_timeout_usec_ = usec;
  5286. }
  5287. void ClientImpl::set_write_timeout(time_t sec, time_t usec) {
  5288. write_timeout_sec_ = sec;
  5289. write_timeout_usec_ = usec;
  5290. }
  5291. void ClientImpl::set_max_timeout(time_t msec) {
  5292. max_timeout_msec_ = msec;
  5293. }
  5294. void ClientImpl::set_basic_auth(const std::string &username,
  5295. const std::string &password) {
  5296. basic_auth_username_ = username;
  5297. basic_auth_password_ = password;
  5298. }
  5299. void ClientImpl::set_bearer_token_auth(const std::string &token) {
  5300. bearer_token_auth_token_ = token;
  5301. }
  5302. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  5303. void ClientImpl::set_digest_auth(const std::string &username,
  5304. const std::string &password) {
  5305. digest_auth_username_ = username;
  5306. digest_auth_password_ = password;
  5307. }
  5308. #endif
  5309. void ClientImpl::set_keep_alive(bool on) { keep_alive_ = on; }
  5310. void ClientImpl::set_follow_location(bool on) { follow_location_ = on; }
  5311. void ClientImpl::set_url_encode(bool on) { url_encode_ = on; }
  5312. void
  5313. ClientImpl::set_hostname_addr_map(std::map<std::string, std::string> addr_map) {
  5314. addr_map_ = std::move(addr_map);
  5315. }
  5316. void ClientImpl::set_default_headers(Headers headers) {
  5317. default_headers_ = std::move(headers);
  5318. }
  5319. void ClientImpl::set_header_writer(
  5320. std::function<ssize_t(Stream &, Headers &)> const &writer) {
  5321. header_writer_ = writer;
  5322. }
  5323. void ClientImpl::set_address_family(int family) {
  5324. address_family_ = family;
  5325. }
  5326. void ClientImpl::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; }
  5327. void ClientImpl::set_ipv6_v6only(bool on) { ipv6_v6only_ = on; }
  5328. void ClientImpl::set_socket_options(SocketOptions socket_options) {
  5329. socket_options_ = std::move(socket_options);
  5330. }
  5331. void ClientImpl::set_compress(bool on) { compress_ = on; }
  5332. void ClientImpl::set_decompress(bool on) { decompress_ = on; }
  5333. void ClientImpl::set_interface(const std::string &intf) {
  5334. interface_ = intf;
  5335. }
  5336. void ClientImpl::set_proxy(const std::string &host, int port) {
  5337. proxy_host_ = host;
  5338. proxy_port_ = port;
  5339. }
  5340. void ClientImpl::set_proxy_basic_auth(const std::string &username,
  5341. const std::string &password) {
  5342. proxy_basic_auth_username_ = username;
  5343. proxy_basic_auth_password_ = password;
  5344. }
  5345. void ClientImpl::set_proxy_bearer_token_auth(const std::string &token) {
  5346. proxy_bearer_token_auth_token_ = token;
  5347. }
  5348. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  5349. void ClientImpl::set_proxy_digest_auth(const std::string &username,
  5350. const std::string &password) {
  5351. proxy_digest_auth_username_ = username;
  5352. proxy_digest_auth_password_ = password;
  5353. }
  5354. void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path,
  5355. const std::string &ca_cert_dir_path) {
  5356. ca_cert_file_path_ = ca_cert_file_path;
  5357. ca_cert_dir_path_ = ca_cert_dir_path;
  5358. }
  5359. void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
  5360. if (ca_cert_store && ca_cert_store != ca_cert_store_) {
  5361. ca_cert_store_ = ca_cert_store;
  5362. }
  5363. }
  5364. X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert,
  5365. std::size_t size) const {
  5366. auto mem = BIO_new_mem_buf(ca_cert, static_cast<int>(size));
  5367. auto se = detail::scope_exit([&] { BIO_free_all(mem); });
  5368. if (!mem) { return nullptr; }
  5369. auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr);
  5370. if (!inf) { return nullptr; }
  5371. auto cts = X509_STORE_new();
  5372. if (cts) {
  5373. for (auto i = 0; i < static_cast<int>(sk_X509_INFO_num(inf)); i++) {
  5374. auto itmp = sk_X509_INFO_value(inf, i);
  5375. if (!itmp) { continue; }
  5376. if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); }
  5377. if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); }
  5378. }
  5379. }
  5380. sk_X509_INFO_pop_free(inf, X509_INFO_free);
  5381. return cts;
  5382. }
  5383. void ClientImpl::enable_server_certificate_verification(bool enabled) {
  5384. server_certificate_verification_ = enabled;
  5385. }
  5386. void ClientImpl::enable_server_hostname_verification(bool enabled) {
  5387. server_hostname_verification_ = enabled;
  5388. }
  5389. void ClientImpl::set_server_certificate_verifier(
  5390. std::function<SSLVerifierResponse(SSL *ssl)> verifier) {
  5391. server_certificate_verifier_ = verifier;
  5392. }
  5393. #endif
  5394. void ClientImpl::set_logger(Logger logger) {
  5395. logger_ = std::move(logger);
  5396. }
  5397. /*
  5398. * SSL Implementation
  5399. */
  5400. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  5401. namespace detail {
  5402. template <typename U, typename V>
  5403. SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex,
  5404. U SSL_connect_or_accept, V setup) {
  5405. SSL *ssl = nullptr;
  5406. {
  5407. std::lock_guard<std::mutex> guard(ctx_mutex);
  5408. ssl = SSL_new(ctx);
  5409. }
  5410. if (ssl) {
  5411. set_nonblocking(sock, true);
  5412. auto bio = BIO_new_socket(static_cast<int>(sock), BIO_NOCLOSE);
  5413. BIO_set_nbio(bio, 1);
  5414. SSL_set_bio(ssl, bio, bio);
  5415. if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) {
  5416. SSL_shutdown(ssl);
  5417. {
  5418. std::lock_guard<std::mutex> guard(ctx_mutex);
  5419. SSL_free(ssl);
  5420. }
  5421. set_nonblocking(sock, false);
  5422. return nullptr;
  5423. }
  5424. BIO_set_nbio(bio, 0);
  5425. set_nonblocking(sock, false);
  5426. }
  5427. return ssl;
  5428. }
  5429. void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
  5430. bool shutdown_gracefully) {
  5431. // sometimes we may want to skip this to try to avoid SIGPIPE if we know
  5432. // the remote has closed the network connection
  5433. // Note that it is not always possible to avoid SIGPIPE, this is merely a
  5434. // best-efforts.
  5435. if (shutdown_gracefully) {
  5436. (void)(sock);
  5437. // SSL_shutdown() returns 0 on first call (indicating close_notify alert
  5438. // sent) and 1 on subsequent call (indicating close_notify alert received)
  5439. if (SSL_shutdown(ssl) == 0) {
  5440. // Expected to return 1, but even if it doesn't, we free ssl
  5441. SSL_shutdown(ssl);
  5442. }
  5443. }
  5444. std::lock_guard<std::mutex> guard(ctx_mutex);
  5445. SSL_free(ssl);
  5446. }
  5447. template <typename U>
  5448. bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl,
  5449. U ssl_connect_or_accept,
  5450. time_t timeout_sec,
  5451. time_t timeout_usec) {
  5452. auto res = 0;
  5453. while ((res = ssl_connect_or_accept(ssl)) != 1) {
  5454. auto err = SSL_get_error(ssl, res);
  5455. switch (err) {
  5456. case SSL_ERROR_WANT_READ:
  5457. if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; }
  5458. break;
  5459. case SSL_ERROR_WANT_WRITE:
  5460. if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; }
  5461. break;
  5462. default: break;
  5463. }
  5464. return false;
  5465. }
  5466. return true;
  5467. }
  5468. template <typename T>
  5469. bool process_server_socket_ssl(
  5470. const std::atomic<socket_t> &svr_sock, SSL *ssl, socket_t sock,
  5471. size_t keep_alive_max_count, time_t keep_alive_timeout_sec,
  5472. time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
  5473. time_t write_timeout_usec, T callback) {
  5474. return process_server_socket_core(
  5475. svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
  5476. [&](bool close_connection, bool &connection_closed) {
  5477. SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
  5478. write_timeout_sec, write_timeout_usec);
  5479. return callback(strm, close_connection, connection_closed);
  5480. });
  5481. }
  5482. template <typename T>
  5483. bool process_client_socket_ssl(
  5484. SSL *ssl, socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
  5485. time_t write_timeout_sec, time_t write_timeout_usec,
  5486. time_t max_timeout_msec,
  5487. std::chrono::time_point<std::chrono::steady_clock> start_time, T callback) {
  5488. SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
  5489. write_timeout_sec, write_timeout_usec, max_timeout_msec,
  5490. start_time);
  5491. return callback(strm);
  5492. }
  5493. // SSL socket stream implementation
  5494. SSLSocketStream::SSLSocketStream(
  5495. socket_t sock, SSL *ssl, time_t read_timeout_sec, time_t read_timeout_usec,
  5496. time_t write_timeout_sec, time_t write_timeout_usec,
  5497. time_t max_timeout_msec,
  5498. std::chrono::time_point<std::chrono::steady_clock> start_time)
  5499. : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec),
  5500. read_timeout_usec_(read_timeout_usec),
  5501. write_timeout_sec_(write_timeout_sec),
  5502. write_timeout_usec_(write_timeout_usec),
  5503. max_timeout_msec_(max_timeout_msec), start_time_(start_time) {
  5504. SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
  5505. }
  5506. SSLSocketStream::~SSLSocketStream() = default;
  5507. bool SSLSocketStream::is_readable() const {
  5508. return SSL_pending(ssl_) > 0;
  5509. }
  5510. bool SSLSocketStream::wait_readable() const {
  5511. if (max_timeout_msec_ <= 0) {
  5512. return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
  5513. }
  5514. time_t read_timeout_sec;
  5515. time_t read_timeout_usec;
  5516. calc_actual_timeout(max_timeout_msec_, duration(), read_timeout_sec_,
  5517. read_timeout_usec_, read_timeout_sec, read_timeout_usec);
  5518. return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
  5519. }
  5520. bool SSLSocketStream::wait_writable() const {
  5521. return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
  5522. is_socket_alive(sock_) && !is_ssl_peer_could_be_closed(ssl_, sock_);
  5523. }
  5524. ssize_t SSLSocketStream::read(char *ptr, size_t size) {
  5525. if (SSL_pending(ssl_) > 0) {
  5526. return SSL_read(ssl_, ptr, static_cast<int>(size));
  5527. } else if (wait_readable()) {
  5528. auto ret = SSL_read(ssl_, ptr, static_cast<int>(size));
  5529. if (ret < 0) {
  5530. auto err = SSL_get_error(ssl_, ret);
  5531. auto n = 1000;
  5532. #ifdef _WIN32
  5533. while (--n >= 0 && (err == SSL_ERROR_WANT_READ ||
  5534. (err == SSL_ERROR_SYSCALL &&
  5535. WSAGetLastError() == WSAETIMEDOUT))) {
  5536. #else
  5537. while (--n >= 0 && err == SSL_ERROR_WANT_READ) {
  5538. #endif
  5539. if (SSL_pending(ssl_) > 0) {
  5540. return SSL_read(ssl_, ptr, static_cast<int>(size));
  5541. } else if (wait_readable()) {
  5542. std::this_thread::sleep_for(std::chrono::microseconds{10});
  5543. ret = SSL_read(ssl_, ptr, static_cast<int>(size));
  5544. if (ret >= 0) { return ret; }
  5545. err = SSL_get_error(ssl_, ret);
  5546. } else {
  5547. return -1;
  5548. }
  5549. }
  5550. }
  5551. return ret;
  5552. } else {
  5553. return -1;
  5554. }
  5555. }
  5556. ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
  5557. if (wait_writable()) {
  5558. auto handle_size = static_cast<int>(
  5559. std::min<size_t>(size, (std::numeric_limits<int>::max)()));
  5560. auto ret = SSL_write(ssl_, ptr, static_cast<int>(handle_size));
  5561. if (ret < 0) {
  5562. auto err = SSL_get_error(ssl_, ret);
  5563. auto n = 1000;
  5564. #ifdef _WIN32
  5565. while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE ||
  5566. (err == SSL_ERROR_SYSCALL &&
  5567. WSAGetLastError() == WSAETIMEDOUT))) {
  5568. #else
  5569. while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) {
  5570. #endif
  5571. if (wait_writable()) {
  5572. std::this_thread::sleep_for(std::chrono::microseconds{10});
  5573. ret = SSL_write(ssl_, ptr, static_cast<int>(handle_size));
  5574. if (ret >= 0) { return ret; }
  5575. err = SSL_get_error(ssl_, ret);
  5576. } else {
  5577. return -1;
  5578. }
  5579. }
  5580. }
  5581. return ret;
  5582. }
  5583. return -1;
  5584. }
  5585. void SSLSocketStream::get_remote_ip_and_port(std::string &ip,
  5586. int &port) const {
  5587. detail::get_remote_ip_and_port(sock_, ip, port);
  5588. }
  5589. void SSLSocketStream::get_local_ip_and_port(std::string &ip,
  5590. int &port) const {
  5591. detail::get_local_ip_and_port(sock_, ip, port);
  5592. }
  5593. socket_t SSLSocketStream::socket() const { return sock_; }
  5594. time_t SSLSocketStream::duration() const {
  5595. return std::chrono::duration_cast<std::chrono::milliseconds>(
  5596. std::chrono::steady_clock::now() - start_time_)
  5597. .count();
  5598. }
  5599. } // namespace detail
  5600. // SSL HTTP server implementation
  5601. SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
  5602. const char *client_ca_cert_file_path,
  5603. const char *client_ca_cert_dir_path,
  5604. const char *private_key_password) {
  5605. ctx_ = SSL_CTX_new(TLS_server_method());
  5606. if (ctx_) {
  5607. SSL_CTX_set_options(ctx_,
  5608. SSL_OP_NO_COMPRESSION |
  5609. SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
  5610. SSL_CTX_set_min_proto_version(ctx_, TLS1_2_VERSION);
  5611. if (private_key_password != nullptr && (private_key_password[0] != '\0')) {
  5612. SSL_CTX_set_default_passwd_cb_userdata(
  5613. ctx_,
  5614. reinterpret_cast<void *>(const_cast<char *>(private_key_password)));
  5615. }
  5616. if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 ||
  5617. SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) !=
  5618. 1 ||
  5619. SSL_CTX_check_private_key(ctx_) != 1) {
  5620. SSL_CTX_free(ctx_);
  5621. ctx_ = nullptr;
  5622. } else if (client_ca_cert_file_path || client_ca_cert_dir_path) {
  5623. SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path,
  5624. client_ca_cert_dir_path);
  5625. SSL_CTX_set_verify(
  5626. ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
  5627. }
  5628. }
  5629. }
  5630. SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
  5631. X509_STORE *client_ca_cert_store) {
  5632. ctx_ = SSL_CTX_new(TLS_server_method());
  5633. if (ctx_) {
  5634. SSL_CTX_set_options(ctx_,
  5635. SSL_OP_NO_COMPRESSION |
  5636. SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
  5637. SSL_CTX_set_min_proto_version(ctx_, TLS1_2_VERSION);
  5638. if (SSL_CTX_use_certificate(ctx_, cert) != 1 ||
  5639. SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) {
  5640. SSL_CTX_free(ctx_);
  5641. ctx_ = nullptr;
  5642. } else if (client_ca_cert_store) {
  5643. SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
  5644. SSL_CTX_set_verify(
  5645. ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
  5646. }
  5647. }
  5648. }
  5649. SSLServer::SSLServer(
  5650. const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback) {
  5651. ctx_ = SSL_CTX_new(TLS_method());
  5652. if (ctx_) {
  5653. if (!setup_ssl_ctx_callback(*ctx_)) {
  5654. SSL_CTX_free(ctx_);
  5655. ctx_ = nullptr;
  5656. }
  5657. }
  5658. }
  5659. SSLServer::~SSLServer() {
  5660. if (ctx_) { SSL_CTX_free(ctx_); }
  5661. }
  5662. bool SSLServer::is_valid() const { return ctx_; }
  5663. SSL_CTX *SSLServer::ssl_context() const { return ctx_; }
  5664. void SSLServer::update_certs(X509 *cert, EVP_PKEY *private_key,
  5665. X509_STORE *client_ca_cert_store) {
  5666. std::lock_guard<std::mutex> guard(ctx_mutex_);
  5667. SSL_CTX_use_certificate(ctx_, cert);
  5668. SSL_CTX_use_PrivateKey(ctx_, private_key);
  5669. if (client_ca_cert_store != nullptr) {
  5670. SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
  5671. }
  5672. }
  5673. bool SSLServer::process_and_close_socket(socket_t sock) {
  5674. auto ssl = detail::ssl_new(
  5675. sock, ctx_, ctx_mutex_,
  5676. [&](SSL *ssl2) {
  5677. return detail::ssl_connect_or_accept_nonblocking(
  5678. sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_);
  5679. },
  5680. [](SSL * /*ssl2*/) { return true; });
  5681. auto ret = false;
  5682. if (ssl) {
  5683. std::string remote_addr;
  5684. int remote_port = 0;
  5685. detail::get_remote_ip_and_port(sock, remote_addr, remote_port);
  5686. std::string local_addr;
  5687. int local_port = 0;
  5688. detail::get_local_ip_and_port(sock, local_addr, local_port);
  5689. ret = detail::process_server_socket_ssl(
  5690. svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
  5691. read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
  5692. write_timeout_usec_,
  5693. [&](Stream &strm, bool close_connection, bool &connection_closed) {
  5694. return process_request(strm, remote_addr, remote_port, local_addr,
  5695. local_port, close_connection,
  5696. connection_closed,
  5697. [&](Request &req) { req.ssl = ssl; });
  5698. });
  5699. // Shutdown gracefully if the result seemed successful, non-gracefully if
  5700. // the connection appeared to be closed.
  5701. const bool shutdown_gracefully = ret;
  5702. detail::ssl_delete(ctx_mutex_, ssl, sock, shutdown_gracefully);
  5703. }
  5704. detail::shutdown_socket(sock);
  5705. detail::close_socket(sock);
  5706. return ret;
  5707. }
  5708. // SSL HTTP client implementation
  5709. SSLClient::SSLClient(const std::string &host)
  5710. : SSLClient(host, 443, std::string(), std::string()) {}
  5711. SSLClient::SSLClient(const std::string &host, int port)
  5712. : SSLClient(host, port, std::string(), std::string()) {}
  5713. SSLClient::SSLClient(const std::string &host, int port,
  5714. const std::string &client_cert_path,
  5715. const std::string &client_key_path,
  5716. const std::string &private_key_password)
  5717. : ClientImpl(host, port, client_cert_path, client_key_path) {
  5718. ctx_ = SSL_CTX_new(TLS_client_method());
  5719. SSL_CTX_set_min_proto_version(ctx_, TLS1_2_VERSION);
  5720. detail::split(&host_[0], &host_[host_.size()], '.',
  5721. [&](const char *b, const char *e) {
  5722. host_components_.emplace_back(b, e);
  5723. });
  5724. if (!client_cert_path.empty() && !client_key_path.empty()) {
  5725. if (!private_key_password.empty()) {
  5726. SSL_CTX_set_default_passwd_cb_userdata(
  5727. ctx_, reinterpret_cast<void *>(
  5728. const_cast<char *>(private_key_password.c_str())));
  5729. }
  5730. if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(),
  5731. SSL_FILETYPE_PEM) != 1 ||
  5732. SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(),
  5733. SSL_FILETYPE_PEM) != 1) {
  5734. SSL_CTX_free(ctx_);
  5735. ctx_ = nullptr;
  5736. }
  5737. }
  5738. }
  5739. SSLClient::SSLClient(const std::string &host, int port,
  5740. X509 *client_cert, EVP_PKEY *client_key,
  5741. const std::string &private_key_password)
  5742. : ClientImpl(host, port) {
  5743. ctx_ = SSL_CTX_new(TLS_client_method());
  5744. detail::split(&host_[0], &host_[host_.size()], '.',
  5745. [&](const char *b, const char *e) {
  5746. host_components_.emplace_back(b, e);
  5747. });
  5748. if (client_cert != nullptr && client_key != nullptr) {
  5749. if (!private_key_password.empty()) {
  5750. SSL_CTX_set_default_passwd_cb_userdata(
  5751. ctx_, reinterpret_cast<void *>(
  5752. const_cast<char *>(private_key_password.c_str())));
  5753. }
  5754. if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 ||
  5755. SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) {
  5756. SSL_CTX_free(ctx_);
  5757. ctx_ = nullptr;
  5758. }
  5759. }
  5760. }
  5761. SSLClient::~SSLClient() {
  5762. if (ctx_) { SSL_CTX_free(ctx_); }
  5763. // Make sure to shut down SSL since shutdown_ssl will resolve to the
  5764. // base function rather than the derived function once we get to the
  5765. // base class destructor, and won't free the SSL (causing a leak).
  5766. shutdown_ssl_impl(socket_, true);
  5767. }
  5768. bool SSLClient::is_valid() const { return ctx_; }
  5769. void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
  5770. if (ca_cert_store) {
  5771. if (ctx_) {
  5772. if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) {
  5773. // Free memory allocated for old cert and use new store `ca_cert_store`
  5774. SSL_CTX_set_cert_store(ctx_, ca_cert_store);
  5775. }
  5776. } else {
  5777. X509_STORE_free(ca_cert_store);
  5778. }
  5779. }
  5780. }
  5781. void SSLClient::load_ca_cert_store(const char *ca_cert,
  5782. std::size_t size) {
  5783. set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size));
  5784. }
  5785. long SSLClient::get_openssl_verify_result() const {
  5786. return verify_result_;
  5787. }
  5788. SSL_CTX *SSLClient::ssl_context() const { return ctx_; }
  5789. bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
  5790. return is_valid() && ClientImpl::create_and_connect_socket(socket, error);
  5791. }
  5792. // Assumes that socket_mutex_ is locked and that there are no requests in flight
  5793. bool SSLClient::connect_with_proxy(
  5794. Socket &socket,
  5795. std::chrono::time_point<std::chrono::steady_clock> start_time,
  5796. Response &res, bool &success, Error &error) {
  5797. success = true;
  5798. Response proxy_res;
  5799. if (!detail::process_client_socket(
  5800. socket.sock, read_timeout_sec_, read_timeout_usec_,
  5801. write_timeout_sec_, write_timeout_usec_, max_timeout_msec_,
  5802. start_time, [&](Stream &strm) {
  5803. Request req2;
  5804. req2.method = "CONNECT";
  5805. req2.path = host_and_port_;
  5806. if (max_timeout_msec_ > 0) {
  5807. req2.start_time_ = std::chrono::steady_clock::now();
  5808. }
  5809. return process_request(strm, req2, proxy_res, false, error);
  5810. })) {
  5811. // Thread-safe to close everything because we are assuming there are no
  5812. // requests in flight
  5813. shutdown_ssl(socket, true);
  5814. shutdown_socket(socket);
  5815. close_socket(socket);
  5816. success = false;
  5817. return false;
  5818. }
  5819. if (proxy_res.status == StatusCode::ProxyAuthenticationRequired_407) {
  5820. if (!proxy_digest_auth_username_.empty() &&
  5821. !proxy_digest_auth_password_.empty()) {
  5822. std::map<std::string, std::string> auth;
  5823. if (detail::parse_www_authenticate(proxy_res, auth, true)) {
  5824. proxy_res = Response();
  5825. if (!detail::process_client_socket(
  5826. socket.sock, read_timeout_sec_, read_timeout_usec_,
  5827. write_timeout_sec_, write_timeout_usec_, max_timeout_msec_,
  5828. start_time, [&](Stream &strm) {
  5829. Request req3;
  5830. req3.method = "CONNECT";
  5831. req3.path = host_and_port_;
  5832. req3.headers.insert(detail::make_digest_authentication_header(
  5833. req3, auth, 1, detail::random_string(10),
  5834. proxy_digest_auth_username_, proxy_digest_auth_password_,
  5835. true));
  5836. if (max_timeout_msec_ > 0) {
  5837. req3.start_time_ = std::chrono::steady_clock::now();
  5838. }
  5839. return process_request(strm, req3, proxy_res, false, error);
  5840. })) {
  5841. // Thread-safe to close everything because we are assuming there are
  5842. // no requests in flight
  5843. shutdown_ssl(socket, true);
  5844. shutdown_socket(socket);
  5845. close_socket(socket);
  5846. success = false;
  5847. return false;
  5848. }
  5849. }
  5850. }
  5851. }
  5852. // If status code is not 200, proxy request is failed.
  5853. // Set error to ProxyConnection and return proxy response
  5854. // as the response of the request
  5855. if (proxy_res.status != StatusCode::OK_200) {
  5856. error = Error::ProxyConnection;
  5857. res = std::move(proxy_res);
  5858. // Thread-safe to close everything because we are assuming there are
  5859. // no requests in flight
  5860. shutdown_ssl(socket, true);
  5861. shutdown_socket(socket);
  5862. close_socket(socket);
  5863. return false;
  5864. }
  5865. return true;
  5866. }
  5867. bool SSLClient::load_certs() {
  5868. auto ret = true;
  5869. std::call_once(initialize_cert_, [&]() {
  5870. std::lock_guard<std::mutex> guard(ctx_mutex_);
  5871. if (!ca_cert_file_path_.empty()) {
  5872. if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(),
  5873. nullptr)) {
  5874. ret = false;
  5875. }
  5876. } else if (!ca_cert_dir_path_.empty()) {
  5877. if (!SSL_CTX_load_verify_locations(ctx_, nullptr,
  5878. ca_cert_dir_path_.c_str())) {
  5879. ret = false;
  5880. }
  5881. } else {
  5882. auto loaded = false;
  5883. #ifdef _WIN32
  5884. loaded =
  5885. detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_));
  5886. #elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
  5887. #if TARGET_OS_OSX
  5888. loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_));
  5889. #endif // TARGET_OS_OSX
  5890. #endif // _WIN32
  5891. if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); }
  5892. }
  5893. });
  5894. return ret;
  5895. }
  5896. bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
  5897. auto ssl = detail::ssl_new(
  5898. socket.sock, ctx_, ctx_mutex_,
  5899. [&](SSL *ssl2) {
  5900. if (server_certificate_verification_) {
  5901. if (!load_certs()) {
  5902. error = Error::SSLLoadingCerts;
  5903. return false;
  5904. }
  5905. SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr);
  5906. }
  5907. if (!detail::ssl_connect_or_accept_nonblocking(
  5908. socket.sock, ssl2, SSL_connect, connection_timeout_sec_,
  5909. connection_timeout_usec_)) {
  5910. error = Error::SSLConnection;
  5911. return false;
  5912. }
  5913. if (server_certificate_verification_) {
  5914. auto verification_status = SSLVerifierResponse::NoDecisionMade;
  5915. if (server_certificate_verifier_) {
  5916. verification_status = server_certificate_verifier_(ssl2);
  5917. }
  5918. if (verification_status == SSLVerifierResponse::CertificateRejected) {
  5919. error = Error::SSLServerVerification;
  5920. return false;
  5921. }
  5922. if (verification_status == SSLVerifierResponse::NoDecisionMade) {
  5923. verify_result_ = SSL_get_verify_result(ssl2);
  5924. if (verify_result_ != X509_V_OK) {
  5925. error = Error::SSLServerVerification;
  5926. return false;
  5927. }
  5928. auto server_cert = SSL_get1_peer_certificate(ssl2);
  5929. auto se = detail::scope_exit([&] { X509_free(server_cert); });
  5930. if (server_cert == nullptr) {
  5931. error = Error::SSLServerVerification;
  5932. return false;
  5933. }
  5934. if (server_hostname_verification_) {
  5935. if (!verify_host(server_cert)) {
  5936. error = Error::SSLServerHostnameVerification;
  5937. return false;
  5938. }
  5939. }
  5940. }
  5941. }
  5942. return true;
  5943. },
  5944. [&](SSL *ssl2) {
  5945. #if defined(OPENSSL_IS_BORINGSSL)
  5946. SSL_set_tlsext_host_name(ssl2, host_.c_str());
  5947. #else
  5948. // NOTE: Direct call instead of using the OpenSSL macro to suppress
  5949. // -Wold-style-cast warning
  5950. SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name,
  5951. static_cast<void *>(const_cast<char *>(host_.c_str())));
  5952. #endif
  5953. return true;
  5954. });
  5955. if (ssl) {
  5956. socket.ssl = ssl;
  5957. return true;
  5958. }
  5959. shutdown_socket(socket);
  5960. close_socket(socket);
  5961. return false;
  5962. }
  5963. void SSLClient::shutdown_ssl(Socket &socket, bool shutdown_gracefully) {
  5964. shutdown_ssl_impl(socket, shutdown_gracefully);
  5965. }
  5966. void SSLClient::shutdown_ssl_impl(Socket &socket,
  5967. bool shutdown_gracefully) {
  5968. if (socket.sock == INVALID_SOCKET) {
  5969. assert(socket.ssl == nullptr);
  5970. return;
  5971. }
  5972. if (socket.ssl) {
  5973. detail::ssl_delete(ctx_mutex_, socket.ssl, socket.sock,
  5974. shutdown_gracefully);
  5975. socket.ssl = nullptr;
  5976. }
  5977. assert(socket.ssl == nullptr);
  5978. }
  5979. bool SSLClient::process_socket(
  5980. const Socket &socket,
  5981. std::chrono::time_point<std::chrono::steady_clock> start_time,
  5982. std::function<bool(Stream &strm)> callback) {
  5983. assert(socket.ssl);
  5984. return detail::process_client_socket_ssl(
  5985. socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_,
  5986. write_timeout_sec_, write_timeout_usec_, max_timeout_msec_, start_time,
  5987. std::move(callback));
  5988. }
  5989. bool SSLClient::is_ssl() const { return true; }
  5990. bool SSLClient::verify_host(X509 *server_cert) const {
  5991. /* Quote from RFC2818 section 3.1 "Server Identity"
  5992. If a subjectAltName extension of type dNSName is present, that MUST
  5993. be used as the identity. Otherwise, the (most specific) Common Name
  5994. field in the Subject field of the certificate MUST be used. Although
  5995. the use of the Common Name is existing practice, it is deprecated and
  5996. Certification Authorities are encouraged to use the dNSName instead.
  5997. Matching is performed using the matching rules specified by
  5998. [RFC2459]. If more than one identity of a given type is present in
  5999. the certificate (e.g., more than one dNSName name, a match in any one
  6000. of the set is considered acceptable.) Names may contain the wildcard
  6001. character * which is considered to match any single domain name
  6002. component or component fragment. E.g., *.a.com matches foo.a.com but
  6003. not bar.foo.a.com. f*.com matches foo.com but not bar.com.
  6004. In some cases, the URI is specified as an IP address rather than a
  6005. hostname. In this case, the iPAddress subjectAltName must be present
  6006. in the certificate and must exactly match the IP in the URI.
  6007. */
  6008. return verify_host_with_subject_alt_name(server_cert) ||
  6009. verify_host_with_common_name(server_cert);
  6010. }
  6011. bool
  6012. SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const {
  6013. auto ret = false;
  6014. auto type = GEN_DNS;
  6015. struct in6_addr addr6 = {};
  6016. struct in_addr addr = {};
  6017. size_t addr_len = 0;
  6018. #ifndef __MINGW32__
  6019. if (inet_pton(AF_INET6, host_.c_str(), &addr6)) {
  6020. type = GEN_IPADD;
  6021. addr_len = sizeof(struct in6_addr);
  6022. } else if (inet_pton(AF_INET, host_.c_str(), &addr)) {
  6023. type = GEN_IPADD;
  6024. addr_len = sizeof(struct in_addr);
  6025. }
  6026. #endif
  6027. auto alt_names = static_cast<const struct stack_st_GENERAL_NAME *>(
  6028. X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr));
  6029. if (alt_names) {
  6030. auto dsn_matched = false;
  6031. auto ip_matched = false;
  6032. auto count = sk_GENERAL_NAME_num(alt_names);
  6033. for (decltype(count) i = 0; i < count && !dsn_matched; i++) {
  6034. auto val = sk_GENERAL_NAME_value(alt_names, i);
  6035. if (val->type == type) {
  6036. auto name =
  6037. reinterpret_cast<const char *>(ASN1_STRING_get0_data(val->d.ia5));
  6038. auto name_len = static_cast<size_t>(ASN1_STRING_length(val->d.ia5));
  6039. switch (type) {
  6040. case GEN_DNS: dsn_matched = check_host_name(name, name_len); break;
  6041. case GEN_IPADD:
  6042. if (!memcmp(&addr6, name, addr_len) ||
  6043. !memcmp(&addr, name, addr_len)) {
  6044. ip_matched = true;
  6045. }
  6046. break;
  6047. }
  6048. }
  6049. }
  6050. if (dsn_matched || ip_matched) { ret = true; }
  6051. }
  6052. GENERAL_NAMES_free(const_cast<STACK_OF(GENERAL_NAME) *>(
  6053. reinterpret_cast<const STACK_OF(GENERAL_NAME) *>(alt_names)));
  6054. return ret;
  6055. }
  6056. bool SSLClient::verify_host_with_common_name(X509 *server_cert) const {
  6057. const auto subject_name = X509_get_subject_name(server_cert);
  6058. if (subject_name != nullptr) {
  6059. char name[BUFSIZ];
  6060. auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName,
  6061. name, sizeof(name));
  6062. if (name_len != -1) {
  6063. return check_host_name(name, static_cast<size_t>(name_len));
  6064. }
  6065. }
  6066. return false;
  6067. }
  6068. bool SSLClient::check_host_name(const char *pattern,
  6069. size_t pattern_len) const {
  6070. if (host_.size() == pattern_len && host_ == pattern) { return true; }
  6071. // Wildcard match
  6072. // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484
  6073. std::vector<std::string> pattern_components;
  6074. detail::split(&pattern[0], &pattern[pattern_len], '.',
  6075. [&](const char *b, const char *e) {
  6076. pattern_components.emplace_back(b, e);
  6077. });
  6078. if (host_components_.size() != pattern_components.size()) { return false; }
  6079. auto itr = pattern_components.begin();
  6080. for (const auto &h : host_components_) {
  6081. auto &p = *itr;
  6082. if (p != h && p != "*") {
  6083. auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' &&
  6084. !p.compare(0, p.size() - 1, h));
  6085. if (!partial_match) { return false; }
  6086. }
  6087. ++itr;
  6088. }
  6089. return true;
  6090. }
  6091. #endif
  6092. // Universal client implementation
  6093. Client::Client(const std::string &scheme_host_port)
  6094. : Client(scheme_host_port, std::string(), std::string()) {}
  6095. Client::Client(const std::string &scheme_host_port,
  6096. const std::string &client_cert_path,
  6097. const std::string &client_key_path) {
  6098. const static std::regex re(
  6099. R"((?:([a-z]+):\/\/)?(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
  6100. std::smatch m;
  6101. if (std::regex_match(scheme_host_port, m, re)) {
  6102. auto scheme = m[1].str();
  6103. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6104. if (!scheme.empty() && (scheme != "http" && scheme != "https")) {
  6105. #else
  6106. if (!scheme.empty() && scheme != "http") {
  6107. #endif
  6108. #ifndef CPPHTTPLIB_NO_EXCEPTIONS
  6109. std::string msg = "'" + scheme + "' scheme is not supported.";
  6110. throw std::invalid_argument(msg);
  6111. #endif
  6112. return;
  6113. }
  6114. auto is_ssl = scheme == "https";
  6115. auto host = m[2].str();
  6116. if (host.empty()) { host = m[3].str(); }
  6117. auto port_str = m[4].str();
  6118. auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
  6119. if (is_ssl) {
  6120. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6121. cli_ = detail::make_unique<SSLClient>(host, port, client_cert_path,
  6122. client_key_path);
  6123. is_ssl_ = is_ssl;
  6124. #endif
  6125. } else {
  6126. cli_ = detail::make_unique<ClientImpl>(host, port, client_cert_path,
  6127. client_key_path);
  6128. }
  6129. } else {
  6130. // NOTE: Update TEST(UniversalClientImplTest, Ipv6LiteralAddress)
  6131. // if port param below changes.
  6132. cli_ = detail::make_unique<ClientImpl>(scheme_host_port, 80,
  6133. client_cert_path, client_key_path);
  6134. }
  6135. } // namespace detail
  6136. Client::Client(const std::string &host, int port)
  6137. : cli_(detail::make_unique<ClientImpl>(host, port)) {}
  6138. Client::Client(const std::string &host, int port,
  6139. const std::string &client_cert_path,
  6140. const std::string &client_key_path)
  6141. : cli_(detail::make_unique<ClientImpl>(host, port, client_cert_path,
  6142. client_key_path)) {}
  6143. Client::~Client() = default;
  6144. bool Client::is_valid() const {
  6145. return cli_ != nullptr && cli_->is_valid();
  6146. }
  6147. Result Client::Get(const std::string &path) { return cli_->Get(path); }
  6148. Result Client::Get(const std::string &path, const Headers &headers) {
  6149. return cli_->Get(path, headers);
  6150. }
  6151. Result Client::Get(const std::string &path, Progress progress) {
  6152. return cli_->Get(path, std::move(progress));
  6153. }
  6154. Result Client::Get(const std::string &path, const Headers &headers,
  6155. Progress progress) {
  6156. return cli_->Get(path, headers, std::move(progress));
  6157. }
  6158. Result Client::Get(const std::string &path,
  6159. ContentReceiver content_receiver) {
  6160. return cli_->Get(path, std::move(content_receiver));
  6161. }
  6162. Result Client::Get(const std::string &path, const Headers &headers,
  6163. ContentReceiver content_receiver) {
  6164. return cli_->Get(path, headers, std::move(content_receiver));
  6165. }
  6166. Result Client::Get(const std::string &path,
  6167. ContentReceiver content_receiver, Progress progress) {
  6168. return cli_->Get(path, std::move(content_receiver), std::move(progress));
  6169. }
  6170. Result Client::Get(const std::string &path, const Headers &headers,
  6171. ContentReceiver content_receiver, Progress progress) {
  6172. return cli_->Get(path, headers, std::move(content_receiver),
  6173. std::move(progress));
  6174. }
  6175. Result Client::Get(const std::string &path,
  6176. ResponseHandler response_handler,
  6177. ContentReceiver content_receiver) {
  6178. return cli_->Get(path, std::move(response_handler),
  6179. std::move(content_receiver));
  6180. }
  6181. Result Client::Get(const std::string &path, const Headers &headers,
  6182. ResponseHandler response_handler,
  6183. ContentReceiver content_receiver) {
  6184. return cli_->Get(path, headers, std::move(response_handler),
  6185. std::move(content_receiver));
  6186. }
  6187. Result Client::Get(const std::string &path,
  6188. ResponseHandler response_handler,
  6189. ContentReceiver content_receiver, Progress progress) {
  6190. return cli_->Get(path, std::move(response_handler),
  6191. std::move(content_receiver), std::move(progress));
  6192. }
  6193. Result Client::Get(const std::string &path, const Headers &headers,
  6194. ResponseHandler response_handler,
  6195. ContentReceiver content_receiver, Progress progress) {
  6196. return cli_->Get(path, headers, std::move(response_handler),
  6197. std::move(content_receiver), std::move(progress));
  6198. }
  6199. Result Client::Get(const std::string &path, const Params &params,
  6200. const Headers &headers, Progress progress) {
  6201. return cli_->Get(path, params, headers, std::move(progress));
  6202. }
  6203. Result Client::Get(const std::string &path, const Params &params,
  6204. const Headers &headers,
  6205. ContentReceiver content_receiver, Progress progress) {
  6206. return cli_->Get(path, params, headers, std::move(content_receiver),
  6207. std::move(progress));
  6208. }
  6209. Result Client::Get(const std::string &path, const Params &params,
  6210. const Headers &headers,
  6211. ResponseHandler response_handler,
  6212. ContentReceiver content_receiver, Progress progress) {
  6213. return cli_->Get(path, params, headers, std::move(response_handler),
  6214. std::move(content_receiver), std::move(progress));
  6215. }
  6216. Result Client::Head(const std::string &path) { return cli_->Head(path); }
  6217. Result Client::Head(const std::string &path, const Headers &headers) {
  6218. return cli_->Head(path, headers);
  6219. }
  6220. Result Client::Post(const std::string &path) { return cli_->Post(path); }
  6221. Result Client::Post(const std::string &path, const Headers &headers) {
  6222. return cli_->Post(path, headers);
  6223. }
  6224. Result Client::Post(const std::string &path, const char *body,
  6225. size_t content_length,
  6226. const std::string &content_type) {
  6227. return cli_->Post(path, body, content_length, content_type);
  6228. }
  6229. Result Client::Post(const std::string &path, const Headers &headers,
  6230. const char *body, size_t content_length,
  6231. const std::string &content_type) {
  6232. return cli_->Post(path, headers, body, content_length, content_type);
  6233. }
  6234. Result Client::Post(const std::string &path, const Headers &headers,
  6235. const char *body, size_t content_length,
  6236. const std::string &content_type, Progress progress) {
  6237. return cli_->Post(path, headers, body, content_length, content_type,
  6238. progress);
  6239. }
  6240. Result Client::Post(const std::string &path, const std::string &body,
  6241. const std::string &content_type) {
  6242. return cli_->Post(path, body, content_type);
  6243. }
  6244. Result Client::Post(const std::string &path, const std::string &body,
  6245. const std::string &content_type, Progress progress) {
  6246. return cli_->Post(path, body, content_type, progress);
  6247. }
  6248. Result Client::Post(const std::string &path, const Headers &headers,
  6249. const std::string &body,
  6250. const std::string &content_type) {
  6251. return cli_->Post(path, headers, body, content_type);
  6252. }
  6253. Result Client::Post(const std::string &path, const Headers &headers,
  6254. const std::string &body,
  6255. const std::string &content_type, Progress progress) {
  6256. return cli_->Post(path, headers, body, content_type, progress);
  6257. }
  6258. Result Client::Post(const std::string &path, size_t content_length,
  6259. ContentProvider content_provider,
  6260. const std::string &content_type) {
  6261. return cli_->Post(path, content_length, std::move(content_provider),
  6262. content_type);
  6263. }
  6264. Result Client::Post(const std::string &path,
  6265. ContentProviderWithoutLength content_provider,
  6266. const std::string &content_type) {
  6267. return cli_->Post(path, std::move(content_provider), content_type);
  6268. }
  6269. Result Client::Post(const std::string &path, const Headers &headers,
  6270. size_t content_length,
  6271. ContentProvider content_provider,
  6272. const std::string &content_type) {
  6273. return cli_->Post(path, headers, content_length, std::move(content_provider),
  6274. content_type);
  6275. }
  6276. Result Client::Post(const std::string &path, const Headers &headers,
  6277. ContentProviderWithoutLength content_provider,
  6278. const std::string &content_type) {
  6279. return cli_->Post(path, headers, std::move(content_provider), content_type);
  6280. }
  6281. Result Client::Post(const std::string &path, const Params &params) {
  6282. return cli_->Post(path, params);
  6283. }
  6284. Result Client::Post(const std::string &path, const Headers &headers,
  6285. const Params &params) {
  6286. return cli_->Post(path, headers, params);
  6287. }
  6288. Result Client::Post(const std::string &path, const Headers &headers,
  6289. const Params &params, Progress progress) {
  6290. return cli_->Post(path, headers, params, progress);
  6291. }
  6292. Result Client::Post(const std::string &path,
  6293. const MultipartFormDataItems &items) {
  6294. return cli_->Post(path, items);
  6295. }
  6296. Result Client::Post(const std::string &path, const Headers &headers,
  6297. const MultipartFormDataItems &items) {
  6298. return cli_->Post(path, headers, items);
  6299. }
  6300. Result Client::Post(const std::string &path, const Headers &headers,
  6301. const MultipartFormDataItems &items,
  6302. const std::string &boundary) {
  6303. return cli_->Post(path, headers, items, boundary);
  6304. }
  6305. Result
  6306. Client::Post(const std::string &path, const Headers &headers,
  6307. const MultipartFormDataItems &items,
  6308. const MultipartFormDataProviderItems &provider_items) {
  6309. return cli_->Post(path, headers, items, provider_items);
  6310. }
  6311. Result Client::Put(const std::string &path) { return cli_->Put(path); }
  6312. Result Client::Put(const std::string &path, const char *body,
  6313. size_t content_length,
  6314. const std::string &content_type) {
  6315. return cli_->Put(path, body, content_length, content_type);
  6316. }
  6317. Result Client::Put(const std::string &path, const Headers &headers,
  6318. const char *body, size_t content_length,
  6319. const std::string &content_type) {
  6320. return cli_->Put(path, headers, body, content_length, content_type);
  6321. }
  6322. Result Client::Put(const std::string &path, const Headers &headers,
  6323. const char *body, size_t content_length,
  6324. const std::string &content_type, Progress progress) {
  6325. return cli_->Put(path, headers, body, content_length, content_type, progress);
  6326. }
  6327. Result Client::Put(const std::string &path, const std::string &body,
  6328. const std::string &content_type) {
  6329. return cli_->Put(path, body, content_type);
  6330. }
  6331. Result Client::Put(const std::string &path, const std::string &body,
  6332. const std::string &content_type, Progress progress) {
  6333. return cli_->Put(path, body, content_type, progress);
  6334. }
  6335. Result Client::Put(const std::string &path, const Headers &headers,
  6336. const std::string &body,
  6337. const std::string &content_type) {
  6338. return cli_->Put(path, headers, body, content_type);
  6339. }
  6340. Result Client::Put(const std::string &path, const Headers &headers,
  6341. const std::string &body,
  6342. const std::string &content_type, Progress progress) {
  6343. return cli_->Put(path, headers, body, content_type, progress);
  6344. }
  6345. Result Client::Put(const std::string &path, size_t content_length,
  6346. ContentProvider content_provider,
  6347. const std::string &content_type) {
  6348. return cli_->Put(path, content_length, std::move(content_provider),
  6349. content_type);
  6350. }
  6351. Result Client::Put(const std::string &path,
  6352. ContentProviderWithoutLength content_provider,
  6353. const std::string &content_type) {
  6354. return cli_->Put(path, std::move(content_provider), content_type);
  6355. }
  6356. Result Client::Put(const std::string &path, const Headers &headers,
  6357. size_t content_length,
  6358. ContentProvider content_provider,
  6359. const std::string &content_type) {
  6360. return cli_->Put(path, headers, content_length, std::move(content_provider),
  6361. content_type);
  6362. }
  6363. Result Client::Put(const std::string &path, const Headers &headers,
  6364. ContentProviderWithoutLength content_provider,
  6365. const std::string &content_type) {
  6366. return cli_->Put(path, headers, std::move(content_provider), content_type);
  6367. }
  6368. Result Client::Put(const std::string &path, const Params &params) {
  6369. return cli_->Put(path, params);
  6370. }
  6371. Result Client::Put(const std::string &path, const Headers &headers,
  6372. const Params &params) {
  6373. return cli_->Put(path, headers, params);
  6374. }
  6375. Result Client::Put(const std::string &path, const Headers &headers,
  6376. const Params &params, Progress progress) {
  6377. return cli_->Put(path, headers, params, progress);
  6378. }
  6379. Result Client::Put(const std::string &path,
  6380. const MultipartFormDataItems &items) {
  6381. return cli_->Put(path, items);
  6382. }
  6383. Result Client::Put(const std::string &path, const Headers &headers,
  6384. const MultipartFormDataItems &items) {
  6385. return cli_->Put(path, headers, items);
  6386. }
  6387. Result Client::Put(const std::string &path, const Headers &headers,
  6388. const MultipartFormDataItems &items,
  6389. const std::string &boundary) {
  6390. return cli_->Put(path, headers, items, boundary);
  6391. }
  6392. Result
  6393. Client::Put(const std::string &path, const Headers &headers,
  6394. const MultipartFormDataItems &items,
  6395. const MultipartFormDataProviderItems &provider_items) {
  6396. return cli_->Put(path, headers, items, provider_items);
  6397. }
  6398. Result Client::Patch(const std::string &path) {
  6399. return cli_->Patch(path);
  6400. }
  6401. Result Client::Patch(const std::string &path, const char *body,
  6402. size_t content_length,
  6403. const std::string &content_type) {
  6404. return cli_->Patch(path, body, content_length, content_type);
  6405. }
  6406. Result Client::Patch(const std::string &path, const char *body,
  6407. size_t content_length,
  6408. const std::string &content_type,
  6409. Progress progress) {
  6410. return cli_->Patch(path, body, content_length, content_type, progress);
  6411. }
  6412. Result Client::Patch(const std::string &path, const Headers &headers,
  6413. const char *body, size_t content_length,
  6414. const std::string &content_type) {
  6415. return cli_->Patch(path, headers, body, content_length, content_type);
  6416. }
  6417. Result Client::Patch(const std::string &path, const Headers &headers,
  6418. const char *body, size_t content_length,
  6419. const std::string &content_type,
  6420. Progress progress) {
  6421. return cli_->Patch(path, headers, body, content_length, content_type,
  6422. progress);
  6423. }
  6424. Result Client::Patch(const std::string &path, const std::string &body,
  6425. const std::string &content_type) {
  6426. return cli_->Patch(path, body, content_type);
  6427. }
  6428. Result Client::Patch(const std::string &path, const std::string &body,
  6429. const std::string &content_type,
  6430. Progress progress) {
  6431. return cli_->Patch(path, body, content_type, progress);
  6432. }
  6433. Result Client::Patch(const std::string &path, const Headers &headers,
  6434. const std::string &body,
  6435. const std::string &content_type) {
  6436. return cli_->Patch(path, headers, body, content_type);
  6437. }
  6438. Result Client::Patch(const std::string &path, const Headers &headers,
  6439. const std::string &body,
  6440. const std::string &content_type,
  6441. Progress progress) {
  6442. return cli_->Patch(path, headers, body, content_type, progress);
  6443. }
  6444. Result Client::Patch(const std::string &path, size_t content_length,
  6445. ContentProvider content_provider,
  6446. const std::string &content_type) {
  6447. return cli_->Patch(path, content_length, std::move(content_provider),
  6448. content_type);
  6449. }
  6450. Result Client::Patch(const std::string &path,
  6451. ContentProviderWithoutLength content_provider,
  6452. const std::string &content_type) {
  6453. return cli_->Patch(path, std::move(content_provider), content_type);
  6454. }
  6455. Result Client::Patch(const std::string &path, const Headers &headers,
  6456. size_t content_length,
  6457. ContentProvider content_provider,
  6458. const std::string &content_type) {
  6459. return cli_->Patch(path, headers, content_length, std::move(content_provider),
  6460. content_type);
  6461. }
  6462. Result Client::Patch(const std::string &path, const Headers &headers,
  6463. ContentProviderWithoutLength content_provider,
  6464. const std::string &content_type) {
  6465. return cli_->Patch(path, headers, std::move(content_provider), content_type);
  6466. }
  6467. Result Client::Delete(const std::string &path) {
  6468. return cli_->Delete(path);
  6469. }
  6470. Result Client::Delete(const std::string &path, const Headers &headers) {
  6471. return cli_->Delete(path, headers);
  6472. }
  6473. Result Client::Delete(const std::string &path, const char *body,
  6474. size_t content_length,
  6475. const std::string &content_type) {
  6476. return cli_->Delete(path, body, content_length, content_type);
  6477. }
  6478. Result Client::Delete(const std::string &path, const char *body,
  6479. size_t content_length,
  6480. const std::string &content_type,
  6481. Progress progress) {
  6482. return cli_->Delete(path, body, content_length, content_type, progress);
  6483. }
  6484. Result Client::Delete(const std::string &path, const Headers &headers,
  6485. const char *body, size_t content_length,
  6486. const std::string &content_type) {
  6487. return cli_->Delete(path, headers, body, content_length, content_type);
  6488. }
  6489. Result Client::Delete(const std::string &path, const Headers &headers,
  6490. const char *body, size_t content_length,
  6491. const std::string &content_type,
  6492. Progress progress) {
  6493. return cli_->Delete(path, headers, body, content_length, content_type,
  6494. progress);
  6495. }
  6496. Result Client::Delete(const std::string &path, const std::string &body,
  6497. const std::string &content_type) {
  6498. return cli_->Delete(path, body, content_type);
  6499. }
  6500. Result Client::Delete(const std::string &path, const std::string &body,
  6501. const std::string &content_type,
  6502. Progress progress) {
  6503. return cli_->Delete(path, body, content_type, progress);
  6504. }
  6505. Result Client::Delete(const std::string &path, const Headers &headers,
  6506. const std::string &body,
  6507. const std::string &content_type) {
  6508. return cli_->Delete(path, headers, body, content_type);
  6509. }
  6510. Result Client::Delete(const std::string &path, const Headers &headers,
  6511. const std::string &body,
  6512. const std::string &content_type,
  6513. Progress progress) {
  6514. return cli_->Delete(path, headers, body, content_type, progress);
  6515. }
  6516. Result Client::Options(const std::string &path) {
  6517. return cli_->Options(path);
  6518. }
  6519. Result Client::Options(const std::string &path, const Headers &headers) {
  6520. return cli_->Options(path, headers);
  6521. }
  6522. bool Client::send(Request &req, Response &res, Error &error) {
  6523. return cli_->send(req, res, error);
  6524. }
  6525. Result Client::send(const Request &req) { return cli_->send(req); }
  6526. void Client::stop() { cli_->stop(); }
  6527. std::string Client::host() const { return cli_->host(); }
  6528. int Client::port() const { return cli_->port(); }
  6529. size_t Client::is_socket_open() const { return cli_->is_socket_open(); }
  6530. socket_t Client::socket() const { return cli_->socket(); }
  6531. void
  6532. Client::set_hostname_addr_map(std::map<std::string, std::string> addr_map) {
  6533. cli_->set_hostname_addr_map(std::move(addr_map));
  6534. }
  6535. void Client::set_default_headers(Headers headers) {
  6536. cli_->set_default_headers(std::move(headers));
  6537. }
  6538. void Client::set_header_writer(
  6539. std::function<ssize_t(Stream &, Headers &)> const &writer) {
  6540. cli_->set_header_writer(writer);
  6541. }
  6542. void Client::set_address_family(int family) {
  6543. cli_->set_address_family(family);
  6544. }
  6545. void Client::set_tcp_nodelay(bool on) { cli_->set_tcp_nodelay(on); }
  6546. void Client::set_socket_options(SocketOptions socket_options) {
  6547. cli_->set_socket_options(std::move(socket_options));
  6548. }
  6549. void Client::set_connection_timeout(time_t sec, time_t usec) {
  6550. cli_->set_connection_timeout(sec, usec);
  6551. }
  6552. void Client::set_read_timeout(time_t sec, time_t usec) {
  6553. cli_->set_read_timeout(sec, usec);
  6554. }
  6555. void Client::set_write_timeout(time_t sec, time_t usec) {
  6556. cli_->set_write_timeout(sec, usec);
  6557. }
  6558. void Client::set_basic_auth(const std::string &username,
  6559. const std::string &password) {
  6560. cli_->set_basic_auth(username, password);
  6561. }
  6562. void Client::set_bearer_token_auth(const std::string &token) {
  6563. cli_->set_bearer_token_auth(token);
  6564. }
  6565. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6566. void Client::set_digest_auth(const std::string &username,
  6567. const std::string &password) {
  6568. cli_->set_digest_auth(username, password);
  6569. }
  6570. #endif
  6571. void Client::set_keep_alive(bool on) { cli_->set_keep_alive(on); }
  6572. void Client::set_follow_location(bool on) {
  6573. cli_->set_follow_location(on);
  6574. }
  6575. void Client::set_url_encode(bool on) { cli_->set_url_encode(on); }
  6576. void Client::set_compress(bool on) { cli_->set_compress(on); }
  6577. void Client::set_decompress(bool on) { cli_->set_decompress(on); }
  6578. void Client::set_interface(const std::string &intf) {
  6579. cli_->set_interface(intf);
  6580. }
  6581. void Client::set_proxy(const std::string &host, int port) {
  6582. cli_->set_proxy(host, port);
  6583. }
  6584. void Client::set_proxy_basic_auth(const std::string &username,
  6585. const std::string &password) {
  6586. cli_->set_proxy_basic_auth(username, password);
  6587. }
  6588. void Client::set_proxy_bearer_token_auth(const std::string &token) {
  6589. cli_->set_proxy_bearer_token_auth(token);
  6590. }
  6591. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6592. void Client::set_proxy_digest_auth(const std::string &username,
  6593. const std::string &password) {
  6594. cli_->set_proxy_digest_auth(username, password);
  6595. }
  6596. #endif
  6597. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6598. void Client::enable_server_certificate_verification(bool enabled) {
  6599. cli_->enable_server_certificate_verification(enabled);
  6600. }
  6601. void Client::enable_server_hostname_verification(bool enabled) {
  6602. cli_->enable_server_hostname_verification(enabled);
  6603. }
  6604. void Client::set_server_certificate_verifier(
  6605. std::function<SSLVerifierResponse(SSL *ssl)> verifier) {
  6606. cli_->set_server_certificate_verifier(verifier);
  6607. }
  6608. #endif
  6609. void Client::set_logger(Logger logger) {
  6610. cli_->set_logger(std::move(logger));
  6611. }
  6612. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  6613. void Client::set_ca_cert_path(const std::string &ca_cert_file_path,
  6614. const std::string &ca_cert_dir_path) {
  6615. cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path);
  6616. }
  6617. void Client::set_ca_cert_store(X509_STORE *ca_cert_store) {
  6618. if (is_ssl_) {
  6619. static_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
  6620. } else {
  6621. cli_->set_ca_cert_store(ca_cert_store);
  6622. }
  6623. }
  6624. void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) {
  6625. set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size));
  6626. }
  6627. long Client::get_openssl_verify_result() const {
  6628. if (is_ssl_) {
  6629. return static_cast<SSLClient &>(*cli_).get_openssl_verify_result();
  6630. }
  6631. return -1; // NOTE: -1 doesn't match any of X509_V_ERR_???
  6632. }
  6633. SSL_CTX *Client::ssl_context() const {
  6634. if (is_ssl_) { return static_cast<SSLClient &>(*cli_).ssl_context(); }
  6635. return nullptr;
  6636. }
  6637. #endif
  6638. } // namespace httplib