package Ġproxy Ċ Ċ import Ġio . ktor . application . Application Call Ċ import Ġio . ktor . client . HttpClient Ċ import Ġio . ktor . client . request . request Ċ import Ġio . ktor . client . statement . HttpResponse Ċ import Ġio . ktor . client . statement . Http Statement Ċ import Ġio . ktor . http . ContentType Ċ import Ġio . ktor . http . Headers Ċ import Ġio . ktor . http . HttpHeaders Ċ import Ġio . ktor . http . content . Outgoing Content Ċ import Ġio . ktor . request . Application Request Ċ import Ġio . ktor . request . http Method Ċ import Ġio . ktor . request . receive Text Ċ import Ġio . ktor . request . uri Ċ import Ġio . ktor . response . respond Ċ import Ġio . ktor . util . filter Ċ import Ġio . ktor . utils . io . Byte Write Channel Ċ import Ġio . ktor . utils . io . copy And Close ĊĊ Ċ suspend Ġfun ĠApplication Call . proxy ( target : ĠString ) Ġ{ ĊĠĠĠ Ġval Ġurl Ġ= Ġ"$ target /${ request . uri }" ĊĠĠĠ Ġval Ġresponse Ġ= Ġrequest . proxy ( url ) ĊĊĠĠĠ Ġproxy Response ( response ) Ċ } Ċ Ċ suspend Ġfun ĠApplication Request . proxy ( url : ĠString ): ĠHttpResponse Ġ{ ĊĠĠĠ Ġreturn Ġclient . request < Http Statement >( url ) Ġ{ ĊĠĠĠĠĠĠĠ Ġmethod Ġ= Ġcall . request . http Method ĊĠĠĠĠĠĠĠ Ġbody Ġ= Ġcall . receive Text () ĊĊĠĠĠĠĠĠĠ Ġval Ġoriginal Headers Ġ= Ġcall . request . headers ĊĊĠĠĠĠĠĠĠ Ġ// ĠThere Ġmust Ġbe Ġa Ġcontent Ġtype Ġfor Ġus Ġto Ġproxy Ġthe Ġrequest ĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġthere Ġwas Ġno Ġcontent Ġtype Ġset , Ġuse ĠAny ĊĠĠĠĠĠĠĠ Ġval ĠcontentType Ġ= Ġoriginal Headers [ HttpHeaders . ContentType ]?. let Ġ{ ĠContentType . parse ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: ĠContentType . Any ĊĊĠĠĠĠĠĠĠ Ġ// ĠSome Ġheaders Ġshould Ġnot Ġbe Ġset Ġby Ġthe Ġproxy , Ġsince Ġthey Ġare Ġintended Ġfor Ġinternal Ġuse Ġonly ĊĠĠĠĠĠĠĠ Ġval Ġsafe Headers Ġ= Ġif Ġ( contentType . match ( ContentType . Text . Plain )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoriginal Headers . filter Ġ{ Ġkey , Ġ_ Ġ-> Ġ! HttpHeaders . is Unsafe ( key ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoriginal Headers . filter Ġ{ Ġkey , Ġ_ Ġ-> Ġkey Ġ!= ĠHttp Headers . Content Length Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġthis . headers . append All ( safe Headers ) ĊĠĠĠ Ġ}. execute () Ċ } Ċ Ċ suspend Ġfun ĠApplication Call . proxy Response ( response : ĠHttpResponse ) Ġ{ ĊĠĠĠ Ġrespond ( Proxy Response ( response )) Ċ } Ċ Ċ val Ġignored Headers Ġ= Ġset Of ( HttpHeaders . ContentType , ĠHttp Headers . Transfer Encoding , ĠHttp Headers . Content Length ) Ċ Ċ data Ġclass ĠProxy Response ( private Ġval Ġresponse : ĠHttpResponse ) Ġ: ĠOut going Content . Write Channel Content () Ġ{ ĊĠĠĠ Ġprivate Ġval Ġoriginal Headers Ġ= Ġresponse . headers ĊĠĠĠ Ġoverride Ġval Ġcontent Length Ġ= Ġoriginal Headers [ HttpHeaders . Content Length ]?. to Long () ĊĠĠĠ Ġoverride Ġval ĠcontentType Ġ= Ġoriginal Headers [ HttpHeaders . ContentType ]?. let Ġ{ ĠContentType . parse ( it ) Ġ} ĊĊĠĠĠ Ġ// ĠWe Ġshouldn 't Ġchange Ġsome Ġheaders , Ġsince Ġthey 'll Ġbe Ġset Ġbased Ġon Ġcontent Length Ġand ĠcontentType Ġvariables Ġinstead ĊĠĠĠ Ġoverride Ġval Ġheaders Ġ= ĠHeaders . build Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġoriginal Headers Ġis Ġa Ġmap , Ġbut Ġwe Ġfilter Ġonly Ġby Ġkeys , Ġso Ġwe Ġignore Ġvalues Ġby Ġusing Ġ_ ĊĠĠĠĠĠĠĠ Ġappend All ( original Headers . filter Ġ{ Ġkey , Ġ_ Ġ-> Ġ! ignored Headers . contains ( key ) Ġ}) ĊĠĠĠ Ġ} ĊĠĠĠ Ġoverride Ġval Ġstatus Ġ= Ġresponse . status ĊĠĠĠ Ġoverride Ġsuspend Ġfun ĠwriteTo ( channel : ĠByte Write Channel ) Ġ{ ĊĠĠĠĠĠĠĠ Ġresponse . content . copy And Close ( channel ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġval Ġclient Ġ= ĠHttpClient Ġ{ ĊĠĠĠ Ġexpect Success Ġ= Ġfalse Ġ// ĠProxy Ġerror Ġcodes Ġinstead Ġof Ġthrowing Ġan Ġexception Ċ }