/* Ċ * ĠCopyright Ġ 2 0 1 4 - 2 0 2 1 ĠJetBrains Ġs . r . o Ġand Ġcontributors . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense . Ċ */ Ċ Ċ package Ġio . ktor . server . testing . client Ċ Ċ import Ġio . ktor . client . call .* Ċ import Ġio . ktor . client . engine .* Ċ import Ġio . ktor . client . request .* Ċ import Ġio . ktor . http .* Ċ import Ġio . ktor . http . content .* Ċ import Ġio . ktor . server . testing .* Ċ import Ġio . ktor . util .* Ċ import Ġio . ktor . util . date .* Ċ import Ġio . ktor . utils . io .* Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlin . coroutines .* Ċ Ċ @ Suppress (" K Doc Missing Documentation ") Ċ public Ġclass ĠTest HttpClient Engine ( override Ġval Ġconfig : ĠTest HttpClient Config ) Ġ: ĠHttpClient Engine Base (" ktor - test ") Ġ{ ĊĊĠĠĠ Ġoverride Ġval Ġdispatcher Ġ= ĠDispatch ers . IO ĊĊĠĠĠ Ġoverride Ġval Ġsupported Capabilities Ġ= Ġempty Set < HttpClient Engine Capability <* >>() ĊĊĠĠĠ Ġprivate Ġval Ġapp : ĠTest Application Engine Ġ= Ġconfig . app ĊĊĠĠĠ Ġprivate Ġval Ġclient Job : ĠComp letable Job Ġ= ĠJob ( app . coroutine Context [ Job ]) ĊĊĠĠĠ Ġoverride Ġval Ġcoroutine Context : ĠCor outine Context Ġ= Ġdispatcher Ġ+ Ġclient Job ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġexecute ( data : ĠHttpRequest Data ): ĠHttpResponse Data Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtest Server Call Ġ= Ġwith ( data ) Ġ{ Ġrun Request ( method , Ġurl . fullPath , Ġheaders , Ġbody ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġwith ( test Server Call . response ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠHttpResponse Data ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstatus () Ġ?: ĠHttpStatusCode . NotFound , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠGMT Date (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġheaders . all Values (). take Unless Ġ{ Ġit . isEmpty () Ġ} Ġ?: ĠHeaders ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build Ġ{ Ġthis [ HttpHeaders . Content Length ] Ġ= Ġ" 0 " Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttp Protocol Version . HTTP _ 1 _ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByte Read Channel ( byte Content Ġ?: Ġbyte ArrayOf ()), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Context () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrun Request ( ĊĠĠĠĠĠĠĠ Ġmethod : ĠHttpMethod , ĊĠĠĠĠĠĠĠ Ġurl : ĠString , ĊĠĠĠĠĠĠĠ Ġheaders : ĠHeaders , ĊĠĠĠĠĠĠĠ Ġcontent : ĠOut going Content ĊĠĠĠ Ġ): ĠTest Application Call Ġ= Ġapp . handle Request ( method , Ġurl ) Ġ{ ĊĠĠĠĠĠĠĠ Ġheaders . flatten ForEach Ġ{ Ġname , Ġvalue Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( HttpHeaders . Content Length Ġ== Ġname ) Ġreturn @ flatten ForEach Ġ// Ġset Ġlater ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( HttpHeaders . ContentType Ġ== Ġname ) Ġreturn @ flatten ForEach Ġ// Ġset Ġlater ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Header ( name , Ġvalue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontent . headers . flatten ForEach Ġ{ Ġname , Ġvalue Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( HttpHeaders . Content Length Ġ== Ġname ) Ġreturn @ flatten ForEach Ġ// ĠTODO : Ġthrow Ġexception Ġfor Ġunsafe Ġheader ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( HttpHeaders . ContentType Ġ== Ġname ) Ġreturn @ flatten ForEach ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Header ( name , Ġvalue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcontent Length Ġ= Ġheaders [ HttpHeaders . Content Length ] Ġ?: Ġcontent . content Length ?. toString () ĊĠĠĠĠĠĠĠ Ġval ĠcontentType Ġ= Ġheaders [ HttpHeaders . ContentType ] Ġ?: Ġcontent . contentType ?. toString () ĊĊĠĠĠĠĠĠĠ Ġcontent Length ?. let Ġ{ Ġadd Header ( HttpHeaders . Content Length , Ġit ) Ġ} ĊĠĠĠĠĠĠĠ ĠcontentType ?. let Ġ{ Ġadd Header ( HttpHeaders . ContentType , Ġit ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( content Ġ! is ĠOut going Content . No Content ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbody Channel Ġ= Ġcontent . to Byte Read Channel () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠ Ġclient Job . complete () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġpublic Ġcompanion Ġobject Ġ: ĠHttpClient Engine Factory < Test HttpClient Config > Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġcreate ( block : ĠTest HttpClient Config . () Ġ-> ĠUnit ): ĠHttpClient Engine Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġconfig Ġ= ĠTest HttpClient Config (). apply ( block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠTest HttpClient Engine ( config ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠOut going Content . to Byte Read Channel (): ĠByte Read Channel Ġ= Ġwhen Ġ( this ) Ġ{ ĊĠĠĠĠĠĠĠ Ġis ĠOut going Content . No Content Ġ-> ĠByte Read Channel . Empty ĊĠĠĠĠĠĠĠ Ġis ĠOut going Content . ByteArray Content Ġ-> ĠByte Read Channel ( bytes ()) ĊĠĠĠĠĠĠĠ Ġis ĠOut going Content . Read Channel Content Ġ-> Ġread From () ĊĠĠĠĠĠĠĠ Ġis ĠOut going Content . Write Channel Content Ġ-> Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter ( coroutine Context ) Ġ{ ĠwriteTo ( channel ) Ġ}. channel ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġis ĠOut going Content . Protocol Upgrade Ġ-> Ġthrow ĠUnsupported ContentType Exception ( this ) ĊĠĠĠ Ġ} Ċ } Ċ