test.c 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "http_parser.h"
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include <stdio.h>
  25. #include <stdlib.h> /* rand */
  26. #include <string.h>
  27. #include <stdarg.h>
  28. #if defined(__APPLE__)
  29. # undef strlcat
  30. # undef strlncpy
  31. # undef strlcpy
  32. #endif /* defined(__APPLE__) */
  33. #undef TRUE
  34. #define TRUE 1
  35. #undef FALSE
  36. #define FALSE 0
  37. #define MAX_HEADERS 13
  38. #define MAX_ELEMENT_SIZE 2048
  39. #define MAX_CHUNKS 16
  40. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  41. static http_parser *parser;
  42. struct message {
  43. const char *name; // for debugging purposes
  44. const char *raw;
  45. enum http_parser_type type;
  46. enum http_method method;
  47. int status_code;
  48. char response_status[MAX_ELEMENT_SIZE];
  49. char request_path[MAX_ELEMENT_SIZE];
  50. char request_url[MAX_ELEMENT_SIZE];
  51. char fragment[MAX_ELEMENT_SIZE];
  52. char query_string[MAX_ELEMENT_SIZE];
  53. char body[MAX_ELEMENT_SIZE];
  54. size_t body_size;
  55. const char *host;
  56. const char *userinfo;
  57. uint16_t port;
  58. int num_headers;
  59. enum { NONE=0, FIELD, VALUE } last_header_element;
  60. char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
  61. int should_keep_alive;
  62. int num_chunks;
  63. int num_chunks_complete;
  64. int chunk_lengths[MAX_CHUNKS];
  65. const char *upgrade; // upgraded body
  66. unsigned short http_major;
  67. unsigned short http_minor;
  68. int message_begin_cb_called;
  69. int headers_complete_cb_called;
  70. int message_complete_cb_called;
  71. int message_complete_on_eof;
  72. int body_is_final;
  73. };
  74. static int currently_parsing_eof;
  75. static struct message messages[5];
  76. static int num_messages;
  77. static http_parser_settings *current_pause_parser;
  78. /* * R E Q U E S T S * */
  79. const struct message requests[] =
  80. #define CURL_GET 0
  81. { {.name= "curl get"
  82. ,.type= HTTP_REQUEST
  83. ,.raw= "GET /test HTTP/1.1\r\n"
  84. "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
  85. "Host: 0.0.0.0=5000\r\n"
  86. "Accept: */*\r\n"
  87. "\r\n"
  88. ,.should_keep_alive= TRUE
  89. ,.message_complete_on_eof= FALSE
  90. ,.http_major= 1
  91. ,.http_minor= 1
  92. ,.method= HTTP_GET
  93. ,.query_string= ""
  94. ,.fragment= ""
  95. ,.request_path= "/test"
  96. ,.request_url= "/test"
  97. ,.num_headers= 3
  98. ,.headers=
  99. { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }
  100. , { "Host", "0.0.0.0=5000" }
  101. , { "Accept", "*/*" }
  102. }
  103. ,.body= ""
  104. }
  105. #define FIREFOX_GET 1
  106. , {.name= "firefox get"
  107. ,.type= HTTP_REQUEST
  108. ,.raw= "GET /favicon.ico HTTP/1.1\r\n"
  109. "Host: 0.0.0.0=5000\r\n"
  110. "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
  111. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
  112. "Accept-Language: en-us,en;q=0.5\r\n"
  113. "Accept-Encoding: gzip,deflate\r\n"
  114. "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
  115. "Keep-Alive: 300\r\n"
  116. "Connection: keep-alive\r\n"
  117. "\r\n"
  118. ,.should_keep_alive= TRUE
  119. ,.message_complete_on_eof= FALSE
  120. ,.http_major= 1
  121. ,.http_minor= 1
  122. ,.method= HTTP_GET
  123. ,.query_string= ""
  124. ,.fragment= ""
  125. ,.request_path= "/favicon.ico"
  126. ,.request_url= "/favicon.ico"
  127. ,.num_headers= 8
  128. ,.headers=
  129. { { "Host", "0.0.0.0=5000" }
  130. , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }
  131. , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }
  132. , { "Accept-Language", "en-us,en;q=0.5" }
  133. , { "Accept-Encoding", "gzip,deflate" }
  134. , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }
  135. , { "Keep-Alive", "300" }
  136. , { "Connection", "keep-alive" }
  137. }
  138. ,.body= ""
  139. }
  140. #define DUMBFUCK 2
  141. , {.name= "dumbfuck"
  142. ,.type= HTTP_REQUEST
  143. ,.raw= "GET /dumbfuck HTTP/1.1\r\n"
  144. "aaaaaaaaaaaaa:++++++++++\r\n"
  145. "\r\n"
  146. ,.should_keep_alive= TRUE
  147. ,.message_complete_on_eof= FALSE
  148. ,.http_major= 1
  149. ,.http_minor= 1
  150. ,.method= HTTP_GET
  151. ,.query_string= ""
  152. ,.fragment= ""
  153. ,.request_path= "/dumbfuck"
  154. ,.request_url= "/dumbfuck"
  155. ,.num_headers= 1
  156. ,.headers=
  157. { { "aaaaaaaaaaaaa", "++++++++++" }
  158. }
  159. ,.body= ""
  160. }
  161. #define FRAGMENT_IN_URI 3
  162. , {.name= "fragment in url"
  163. ,.type= HTTP_REQUEST
  164. ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
  165. "\r\n"
  166. ,.should_keep_alive= TRUE
  167. ,.message_complete_on_eof= FALSE
  168. ,.http_major= 1
  169. ,.http_minor= 1
  170. ,.method= HTTP_GET
  171. ,.query_string= "page=1"
  172. ,.fragment= "posts-17408"
  173. ,.request_path= "/forums/1/topics/2375"
  174. /* XXX request url does include fragment? */
  175. ,.request_url= "/forums/1/topics/2375?page=1#posts-17408"
  176. ,.num_headers= 0
  177. ,.body= ""
  178. }
  179. #define GET_NO_HEADERS_NO_BODY 4
  180. , {.name= "get no headers no body"
  181. ,.type= HTTP_REQUEST
  182. ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
  183. "\r\n"
  184. ,.should_keep_alive= TRUE
  185. ,.message_complete_on_eof= FALSE /* would need Connection: close */
  186. ,.http_major= 1
  187. ,.http_minor= 1
  188. ,.method= HTTP_GET
  189. ,.query_string= ""
  190. ,.fragment= ""
  191. ,.request_path= "/get_no_headers_no_body/world"
  192. ,.request_url= "/get_no_headers_no_body/world"
  193. ,.num_headers= 0
  194. ,.body= ""
  195. }
  196. #define GET_ONE_HEADER_NO_BODY 5
  197. , {.name= "get one header no body"
  198. ,.type= HTTP_REQUEST
  199. ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n"
  200. "Accept: */*\r\n"
  201. "\r\n"
  202. ,.should_keep_alive= TRUE
  203. ,.message_complete_on_eof= FALSE /* would need Connection: close */
  204. ,.http_major= 1
  205. ,.http_minor= 1
  206. ,.method= HTTP_GET
  207. ,.query_string= ""
  208. ,.fragment= ""
  209. ,.request_path= "/get_one_header_no_body"
  210. ,.request_url= "/get_one_header_no_body"
  211. ,.num_headers= 1
  212. ,.headers=
  213. { { "Accept" , "*/*" }
  214. }
  215. ,.body= ""
  216. }
  217. #define GET_FUNKY_CONTENT_LENGTH 6
  218. , {.name= "get funky content length body hello"
  219. ,.type= HTTP_REQUEST
  220. ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
  221. "conTENT-Length: 5\r\n"
  222. "\r\n"
  223. "HELLO"
  224. ,.should_keep_alive= FALSE
  225. ,.message_complete_on_eof= FALSE
  226. ,.http_major= 1
  227. ,.http_minor= 0
  228. ,.method= HTTP_GET
  229. ,.query_string= ""
  230. ,.fragment= ""
  231. ,.request_path= "/get_funky_content_length_body_hello"
  232. ,.request_url= "/get_funky_content_length_body_hello"
  233. ,.num_headers= 1
  234. ,.headers=
  235. { { "conTENT-Length" , "5" }
  236. }
  237. ,.body= "HELLO"
  238. }
  239. #define POST_IDENTITY_BODY_WORLD 7
  240. , {.name= "post identity body world"
  241. ,.type= HTTP_REQUEST
  242. ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
  243. "Accept: */*\r\n"
  244. "Transfer-Encoding: identity\r\n"
  245. "Content-Length: 5\r\n"
  246. "\r\n"
  247. "World"
  248. ,.should_keep_alive= TRUE
  249. ,.message_complete_on_eof= FALSE
  250. ,.http_major= 1
  251. ,.http_minor= 1
  252. ,.method= HTTP_POST
  253. ,.query_string= "q=search"
  254. ,.fragment= "hey"
  255. ,.request_path= "/post_identity_body_world"
  256. ,.request_url= "/post_identity_body_world?q=search#hey"
  257. ,.num_headers= 3
  258. ,.headers=
  259. { { "Accept", "*/*" }
  260. , { "Transfer-Encoding", "identity" }
  261. , { "Content-Length", "5" }
  262. }
  263. ,.body= "World"
  264. }
  265. #define POST_CHUNKED_ALL_YOUR_BASE 8
  266. , {.name= "post - chunked body: all your base are belong to us"
  267. ,.type= HTTP_REQUEST
  268. ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n"
  269. "Transfer-Encoding: chunked\r\n"
  270. "\r\n"
  271. "1e\r\nall your base are belong to us\r\n"
  272. "0\r\n"
  273. "\r\n"
  274. ,.should_keep_alive= TRUE
  275. ,.message_complete_on_eof= FALSE
  276. ,.http_major= 1
  277. ,.http_minor= 1
  278. ,.method= HTTP_POST
  279. ,.query_string= ""
  280. ,.fragment= ""
  281. ,.request_path= "/post_chunked_all_your_base"
  282. ,.request_url= "/post_chunked_all_your_base"
  283. ,.num_headers= 1
  284. ,.headers=
  285. { { "Transfer-Encoding" , "chunked" }
  286. }
  287. ,.body= "all your base are belong to us"
  288. ,.num_chunks_complete= 2
  289. ,.chunk_lengths= { 0x1e }
  290. }
  291. #define TWO_CHUNKS_MULT_ZERO_END 9
  292. , {.name= "two chunks ; triple zero ending"
  293. ,.type= HTTP_REQUEST
  294. ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
  295. "Transfer-Encoding: chunked\r\n"
  296. "\r\n"
  297. "5\r\nhello\r\n"
  298. "6\r\n world\r\n"
  299. "000\r\n"
  300. "\r\n"
  301. ,.should_keep_alive= TRUE
  302. ,.message_complete_on_eof= FALSE
  303. ,.http_major= 1
  304. ,.http_minor= 1
  305. ,.method= HTTP_POST
  306. ,.query_string= ""
  307. ,.fragment= ""
  308. ,.request_path= "/two_chunks_mult_zero_end"
  309. ,.request_url= "/two_chunks_mult_zero_end"
  310. ,.num_headers= 1
  311. ,.headers=
  312. { { "Transfer-Encoding", "chunked" }
  313. }
  314. ,.body= "hello world"
  315. ,.num_chunks_complete= 3
  316. ,.chunk_lengths= { 5, 6 }
  317. }
  318. #define CHUNKED_W_TRAILING_HEADERS 10
  319. , {.name= "chunked with trailing headers. blech."
  320. ,.type= HTTP_REQUEST
  321. ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
  322. "Transfer-Encoding: chunked\r\n"
  323. "\r\n"
  324. "5\r\nhello\r\n"
  325. "6\r\n world\r\n"
  326. "0\r\n"
  327. "Vary: *\r\n"
  328. "Content-Type: text/plain\r\n"
  329. "\r\n"
  330. ,.should_keep_alive= TRUE
  331. ,.message_complete_on_eof= FALSE
  332. ,.http_major= 1
  333. ,.http_minor= 1
  334. ,.method= HTTP_POST
  335. ,.query_string= ""
  336. ,.fragment= ""
  337. ,.request_path= "/chunked_w_trailing_headers"
  338. ,.request_url= "/chunked_w_trailing_headers"
  339. ,.num_headers= 3
  340. ,.headers=
  341. { { "Transfer-Encoding", "chunked" }
  342. , { "Vary", "*" }
  343. , { "Content-Type", "text/plain" }
  344. }
  345. ,.body= "hello world"
  346. ,.num_chunks_complete= 3
  347. ,.chunk_lengths= { 5, 6 }
  348. }
  349. #define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
  350. , {.name= "with bullshit after the length"
  351. ,.type= HTTP_REQUEST
  352. ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
  353. "Transfer-Encoding: chunked\r\n"
  354. "\r\n"
  355. "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
  356. "6; blahblah; blah\r\n world\r\n"
  357. "0\r\n"
  358. "\r\n"
  359. ,.should_keep_alive= TRUE
  360. ,.message_complete_on_eof= FALSE
  361. ,.http_major= 1
  362. ,.http_minor= 1
  363. ,.method= HTTP_POST
  364. ,.query_string= ""
  365. ,.fragment= ""
  366. ,.request_path= "/chunked_w_bullshit_after_length"
  367. ,.request_url= "/chunked_w_bullshit_after_length"
  368. ,.num_headers= 1
  369. ,.headers=
  370. { { "Transfer-Encoding", "chunked" }
  371. }
  372. ,.body= "hello world"
  373. ,.num_chunks_complete= 3
  374. ,.chunk_lengths= { 5, 6 }
  375. }
  376. #define WITH_QUOTES 12
  377. , {.name= "with quotes"
  378. ,.type= HTTP_REQUEST
  379. ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n"
  380. ,.should_keep_alive= TRUE
  381. ,.message_complete_on_eof= FALSE
  382. ,.http_major= 1
  383. ,.http_minor= 1
  384. ,.method= HTTP_GET
  385. ,.query_string= "foo=\"bar\""
  386. ,.fragment= ""
  387. ,.request_path= "/with_\"stupid\"_quotes"
  388. ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\""
  389. ,.num_headers= 0
  390. ,.headers= { }
  391. ,.body= ""
  392. }
  393. #define APACHEBENCH_GET 13
  394. /* The server receiving this request SHOULD NOT wait for EOF
  395. * to know that content-length == 0.
  396. * How to represent this in a unit test? message_complete_on_eof
  397. * Compare with NO_CONTENT_LENGTH_RESPONSE.
  398. */
  399. , {.name = "apachebench get"
  400. ,.type= HTTP_REQUEST
  401. ,.raw= "GET /test HTTP/1.0\r\n"
  402. "Host: 0.0.0.0:5000\r\n"
  403. "User-Agent: ApacheBench/2.3\r\n"
  404. "Accept: */*\r\n\r\n"
  405. ,.should_keep_alive= FALSE
  406. ,.message_complete_on_eof= FALSE
  407. ,.http_major= 1
  408. ,.http_minor= 0
  409. ,.method= HTTP_GET
  410. ,.query_string= ""
  411. ,.fragment= ""
  412. ,.request_path= "/test"
  413. ,.request_url= "/test"
  414. ,.num_headers= 3
  415. ,.headers= { { "Host", "0.0.0.0:5000" }
  416. , { "User-Agent", "ApacheBench/2.3" }
  417. , { "Accept", "*/*" }
  418. }
  419. ,.body= ""
  420. }
  421. #define QUERY_URL_WITH_QUESTION_MARK_GET 14
  422. /* Some clients include '?' characters in query strings.
  423. */
  424. , {.name = "query url with question mark"
  425. ,.type= HTTP_REQUEST
  426. ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n"
  427. ,.should_keep_alive= TRUE
  428. ,.message_complete_on_eof= FALSE
  429. ,.http_major= 1
  430. ,.http_minor= 1
  431. ,.method= HTTP_GET
  432. ,.query_string= "foo=bar?baz"
  433. ,.fragment= ""
  434. ,.request_path= "/test.cgi"
  435. ,.request_url= "/test.cgi?foo=bar?baz"
  436. ,.num_headers= 0
  437. ,.headers= {}
  438. ,.body= ""
  439. }
  440. #define PREFIX_NEWLINE_GET 15
  441. /* Some clients, especially after a POST in a keep-alive connection,
  442. * will send an extra CRLF before the next request
  443. */
  444. , {.name = "newline prefix get"
  445. ,.type= HTTP_REQUEST
  446. ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n"
  447. ,.should_keep_alive= TRUE
  448. ,.message_complete_on_eof= FALSE
  449. ,.http_major= 1
  450. ,.http_minor= 1
  451. ,.method= HTTP_GET
  452. ,.query_string= ""
  453. ,.fragment= ""
  454. ,.request_path= "/test"
  455. ,.request_url= "/test"
  456. ,.num_headers= 0
  457. ,.headers= { }
  458. ,.body= ""
  459. }
  460. #define UPGRADE_REQUEST 16
  461. , {.name = "upgrade request"
  462. ,.type= HTTP_REQUEST
  463. ,.raw= "GET /demo HTTP/1.1\r\n"
  464. "Host: example.com\r\n"
  465. "Connection: Upgrade\r\n"
  466. "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
  467. "Sec-WebSocket-Protocol: sample\r\n"
  468. "Upgrade: WebSocket\r\n"
  469. "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
  470. "Origin: http://example.com\r\n"
  471. "\r\n"
  472. "Hot diggity dogg"
  473. ,.should_keep_alive= TRUE
  474. ,.message_complete_on_eof= FALSE
  475. ,.http_major= 1
  476. ,.http_minor= 1
  477. ,.method= HTTP_GET
  478. ,.query_string= ""
  479. ,.fragment= ""
  480. ,.request_path= "/demo"
  481. ,.request_url= "/demo"
  482. ,.num_headers= 7
  483. ,.upgrade="Hot diggity dogg"
  484. ,.headers= { { "Host", "example.com" }
  485. , { "Connection", "Upgrade" }
  486. , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }
  487. , { "Sec-WebSocket-Protocol", "sample" }
  488. , { "Upgrade", "WebSocket" }
  489. , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" }
  490. , { "Origin", "http://example.com" }
  491. }
  492. ,.body= ""
  493. }
  494. #define CONNECT_REQUEST 17
  495. , {.name = "connect request"
  496. ,.type= HTTP_REQUEST
  497. ,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n"
  498. "User-agent: Mozilla/1.1N\r\n"
  499. "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
  500. "\r\n"
  501. "some data\r\n"
  502. "and yet even more data"
  503. ,.should_keep_alive= FALSE
  504. ,.message_complete_on_eof= FALSE
  505. ,.http_major= 1
  506. ,.http_minor= 0
  507. ,.method= HTTP_CONNECT
  508. ,.query_string= ""
  509. ,.fragment= ""
  510. ,.request_path= ""
  511. ,.request_url= "0-home0.netscape.com:443"
  512. ,.num_headers= 2
  513. ,.upgrade="some data\r\nand yet even more data"
  514. ,.headers= { { "User-agent", "Mozilla/1.1N" }
  515. , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
  516. }
  517. ,.body= ""
  518. }
  519. #define REPORT_REQ 18
  520. , {.name= "report request"
  521. ,.type= HTTP_REQUEST
  522. ,.raw= "REPORT /test HTTP/1.1\r\n"
  523. "\r\n"
  524. ,.should_keep_alive= TRUE
  525. ,.message_complete_on_eof= FALSE
  526. ,.http_major= 1
  527. ,.http_minor= 1
  528. ,.method= HTTP_REPORT
  529. ,.query_string= ""
  530. ,.fragment= ""
  531. ,.request_path= "/test"
  532. ,.request_url= "/test"
  533. ,.num_headers= 0
  534. ,.headers= {}
  535. ,.body= ""
  536. }
  537. #define NO_HTTP_VERSION 19
  538. , {.name= "request with no http version"
  539. ,.type= HTTP_REQUEST
  540. ,.raw= "GET /\r\n"
  541. "\r\n"
  542. ,.should_keep_alive= FALSE
  543. ,.message_complete_on_eof= FALSE
  544. ,.http_major= 0
  545. ,.http_minor= 9
  546. ,.method= HTTP_GET
  547. ,.query_string= ""
  548. ,.fragment= ""
  549. ,.request_path= "/"
  550. ,.request_url= "/"
  551. ,.num_headers= 0
  552. ,.headers= {}
  553. ,.body= ""
  554. }
  555. #define MSEARCH_REQ 20
  556. , {.name= "m-search request"
  557. ,.type= HTTP_REQUEST
  558. ,.raw= "M-SEARCH * HTTP/1.1\r\n"
  559. "HOST: 239.255.255.250:1900\r\n"
  560. "MAN: \"ssdp:discover\"\r\n"
  561. "ST: \"ssdp:all\"\r\n"
  562. "\r\n"
  563. ,.should_keep_alive= TRUE
  564. ,.message_complete_on_eof= FALSE
  565. ,.http_major= 1
  566. ,.http_minor= 1
  567. ,.method= HTTP_MSEARCH
  568. ,.query_string= ""
  569. ,.fragment= ""
  570. ,.request_path= "*"
  571. ,.request_url= "*"
  572. ,.num_headers= 3
  573. ,.headers= { { "HOST", "239.255.255.250:1900" }
  574. , { "MAN", "\"ssdp:discover\"" }
  575. , { "ST", "\"ssdp:all\"" }
  576. }
  577. ,.body= ""
  578. }
  579. #define LINE_FOLDING_IN_HEADER 21
  580. , {.name= "line folding in header value"
  581. ,.type= HTTP_REQUEST
  582. ,.raw= "GET / HTTP/1.1\r\n"
  583. "Line1: abc\r\n"
  584. "\tdef\r\n"
  585. " ghi\r\n"
  586. "\t\tjkl\r\n"
  587. " mno \r\n"
  588. "\t \tqrs\r\n"
  589. "Line2: \t line2\t\r\n"
  590. "Line3:\r\n"
  591. " line3\r\n"
  592. "Line4: \r\n"
  593. " \r\n"
  594. "Connection:\r\n"
  595. " close\r\n"
  596. "\r\n"
  597. ,.should_keep_alive= FALSE
  598. ,.message_complete_on_eof= FALSE
  599. ,.http_major= 1
  600. ,.http_minor= 1
  601. ,.method= HTTP_GET
  602. ,.query_string= ""
  603. ,.fragment= ""
  604. ,.request_path= "/"
  605. ,.request_url= "/"
  606. ,.num_headers= 5
  607. ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
  608. , { "Line2", "line2\t" }
  609. , { "Line3", "line3" }
  610. , { "Line4", "" }
  611. , { "Connection", "close" },
  612. }
  613. ,.body= ""
  614. }
  615. #define QUERY_TERMINATED_HOST 22
  616. , {.name= "host terminated by a query string"
  617. ,.type= HTTP_REQUEST
  618. ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
  619. "\r\n"
  620. ,.should_keep_alive= TRUE
  621. ,.message_complete_on_eof= FALSE
  622. ,.http_major= 1
  623. ,.http_minor= 1
  624. ,.method= HTTP_GET
  625. ,.query_string= "hail=all"
  626. ,.fragment= ""
  627. ,.request_path= ""
  628. ,.request_url= "http://hypnotoad.org?hail=all"
  629. ,.host= "hypnotoad.org"
  630. ,.num_headers= 0
  631. ,.headers= { }
  632. ,.body= ""
  633. }
  634. #define QUERY_TERMINATED_HOSTPORT 23
  635. , {.name= "host:port terminated by a query string"
  636. ,.type= HTTP_REQUEST
  637. ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
  638. "\r\n"
  639. ,.should_keep_alive= TRUE
  640. ,.message_complete_on_eof= FALSE
  641. ,.http_major= 1
  642. ,.http_minor= 1
  643. ,.method= HTTP_GET
  644. ,.query_string= "hail=all"
  645. ,.fragment= ""
  646. ,.request_path= ""
  647. ,.request_url= "http://hypnotoad.org:1234?hail=all"
  648. ,.host= "hypnotoad.org"
  649. ,.port= 1234
  650. ,.num_headers= 0
  651. ,.headers= { }
  652. ,.body= ""
  653. }
  654. #define SPACE_TERMINATED_HOSTPORT 24
  655. , {.name= "host:port terminated by a space"
  656. ,.type= HTTP_REQUEST
  657. ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
  658. "\r\n"
  659. ,.should_keep_alive= TRUE
  660. ,.message_complete_on_eof= FALSE
  661. ,.http_major= 1
  662. ,.http_minor= 1
  663. ,.method= HTTP_GET
  664. ,.query_string= ""
  665. ,.fragment= ""
  666. ,.request_path= ""
  667. ,.request_url= "http://hypnotoad.org:1234"
  668. ,.host= "hypnotoad.org"
  669. ,.port= 1234
  670. ,.num_headers= 0
  671. ,.headers= { }
  672. ,.body= ""
  673. }
  674. #define PATCH_REQ 25
  675. , {.name = "PATCH request"
  676. ,.type= HTTP_REQUEST
  677. ,.raw= "PATCH /file.txt HTTP/1.1\r\n"
  678. "Host: www.example.com\r\n"
  679. "Content-Type: application/example\r\n"
  680. "If-Match: \"e0023aa4e\"\r\n"
  681. "Content-Length: 10\r\n"
  682. "\r\n"
  683. "cccccccccc"
  684. ,.should_keep_alive= TRUE
  685. ,.message_complete_on_eof= FALSE
  686. ,.http_major= 1
  687. ,.http_minor= 1
  688. ,.method= HTTP_PATCH
  689. ,.query_string= ""
  690. ,.fragment= ""
  691. ,.request_path= "/file.txt"
  692. ,.request_url= "/file.txt"
  693. ,.num_headers= 4
  694. ,.headers= { { "Host", "www.example.com" }
  695. , { "Content-Type", "application/example" }
  696. , { "If-Match", "\"e0023aa4e\"" }
  697. , { "Content-Length", "10" }
  698. }
  699. ,.body= "cccccccccc"
  700. }
  701. #define CONNECT_CAPS_REQUEST 26
  702. , {.name = "connect caps request"
  703. ,.type= HTTP_REQUEST
  704. ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n"
  705. "User-agent: Mozilla/1.1N\r\n"
  706. "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
  707. "\r\n"
  708. ,.should_keep_alive= FALSE
  709. ,.message_complete_on_eof= FALSE
  710. ,.http_major= 1
  711. ,.http_minor= 0
  712. ,.method= HTTP_CONNECT
  713. ,.query_string= ""
  714. ,.fragment= ""
  715. ,.request_path= ""
  716. ,.request_url= "HOME0.NETSCAPE.COM:443"
  717. ,.num_headers= 2
  718. ,.upgrade=""
  719. ,.headers= { { "User-agent", "Mozilla/1.1N" }
  720. , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
  721. }
  722. ,.body= ""
  723. }
  724. #if !HTTP_PARSER_STRICT
  725. #define UTF8_PATH_REQ 27
  726. , {.name= "utf-8 path request"
  727. ,.type= HTTP_REQUEST
  728. ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
  729. "Host: github.com\r\n"
  730. "\r\n"
  731. ,.should_keep_alive= TRUE
  732. ,.message_complete_on_eof= FALSE
  733. ,.http_major= 1
  734. ,.http_minor= 1
  735. ,.method= HTTP_GET
  736. ,.query_string= "q=1"
  737. ,.fragment= "narf"
  738. ,.request_path= "/δ¶/δt/pope"
  739. ,.request_url= "/δ¶/δt/pope?q=1#narf"
  740. ,.num_headers= 1
  741. ,.headers= { {"Host", "github.com" }
  742. }
  743. ,.body= ""
  744. }
  745. #define HOSTNAME_UNDERSCORE 28
  746. , {.name = "hostname underscore"
  747. ,.type= HTTP_REQUEST
  748. ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n"
  749. "User-agent: Mozilla/1.1N\r\n"
  750. "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
  751. "\r\n"
  752. ,.should_keep_alive= FALSE
  753. ,.message_complete_on_eof= FALSE
  754. ,.http_major= 1
  755. ,.http_minor= 0
  756. ,.method= HTTP_CONNECT
  757. ,.query_string= ""
  758. ,.fragment= ""
  759. ,.request_path= ""
  760. ,.request_url= "home_0.netscape.com:443"
  761. ,.num_headers= 2
  762. ,.upgrade=""
  763. ,.headers= { { "User-agent", "Mozilla/1.1N" }
  764. , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
  765. }
  766. ,.body= ""
  767. }
  768. #endif /* !HTTP_PARSER_STRICT */
  769. /* see https://github.com/ry/http-parser/issues/47 */
  770. #define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29
  771. , {.name = "eat CRLF between requests, no \"Connection: close\" header"
  772. ,.raw= "POST / HTTP/1.1\r\n"
  773. "Host: www.example.com\r\n"
  774. "Content-Type: application/x-www-form-urlencoded\r\n"
  775. "Content-Length: 4\r\n"
  776. "\r\n"
  777. "q=42\r\n" /* note the trailing CRLF */
  778. ,.should_keep_alive= TRUE
  779. ,.message_complete_on_eof= FALSE
  780. ,.http_major= 1
  781. ,.http_minor= 1
  782. ,.method= HTTP_POST
  783. ,.query_string= ""
  784. ,.fragment= ""
  785. ,.request_path= "/"
  786. ,.request_url= "/"
  787. ,.num_headers= 3
  788. ,.upgrade= 0
  789. ,.headers= { { "Host", "www.example.com" }
  790. , { "Content-Type", "application/x-www-form-urlencoded" }
  791. , { "Content-Length", "4" }
  792. }
  793. ,.body= "q=42"
  794. }
  795. /* see https://github.com/ry/http-parser/issues/47 */
  796. #define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30
  797. , {.name = "eat CRLF between requests even if \"Connection: close\" is set"
  798. ,.raw= "POST / HTTP/1.1\r\n"
  799. "Host: www.example.com\r\n"
  800. "Content-Type: application/x-www-form-urlencoded\r\n"
  801. "Content-Length: 4\r\n"
  802. "Connection: close\r\n"
  803. "\r\n"
  804. "q=42\r\n" /* note the trailing CRLF */
  805. ,.should_keep_alive= FALSE
  806. ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */
  807. ,.http_major= 1
  808. ,.http_minor= 1
  809. ,.method= HTTP_POST
  810. ,.query_string= ""
  811. ,.fragment= ""
  812. ,.request_path= "/"
  813. ,.request_url= "/"
  814. ,.num_headers= 4
  815. ,.upgrade= 0
  816. ,.headers= { { "Host", "www.example.com" }
  817. , { "Content-Type", "application/x-www-form-urlencoded" }
  818. , { "Content-Length", "4" }
  819. , { "Connection", "close" }
  820. }
  821. ,.body= "q=42"
  822. }
  823. #define PURGE_REQ 31
  824. , {.name = "PURGE request"
  825. ,.type= HTTP_REQUEST
  826. ,.raw= "PURGE /file.txt HTTP/1.1\r\n"
  827. "Host: www.example.com\r\n"
  828. "\r\n"
  829. ,.should_keep_alive= TRUE
  830. ,.message_complete_on_eof= FALSE
  831. ,.http_major= 1
  832. ,.http_minor= 1
  833. ,.method= HTTP_PURGE
  834. ,.query_string= ""
  835. ,.fragment= ""
  836. ,.request_path= "/file.txt"
  837. ,.request_url= "/file.txt"
  838. ,.num_headers= 1
  839. ,.headers= { { "Host", "www.example.com" } }
  840. ,.body= ""
  841. }
  842. #define SEARCH_REQ 32
  843. , {.name = "SEARCH request"
  844. ,.type= HTTP_REQUEST
  845. ,.raw= "SEARCH / HTTP/1.1\r\n"
  846. "Host: www.example.com\r\n"
  847. "\r\n"
  848. ,.should_keep_alive= TRUE
  849. ,.message_complete_on_eof= FALSE
  850. ,.http_major= 1
  851. ,.http_minor= 1
  852. ,.method= HTTP_SEARCH
  853. ,.query_string= ""
  854. ,.fragment= ""
  855. ,.request_path= "/"
  856. ,.request_url= "/"
  857. ,.num_headers= 1
  858. ,.headers= { { "Host", "www.example.com" } }
  859. ,.body= ""
  860. }
  861. #define PROXY_WITH_BASIC_AUTH 33
  862. , {.name= "host:port and basic_auth"
  863. ,.type= HTTP_REQUEST
  864. ,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n"
  865. "\r\n"
  866. ,.should_keep_alive= TRUE
  867. ,.message_complete_on_eof= FALSE
  868. ,.http_major= 1
  869. ,.http_minor= 1
  870. ,.method= HTTP_GET
  871. ,.fragment= ""
  872. ,.request_path= "/toto"
  873. ,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto"
  874. ,.host= "hypnotoad.org"
  875. ,.userinfo= "a%12:b!&*$"
  876. ,.port= 1234
  877. ,.num_headers= 0
  878. ,.headers= { }
  879. ,.body= ""
  880. }
  881. #define LINE_FOLDING_IN_HEADER_WITH_LF 34
  882. , {.name= "line folding in header value"
  883. ,.type= HTTP_REQUEST
  884. ,.raw= "GET / HTTP/1.1\n"
  885. "Line1: abc\n"
  886. "\tdef\n"
  887. " ghi\n"
  888. "\t\tjkl\n"
  889. " mno \n"
  890. "\t \tqrs\n"
  891. "Line2: \t line2\t\n"
  892. "Line3:\n"
  893. " line3\n"
  894. "Line4: \n"
  895. " \n"
  896. "Connection:\n"
  897. " close\n"
  898. "\n"
  899. ,.should_keep_alive= FALSE
  900. ,.message_complete_on_eof= FALSE
  901. ,.http_major= 1
  902. ,.http_minor= 1
  903. ,.method= HTTP_GET
  904. ,.query_string= ""
  905. ,.fragment= ""
  906. ,.request_path= "/"
  907. ,.request_url= "/"
  908. ,.num_headers= 5
  909. ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
  910. , { "Line2", "line2\t" }
  911. , { "Line3", "line3" }
  912. , { "Line4", "" }
  913. , { "Connection", "close" },
  914. }
  915. ,.body= ""
  916. }
  917. #define CONNECTION_MULTI 35
  918. , {.name = "multiple connection header values with folding"
  919. ,.type= HTTP_REQUEST
  920. ,.raw= "GET /demo HTTP/1.1\r\n"
  921. "Host: example.com\r\n"
  922. "Connection: Something,\r\n"
  923. " Upgrade, ,Keep-Alive\r\n"
  924. "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
  925. "Sec-WebSocket-Protocol: sample\r\n"
  926. "Upgrade: WebSocket\r\n"
  927. "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
  928. "Origin: http://example.com\r\n"
  929. "\r\n"
  930. "Hot diggity dogg"
  931. ,.should_keep_alive= TRUE
  932. ,.message_complete_on_eof= FALSE
  933. ,.http_major= 1
  934. ,.http_minor= 1
  935. ,.method= HTTP_GET
  936. ,.query_string= ""
  937. ,.fragment= ""
  938. ,.request_path= "/demo"
  939. ,.request_url= "/demo"
  940. ,.num_headers= 7
  941. ,.upgrade="Hot diggity dogg"
  942. ,.headers= { { "Host", "example.com" }
  943. , { "Connection", "Something, Upgrade, ,Keep-Alive" }
  944. , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }
  945. , { "Sec-WebSocket-Protocol", "sample" }
  946. , { "Upgrade", "WebSocket" }
  947. , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" }
  948. , { "Origin", "http://example.com" }
  949. }
  950. ,.body= ""
  951. }
  952. #define CONNECTION_MULTI_LWS 36
  953. , {.name = "multiple connection header values with folding and lws"
  954. ,.type= HTTP_REQUEST
  955. ,.raw= "GET /demo HTTP/1.1\r\n"
  956. "Connection: keep-alive, upgrade\r\n"
  957. "Upgrade: WebSocket\r\n"
  958. "\r\n"
  959. "Hot diggity dogg"
  960. ,.should_keep_alive= TRUE
  961. ,.message_complete_on_eof= FALSE
  962. ,.http_major= 1
  963. ,.http_minor= 1
  964. ,.method= HTTP_GET
  965. ,.query_string= ""
  966. ,.fragment= ""
  967. ,.request_path= "/demo"
  968. ,.request_url= "/demo"
  969. ,.num_headers= 2
  970. ,.upgrade="Hot diggity dogg"
  971. ,.headers= { { "Connection", "keep-alive, upgrade" }
  972. , { "Upgrade", "WebSocket" }
  973. }
  974. ,.body= ""
  975. }
  976. #define CONNECTION_MULTI_LWS_CRLF 37
  977. , {.name = "multiple connection header values with folding and lws"
  978. ,.type= HTTP_REQUEST
  979. ,.raw= "GET /demo HTTP/1.1\r\n"
  980. "Connection: keep-alive, \r\n upgrade\r\n"
  981. "Upgrade: WebSocket\r\n"
  982. "\r\n"
  983. "Hot diggity dogg"
  984. ,.should_keep_alive= TRUE
  985. ,.message_complete_on_eof= FALSE
  986. ,.http_major= 1
  987. ,.http_minor= 1
  988. ,.method= HTTP_GET
  989. ,.query_string= ""
  990. ,.fragment= ""
  991. ,.request_path= "/demo"
  992. ,.request_url= "/demo"
  993. ,.num_headers= 2
  994. ,.upgrade="Hot diggity dogg"
  995. ,.headers= { { "Connection", "keep-alive, upgrade" }
  996. , { "Upgrade", "WebSocket" }
  997. }
  998. ,.body= ""
  999. }
  1000. #define UPGRADE_POST_REQUEST 38
  1001. , {.name = "upgrade post request"
  1002. ,.type= HTTP_REQUEST
  1003. ,.raw= "POST /demo HTTP/1.1\r\n"
  1004. "Host: example.com\r\n"
  1005. "Connection: Upgrade\r\n"
  1006. "Upgrade: HTTP/2.0\r\n"
  1007. "Content-Length: 15\r\n"
  1008. "\r\n"
  1009. "sweet post body"
  1010. "Hot diggity dogg"
  1011. ,.should_keep_alive= TRUE
  1012. ,.message_complete_on_eof= FALSE
  1013. ,.http_major= 1
  1014. ,.http_minor= 1
  1015. ,.method= HTTP_POST
  1016. ,.request_path= "/demo"
  1017. ,.request_url= "/demo"
  1018. ,.num_headers= 4
  1019. ,.upgrade="Hot diggity dogg"
  1020. ,.headers= { { "Host", "example.com" }
  1021. , { "Connection", "Upgrade" }
  1022. , { "Upgrade", "HTTP/2.0" }
  1023. , { "Content-Length", "15" }
  1024. }
  1025. ,.body= "sweet post body"
  1026. }
  1027. #define CONNECT_WITH_BODY_REQUEST 39
  1028. , {.name = "connect with body request"
  1029. ,.type= HTTP_REQUEST
  1030. ,.raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n"
  1031. "User-agent: Mozilla/1.1N\r\n"
  1032. "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
  1033. "Content-Length: 10\r\n"
  1034. "\r\n"
  1035. "blarfcicle"
  1036. ,.should_keep_alive= FALSE
  1037. ,.message_complete_on_eof= FALSE
  1038. ,.http_major= 1
  1039. ,.http_minor= 0
  1040. ,.method= HTTP_CONNECT
  1041. ,.request_url= "foo.bar.com:443"
  1042. ,.num_headers= 3
  1043. ,.upgrade="blarfcicle"
  1044. ,.headers= { { "User-agent", "Mozilla/1.1N" }
  1045. , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
  1046. , { "Content-Length", "10" }
  1047. }
  1048. ,.body= ""
  1049. }
  1050. , {.name= NULL } /* sentinel */
  1051. };
  1052. /* * R E S P O N S E S * */
  1053. const struct message responses[] =
  1054. #define GOOGLE_301 0
  1055. { {.name= "google 301"
  1056. ,.type= HTTP_RESPONSE
  1057. ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"
  1058. "Location: http://www.google.com/\r\n"
  1059. "Content-Type: text/html; charset=UTF-8\r\n"
  1060. "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"
  1061. "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"
  1062. "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */
  1063. "Cache-Control: public, max-age=2592000\r\n"
  1064. "Server: gws\r\n"
  1065. "Content-Length: 219 \r\n"
  1066. "\r\n"
  1067. "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
  1068. "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
  1069. "<H1>301 Moved</H1>\n"
  1070. "The document has moved\n"
  1071. "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
  1072. "</BODY></HTML>\r\n"
  1073. ,.should_keep_alive= TRUE
  1074. ,.message_complete_on_eof= FALSE
  1075. ,.http_major= 1
  1076. ,.http_minor= 1
  1077. ,.status_code= 301
  1078. ,.response_status= "Moved Permanently"
  1079. ,.num_headers= 8
  1080. ,.headers=
  1081. { { "Location", "http://www.google.com/" }
  1082. , { "Content-Type", "text/html; charset=UTF-8" }
  1083. , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }
  1084. , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" }
  1085. , { "X-$PrototypeBI-Version", "1.6.0.3" }
  1086. , { "Cache-Control", "public, max-age=2592000" }
  1087. , { "Server", "gws" }
  1088. , { "Content-Length", "219 " }
  1089. }
  1090. ,.body= "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
  1091. "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
  1092. "<H1>301 Moved</H1>\n"
  1093. "The document has moved\n"
  1094. "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
  1095. "</BODY></HTML>\r\n"
  1096. }
  1097. #define NO_CONTENT_LENGTH_RESPONSE 1
  1098. /* The client should wait for the server's EOF. That is, when content-length
  1099. * is not specified, and "Connection: close", the end of body is specified
  1100. * by the EOF.
  1101. * Compare with APACHEBENCH_GET
  1102. */
  1103. , {.name= "no content-length response"
  1104. ,.type= HTTP_RESPONSE
  1105. ,.raw= "HTTP/1.1 200 OK\r\n"
  1106. "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"
  1107. "Server: Apache\r\n"
  1108. "X-Powered-By: Servlet/2.5 JSP/2.1\r\n"
  1109. "Content-Type: text/xml; charset=utf-8\r\n"
  1110. "Connection: close\r\n"
  1111. "\r\n"
  1112. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  1113. "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
  1114. " <SOAP-ENV:Body>\n"
  1115. " <SOAP-ENV:Fault>\n"
  1116. " <faultcode>SOAP-ENV:Client</faultcode>\n"
  1117. " <faultstring>Client Error</faultstring>\n"
  1118. " </SOAP-ENV:Fault>\n"
  1119. " </SOAP-ENV:Body>\n"
  1120. "</SOAP-ENV:Envelope>"
  1121. ,.should_keep_alive= FALSE
  1122. ,.message_complete_on_eof= TRUE
  1123. ,.http_major= 1
  1124. ,.http_minor= 1
  1125. ,.status_code= 200
  1126. ,.response_status= "OK"
  1127. ,.num_headers= 5
  1128. ,.headers=
  1129. { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
  1130. , { "Server", "Apache" }
  1131. , { "X-Powered-By", "Servlet/2.5 JSP/2.1" }
  1132. , { "Content-Type", "text/xml; charset=utf-8" }
  1133. , { "Connection", "close" }
  1134. }
  1135. ,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  1136. "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
  1137. " <SOAP-ENV:Body>\n"
  1138. " <SOAP-ENV:Fault>\n"
  1139. " <faultcode>SOAP-ENV:Client</faultcode>\n"
  1140. " <faultstring>Client Error</faultstring>\n"
  1141. " </SOAP-ENV:Fault>\n"
  1142. " </SOAP-ENV:Body>\n"
  1143. "</SOAP-ENV:Envelope>"
  1144. }
  1145. #define NO_HEADERS_NO_BODY_404 2
  1146. , {.name= "404 no headers no body"
  1147. ,.type= HTTP_RESPONSE
  1148. ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
  1149. ,.should_keep_alive= FALSE
  1150. ,.message_complete_on_eof= TRUE
  1151. ,.http_major= 1
  1152. ,.http_minor= 1
  1153. ,.status_code= 404
  1154. ,.response_status= "Not Found"
  1155. ,.num_headers= 0
  1156. ,.headers= {}
  1157. ,.body_size= 0
  1158. ,.body= ""
  1159. }
  1160. #define NO_REASON_PHRASE 3
  1161. , {.name= "301 no response phrase"
  1162. ,.type= HTTP_RESPONSE
  1163. ,.raw= "HTTP/1.1 301\r\n\r\n"
  1164. ,.should_keep_alive = FALSE
  1165. ,.message_complete_on_eof= TRUE
  1166. ,.http_major= 1
  1167. ,.http_minor= 1
  1168. ,.status_code= 301
  1169. ,.response_status= ""
  1170. ,.num_headers= 0
  1171. ,.headers= {}
  1172. ,.body= ""
  1173. }
  1174. #define TRAILING_SPACE_ON_CHUNKED_BODY 4
  1175. , {.name="200 trailing space on chunked body"
  1176. ,.type= HTTP_RESPONSE
  1177. ,.raw= "HTTP/1.1 200 OK\r\n"
  1178. "Content-Type: text/plain\r\n"
  1179. "Transfer-Encoding: chunked\r\n"
  1180. "\r\n"
  1181. "25 \r\n"
  1182. "This is the data in the first chunk\r\n"
  1183. "\r\n"
  1184. "1C\r\n"
  1185. "and this is the second one\r\n"
  1186. "\r\n"
  1187. "0 \r\n"
  1188. "\r\n"
  1189. ,.should_keep_alive= TRUE
  1190. ,.message_complete_on_eof= FALSE
  1191. ,.http_major= 1
  1192. ,.http_minor= 1
  1193. ,.status_code= 200
  1194. ,.response_status= "OK"
  1195. ,.num_headers= 2
  1196. ,.headers=
  1197. { {"Content-Type", "text/plain" }
  1198. , {"Transfer-Encoding", "chunked" }
  1199. }
  1200. ,.body_size = 37+28
  1201. ,.body =
  1202. "This is the data in the first chunk\r\n"
  1203. "and this is the second one\r\n"
  1204. ,.num_chunks_complete= 3
  1205. ,.chunk_lengths= { 0x25, 0x1c }
  1206. }
  1207. #define NO_CARRIAGE_RET 5
  1208. , {.name="no carriage ret"
  1209. ,.type= HTTP_RESPONSE
  1210. ,.raw= "HTTP/1.1 200 OK\n"
  1211. "Content-Type: text/html; charset=utf-8\n"
  1212. "Connection: close\n"
  1213. "\n"
  1214. "these headers are from http://news.ycombinator.com/"
  1215. ,.should_keep_alive= FALSE
  1216. ,.message_complete_on_eof= TRUE
  1217. ,.http_major= 1
  1218. ,.http_minor= 1
  1219. ,.status_code= 200
  1220. ,.response_status= "OK"
  1221. ,.num_headers= 2
  1222. ,.headers=
  1223. { {"Content-Type", "text/html; charset=utf-8" }
  1224. , {"Connection", "close" }
  1225. }
  1226. ,.body= "these headers are from http://news.ycombinator.com/"
  1227. }
  1228. #define PROXY_CONNECTION 6
  1229. , {.name="proxy connection"
  1230. ,.type= HTTP_RESPONSE
  1231. ,.raw= "HTTP/1.1 200 OK\r\n"
  1232. "Content-Type: text/html; charset=UTF-8\r\n"
  1233. "Content-Length: 11\r\n"
  1234. "Proxy-Connection: close\r\n"
  1235. "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n"
  1236. "\r\n"
  1237. "hello world"
  1238. ,.should_keep_alive= FALSE
  1239. ,.message_complete_on_eof= FALSE
  1240. ,.http_major= 1
  1241. ,.http_minor= 1
  1242. ,.status_code= 200
  1243. ,.response_status= "OK"
  1244. ,.num_headers= 4
  1245. ,.headers=
  1246. { {"Content-Type", "text/html; charset=UTF-8" }
  1247. , {"Content-Length", "11" }
  1248. , {"Proxy-Connection", "close" }
  1249. , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"}
  1250. }
  1251. ,.body= "hello world"
  1252. }
  1253. #define UNDERSTORE_HEADER_KEY 7
  1254. // shown by
  1255. // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;"
  1256. , {.name="underscore header key"
  1257. ,.type= HTTP_RESPONSE
  1258. ,.raw= "HTTP/1.1 200 OK\r\n"
  1259. "Server: DCLK-AdSvr\r\n"
  1260. "Content-Type: text/xml\r\n"
  1261. "Content-Length: 0\r\n"
  1262. "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n"
  1263. ,.should_keep_alive= TRUE
  1264. ,.message_complete_on_eof= FALSE
  1265. ,.http_major= 1
  1266. ,.http_minor= 1
  1267. ,.status_code= 200
  1268. ,.response_status= "OK"
  1269. ,.num_headers= 4
  1270. ,.headers=
  1271. { {"Server", "DCLK-AdSvr" }
  1272. , {"Content-Type", "text/xml" }
  1273. , {"Content-Length", "0" }
  1274. , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" }
  1275. }
  1276. ,.body= ""
  1277. }
  1278. #define BONJOUR_MADAME_FR 8
  1279. /* The client should not merge two headers fields when the first one doesn't
  1280. * have a value.
  1281. */
  1282. , {.name= "bonjourmadame.fr"
  1283. ,.type= HTTP_RESPONSE
  1284. ,.raw= "HTTP/1.0 301 Moved Permanently\r\n"
  1285. "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n"
  1286. "Server: Apache/2.2.3 (Red Hat)\r\n"
  1287. "Cache-Control: public\r\n"
  1288. "Pragma: \r\n"
  1289. "Location: http://www.bonjourmadame.fr/\r\n"
  1290. "Vary: Accept-Encoding\r\n"
  1291. "Content-Length: 0\r\n"
  1292. "Content-Type: text/html; charset=UTF-8\r\n"
  1293. "Connection: keep-alive\r\n"
  1294. "\r\n"
  1295. ,.should_keep_alive= TRUE
  1296. ,.message_complete_on_eof= FALSE
  1297. ,.http_major= 1
  1298. ,.http_minor= 0
  1299. ,.status_code= 301
  1300. ,.response_status= "Moved Permanently"
  1301. ,.num_headers= 9
  1302. ,.headers=
  1303. { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
  1304. , { "Server", "Apache/2.2.3 (Red Hat)" }
  1305. , { "Cache-Control", "public" }
  1306. , { "Pragma", "" }
  1307. , { "Location", "http://www.bonjourmadame.fr/" }
  1308. , { "Vary", "Accept-Encoding" }
  1309. , { "Content-Length", "0" }
  1310. , { "Content-Type", "text/html; charset=UTF-8" }
  1311. , { "Connection", "keep-alive" }
  1312. }
  1313. ,.body= ""
  1314. }
  1315. #define RES_FIELD_UNDERSCORE 9
  1316. /* Should handle spaces in header fields */
  1317. , {.name= "field underscore"
  1318. ,.type= HTTP_RESPONSE
  1319. ,.raw= "HTTP/1.1 200 OK\r\n"
  1320. "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n"
  1321. "Server: Apache\r\n"
  1322. "Cache-Control: no-cache, must-revalidate\r\n"
  1323. "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
  1324. ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n"
  1325. "Vary: Accept-Encoding\r\n"
  1326. "_eep-Alive: timeout=45\r\n" /* semantic value ignored */
  1327. "_onnection: Keep-Alive\r\n" /* semantic value ignored */
  1328. "Transfer-Encoding: chunked\r\n"
  1329. "Content-Type: text/html\r\n"
  1330. "Connection: close\r\n"
  1331. "\r\n"
  1332. "0\r\n\r\n"
  1333. ,.should_keep_alive= FALSE
  1334. ,.message_complete_on_eof= FALSE
  1335. ,.http_major= 1
  1336. ,.http_minor= 1
  1337. ,.status_code= 200
  1338. ,.response_status= "OK"
  1339. ,.num_headers= 11
  1340. ,.headers=
  1341. { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
  1342. , { "Server", "Apache" }
  1343. , { "Cache-Control", "no-cache, must-revalidate" }
  1344. , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" }
  1345. , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" }
  1346. , { "Vary", "Accept-Encoding" }
  1347. , { "_eep-Alive", "timeout=45" }
  1348. , { "_onnection", "Keep-Alive" }
  1349. , { "Transfer-Encoding", "chunked" }
  1350. , { "Content-Type", "text/html" }
  1351. , { "Connection", "close" }
  1352. }
  1353. ,.body= ""
  1354. ,.num_chunks_complete= 1
  1355. ,.chunk_lengths= {}
  1356. }
  1357. #define NON_ASCII_IN_STATUS_LINE 10
  1358. /* Should handle non-ASCII in status line */
  1359. , {.name= "non-ASCII in status line"
  1360. ,.type= HTTP_RESPONSE
  1361. ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n"
  1362. "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n"
  1363. "Content-Length: 0\r\n"
  1364. "Connection: close\r\n"
  1365. "\r\n"
  1366. ,.should_keep_alive= FALSE
  1367. ,.message_complete_on_eof= FALSE
  1368. ,.http_major= 1
  1369. ,.http_minor= 1
  1370. ,.status_code= 500
  1371. ,.response_status= "Oriëntatieprobleem"
  1372. ,.num_headers= 3
  1373. ,.headers=
  1374. { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
  1375. , { "Content-Length", "0" }
  1376. , { "Connection", "close" }
  1377. }
  1378. ,.body= ""
  1379. }
  1380. #define HTTP_VERSION_0_9 11
  1381. /* Should handle HTTP/0.9 */
  1382. , {.name= "http version 0.9"
  1383. ,.type= HTTP_RESPONSE
  1384. ,.raw= "HTTP/0.9 200 OK\r\n"
  1385. "\r\n"
  1386. ,.should_keep_alive= FALSE
  1387. ,.message_complete_on_eof= TRUE
  1388. ,.http_major= 0
  1389. ,.http_minor= 9
  1390. ,.status_code= 200
  1391. ,.response_status= "OK"
  1392. ,.num_headers= 0
  1393. ,.headers=
  1394. {}
  1395. ,.body= ""
  1396. }
  1397. #define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12
  1398. /* The client should wait for the server's EOF. That is, when neither
  1399. * content-length nor transfer-encoding is specified, the end of body
  1400. * is specified by the EOF.
  1401. */
  1402. , {.name= "neither content-length nor transfer-encoding response"
  1403. ,.type= HTTP_RESPONSE
  1404. ,.raw= "HTTP/1.1 200 OK\r\n"
  1405. "Content-Type: text/plain\r\n"
  1406. "\r\n"
  1407. "hello world"
  1408. ,.should_keep_alive= FALSE
  1409. ,.message_complete_on_eof= TRUE
  1410. ,.http_major= 1
  1411. ,.http_minor= 1
  1412. ,.status_code= 200
  1413. ,.response_status= "OK"
  1414. ,.num_headers= 1
  1415. ,.headers=
  1416. { { "Content-Type", "text/plain" }
  1417. }
  1418. ,.body= "hello world"
  1419. }
  1420. #define NO_BODY_HTTP10_KA_200 13
  1421. , {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status"
  1422. ,.type= HTTP_RESPONSE
  1423. ,.raw= "HTTP/1.0 200 OK\r\n"
  1424. "Connection: keep-alive\r\n"
  1425. "\r\n"
  1426. ,.should_keep_alive= FALSE
  1427. ,.message_complete_on_eof= TRUE
  1428. ,.http_major= 1
  1429. ,.http_minor= 0
  1430. ,.status_code= 200
  1431. ,.response_status= "OK"
  1432. ,.num_headers= 1
  1433. ,.headers=
  1434. { { "Connection", "keep-alive" }
  1435. }
  1436. ,.body_size= 0
  1437. ,.body= ""
  1438. }
  1439. #define NO_BODY_HTTP10_KA_204 14
  1440. , {.name= "HTTP/1.0 with keep-alive and a 204 status"
  1441. ,.type= HTTP_RESPONSE
  1442. ,.raw= "HTTP/1.0 204 No content\r\n"
  1443. "Connection: keep-alive\r\n"
  1444. "\r\n"
  1445. ,.should_keep_alive= TRUE
  1446. ,.message_complete_on_eof= FALSE
  1447. ,.http_major= 1
  1448. ,.http_minor= 0
  1449. ,.status_code= 204
  1450. ,.response_status= "No content"
  1451. ,.num_headers= 1
  1452. ,.headers=
  1453. { { "Connection", "keep-alive" }
  1454. }
  1455. ,.body_size= 0
  1456. ,.body= ""
  1457. }
  1458. #define NO_BODY_HTTP11_KA_200 15
  1459. , {.name= "HTTP/1.1 with an EOF-terminated 200 status"
  1460. ,.type= HTTP_RESPONSE
  1461. ,.raw= "HTTP/1.1 200 OK\r\n"
  1462. "\r\n"
  1463. ,.should_keep_alive= FALSE
  1464. ,.message_complete_on_eof= TRUE
  1465. ,.http_major= 1
  1466. ,.http_minor= 1
  1467. ,.status_code= 200
  1468. ,.response_status= "OK"
  1469. ,.num_headers= 0
  1470. ,.headers={}
  1471. ,.body_size= 0
  1472. ,.body= ""
  1473. }
  1474. #define NO_BODY_HTTP11_KA_204 16
  1475. , {.name= "HTTP/1.1 with a 204 status"
  1476. ,.type= HTTP_RESPONSE
  1477. ,.raw= "HTTP/1.1 204 No content\r\n"
  1478. "\r\n"
  1479. ,.should_keep_alive= TRUE
  1480. ,.message_complete_on_eof= FALSE
  1481. ,.http_major= 1
  1482. ,.http_minor= 1
  1483. ,.status_code= 204
  1484. ,.response_status= "No content"
  1485. ,.num_headers= 0
  1486. ,.headers={}
  1487. ,.body_size= 0
  1488. ,.body= ""
  1489. }
  1490. #define NO_BODY_HTTP11_NOKA_204 17
  1491. , {.name= "HTTP/1.1 with a 204 status and keep-alive disabled"
  1492. ,.type= HTTP_RESPONSE
  1493. ,.raw= "HTTP/1.1 204 No content\r\n"
  1494. "Connection: close\r\n"
  1495. "\r\n"
  1496. ,.should_keep_alive= FALSE
  1497. ,.message_complete_on_eof= FALSE
  1498. ,.http_major= 1
  1499. ,.http_minor= 1
  1500. ,.status_code= 204
  1501. ,.response_status= "No content"
  1502. ,.num_headers= 1
  1503. ,.headers=
  1504. { { "Connection", "close" }
  1505. }
  1506. ,.body_size= 0
  1507. ,.body= ""
  1508. }
  1509. #define NO_BODY_HTTP11_KA_CHUNKED_200 18
  1510. , {.name= "HTTP/1.1 with chunked endocing and a 200 response"
  1511. ,.type= HTTP_RESPONSE
  1512. ,.raw= "HTTP/1.1 200 OK\r\n"
  1513. "Transfer-Encoding: chunked\r\n"
  1514. "\r\n"
  1515. "0\r\n"
  1516. "\r\n"
  1517. ,.should_keep_alive= TRUE
  1518. ,.message_complete_on_eof= FALSE
  1519. ,.http_major= 1
  1520. ,.http_minor= 1
  1521. ,.status_code= 200
  1522. ,.response_status= "OK"
  1523. ,.num_headers= 1
  1524. ,.headers=
  1525. { { "Transfer-Encoding", "chunked" }
  1526. }
  1527. ,.body_size= 0
  1528. ,.body= ""
  1529. ,.num_chunks_complete= 1
  1530. }
  1531. #if !HTTP_PARSER_STRICT
  1532. #define SPACE_IN_FIELD_RES 19
  1533. /* Should handle spaces in header fields */
  1534. , {.name= "field space"
  1535. ,.type= HTTP_RESPONSE
  1536. ,.raw= "HTTP/1.1 200 OK\r\n"
  1537. "Server: Microsoft-IIS/6.0\r\n"
  1538. "X-Powered-By: ASP.NET\r\n"
  1539. "en-US Content-Type: text/xml\r\n" /* this is the problem */
  1540. "Content-Type: text/xml\r\n"
  1541. "Content-Length: 16\r\n"
  1542. "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"
  1543. "Connection: keep-alive\r\n"
  1544. "\r\n"
  1545. "<xml>hello</xml>" /* fake body */
  1546. ,.should_keep_alive= TRUE
  1547. ,.message_complete_on_eof= FALSE
  1548. ,.http_major= 1
  1549. ,.http_minor= 1
  1550. ,.status_code= 200
  1551. ,.response_status= "OK"
  1552. ,.num_headers= 7
  1553. ,.headers=
  1554. { { "Server", "Microsoft-IIS/6.0" }
  1555. , { "X-Powered-By", "ASP.NET" }
  1556. , { "en-US Content-Type", "text/xml" }
  1557. , { "Content-Type", "text/xml" }
  1558. , { "Content-Length", "16" }
  1559. , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }
  1560. , { "Connection", "keep-alive" }
  1561. }
  1562. ,.body= "<xml>hello</xml>"
  1563. }
  1564. #endif /* !HTTP_PARSER_STRICT */
  1565. #define AMAZON_COM 20
  1566. , {.name= "amazon.com"
  1567. ,.type= HTTP_RESPONSE
  1568. ,.raw= "HTTP/1.1 301 MovedPermanently\r\n"
  1569. "Date: Wed, 15 May 2013 17:06:33 GMT\r\n"
  1570. "Server: Server\r\n"
  1571. "x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n"
  1572. "p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n"
  1573. "x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n"
  1574. "Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n"
  1575. "Vary: Accept-Encoding,User-Agent\r\n"
  1576. "Content-Type: text/html; charset=ISO-8859-1\r\n"
  1577. "Transfer-Encoding: chunked\r\n"
  1578. "\r\n"
  1579. "1\r\n"
  1580. "\n\r\n"
  1581. "0\r\n"
  1582. "\r\n"
  1583. ,.should_keep_alive= TRUE
  1584. ,.message_complete_on_eof= FALSE
  1585. ,.http_major= 1
  1586. ,.http_minor= 1
  1587. ,.status_code= 301
  1588. ,.response_status= "MovedPermanently"
  1589. ,.num_headers= 9
  1590. ,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" }
  1591. , { "Server", "Server" }
  1592. , { "x-amz-id-1", "0GPHKXSJQ826RK7GZEB2" }
  1593. , { "p3p", "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" }
  1594. , { "x-amz-id-2", "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" }
  1595. , { "Location", "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" }
  1596. , { "Vary", "Accept-Encoding,User-Agent" }
  1597. , { "Content-Type", "text/html; charset=ISO-8859-1" }
  1598. , { "Transfer-Encoding", "chunked" }
  1599. }
  1600. ,.body= "\n"
  1601. ,.num_chunks_complete= 2
  1602. ,.chunk_lengths= { 1 }
  1603. }
  1604. #define EMPTY_REASON_PHRASE_AFTER_SPACE 20
  1605. , {.name= "empty reason phrase after space"
  1606. ,.type= HTTP_RESPONSE
  1607. ,.raw= "HTTP/1.1 200 \r\n"
  1608. "\r\n"
  1609. ,.should_keep_alive= FALSE
  1610. ,.message_complete_on_eof= TRUE
  1611. ,.http_major= 1
  1612. ,.http_minor= 1
  1613. ,.status_code= 200
  1614. ,.response_status= ""
  1615. ,.num_headers= 0
  1616. ,.headers= {}
  1617. ,.body= ""
  1618. }
  1619. , {.name= NULL } /* sentinel */
  1620. };
  1621. /* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
  1622. * define it ourselves.
  1623. */
  1624. size_t
  1625. strnlen(const char *s, size_t maxlen)
  1626. {
  1627. const char *p;
  1628. p = memchr(s, '\0', maxlen);
  1629. if (p == NULL)
  1630. return maxlen;
  1631. return p - s;
  1632. }
  1633. size_t
  1634. strlncat(char *dst, size_t len, const char *src, size_t n)
  1635. {
  1636. size_t slen;
  1637. size_t dlen;
  1638. size_t rlen;
  1639. size_t ncpy;
  1640. slen = strnlen(src, n);
  1641. dlen = strnlen(dst, len);
  1642. if (dlen < len) {
  1643. rlen = len - dlen;
  1644. ncpy = slen < rlen ? slen : (rlen - 1);
  1645. memcpy(dst + dlen, src, ncpy);
  1646. dst[dlen + ncpy] = '\0';
  1647. }
  1648. assert(len > slen + dlen);
  1649. return slen + dlen;
  1650. }
  1651. size_t
  1652. strlcat(char *dst, const char *src, size_t len)
  1653. {
  1654. return strlncat(dst, len, src, (size_t) -1);
  1655. }
  1656. size_t
  1657. strlncpy(char *dst, size_t len, const char *src, size_t n)
  1658. {
  1659. size_t slen;
  1660. size_t ncpy;
  1661. slen = strnlen(src, n);
  1662. if (len > 0) {
  1663. ncpy = slen < len ? slen : (len - 1);
  1664. memcpy(dst, src, ncpy);
  1665. dst[ncpy] = '\0';
  1666. }
  1667. assert(len > slen);
  1668. return slen;
  1669. }
  1670. size_t
  1671. strlcpy(char *dst, const char *src, size_t len)
  1672. {
  1673. return strlncpy(dst, len, src, (size_t) -1);
  1674. }
  1675. int
  1676. request_url_cb (http_parser *p, const char *buf, size_t len)
  1677. {
  1678. assert(p == parser);
  1679. strlncat(messages[num_messages].request_url,
  1680. sizeof(messages[num_messages].request_url),
  1681. buf,
  1682. len);
  1683. return 0;
  1684. }
  1685. int
  1686. header_field_cb (http_parser *p, const char *buf, size_t len)
  1687. {
  1688. assert(p == parser);
  1689. struct message *m = &messages[num_messages];
  1690. if (m->last_header_element != FIELD)
  1691. m->num_headers++;
  1692. strlncat(m->headers[m->num_headers-1][0],
  1693. sizeof(m->headers[m->num_headers-1][0]),
  1694. buf,
  1695. len);
  1696. m->last_header_element = FIELD;
  1697. return 0;
  1698. }
  1699. int
  1700. header_value_cb (http_parser *p, const char *buf, size_t len)
  1701. {
  1702. assert(p == parser);
  1703. struct message *m = &messages[num_messages];
  1704. strlncat(m->headers[m->num_headers-1][1],
  1705. sizeof(m->headers[m->num_headers-1][1]),
  1706. buf,
  1707. len);
  1708. m->last_header_element = VALUE;
  1709. return 0;
  1710. }
  1711. void
  1712. check_body_is_final (const http_parser *p)
  1713. {
  1714. if (messages[num_messages].body_is_final) {
  1715. fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
  1716. "on last on_body callback call "
  1717. "but it doesn't! ***\n\n");
  1718. assert(0);
  1719. abort();
  1720. }
  1721. messages[num_messages].body_is_final = http_body_is_final(p);
  1722. }
  1723. int
  1724. body_cb (http_parser *p, const char *buf, size_t len)
  1725. {
  1726. assert(p == parser);
  1727. strlncat(messages[num_messages].body,
  1728. sizeof(messages[num_messages].body),
  1729. buf,
  1730. len);
  1731. messages[num_messages].body_size += len;
  1732. check_body_is_final(p);
  1733. // printf("body_cb: '%s'\n", requests[num_messages].body);
  1734. return 0;
  1735. }
  1736. int
  1737. count_body_cb (http_parser *p, const char *buf, size_t len)
  1738. {
  1739. assert(p == parser);
  1740. assert(buf);
  1741. messages[num_messages].body_size += len;
  1742. check_body_is_final(p);
  1743. return 0;
  1744. }
  1745. int
  1746. message_begin_cb (http_parser *p)
  1747. {
  1748. assert(p == parser);
  1749. messages[num_messages].message_begin_cb_called = TRUE;
  1750. return 0;
  1751. }
  1752. int
  1753. headers_complete_cb (http_parser *p)
  1754. {
  1755. assert(p == parser);
  1756. messages[num_messages].method = parser->method;
  1757. messages[num_messages].status_code = parser->status_code;
  1758. messages[num_messages].http_major = parser->http_major;
  1759. messages[num_messages].http_minor = parser->http_minor;
  1760. messages[num_messages].headers_complete_cb_called = TRUE;
  1761. messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
  1762. return 0;
  1763. }
  1764. int
  1765. message_complete_cb (http_parser *p)
  1766. {
  1767. assert(p == parser);
  1768. if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser))
  1769. {
  1770. fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "
  1771. "value in both on_message_complete and on_headers_complete "
  1772. "but it doesn't! ***\n\n");
  1773. assert(0);
  1774. abort();
  1775. }
  1776. if (messages[num_messages].body_size &&
  1777. http_body_is_final(p) &&
  1778. !messages[num_messages].body_is_final)
  1779. {
  1780. fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
  1781. "on last on_body callback call "
  1782. "but it doesn't! ***\n\n");
  1783. assert(0);
  1784. abort();
  1785. }
  1786. messages[num_messages].message_complete_cb_called = TRUE;
  1787. messages[num_messages].message_complete_on_eof = currently_parsing_eof;
  1788. num_messages++;
  1789. return 0;
  1790. }
  1791. int
  1792. response_status_cb (http_parser *p, const char *buf, size_t len)
  1793. {
  1794. assert(p == parser);
  1795. strlncat(messages[num_messages].response_status,
  1796. sizeof(messages[num_messages].response_status),
  1797. buf,
  1798. len);
  1799. return 0;
  1800. }
  1801. int
  1802. chunk_header_cb (http_parser *p)
  1803. {
  1804. assert(p == parser);
  1805. int chunk_idx = messages[num_messages].num_chunks;
  1806. messages[num_messages].num_chunks++;
  1807. if (chunk_idx < MAX_CHUNKS) {
  1808. messages[num_messages].chunk_lengths[chunk_idx] = p->content_length;
  1809. }
  1810. return 0;
  1811. }
  1812. int
  1813. chunk_complete_cb (http_parser *p)
  1814. {
  1815. assert(p == parser);
  1816. /* Here we want to verify that each chunk_header_cb is matched by a
  1817. * chunk_complete_cb, so not only should the total number of calls to
  1818. * both callbacks be the same, but they also should be interleaved
  1819. * properly */
  1820. assert(messages[num_messages].num_chunks ==
  1821. messages[num_messages].num_chunks_complete + 1);
  1822. messages[num_messages].num_chunks_complete++;
  1823. return 0;
  1824. }
  1825. /* These dontcall_* callbacks exist so that we can verify that when we're
  1826. * paused, no additional callbacks are invoked */
  1827. int
  1828. dontcall_message_begin_cb (http_parser *p)
  1829. {
  1830. if (p) { } // gcc
  1831. fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n");
  1832. abort();
  1833. }
  1834. int
  1835. dontcall_header_field_cb (http_parser *p, const char *buf, size_t len)
  1836. {
  1837. if (p || buf || len) { } // gcc
  1838. fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n");
  1839. abort();
  1840. }
  1841. int
  1842. dontcall_header_value_cb (http_parser *p, const char *buf, size_t len)
  1843. {
  1844. if (p || buf || len) { } // gcc
  1845. fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n");
  1846. abort();
  1847. }
  1848. int
  1849. dontcall_request_url_cb (http_parser *p, const char *buf, size_t len)
  1850. {
  1851. if (p || buf || len) { } // gcc
  1852. fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n");
  1853. abort();
  1854. }
  1855. int
  1856. dontcall_body_cb (http_parser *p, const char *buf, size_t len)
  1857. {
  1858. if (p || buf || len) { } // gcc
  1859. fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n");
  1860. abort();
  1861. }
  1862. int
  1863. dontcall_headers_complete_cb (http_parser *p)
  1864. {
  1865. if (p) { } // gcc
  1866. fprintf(stderr, "\n\n*** on_headers_complete() called on paused "
  1867. "parser ***\n\n");
  1868. abort();
  1869. }
  1870. int
  1871. dontcall_message_complete_cb (http_parser *p)
  1872. {
  1873. if (p) { } // gcc
  1874. fprintf(stderr, "\n\n*** on_message_complete() called on paused "
  1875. "parser ***\n\n");
  1876. abort();
  1877. }
  1878. int
  1879. dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
  1880. {
  1881. if (p || buf || len) { } // gcc
  1882. fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n");
  1883. abort();
  1884. }
  1885. int
  1886. dontcall_chunk_header_cb (http_parser *p)
  1887. {
  1888. if (p) { } // gcc
  1889. fprintf(stderr, "\n\n*** on_chunk_header() called on paused parser ***\n\n");
  1890. exit(1);
  1891. }
  1892. int
  1893. dontcall_chunk_complete_cb (http_parser *p)
  1894. {
  1895. if (p) { } // gcc
  1896. fprintf(stderr, "\n\n*** on_chunk_complete() "
  1897. "called on paused parser ***\n\n");
  1898. exit(1);
  1899. }
  1900. static http_parser_settings settings_dontcall =
  1901. {.on_message_begin = dontcall_message_begin_cb
  1902. ,.on_header_field = dontcall_header_field_cb
  1903. ,.on_header_value = dontcall_header_value_cb
  1904. ,.on_url = dontcall_request_url_cb
  1905. ,.on_status = dontcall_response_status_cb
  1906. ,.on_body = dontcall_body_cb
  1907. ,.on_headers_complete = dontcall_headers_complete_cb
  1908. ,.on_message_complete = dontcall_message_complete_cb
  1909. ,.on_chunk_header = dontcall_chunk_header_cb
  1910. ,.on_chunk_complete = dontcall_chunk_complete_cb
  1911. };
  1912. /* These pause_* callbacks always pause the parser and just invoke the regular
  1913. * callback that tracks content. Before returning, we overwrite the parser
  1914. * settings to point to the _dontcall variety so that we can verify that
  1915. * the pause actually did, you know, pause. */
  1916. int
  1917. pause_message_begin_cb (http_parser *p)
  1918. {
  1919. http_parser_pause(p, 1);
  1920. *current_pause_parser = settings_dontcall;
  1921. return message_begin_cb(p);
  1922. }
  1923. int
  1924. pause_header_field_cb (http_parser *p, const char *buf, size_t len)
  1925. {
  1926. http_parser_pause(p, 1);
  1927. *current_pause_parser = settings_dontcall;
  1928. return header_field_cb(p, buf, len);
  1929. }
  1930. int
  1931. pause_header_value_cb (http_parser *p, const char *buf, size_t len)
  1932. {
  1933. http_parser_pause(p, 1);
  1934. *current_pause_parser = settings_dontcall;
  1935. return header_value_cb(p, buf, len);
  1936. }
  1937. int
  1938. pause_request_url_cb (http_parser *p, const char *buf, size_t len)
  1939. {
  1940. http_parser_pause(p, 1);
  1941. *current_pause_parser = settings_dontcall;
  1942. return request_url_cb(p, buf, len);
  1943. }
  1944. int
  1945. pause_body_cb (http_parser *p, const char *buf, size_t len)
  1946. {
  1947. http_parser_pause(p, 1);
  1948. *current_pause_parser = settings_dontcall;
  1949. return body_cb(p, buf, len);
  1950. }
  1951. int
  1952. pause_headers_complete_cb (http_parser *p)
  1953. {
  1954. http_parser_pause(p, 1);
  1955. *current_pause_parser = settings_dontcall;
  1956. return headers_complete_cb(p);
  1957. }
  1958. int
  1959. pause_message_complete_cb (http_parser *p)
  1960. {
  1961. http_parser_pause(p, 1);
  1962. *current_pause_parser = settings_dontcall;
  1963. return message_complete_cb(p);
  1964. }
  1965. int
  1966. pause_response_status_cb (http_parser *p, const char *buf, size_t len)
  1967. {
  1968. http_parser_pause(p, 1);
  1969. *current_pause_parser = settings_dontcall;
  1970. return response_status_cb(p, buf, len);
  1971. }
  1972. int
  1973. pause_chunk_header_cb (http_parser *p)
  1974. {
  1975. http_parser_pause(p, 1);
  1976. *current_pause_parser = settings_dontcall;
  1977. return chunk_header_cb(p);
  1978. }
  1979. int
  1980. pause_chunk_complete_cb (http_parser *p)
  1981. {
  1982. http_parser_pause(p, 1);
  1983. *current_pause_parser = settings_dontcall;
  1984. return chunk_complete_cb(p);
  1985. }
  1986. static http_parser_settings settings_pause =
  1987. {.on_message_begin = pause_message_begin_cb
  1988. ,.on_header_field = pause_header_field_cb
  1989. ,.on_header_value = pause_header_value_cb
  1990. ,.on_url = pause_request_url_cb
  1991. ,.on_status = pause_response_status_cb
  1992. ,.on_body = pause_body_cb
  1993. ,.on_headers_complete = pause_headers_complete_cb
  1994. ,.on_message_complete = pause_message_complete_cb
  1995. ,.on_chunk_header = pause_chunk_header_cb
  1996. ,.on_chunk_complete = pause_chunk_complete_cb
  1997. };
  1998. static http_parser_settings settings =
  1999. {.on_message_begin = message_begin_cb
  2000. ,.on_header_field = header_field_cb
  2001. ,.on_header_value = header_value_cb
  2002. ,.on_url = request_url_cb
  2003. ,.on_status = response_status_cb
  2004. ,.on_body = body_cb
  2005. ,.on_headers_complete = headers_complete_cb
  2006. ,.on_message_complete = message_complete_cb
  2007. ,.on_chunk_header = chunk_header_cb
  2008. ,.on_chunk_complete = chunk_complete_cb
  2009. };
  2010. static http_parser_settings settings_count_body =
  2011. {.on_message_begin = message_begin_cb
  2012. ,.on_header_field = header_field_cb
  2013. ,.on_header_value = header_value_cb
  2014. ,.on_url = request_url_cb
  2015. ,.on_status = response_status_cb
  2016. ,.on_body = count_body_cb
  2017. ,.on_headers_complete = headers_complete_cb
  2018. ,.on_message_complete = message_complete_cb
  2019. ,.on_chunk_header = chunk_header_cb
  2020. ,.on_chunk_complete = chunk_complete_cb
  2021. };
  2022. static http_parser_settings settings_null =
  2023. {.on_message_begin = 0
  2024. ,.on_header_field = 0
  2025. ,.on_header_value = 0
  2026. ,.on_url = 0
  2027. ,.on_status = 0
  2028. ,.on_body = 0
  2029. ,.on_headers_complete = 0
  2030. ,.on_message_complete = 0
  2031. ,.on_chunk_header = 0
  2032. ,.on_chunk_complete = 0
  2033. };
  2034. void
  2035. parser_init (enum http_parser_type type)
  2036. {
  2037. num_messages = 0;
  2038. assert(parser == NULL);
  2039. parser = malloc(sizeof(http_parser));
  2040. http_parser_init(parser, type);
  2041. memset(&messages, 0, sizeof messages);
  2042. }
  2043. void
  2044. parser_free ()
  2045. {
  2046. assert(parser);
  2047. free(parser);
  2048. parser = NULL;
  2049. }
  2050. size_t parse (const char *buf, size_t len)
  2051. {
  2052. size_t nparsed;
  2053. currently_parsing_eof = (len == 0);
  2054. nparsed = http_parser_execute(parser, &settings, buf, len);
  2055. return nparsed;
  2056. }
  2057. size_t parse_count_body (const char *buf, size_t len)
  2058. {
  2059. size_t nparsed;
  2060. currently_parsing_eof = (len == 0);
  2061. nparsed = http_parser_execute(parser, &settings_count_body, buf, len);
  2062. return nparsed;
  2063. }
  2064. size_t parse_pause (const char *buf, size_t len)
  2065. {
  2066. size_t nparsed;
  2067. http_parser_settings s = settings_pause;
  2068. currently_parsing_eof = (len == 0);
  2069. current_pause_parser = &s;
  2070. nparsed = http_parser_execute(parser, current_pause_parser, buf, len);
  2071. return nparsed;
  2072. }
  2073. static inline int
  2074. check_str_eq (const struct message *m,
  2075. const char *prop,
  2076. const char *expected,
  2077. const char *found) {
  2078. if ((expected == NULL) != (found == NULL)) {
  2079. printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
  2080. printf("expected %s\n", (expected == NULL) ? "NULL" : expected);
  2081. printf(" found %s\n", (found == NULL) ? "NULL" : found);
  2082. return 0;
  2083. }
  2084. if (expected != NULL && 0 != strcmp(expected, found)) {
  2085. printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
  2086. printf("expected '%s'\n", expected);
  2087. printf(" found '%s'\n", found);
  2088. return 0;
  2089. }
  2090. return 1;
  2091. }
  2092. static inline int
  2093. check_num_eq (const struct message *m,
  2094. const char *prop,
  2095. int expected,
  2096. int found) {
  2097. if (expected != found) {
  2098. printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
  2099. printf("expected %d\n", expected);
  2100. printf(" found %d\n", found);
  2101. return 0;
  2102. }
  2103. return 1;
  2104. }
  2105. #define MESSAGE_CHECK_STR_EQ(expected, found, prop) \
  2106. if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0
  2107. #define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \
  2108. if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0
  2109. #define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \
  2110. do { \
  2111. char ubuf[256]; \
  2112. \
  2113. if ((u)->field_set & (1 << (fn))) { \
  2114. memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \
  2115. (u)->field_data[(fn)].len); \
  2116. ubuf[(u)->field_data[(fn)].len] = '\0'; \
  2117. } else { \
  2118. ubuf[0] = '\0'; \
  2119. } \
  2120. \
  2121. check_str_eq(expected, #prop, expected->prop, ubuf); \
  2122. } while(0)
  2123. int
  2124. message_eq (int index, const struct message *expected)
  2125. {
  2126. int i;
  2127. struct message *m = &messages[index];
  2128. MESSAGE_CHECK_NUM_EQ(expected, m, http_major);
  2129. MESSAGE_CHECK_NUM_EQ(expected, m, http_minor);
  2130. if (expected->type == HTTP_REQUEST) {
  2131. MESSAGE_CHECK_NUM_EQ(expected, m, method);
  2132. } else {
  2133. MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
  2134. MESSAGE_CHECK_STR_EQ(expected, m, response_status);
  2135. }
  2136. MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
  2137. MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof);
  2138. assert(m->message_begin_cb_called);
  2139. assert(m->headers_complete_cb_called);
  2140. assert(m->message_complete_cb_called);
  2141. MESSAGE_CHECK_STR_EQ(expected, m, request_url);
  2142. /* Check URL components; we can't do this w/ CONNECT since it doesn't
  2143. * send us a well-formed URL.
  2144. */
  2145. if (*m->request_url && m->method != HTTP_CONNECT) {
  2146. struct http_parser_url u;
  2147. if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) {
  2148. fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n",
  2149. m->request_url);
  2150. abort();
  2151. }
  2152. if (expected->host) {
  2153. MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST);
  2154. }
  2155. if (expected->userinfo) {
  2156. MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO);
  2157. }
  2158. m->port = (u.field_set & (1 << UF_PORT)) ?
  2159. u.port : 0;
  2160. MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY);
  2161. MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT);
  2162. MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH);
  2163. MESSAGE_CHECK_NUM_EQ(expected, m, port);
  2164. }
  2165. if (expected->body_size) {
  2166. MESSAGE_CHECK_NUM_EQ(expected, m, body_size);
  2167. } else {
  2168. MESSAGE_CHECK_STR_EQ(expected, m, body);
  2169. }
  2170. assert(m->num_chunks == m->num_chunks_complete);
  2171. MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete);
  2172. for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) {
  2173. MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]);
  2174. }
  2175. MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
  2176. int r;
  2177. for (i = 0; i < m->num_headers; i++) {
  2178. r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]);
  2179. if (!r) return 0;
  2180. r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]);
  2181. if (!r) return 0;
  2182. }
  2183. MESSAGE_CHECK_STR_EQ(expected, m, upgrade);
  2184. return 1;
  2185. }
  2186. /* Given a sequence of varargs messages, return the number of them that the
  2187. * parser should successfully parse, taking into account that upgraded
  2188. * messages prevent all subsequent messages from being parsed.
  2189. */
  2190. size_t
  2191. count_parsed_messages(const size_t nmsgs, ...) {
  2192. size_t i;
  2193. va_list ap;
  2194. va_start(ap, nmsgs);
  2195. for (i = 0; i < nmsgs; i++) {
  2196. struct message *m = va_arg(ap, struct message *);
  2197. if (m->upgrade) {
  2198. va_end(ap);
  2199. return i + 1;
  2200. }
  2201. }
  2202. va_end(ap);
  2203. return nmsgs;
  2204. }
  2205. /* Given a sequence of bytes and the number of these that we were able to
  2206. * parse, verify that upgrade bodies are correct.
  2207. */
  2208. void
  2209. upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
  2210. va_list ap;
  2211. size_t i;
  2212. size_t off = 0;
  2213. va_start(ap, nmsgs);
  2214. for (i = 0; i < nmsgs; i++) {
  2215. struct message *m = va_arg(ap, struct message *);
  2216. off += strlen(m->raw);
  2217. if (m->upgrade) {
  2218. off -= strlen(m->upgrade);
  2219. /* Check the portion of the response after its specified upgrade */
  2220. if (!check_str_eq(m, "upgrade", body + off, body + nread)) {
  2221. abort();
  2222. }
  2223. /* Fix up the response so that message_eq() will verify the beginning
  2224. * of the upgrade */
  2225. *(body + nread + strlen(m->upgrade)) = '\0';
  2226. messages[num_messages -1 ].upgrade = body + nread;
  2227. va_end(ap);
  2228. return;
  2229. }
  2230. }
  2231. va_end(ap);
  2232. printf("\n\n*** Error: expected a message with upgrade ***\n");
  2233. abort();
  2234. }
  2235. static void
  2236. print_error (const char *raw, size_t error_location)
  2237. {
  2238. fprintf(stderr, "\n*** %s ***\n\n",
  2239. http_errno_description(HTTP_PARSER_ERRNO(parser)));
  2240. int this_line = 0, char_len = 0;
  2241. size_t i, j, len = strlen(raw), error_location_line = 0;
  2242. for (i = 0; i < len; i++) {
  2243. if (i == error_location) this_line = 1;
  2244. switch (raw[i]) {
  2245. case '\r':
  2246. char_len = 2;
  2247. fprintf(stderr, "\\r");
  2248. break;
  2249. case '\n':
  2250. fprintf(stderr, "\\n\n");
  2251. if (this_line) goto print;
  2252. error_location_line = 0;
  2253. continue;
  2254. default:
  2255. char_len = 1;
  2256. fputc(raw[i], stderr);
  2257. break;
  2258. }
  2259. if (!this_line) error_location_line += char_len;
  2260. }
  2261. fprintf(stderr, "[eof]\n");
  2262. print:
  2263. for (j = 0; j < error_location_line; j++) {
  2264. fputc(' ', stderr);
  2265. }
  2266. fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location);
  2267. }
  2268. void
  2269. test_preserve_data (void)
  2270. {
  2271. char my_data[] = "application-specific data";
  2272. http_parser parser;
  2273. parser.data = my_data;
  2274. http_parser_init(&parser, HTTP_REQUEST);
  2275. if (parser.data != my_data) {
  2276. printf("\n*** parser.data not preserved accross http_parser_init ***\n\n");
  2277. abort();
  2278. }
  2279. }
  2280. struct url_test {
  2281. const char *name;
  2282. const char *url;
  2283. int is_connect;
  2284. struct http_parser_url u;
  2285. int rv;
  2286. };
  2287. const struct url_test url_tests[] =
  2288. { {.name="proxy request"
  2289. ,.url="http://hostname/"
  2290. ,.is_connect=0
  2291. ,.u=
  2292. {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
  2293. ,.port=0
  2294. ,.field_data=
  2295. {{ 0, 4 } /* UF_SCHEMA */
  2296. ,{ 7, 8 } /* UF_HOST */
  2297. ,{ 0, 0 } /* UF_PORT */
  2298. ,{ 15, 1 } /* UF_PATH */
  2299. ,{ 0, 0 } /* UF_QUERY */
  2300. ,{ 0, 0 } /* UF_FRAGMENT */
  2301. ,{ 0, 0 } /* UF_USERINFO */
  2302. }
  2303. }
  2304. ,.rv=0
  2305. }
  2306. , {.name="proxy request with port"
  2307. ,.url="http://hostname:444/"
  2308. ,.is_connect=0
  2309. ,.u=
  2310. {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
  2311. ,.port=444
  2312. ,.field_data=
  2313. {{ 0, 4 } /* UF_SCHEMA */
  2314. ,{ 7, 8 } /* UF_HOST */
  2315. ,{ 16, 3 } /* UF_PORT */
  2316. ,{ 19, 1 } /* UF_PATH */
  2317. ,{ 0, 0 } /* UF_QUERY */
  2318. ,{ 0, 0 } /* UF_FRAGMENT */
  2319. ,{ 0, 0 } /* UF_USERINFO */
  2320. }
  2321. }
  2322. ,.rv=0
  2323. }
  2324. , {.name="CONNECT request"
  2325. ,.url="hostname:443"
  2326. ,.is_connect=1
  2327. ,.u=
  2328. {.field_set=(1 << UF_HOST) | (1 << UF_PORT)
  2329. ,.port=443
  2330. ,.field_data=
  2331. {{ 0, 0 } /* UF_SCHEMA */
  2332. ,{ 0, 8 } /* UF_HOST */
  2333. ,{ 9, 3 } /* UF_PORT */
  2334. ,{ 0, 0 } /* UF_PATH */
  2335. ,{ 0, 0 } /* UF_QUERY */
  2336. ,{ 0, 0 } /* UF_FRAGMENT */
  2337. ,{ 0, 0 } /* UF_USERINFO */
  2338. }
  2339. }
  2340. ,.rv=0
  2341. }
  2342. , {.name="CONNECT request but not connect"
  2343. ,.url="hostname:443"
  2344. ,.is_connect=0
  2345. ,.rv=1
  2346. }
  2347. , {.name="proxy ipv6 request"
  2348. ,.url="http://[1:2::3:4]/"
  2349. ,.is_connect=0
  2350. ,.u=
  2351. {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
  2352. ,.port=0
  2353. ,.field_data=
  2354. {{ 0, 4 } /* UF_SCHEMA */
  2355. ,{ 8, 8 } /* UF_HOST */
  2356. ,{ 0, 0 } /* UF_PORT */
  2357. ,{ 17, 1 } /* UF_PATH */
  2358. ,{ 0, 0 } /* UF_QUERY */
  2359. ,{ 0, 0 } /* UF_FRAGMENT */
  2360. ,{ 0, 0 } /* UF_USERINFO */
  2361. }
  2362. }
  2363. ,.rv=0
  2364. }
  2365. , {.name="proxy ipv6 request with port"
  2366. ,.url="http://[1:2::3:4]:67/"
  2367. ,.is_connect=0
  2368. ,.u=
  2369. {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
  2370. ,.port=67
  2371. ,.field_data=
  2372. {{ 0, 4 } /* UF_SCHEMA */
  2373. ,{ 8, 8 } /* UF_HOST */
  2374. ,{ 18, 2 } /* UF_PORT */
  2375. ,{ 20, 1 } /* UF_PATH */
  2376. ,{ 0, 0 } /* UF_QUERY */
  2377. ,{ 0, 0 } /* UF_FRAGMENT */
  2378. ,{ 0, 0 } /* UF_USERINFO */
  2379. }
  2380. }
  2381. ,.rv=0
  2382. }
  2383. , {.name="CONNECT ipv6 address"
  2384. ,.url="[1:2::3:4]:443"
  2385. ,.is_connect=1
  2386. ,.u=
  2387. {.field_set=(1 << UF_HOST) | (1 << UF_PORT)
  2388. ,.port=443
  2389. ,.field_data=
  2390. {{ 0, 0 } /* UF_SCHEMA */
  2391. ,{ 1, 8 } /* UF_HOST */
  2392. ,{ 11, 3 } /* UF_PORT */
  2393. ,{ 0, 0 } /* UF_PATH */
  2394. ,{ 0, 0 } /* UF_QUERY */
  2395. ,{ 0, 0 } /* UF_FRAGMENT */
  2396. ,{ 0, 0 } /* UF_USERINFO */
  2397. }
  2398. }
  2399. ,.rv=0
  2400. }
  2401. , {.name="ipv4 in ipv6 address"
  2402. ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/"
  2403. ,.is_connect=0
  2404. ,.u=
  2405. {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
  2406. ,.port=0
  2407. ,.field_data=
  2408. {{ 0, 4 } /* UF_SCHEMA */
  2409. ,{ 8, 37 } /* UF_HOST */
  2410. ,{ 0, 0 } /* UF_PORT */
  2411. ,{ 46, 1 } /* UF_PATH */
  2412. ,{ 0, 0 } /* UF_QUERY */
  2413. ,{ 0, 0 } /* UF_FRAGMENT */
  2414. ,{ 0, 0 } /* UF_USERINFO */
  2415. }
  2416. }
  2417. ,.rv=0
  2418. }
  2419. , {.name="extra ? in query string"
  2420. ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,"
  2421. "fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,"
  2422. "fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css"
  2423. ,.is_connect=0
  2424. ,.u=
  2425. {.field_set=(1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY)
  2426. ,.port=0
  2427. ,.field_data=
  2428. {{ 0, 4 } /* UF_SCHEMA */
  2429. ,{ 7, 10 } /* UF_HOST */
  2430. ,{ 0, 0 } /* UF_PORT */
  2431. ,{ 17, 12 } /* UF_PATH */
  2432. ,{ 30,187 } /* UF_QUERY */
  2433. ,{ 0, 0 } /* UF_FRAGMENT */
  2434. ,{ 0, 0 } /* UF_USERINFO */
  2435. }
  2436. }
  2437. ,.rv=0
  2438. }
  2439. , {.name="space URL encoded"
  2440. ,.url="/toto.html?toto=a%20b"
  2441. ,.is_connect=0
  2442. ,.u=
  2443. {.field_set= (1<<UF_PATH) | (1<<UF_QUERY)
  2444. ,.port=0
  2445. ,.field_data=
  2446. {{ 0, 0 } /* UF_SCHEMA */
  2447. ,{ 0, 0 } /* UF_HOST */
  2448. ,{ 0, 0 } /* UF_PORT */
  2449. ,{ 0, 10 } /* UF_PATH */
  2450. ,{ 11, 10 } /* UF_QUERY */
  2451. ,{ 0, 0 } /* UF_FRAGMENT */
  2452. ,{ 0, 0 } /* UF_USERINFO */
  2453. }
  2454. }
  2455. ,.rv=0
  2456. }
  2457. , {.name="URL fragment"
  2458. ,.url="/toto.html#titi"
  2459. ,.is_connect=0
  2460. ,.u=
  2461. {.field_set= (1<<UF_PATH) | (1<<UF_FRAGMENT)
  2462. ,.port=0
  2463. ,.field_data=
  2464. {{ 0, 0 } /* UF_SCHEMA */
  2465. ,{ 0, 0 } /* UF_HOST */
  2466. ,{ 0, 0 } /* UF_PORT */
  2467. ,{ 0, 10 } /* UF_PATH */
  2468. ,{ 0, 0 } /* UF_QUERY */
  2469. ,{ 11, 4 } /* UF_FRAGMENT */
  2470. ,{ 0, 0 } /* UF_USERINFO */
  2471. }
  2472. }
  2473. ,.rv=0
  2474. }
  2475. , {.name="complex URL fragment"
  2476. ,.url="http://www.webmasterworld.com/r.cgi?f=21&d=8405&url="
  2477. "http://www.example.com/index.html?foo=bar&hello=world#midpage"
  2478. ,.is_connect=0
  2479. ,.u=
  2480. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY) |\
  2481. (1<<UF_FRAGMENT)
  2482. ,.port=0
  2483. ,.field_data=
  2484. {{ 0, 4 } /* UF_SCHEMA */
  2485. ,{ 7, 22 } /* UF_HOST */
  2486. ,{ 0, 0 } /* UF_PORT */
  2487. ,{ 29, 6 } /* UF_PATH */
  2488. ,{ 36, 69 } /* UF_QUERY */
  2489. ,{106, 7 } /* UF_FRAGMENT */
  2490. ,{ 0, 0 } /* UF_USERINFO */
  2491. }
  2492. }
  2493. ,.rv=0
  2494. }
  2495. , {.name="complex URL from node js url parser doc"
  2496. ,.url="http://host.com:8080/p/a/t/h?query=string#hash"
  2497. ,.is_connect=0
  2498. ,.u=
  2499. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
  2500. (1<<UF_QUERY) | (1<<UF_FRAGMENT)
  2501. ,.port=8080
  2502. ,.field_data=
  2503. {{ 0, 4 } /* UF_SCHEMA */
  2504. ,{ 7, 8 } /* UF_HOST */
  2505. ,{ 16, 4 } /* UF_PORT */
  2506. ,{ 20, 8 } /* UF_PATH */
  2507. ,{ 29, 12 } /* UF_QUERY */
  2508. ,{ 42, 4 } /* UF_FRAGMENT */
  2509. ,{ 0, 0 } /* UF_USERINFO */
  2510. }
  2511. }
  2512. ,.rv=0
  2513. }
  2514. , {.name="complex URL with basic auth from node js url parser doc"
  2515. ,.url="http://a:b@host.com:8080/p/a/t/h?query=string#hash"
  2516. ,.is_connect=0
  2517. ,.u=
  2518. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
  2519. (1<<UF_QUERY) | (1<<UF_FRAGMENT) | (1<<UF_USERINFO)
  2520. ,.port=8080
  2521. ,.field_data=
  2522. {{ 0, 4 } /* UF_SCHEMA */
  2523. ,{ 11, 8 } /* UF_HOST */
  2524. ,{ 20, 4 } /* UF_PORT */
  2525. ,{ 24, 8 } /* UF_PATH */
  2526. ,{ 33, 12 } /* UF_QUERY */
  2527. ,{ 46, 4 } /* UF_FRAGMENT */
  2528. ,{ 7, 3 } /* UF_USERINFO */
  2529. }
  2530. }
  2531. ,.rv=0
  2532. }
  2533. , {.name="double @"
  2534. ,.url="http://a:b@@hostname:443/"
  2535. ,.is_connect=0
  2536. ,.rv=1
  2537. }
  2538. , {.name="proxy empty host"
  2539. ,.url="http://:443/"
  2540. ,.is_connect=0
  2541. ,.rv=1
  2542. }
  2543. , {.name="proxy empty port"
  2544. ,.url="http://hostname:/"
  2545. ,.is_connect=0
  2546. ,.rv=1
  2547. }
  2548. , {.name="CONNECT with basic auth"
  2549. ,.url="a:b@hostname:443"
  2550. ,.is_connect=1
  2551. ,.rv=1
  2552. }
  2553. , {.name="CONNECT empty host"
  2554. ,.url=":443"
  2555. ,.is_connect=1
  2556. ,.rv=1
  2557. }
  2558. , {.name="CONNECT empty port"
  2559. ,.url="hostname:"
  2560. ,.is_connect=1
  2561. ,.rv=1
  2562. }
  2563. , {.name="CONNECT with extra bits"
  2564. ,.url="hostname:443/"
  2565. ,.is_connect=1
  2566. ,.rv=1
  2567. }
  2568. , {.name="space in URL"
  2569. ,.url="/foo bar/"
  2570. ,.rv=1 /* s_dead */
  2571. }
  2572. , {.name="proxy basic auth with space url encoded"
  2573. ,.url="http://a%20:b@host.com/"
  2574. ,.is_connect=0
  2575. ,.u=
  2576. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
  2577. ,.port=0
  2578. ,.field_data=
  2579. {{ 0, 4 } /* UF_SCHEMA */
  2580. ,{ 14, 8 } /* UF_HOST */
  2581. ,{ 0, 0 } /* UF_PORT */
  2582. ,{ 22, 1 } /* UF_PATH */
  2583. ,{ 0, 0 } /* UF_QUERY */
  2584. ,{ 0, 0 } /* UF_FRAGMENT */
  2585. ,{ 7, 6 } /* UF_USERINFO */
  2586. }
  2587. }
  2588. ,.rv=0
  2589. }
  2590. , {.name="carriage return in URL"
  2591. ,.url="/foo\rbar/"
  2592. ,.rv=1 /* s_dead */
  2593. }
  2594. , {.name="proxy double : in URL"
  2595. ,.url="http://hostname::443/"
  2596. ,.rv=1 /* s_dead */
  2597. }
  2598. , {.name="proxy basic auth with double :"
  2599. ,.url="http://a::b@host.com/"
  2600. ,.is_connect=0
  2601. ,.u=
  2602. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
  2603. ,.port=0
  2604. ,.field_data=
  2605. {{ 0, 4 } /* UF_SCHEMA */
  2606. ,{ 12, 8 } /* UF_HOST */
  2607. ,{ 0, 0 } /* UF_PORT */
  2608. ,{ 20, 1 } /* UF_PATH */
  2609. ,{ 0, 0 } /* UF_QUERY */
  2610. ,{ 0, 0 } /* UF_FRAGMENT */
  2611. ,{ 7, 4 } /* UF_USERINFO */
  2612. }
  2613. }
  2614. ,.rv=0
  2615. }
  2616. , {.name="line feed in URL"
  2617. ,.url="/foo\nbar/"
  2618. ,.rv=1 /* s_dead */
  2619. }
  2620. , {.name="proxy empty basic auth"
  2621. ,.url="http://@hostname/fo"
  2622. ,.u=
  2623. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
  2624. ,.port=0
  2625. ,.field_data=
  2626. {{ 0, 4 } /* UF_SCHEMA */
  2627. ,{ 8, 8 } /* UF_HOST */
  2628. ,{ 0, 0 } /* UF_PORT */
  2629. ,{ 16, 3 } /* UF_PATH */
  2630. ,{ 0, 0 } /* UF_QUERY */
  2631. ,{ 0, 0 } /* UF_FRAGMENT */
  2632. ,{ 0, 0 } /* UF_USERINFO */
  2633. }
  2634. }
  2635. ,.rv=0
  2636. }
  2637. , {.name="proxy line feed in hostname"
  2638. ,.url="http://host\name/fo"
  2639. ,.rv=1 /* s_dead */
  2640. }
  2641. , {.name="proxy % in hostname"
  2642. ,.url="http://host%name/fo"
  2643. ,.rv=1 /* s_dead */
  2644. }
  2645. , {.name="proxy ; in hostname"
  2646. ,.url="http://host;ame/fo"
  2647. ,.rv=1 /* s_dead */
  2648. }
  2649. , {.name="proxy basic auth with unreservedchars"
  2650. ,.url="http://a!;-_!=+$@host.com/"
  2651. ,.is_connect=0
  2652. ,.u=
  2653. {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
  2654. ,.port=0
  2655. ,.field_data=
  2656. {{ 0, 4 } /* UF_SCHEMA */
  2657. ,{ 17, 8 } /* UF_HOST */
  2658. ,{ 0, 0 } /* UF_PORT */
  2659. ,{ 25, 1 } /* UF_PATH */
  2660. ,{ 0, 0 } /* UF_QUERY */
  2661. ,{ 0, 0 } /* UF_FRAGMENT */
  2662. ,{ 7, 9 } /* UF_USERINFO */
  2663. }
  2664. }
  2665. ,.rv=0
  2666. }
  2667. , {.name="proxy only empty basic auth"
  2668. ,.url="http://@/fo"
  2669. ,.rv=1 /* s_dead */
  2670. }
  2671. , {.name="proxy only basic auth"
  2672. ,.url="http://toto@/fo"
  2673. ,.rv=1 /* s_dead */
  2674. }
  2675. , {.name="proxy emtpy hostname"
  2676. ,.url="http:///fo"
  2677. ,.rv=1 /* s_dead */
  2678. }
  2679. , {.name="proxy = in URL"
  2680. ,.url="http://host=ame/fo"
  2681. ,.rv=1 /* s_dead */
  2682. }
  2683. #if HTTP_PARSER_STRICT
  2684. , {.name="tab in URL"
  2685. ,.url="/foo\tbar/"
  2686. ,.rv=1 /* s_dead */
  2687. }
  2688. , {.name="form feed in URL"
  2689. ,.url="/foo\fbar/"
  2690. ,.rv=1 /* s_dead */
  2691. }
  2692. #else /* !HTTP_PARSER_STRICT */
  2693. , {.name="tab in URL"
  2694. ,.url="/foo\tbar/"
  2695. ,.u=
  2696. {.field_set=(1 << UF_PATH)
  2697. ,.field_data=
  2698. {{ 0, 0 } /* UF_SCHEMA */
  2699. ,{ 0, 0 } /* UF_HOST */
  2700. ,{ 0, 0 } /* UF_PORT */
  2701. ,{ 0, 9 } /* UF_PATH */
  2702. ,{ 0, 0 } /* UF_QUERY */
  2703. ,{ 0, 0 } /* UF_FRAGMENT */
  2704. ,{ 0, 0 } /* UF_USERINFO */
  2705. }
  2706. }
  2707. ,.rv=0
  2708. }
  2709. , {.name="form feed in URL"
  2710. ,.url="/foo\fbar/"
  2711. ,.u=
  2712. {.field_set=(1 << UF_PATH)
  2713. ,.field_data=
  2714. {{ 0, 0 } /* UF_SCHEMA */
  2715. ,{ 0, 0 } /* UF_HOST */
  2716. ,{ 0, 0 } /* UF_PORT */
  2717. ,{ 0, 9 } /* UF_PATH */
  2718. ,{ 0, 0 } /* UF_QUERY */
  2719. ,{ 0, 0 } /* UF_FRAGMENT */
  2720. ,{ 0, 0 } /* UF_USERINFO */
  2721. }
  2722. }
  2723. ,.rv=0
  2724. }
  2725. #endif
  2726. };
  2727. void
  2728. dump_url (const char *url, const struct http_parser_url *u)
  2729. {
  2730. unsigned int i;
  2731. printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
  2732. for (i = 0; i < UF_MAX; i++) {
  2733. if ((u->field_set & (1 << i)) == 0) {
  2734. printf("\tfield_data[%u]: unset\n", i);
  2735. continue;
  2736. }
  2737. printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",
  2738. i,
  2739. u->field_data[i].off,
  2740. u->field_data[i].len,
  2741. u->field_data[i].len,
  2742. url + u->field_data[i].off);
  2743. }
  2744. }
  2745. void
  2746. test_parse_url (void)
  2747. {
  2748. struct http_parser_url u;
  2749. const struct url_test *test;
  2750. unsigned int i;
  2751. int rv;
  2752. for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) {
  2753. test = &url_tests[i];
  2754. memset(&u, 0, sizeof(u));
  2755. rv = http_parser_parse_url(test->url,
  2756. strlen(test->url),
  2757. test->is_connect,
  2758. &u);
  2759. if (test->rv == 0) {
  2760. if (rv != 0) {
  2761. printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
  2762. "unexpected rv %d ***\n\n", test->url, test->name, rv);
  2763. abort();
  2764. }
  2765. if (memcmp(&u, &test->u, sizeof(u)) != 0) {
  2766. printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n",
  2767. test->url, test->name);
  2768. printf("target http_parser_url:\n");
  2769. dump_url(test->url, &test->u);
  2770. printf("result http_parser_url:\n");
  2771. dump_url(test->url, &u);
  2772. abort();
  2773. }
  2774. } else {
  2775. /* test->rv != 0 */
  2776. if (rv == 0) {
  2777. printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
  2778. "unexpected rv %d ***\n\n", test->url, test->name, rv);
  2779. abort();
  2780. }
  2781. }
  2782. }
  2783. }
  2784. void
  2785. test_method_str (void)
  2786. {
  2787. assert(0 == strcmp("GET", http_method_str(HTTP_GET)));
  2788. assert(0 == strcmp("<unknown>", http_method_str(1337)));
  2789. }
  2790. void
  2791. test_message (const struct message *message)
  2792. {
  2793. size_t raw_len = strlen(message->raw);
  2794. size_t msg1len;
  2795. for (msg1len = 0; msg1len < raw_len; msg1len++) {
  2796. parser_init(message->type);
  2797. size_t read;
  2798. const char *msg1 = message->raw;
  2799. const char *msg2 = msg1 + msg1len;
  2800. size_t msg2len = raw_len - msg1len;
  2801. if (msg1len) {
  2802. read = parse(msg1, msg1len);
  2803. if (message->upgrade && parser->upgrade && num_messages > 0) {
  2804. messages[num_messages - 1].upgrade = msg1 + read;
  2805. goto test;
  2806. }
  2807. if (read != msg1len) {
  2808. print_error(msg1, read);
  2809. abort();
  2810. }
  2811. }
  2812. read = parse(msg2, msg2len);
  2813. if (message->upgrade && parser->upgrade) {
  2814. messages[num_messages - 1].upgrade = msg2 + read;
  2815. goto test;
  2816. }
  2817. if (read != msg2len) {
  2818. print_error(msg2, read);
  2819. abort();
  2820. }
  2821. read = parse(NULL, 0);
  2822. if (read != 0) {
  2823. print_error(message->raw, read);
  2824. abort();
  2825. }
  2826. test:
  2827. if (num_messages != 1) {
  2828. printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
  2829. abort();
  2830. }
  2831. if(!message_eq(0, message)) abort();
  2832. parser_free();
  2833. }
  2834. }
  2835. void
  2836. test_message_count_body (const struct message *message)
  2837. {
  2838. parser_init(message->type);
  2839. size_t read;
  2840. size_t l = strlen(message->raw);
  2841. size_t i, toread;
  2842. size_t chunk = 4024;
  2843. for (i = 0; i < l; i+= chunk) {
  2844. toread = MIN(l-i, chunk);
  2845. read = parse_count_body(message->raw + i, toread);
  2846. if (read != toread) {
  2847. print_error(message->raw, read);
  2848. abort();
  2849. }
  2850. }
  2851. read = parse_count_body(NULL, 0);
  2852. if (read != 0) {
  2853. print_error(message->raw, read);
  2854. abort();
  2855. }
  2856. if (num_messages != 1) {
  2857. printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
  2858. abort();
  2859. }
  2860. if(!message_eq(0, message)) abort();
  2861. parser_free();
  2862. }
  2863. void
  2864. test_simple (const char *buf, enum http_errno err_expected)
  2865. {
  2866. parser_init(HTTP_REQUEST);
  2867. enum http_errno err;
  2868. parse(buf, strlen(buf));
  2869. err = HTTP_PARSER_ERRNO(parser);
  2870. parse(NULL, 0);
  2871. parser_free();
  2872. /* In strict mode, allow us to pass with an unexpected HPE_STRICT as
  2873. * long as the caller isn't expecting success.
  2874. */
  2875. #if HTTP_PARSER_STRICT
  2876. if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) {
  2877. #else
  2878. if (err_expected != err) {
  2879. #endif
  2880. fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n",
  2881. http_errno_name(err_expected), http_errno_name(err), buf);
  2882. abort();
  2883. }
  2884. }
  2885. void
  2886. test_header_overflow_error (int req)
  2887. {
  2888. http_parser parser;
  2889. http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
  2890. size_t parsed;
  2891. const char *buf;
  2892. buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n";
  2893. parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
  2894. assert(parsed == strlen(buf));
  2895. buf = "header-key: header-value\r\n";
  2896. size_t buflen = strlen(buf);
  2897. int i;
  2898. for (i = 0; i < 10000; i++) {
  2899. parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
  2900. if (parsed != buflen) {
  2901. //fprintf(stderr, "error found on iter %d\n", i);
  2902. assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW);
  2903. return;
  2904. }
  2905. }
  2906. fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");
  2907. abort();
  2908. }
  2909. void
  2910. test_header_nread_value ()
  2911. {
  2912. http_parser parser;
  2913. http_parser_init(&parser, HTTP_REQUEST);
  2914. size_t parsed;
  2915. const char *buf;
  2916. buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n";
  2917. parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
  2918. assert(parsed == strlen(buf));
  2919. assert(parser.nread == strlen(buf));
  2920. }
  2921. static void
  2922. test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
  2923. {
  2924. http_parser parser;
  2925. http_parser_init(&parser, HTTP_RESPONSE);
  2926. http_parser_execute(&parser, &settings_null, buf, buflen);
  2927. if (expect_ok)
  2928. assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK);
  2929. else
  2930. assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH);
  2931. }
  2932. void
  2933. test_header_content_length_overflow_error (void)
  2934. {
  2935. #define X(size) \
  2936. "HTTP/1.1 200 OK\r\n" \
  2937. "Content-Length: " #size "\r\n" \
  2938. "\r\n"
  2939. const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */
  2940. const char b[] = X(18446744073709551615); /* 2^64-1 */
  2941. const char c[] = X(18446744073709551616); /* 2^64 */
  2942. #undef X
  2943. test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
  2944. test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
  2945. test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
  2946. }
  2947. void
  2948. test_chunk_content_length_overflow_error (void)
  2949. {
  2950. #define X(size) \
  2951. "HTTP/1.1 200 OK\r\n" \
  2952. "Transfer-Encoding: chunked\r\n" \
  2953. "\r\n" \
  2954. #size "\r\n" \
  2955. "..."
  2956. const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */
  2957. const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */
  2958. const char c[] = X(10000000000000000); /* 2^64 */
  2959. #undef X
  2960. test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
  2961. test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
  2962. test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
  2963. }
  2964. void
  2965. test_no_overflow_long_body (int req, size_t length)
  2966. {
  2967. http_parser parser;
  2968. http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
  2969. size_t parsed;
  2970. size_t i;
  2971. char buf1[3000];
  2972. size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n",
  2973. req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length);
  2974. parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
  2975. if (parsed != buf1len)
  2976. goto err;
  2977. for (i = 0; i < length; i++) {
  2978. char foo = 'a';
  2979. parsed = http_parser_execute(&parser, &settings_null, &foo, 1);
  2980. if (parsed != 1)
  2981. goto err;
  2982. }
  2983. parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
  2984. if (parsed != buf1len) goto err;
  2985. return;
  2986. err:
  2987. fprintf(stderr,
  2988. "\n*** error in test_no_overflow_long_body %s of length %lu ***\n",
  2989. req ? "REQUEST" : "RESPONSE",
  2990. (unsigned long)length);
  2991. abort();
  2992. }
  2993. void
  2994. test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
  2995. {
  2996. int message_count = count_parsed_messages(3, r1, r2, r3);
  2997. char total[ strlen(r1->raw)
  2998. + strlen(r2->raw)
  2999. + strlen(r3->raw)
  3000. + 1
  3001. ];
  3002. total[0] = '\0';
  3003. strcat(total, r1->raw);
  3004. strcat(total, r2->raw);
  3005. strcat(total, r3->raw);
  3006. parser_init(r1->type);
  3007. size_t read;
  3008. read = parse(total, strlen(total));
  3009. if (parser->upgrade) {
  3010. upgrade_message_fix(total, read, 3, r1, r2, r3);
  3011. goto test;
  3012. }
  3013. if (read != strlen(total)) {
  3014. print_error(total, read);
  3015. abort();
  3016. }
  3017. read = parse(NULL, 0);
  3018. if (read != 0) {
  3019. print_error(total, read);
  3020. abort();
  3021. }
  3022. test:
  3023. if (message_count != num_messages) {
  3024. fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages);
  3025. abort();
  3026. }
  3027. if (!message_eq(0, r1)) abort();
  3028. if (message_count > 1 && !message_eq(1, r2)) abort();
  3029. if (message_count > 2 && !message_eq(2, r3)) abort();
  3030. parser_free();
  3031. }
  3032. /* SCAN through every possible breaking to make sure the
  3033. * parser can handle getting the content in any chunks that
  3034. * might come from the socket
  3035. */
  3036. void
  3037. test_scan (const struct message *r1, const struct message *r2, const struct message *r3)
  3038. {
  3039. char total[80*1024] = "\0";
  3040. char buf1[80*1024] = "\0";
  3041. char buf2[80*1024] = "\0";
  3042. char buf3[80*1024] = "\0";
  3043. strcat(total, r1->raw);
  3044. strcat(total, r2->raw);
  3045. strcat(total, r3->raw);
  3046. size_t read;
  3047. int total_len = strlen(total);
  3048. int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2;
  3049. int ops = 0 ;
  3050. size_t buf1_len, buf2_len, buf3_len;
  3051. int message_count = count_parsed_messages(3, r1, r2, r3);
  3052. int i,j,type_both;
  3053. for (type_both = 0; type_both < 2; type_both ++ ) {
  3054. for (j = 2; j < total_len; j ++ ) {
  3055. for (i = 1; i < j; i ++ ) {
  3056. if (ops % 1000 == 0) {
  3057. printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops);
  3058. fflush(stdout);
  3059. }
  3060. ops += 1;
  3061. parser_init(type_both ? HTTP_BOTH : r1->type);
  3062. buf1_len = i;
  3063. strlncpy(buf1, sizeof(buf1), total, buf1_len);
  3064. buf1[buf1_len] = 0;
  3065. buf2_len = j - i;
  3066. strlncpy(buf2, sizeof(buf1), total+i, buf2_len);
  3067. buf2[buf2_len] = 0;
  3068. buf3_len = total_len - j;
  3069. strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
  3070. buf3[buf3_len] = 0;
  3071. read = parse(buf1, buf1_len);
  3072. if (parser->upgrade) goto test;
  3073. if (read != buf1_len) {
  3074. print_error(buf1, read);
  3075. goto error;
  3076. }
  3077. read += parse(buf2, buf2_len);
  3078. if (parser->upgrade) goto test;
  3079. if (read != buf1_len + buf2_len) {
  3080. print_error(buf2, read);
  3081. goto error;
  3082. }
  3083. read += parse(buf3, buf3_len);
  3084. if (parser->upgrade) goto test;
  3085. if (read != buf1_len + buf2_len + buf3_len) {
  3086. print_error(buf3, read);
  3087. goto error;
  3088. }
  3089. parse(NULL, 0);
  3090. test:
  3091. if (parser->upgrade) {
  3092. upgrade_message_fix(total, read, 3, r1, r2, r3);
  3093. }
  3094. if (message_count != num_messages) {
  3095. fprintf(stderr, "\n\nParser didn't see %d messages only %d\n",
  3096. message_count, num_messages);
  3097. goto error;
  3098. }
  3099. if (!message_eq(0, r1)) {
  3100. fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n");
  3101. goto error;
  3102. }
  3103. if (message_count > 1 && !message_eq(1, r2)) {
  3104. fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");
  3105. goto error;
  3106. }
  3107. if (message_count > 2 && !message_eq(2, r3)) {
  3108. fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
  3109. goto error;
  3110. }
  3111. parser_free();
  3112. }
  3113. }
  3114. }
  3115. puts("\b\b\b\b100%");
  3116. return;
  3117. error:
  3118. fprintf(stderr, "i=%d j=%d\n", i, j);
  3119. fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1);
  3120. fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);
  3121. fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3);
  3122. abort();
  3123. }
  3124. // user required to free the result
  3125. // string terminated by \0
  3126. char *
  3127. create_large_chunked_message (int body_size_in_kb, const char* headers)
  3128. {
  3129. int i;
  3130. size_t wrote = 0;
  3131. size_t headers_len = strlen(headers);
  3132. size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6;
  3133. char * buf = malloc(bufsize);
  3134. memcpy(buf, headers, headers_len);
  3135. wrote += headers_len;
  3136. for (i = 0; i < body_size_in_kb; i++) {
  3137. // write 1kb chunk into the body.
  3138. memcpy(buf + wrote, "400\r\n", 5);
  3139. wrote += 5;
  3140. memset(buf + wrote, 'C', 1024);
  3141. wrote += 1024;
  3142. strcpy(buf + wrote, "\r\n");
  3143. wrote += 2;
  3144. }
  3145. memcpy(buf + wrote, "0\r\n\r\n", 6);
  3146. wrote += 6;
  3147. assert(wrote == bufsize);
  3148. return buf;
  3149. }
  3150. /* Verify that we can pause parsing at any of the bytes in the
  3151. * message and still get the result that we're expecting. */
  3152. void
  3153. test_message_pause (const struct message *msg)
  3154. {
  3155. char *buf = (char*) msg->raw;
  3156. size_t buflen = strlen(msg->raw);
  3157. size_t nread;
  3158. parser_init(msg->type);
  3159. do {
  3160. nread = parse_pause(buf, buflen);
  3161. // We can only set the upgrade buffer once we've gotten our message
  3162. // completion callback.
  3163. if (messages[0].message_complete_cb_called &&
  3164. msg->upgrade &&
  3165. parser->upgrade) {
  3166. messages[0].upgrade = buf + nread;
  3167. goto test;
  3168. }
  3169. if (nread < buflen) {
  3170. // Not much do to if we failed a strict-mode check
  3171. if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) {
  3172. parser_free();
  3173. return;
  3174. }
  3175. assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED);
  3176. }
  3177. buf += nread;
  3178. buflen -= nread;
  3179. http_parser_pause(parser, 0);
  3180. } while (buflen > 0);
  3181. nread = parse_pause(NULL, 0);
  3182. assert (nread == 0);
  3183. test:
  3184. if (num_messages != 1) {
  3185. printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
  3186. abort();
  3187. }
  3188. if(!message_eq(0, msg)) abort();
  3189. parser_free();
  3190. }
  3191. int
  3192. main (void)
  3193. {
  3194. parser = NULL;
  3195. int i, j, k;
  3196. int request_count;
  3197. int response_count;
  3198. unsigned long version;
  3199. unsigned major;
  3200. unsigned minor;
  3201. unsigned patch;
  3202. version = http_parser_version();
  3203. major = (version >> 16) & 255;
  3204. minor = (version >> 8) & 255;
  3205. patch = version & 255;
  3206. printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version);
  3207. printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
  3208. for (request_count = 0; requests[request_count].name; request_count++);
  3209. for (response_count = 0; responses[response_count].name; response_count++);
  3210. //// API
  3211. test_preserve_data();
  3212. test_parse_url();
  3213. test_method_str();
  3214. //// NREAD
  3215. test_header_nread_value();
  3216. //// OVERFLOW CONDITIONS
  3217. test_header_overflow_error(HTTP_REQUEST);
  3218. test_no_overflow_long_body(HTTP_REQUEST, 1000);
  3219. test_no_overflow_long_body(HTTP_REQUEST, 100000);
  3220. test_header_overflow_error(HTTP_RESPONSE);
  3221. test_no_overflow_long_body(HTTP_RESPONSE, 1000);
  3222. test_no_overflow_long_body(HTTP_RESPONSE, 100000);
  3223. test_header_content_length_overflow_error();
  3224. test_chunk_content_length_overflow_error();
  3225. //// RESPONSES
  3226. for (i = 0; i < response_count; i++) {
  3227. test_message(&responses[i]);
  3228. }
  3229. for (i = 0; i < response_count; i++) {
  3230. test_message_pause(&responses[i]);
  3231. }
  3232. for (i = 0; i < response_count; i++) {
  3233. if (!responses[i].should_keep_alive) continue;
  3234. for (j = 0; j < response_count; j++) {
  3235. if (!responses[j].should_keep_alive) continue;
  3236. for (k = 0; k < response_count; k++) {
  3237. test_multiple3(&responses[i], &responses[j], &responses[k]);
  3238. }
  3239. }
  3240. }
  3241. test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]);
  3242. test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]);
  3243. // test very large chunked response
  3244. {
  3245. char * msg = create_large_chunked_message(31337,
  3246. "HTTP/1.0 200 OK\r\n"
  3247. "Transfer-Encoding: chunked\r\n"
  3248. "Content-Type: text/plain\r\n"
  3249. "\r\n");
  3250. struct message large_chunked =
  3251. {.name= "large chunked"
  3252. ,.type= HTTP_RESPONSE
  3253. ,.raw= msg
  3254. ,.should_keep_alive= FALSE
  3255. ,.message_complete_on_eof= FALSE
  3256. ,.http_major= 1
  3257. ,.http_minor= 0
  3258. ,.status_code= 200
  3259. ,.response_status= "OK"
  3260. ,.num_headers= 2
  3261. ,.headers=
  3262. { { "Transfer-Encoding", "chunked" }
  3263. , { "Content-Type", "text/plain" }
  3264. }
  3265. ,.body_size= 31337*1024
  3266. ,.num_chunks_complete= 31338
  3267. };
  3268. for (i = 0; i < MAX_CHUNKS; i++) {
  3269. large_chunked.chunk_lengths[i] = 1024;
  3270. }
  3271. test_message_count_body(&large_chunked);
  3272. free(msg);
  3273. }
  3274. printf("response scan 1/2 ");
  3275. test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
  3276. , &responses[NO_BODY_HTTP10_KA_204]
  3277. , &responses[NO_REASON_PHRASE]
  3278. );
  3279. printf("response scan 2/2 ");
  3280. test_scan( &responses[BONJOUR_MADAME_FR]
  3281. , &responses[UNDERSTORE_HEADER_KEY]
  3282. , &responses[NO_CARRIAGE_RET]
  3283. );
  3284. puts("responses okay");
  3285. /// REQUESTS
  3286. test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
  3287. // Well-formed but incomplete
  3288. test_simple("GET / HTTP/1.1\r\n"
  3289. "Content-Type: text/plain\r\n"
  3290. "Content-Length: 6\r\n"
  3291. "\r\n"
  3292. "fooba",
  3293. HPE_OK);
  3294. static const char *all_methods[] = {
  3295. "DELETE",
  3296. "GET",
  3297. "HEAD",
  3298. "POST",
  3299. "PUT",
  3300. //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel
  3301. "OPTIONS",
  3302. "TRACE",
  3303. "COPY",
  3304. "LOCK",
  3305. "MKCOL",
  3306. "MOVE",
  3307. "PROPFIND",
  3308. "PROPPATCH",
  3309. "UNLOCK",
  3310. "REPORT",
  3311. "MKACTIVITY",
  3312. "CHECKOUT",
  3313. "MERGE",
  3314. "M-SEARCH",
  3315. "NOTIFY",
  3316. "SUBSCRIBE",
  3317. "UNSUBSCRIBE",
  3318. "PATCH",
  3319. 0 };
  3320. const char **this_method;
  3321. for (this_method = all_methods; *this_method; this_method++) {
  3322. char buf[200];
  3323. sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
  3324. test_simple(buf, HPE_OK);
  3325. }
  3326. static const char *bad_methods[] = {
  3327. "ASDF",
  3328. "C******",
  3329. "COLA",
  3330. "GEM",
  3331. "GETA",
  3332. "M****",
  3333. "MKCOLA",
  3334. "PROPPATCHA",
  3335. "PUN",
  3336. "PX",
  3337. "SA",
  3338. "hello world",
  3339. 0 };
  3340. for (this_method = bad_methods; *this_method; this_method++) {
  3341. char buf[200];
  3342. sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
  3343. test_simple(buf, HPE_INVALID_METHOD);
  3344. }
  3345. // illegal header field name line folding
  3346. test_simple("GET / HTTP/1.1\r\n"
  3347. "name\r\n"
  3348. " : value\r\n"
  3349. "\r\n",
  3350. HPE_INVALID_HEADER_TOKEN);
  3351. const char *dumbfuck2 =
  3352. "GET / HTTP/1.1\r\n"
  3353. "X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"
  3354. "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
  3355. "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
  3356. "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
  3357. "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n"
  3358. "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n"
  3359. "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n"
  3360. "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n"
  3361. "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n"
  3362. "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n"
  3363. "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n"
  3364. "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n"
  3365. "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n"
  3366. "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n"
  3367. "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n"
  3368. "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n"
  3369. "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n"
  3370. "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n"
  3371. "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n"
  3372. "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n"
  3373. "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n"
  3374. "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n"
  3375. "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n"
  3376. "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n"
  3377. "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n"
  3378. "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n"
  3379. "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n"
  3380. "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n"
  3381. "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n"
  3382. "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n"
  3383. "\tRA==\r\n"
  3384. "\t-----END CERTIFICATE-----\r\n"
  3385. "\r\n";
  3386. test_simple(dumbfuck2, HPE_OK);
  3387. const char *corrupted_connection =
  3388. "GET / HTTP/1.1\r\n"
  3389. "Host: www.example.com\r\n"
  3390. "Connection\r\033\065\325eep-Alive\r\n"
  3391. "Accept-Encoding: gzip\r\n"
  3392. "\r\n";
  3393. test_simple(corrupted_connection, HPE_INVALID_HEADER_TOKEN);
  3394. const char *corrupted_header_name =
  3395. "GET / HTTP/1.1\r\n"
  3396. "Host: www.example.com\r\n"
  3397. "X-Some-Header\r\033\065\325eep-Alive\r\n"
  3398. "Accept-Encoding: gzip\r\n"
  3399. "\r\n";
  3400. test_simple(corrupted_header_name, HPE_INVALID_HEADER_TOKEN);
  3401. #if 0
  3402. // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
  3403. // until EOF.
  3404. //
  3405. // no content-length
  3406. // error if there is a body without content length
  3407. const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n"
  3408. "Accept: */*\r\n"
  3409. "\r\n"
  3410. "HELLO";
  3411. test_simple(bad_get_no_headers_no_body, 0);
  3412. #endif
  3413. /* TODO sending junk and large headers gets rejected */
  3414. /* check to make sure our predefined requests are okay */
  3415. for (i = 0; requests[i].name; i++) {
  3416. test_message(&requests[i]);
  3417. }
  3418. for (i = 0; i < request_count; i++) {
  3419. test_message_pause(&requests[i]);
  3420. }
  3421. for (i = 0; i < request_count; i++) {
  3422. if (!requests[i].should_keep_alive) continue;
  3423. for (j = 0; j < request_count; j++) {
  3424. if (!requests[j].should_keep_alive) continue;
  3425. for (k = 0; k < request_count; k++) {
  3426. test_multiple3(&requests[i], &requests[j], &requests[k]);
  3427. }
  3428. }
  3429. }
  3430. printf("request scan 1/4 ");
  3431. test_scan( &requests[GET_NO_HEADERS_NO_BODY]
  3432. , &requests[GET_ONE_HEADER_NO_BODY]
  3433. , &requests[GET_NO_HEADERS_NO_BODY]
  3434. );
  3435. printf("request scan 2/4 ");
  3436. test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE]
  3437. , &requests[POST_IDENTITY_BODY_WORLD]
  3438. , &requests[GET_FUNKY_CONTENT_LENGTH]
  3439. );
  3440. printf("request scan 3/4 ");
  3441. test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
  3442. , &requests[CHUNKED_W_TRAILING_HEADERS]
  3443. , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
  3444. );
  3445. printf("request scan 4/4 ");
  3446. test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET]
  3447. , &requests[PREFIX_NEWLINE_GET ]
  3448. , &requests[CONNECT_REQUEST]
  3449. );
  3450. puts("requests okay");
  3451. return 0;
  3452. }