package Ġpw . bin om . io . httpClient Ċ Ċ import Ġpw . bin om . Environment Ċ import Ġpw . bin om . charset . Charsets Ċ import Ġpw . bin om . crypto . Sha 1 Message Digest Ċ import Ġpw . bin om . io . IOException Ċ import Ġpw . bin om . io . http .* Ċ import Ġpw . bin om . io . http . websocket . Handshake Secret Ċ import Ġpw . bin om . io . http . websocket . Invalid Security Key Exception Ċ import Ġpw . bin om . io . http . websocket . WebSocket Connection Ċ import Ġpw . bin om . io . httpClient . websocket . Client WebSocket Connection Ċ import Ġpw . bin om . net . URI Ċ import Ġpw . bin om . os Ċ import Ġpw . bin om . platform Ċ import Ġkotlin . time . Duration Ċ import Ġkotlin . time . Experimental Time Ċ Ċ @ Opt In ( Experimental Time :: class ) Ċ class ĠDefault HttpRequest Ġconstructor ( ĊĠĠĠ Ġoverride Ġvar Ġmethod : ĠString , ĊĠĠĠ Ġoverride Ġval Ġuri : ĠURI , ĊĠĠĠ Ġval Ġclient : ĠBase HttpClient , ĊĠĠĠ Ġval Ġchannel : ĠAsync Ascii Channel , ĊĠĠĠ Ġval Ġtimeout : ĠDuration ?, Ċ ) Ġ: ĠHttpRequest Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġclosed Ġ= Ġfalse ĊĠĠĠ Ġoverride Ġval Ġheaders Ġ= ĠHash Headers () ĊĊĠĠĠ Ġprivate Ġfun Ġcheck Closed () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( closed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" HttpRequest Ġalready Ġclosed ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġport Ġ= Ġuri . port ĊĠĠĠĠĠĠĠ Ġval Ġhost Ġ= Ġif Ġ( port Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuri . host ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ uri . host }: $ port " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( client . use KeepAlive ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheaders [ Headers . CONNECTION ] Ġ= ĠHeaders . KEEP _ AL IVE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . HOST ] Ġ= Ġhost ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . ACCEPT _ ENCODING ] Ġ= Ġ" gzip , Ġdef late , Ġidentity " ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . ACCEPT ] Ġ= Ġ"* /* " ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . USER _ AGENT ] Ġ= Ġ" bin om / kotlin ${ Kotlin Version . CURRENT } Ġos /${ Environment . os . name . lowercase () }" ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġsend Headers () Ġ{ ĊĠĠĠĠĠĠĠ Ġchannel . writer . append ( method ). append (" Ġ"). append ( uri . request ). append (" Ġ"). append (" HTTP / 1 . 1 \ r \ n ") ĊĠĠĠĠĠĠĠ Ġheaders . forEach Header Ġ{ Ġkey , Ġvalue Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . writer . append ( key ). append (": Ġ"). append ( value ). append ("\ r \ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġchannel . writer . append ("\ r \ n ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġkeep Alive ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġheaders . keep Alive ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġwrite Data (): ĠAsync HttpRequest Output Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck Closed () ĊĠĠĠĠĠĠĠ Ġif Ġ( headers . content Length Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheaders . transfer Encoding Ġ= ĠEncoding . CHUNK ED ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġsend Headers () ĊĠĠĠĠĠĠĠ Ġval Ġencode Ġ= Ġheaders . transfer Encoding ĊĠĠĠĠĠĠĠ Ġif Ġ( encode Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( encode . lowercase ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEncoding . CHUNK ED . lowercase () Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclosed Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠRequest Async Chunk ed Output ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠURI Ġ= Ġuri , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclient Ġ= Ġclient , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkeep Alive Ġ= Ġkeep Alive , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Ġ= Ġchannel , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Ġ= Ġtimeout , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIOException (" Unknown ĠTransfer ĠEncoding Ġ\"$ encode \" ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġlen Ġ= Ġheaders . content Length ĊĠĠĠĠĠĠĠ Ġif Ġ( len Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclosed Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠRequest Async Content Length Output ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠURI Ġ= Ġuri , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclient Ġ= Ġclient , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkeep Alive Ġ= Ġkeep Alive , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Ġ= Ġchannel , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Length Ġ= Ġlen , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Ġ= Ġtimeout , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Unknown Ġtype Ġof ĠTransfer ĠEncoding ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġwrite Data ( func : Ġsuspend Ġ( Async HttpRequest Output ) Ġ-> ĠUnit ): ĠHttpResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġwrite Data () ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunc ( data ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata . flush () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġdata . getResponse () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Catch ing Ġ{ Ġdata . async Close () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġwrite Text (): ĠAsync HttpRequest Writer Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdata Channel Ġ= Ġwrite Data () ĊĠĠĠĠĠĠĠ Ġreturn ĠRequest Async HttpRequest Writer ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Ġ= Ġdata Channel , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbufferSize Ġ= Ġclient . buffer Size , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcharset Ġ= Ġheaders . charset ?. let Ġ{ ĠChar sets . get ( it ) Ġ} Ġ?: ĠChar sets . UTF 8 ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġwrite Text ( func : Ġsuspend Ġ( Async HttpRequest Writer ) Ġ-> ĠUnit ): ĠHttpResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġwrite Text () ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunc ( data ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata . flush () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġdata . getResponse () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Catch ing Ġ{ Ġdata . async Close () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġget Response (): ĠHttpResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck Closed () ĊĠĠĠĠĠĠĠ Ġval Ġlen Ġ= Ġheaders . content Length ĊĠĠĠĠĠĠĠ Ġif Ġ( len Ġ!= Ġnull Ġ&& Ġlen Ġ> Ġ 0 u L ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Can 't Ġget ĠResponse . ĠHeader Ġcontains Ġ\" ${ Headers . CONTENT _ LENGTH }: Ġ$ len \" . ĠExpected Ġrequest Ġdata Ġ$ len Ġbytes ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġencode Ġ= Ġheaders . transfer Encoding ĊĠĠĠĠĠĠĠ Ġif Ġ( encode Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Can 't Ġget ĠResponse . ĠHeader Ġcontains Ġ\" ${ Headers . TRANSFER _ ENCODING }: Ġ$ encode \" . ĠExpected Ġrequest Ġdata ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġsend Headers () ĊĠĠĠĠĠĠĠ Ġchannel . writer . flush () ĊĠĠĠĠĠĠĠ Ġclosed Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġreturn ĠDefault HttpResponse . read ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuri Ġ= Ġuri , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclient Ġ= Ġclient , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkeep Alive Ġ= Ġkeep Alive , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Ġ= Ġchannel , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Ġ= Ġtimeout , ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġstart WebSocket ( origin : ĠString ?): ĠWebSocket Connection Ġ{ ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . CONNECTION ] Ġ= ĠHeaders . UP GR ADE ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . UP GR ADE ] Ġ= ĠHeaders . WEB SOCKET ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . SEC _ WEB SOCKET _ VERSION ] Ġ= Ġ" 1 3 " ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . ORIGIN ] Ġ= Ġorigin ĊĊĠĠĠĠĠĠĠ Ġval Ġrequest Key Ġ= ĠHand shake Secret . generate Request Key () ĊĠĠĠĠĠĠĠ Ġval Ġresponse Key Ġ= ĠHand shake Secret . generate Response ( Sha 1 Message Digest (), Ġrequest Key ) ĊĠĠĠĠĠĠĠ Ġheaders [ Headers . SEC _ WEB SOCKET _ KEY ] Ġ= Ġrequest Key ĊĠĠĠĠĠĠĠ Ġval Ġresp Ġ= Ġget Response () ĊĠĠĠĠĠĠĠ Ġif Ġ( resp . response Code Ġ!= Ġ 1 0 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Invalid ĠResponse Ġcode : Ġ${ resp . response Code }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresp Key Ġ= Ġresp . headers . get Single ( Headers . SEC _ WEB SOCKET _ ACCEPT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIOException (" Invalid ĠServer ĠResponse . ĠMissing Ġheader Ġ\" ${ Headers . SEC _ WEB SOCKET _ ACCEPT }\" ") ĊĠĠĠĠĠĠĠ Ġif Ġ( resp Key Ġ!= Ġresponse Key ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠInvalid Security Key Exception () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠClient WebSocket Connection ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġchannel . reader , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Ġ= Ġchannel . writer , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġraw Connection Ġ= Ġchannel . channel , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Dispatcher Ġ= Ġclient . network Dispatcher , ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġasync Close () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( closed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġchannel . async Close () ĊĠĠĠĠĠĠĠ Ġclosed Ġ= Ġtrue ĊĠĠĠ Ġ} Ċ }