Открыть боковую панель
Aurora OS
Kotlin Multiplatform
Libraries
ktor
Коммиты
e8de451d
Коммит
e8de451d
создал
Фев 01, 2019
по автору
Leonid Stashevsky
Просмотр файлов
Make client websocket feature common
владелец
6cc32ea3
Изменения
71
Скрыть пробелы
Построчно
Рядом
.gitignore
Просмотр файла @
e8de451d
build
build
.gradle
.gradle
.gradletasknamecache
.idea/*
.idea/*
!.idea/runConfigurations
!.idea/runConfigurations
!.idea/runConfigurations/*
!.idea/runConfigurations/*
...
...
build.gradle
Просмотр файла @
e8de451d
...
@@ -42,7 +42,10 @@ def projectNeedsPlatform(project, platform) {
...
@@ -42,7 +42,10 @@ def projectNeedsPlatform(project, platform) {
def
hasDarwin
=
files
.
any
{
it
.
name
==
"darwin"
}
def
hasDarwin
=
files
.
any
{
it
.
name
==
"darwin"
}
if
(
hasPosix
&&
hasDarwin
)
return
false
if
(
hasPosix
&&
hasDarwin
)
return
false
if
(!
hasDarwin
&&
platform
==
"darwin"
)
return
false
if
(
hasPosix
&&
platform
==
"darwin"
)
return
false
if
(
hasDarwin
&&
platform
==
"posix"
)
return
false
if
(!
hasPosix
&&
!
hasDarwin
&&
platform
==
"darwin"
)
return
false
return
files
.
any
{
it
.
name
==
"common"
||
it
.
name
==
platform
}
return
files
.
any
{
it
.
name
==
"common"
||
it
.
name
==
platform
}
}
}
...
...
gradle.properties
Просмотр файла @
e8de451d
...
@@ -3,7 +3,7 @@ kotlin.code.style=official
...
@@ -3,7 +3,7 @@ kotlin.code.style=official
# config
# config
version
=
1.2.0-SNAPSHOT
version
=
1.2.0-SNAPSHOT
kotlin.incremental.js
=
tru
e
kotlin.incremental.js
=
fals
e
kotlin.incremental.multiplatform
=
true
kotlin.incremental.multiplatform
=
true
# gradle
# gradle
...
...
gradle/js.gradle
Просмотр файла @
e8de451d
...
@@ -90,6 +90,9 @@ prepareMocha.doLast {
...
@@ -90,6 +90,9 @@ prepareMocha.doLast {
<script src="$libraryPath/ktor-client.js"></script>
<script src="$libraryPath/ktor-client.js"></script>
<script src="$libraryPath/ktor-client-json.js"></script>
<script src="$libraryPath/ktor-client-json.js"></script>
<script src="$libraryPath/ktor-client-auth-basic.js"></script>
<script src="$libraryPath/ktor-client-auth-basic.js"></script>
<script src="$libraryPath/ktor-client-tests-dispatcher.js"></script>
<script src="$libraryPath/ktor-client-tests.js"></script>
<script src="$libraryPath/ktor-client-websocket.js"></script>
<script src="$compileTestKotlinJs.outputFile"></script>
<script src="$compileTestKotlinJs.outputFile"></script>
<script>mocha.run();</script>
<script>mocha.run();</script>
</body>
</body>
...
...
gradle/posix.gradle
Просмотр файла @
e8de451d
...
@@ -33,9 +33,18 @@ kotlin {
...
@@ -33,9 +33,18 @@ kotlin {
configure
([
iosArm32Main
,
iosArm64Main
,
iosX64Main
,
macosX64Main
,
linuxX64Main
,
mingwX64Main
])
{
configure
([
iosArm32Main
,
iosArm64Main
,
iosX64Main
,
macosX64Main
,
linuxX64Main
,
mingwX64Main
])
{
dependsOn
posixMain
dependsOn
posixMain
}
}
configure
([
iosArm32Test
,
iosArm64Test
,
iosX64Test
,
macosX64Test
,
linuxX64Test
,
mingwX64Test
])
{
configure
([
iosArm32Test
,
iosArm64Test
,
iosX64Test
,
macosX64Test
,
linuxX64Test
,
mingwX64Test
])
{
dependsOn
posixTest
dependsOn
posixTest
}
}
iosArm32Test
.
dependsOn
iosArm32Main
iosArm64Test
.
dependsOn
iosArm64Main
iosX64Test
.
dependsOn
iosX64Main
linuxX64Test
.
dependsOn
linuxX64Main
macosX64Test
.
dependsOn
macosX64Main
iosX64Test
.
dependsOn
iosX64Main
mingwX64Test
.
dependsOn
mingwX64Main
}
}
}
}
}
}
...
...
ktor-client/build.gradle
Просмотр файла @
e8de451d
kotlin
.
sourceSets
.
commonMain
.
dependencies
{
kotlin
.
sourceSets
.
commonMain
.
dependencies
{
api
project
(
':ktor-client:ktor-client-core'
)
api
project
(
':ktor-client:ktor-client-core'
)
}
}
ktor-client/ktor-client-cio/build.gradle
Просмотр файла @
e8de451d
...
@@ -5,6 +5,7 @@ kotlin.sourceSets {
...
@@ -5,6 +5,7 @@ kotlin.sourceSets {
api
project
(
':ktor-client:ktor-client-core'
)
api
project
(
':ktor-client:ktor-client-core'
)
api
project
(
':ktor-http:ktor-http-cio'
)
api
project
(
':ktor-http:ktor-http-cio'
)
api
project
(
':ktor-network:ktor-network-tls'
)
api
project
(
':ktor-network:ktor-network-tls'
)
api
project
(
':ktor-client:ktor-client-features:ktor-client-websocket'
)
}
}
jvmTest
.
dependencies
{
jvmTest
.
dependencies
{
api
project
(
':ktor-client:ktor-client-tests'
)
api
project
(
':ktor-client:ktor-client-tests'
)
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/CIOEngine.kt
Просмотр файла @
e8de451d
...
@@ -2,7 +2,9 @@ package io.ktor.client.engine.cio
...
@@ -2,7 +2,9 @@ package io.ktor.client.engine.cio
import
io.ktor.client.call.*
import
io.ktor.client.call.*
import
io.ktor.client.engine.*
import
io.ktor.client.engine.*
import
io.ktor.client.features.websocket.*
import
io.ktor.client.request.*
import
io.ktor.client.request.*
import
io.ktor.client.response.*
import
io.ktor.http.*
import
io.ktor.http.*
import
io.ktor.network.selector.*
import
io.ktor.network.selector.*
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
...
@@ -11,7 +13,7 @@ import java.io.*
...
@@ -11,7 +13,7 @@ import java.io.*
import
java.util.concurrent.*
import
java.util.concurrent.*
import
java.util.concurrent.atomic.*
import
java.util.concurrent.atomic.*
internal
class
CIOEngine
(
override
val
config
:
CIOEngineConfig
)
:
HttpClientJvmEngine
(
"ktor-cio"
)
{
internal
class
CIOEngine
(
override
val
config
:
CIOEngineConfig
)
:
HttpClientJvmEngine
(
"ktor-cio"
)
,
WebSocketEngine
{
private
val
endpoints
=
ConcurrentHashMap
<
String
,
Endpoint
>()
private
val
endpoints
=
ConcurrentHashMap
<
String
,
Endpoint
>()
@UseExperimental
(
InternalCoroutinesApi
::
class
)
@UseExperimental
(
InternalCoroutinesApi
::
class
)
...
@@ -29,7 +31,12 @@ internal class CIOEngine(override val config: CIOEngineConfig) : HttpClientJvmEn
...
@@ -29,7 +31,12 @@ internal class CIOEngine(override val config: CIOEngineConfig) : HttpClientJvmEn
return
@withContext
HttpEngineCall
(
request
,
response
)
return
@withContext
HttpEngineCall
(
request
,
response
)
}
}
private
suspend
fun
executeRequest
(
request
:
DefaultHttpRequest
):
CIOHttpResponse
{
override
suspend
fun
execute
(
request
:
HttpRequest
):
WebSocketResponse
{
val
response
=
executeRequest
(
request
)
return
response
as
WebSocketResponse
}
private
suspend
fun
executeRequest
(
request
:
HttpRequest
):
HttpResponse
{
while
(
true
)
{
while
(
true
)
{
if
(
closed
.
get
())
throw
ClientClosedException
()
if
(
closed
.
get
())
throw
ClientClosedException
()
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/CIOHttpResponse.kt
Просмотр файла @
e8de451d
...
@@ -11,9 +11,10 @@ import kotlin.coroutines.*
...
@@ -11,9 +11,10 @@ import kotlin.coroutines.*
internal
class
CIOHttpResponse
(
internal
class
CIOHttpResponse
(
request
:
HttpRequest
,
request
:
HttpRequest
,
override
val
headers
:
Headers
,
override
val
requestTime
:
GMTDate
,
override
val
requestTime
:
GMTDate
,
override
val
content
:
ByteReadChannel
,
override
val
content
:
ByteReadChannel
,
private
val
response
:
Response
,
response
:
Response
,
override
val
coroutineContext
:
CoroutineContext
override
val
coroutineContext
:
CoroutineContext
)
:
HttpResponse
{
)
:
HttpResponse
{
...
@@ -21,14 +22,7 @@ internal class CIOHttpResponse(
...
@@ -21,14 +22,7 @@ internal class CIOHttpResponse(
override
val
status
:
HttpStatusCode
=
HttpStatusCode
(
response
.
status
,
response
.
statusText
.
toString
())
override
val
status
:
HttpStatusCode
=
HttpStatusCode
(
response
.
status
,
response
.
statusText
.
toString
())
override
val
version
:
HttpProtocolVersion
=
HttpProtocolVersion
.
HTTP_1_1
override
val
version
:
HttpProtocolVersion
=
HttpProtocolVersion
.
parse
(
response
.
version
)
override
val
headers
:
Headers
=
Headers
.
build
{
val
origin
=
CIOHeaders
(
response
.
headers
)
origin
.
names
().
forEach
{
appendAll
(
it
,
origin
.
getAll
(
it
))
}
}
override
val
responseTime
:
GMTDate
=
GMTDate
()
override
val
responseTime
:
GMTDate
=
GMTDate
()
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/ConnectionFactory.kt
Просмотр файла @
e8de451d
...
@@ -6,17 +6,20 @@ import io.ktor.network.sockets.*
...
@@ -6,17 +6,20 @@ import io.ktor.network.sockets.*
import
io.ktor.network.sockets.Socket
import
io.ktor.network.sockets.Socket
import
java.net.*
import
java.net.*
internal
class
ConnectionFactory
(
private
val
selector
:
SelectorManager
,
maxConnectionsCount
:
Int
)
{
internal
class
ConnectionFactory
(
private
val
selector
:
SelectorManager
,
maxConnectionsCount
:
Int
)
{
private
val
semaphore
=
Semaphore
(
maxConnectionsCount
)
private
val
semaphore
=
Semaphore
(
maxConnectionsCount
)
suspend
fun
connect
(
address
:
InetSocketAddress
):
Socket
{
suspend
fun
connect
(
address
:
InetSocketAddress
):
Socket
{
semaphore
.
enter
()
semaphore
.
enter
()
return
try
{
return
try
{
aSocket
(
selector
).
tcpNoDelay
().
tcp
().
connect
(
address
)
aSocket
(
selector
).
tcpNoDelay
().
tcp
().
connect
(
address
)
}
catch
(
t
:
Throwable
)
{
}
catch
(
cause
:
Throwable
)
{
// a failure or cancellation
// a failure or cancellation
semaphore
.
leave
()
semaphore
.
leave
()
throw
t
throw
cause
}
}
}
}
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/ConnectionPipeline.kt
Просмотр файла @
e8de451d
...
@@ -76,6 +76,11 @@ internal class ConnectionPipeline(
...
@@ -76,6 +76,11 @@ internal class ConnectionPipeline(
val
transferEncoding
=
rawResponse
.
headers
[
HttpHeaders
.
TransferEncoding
]
val
transferEncoding
=
rawResponse
.
headers
[
HttpHeaders
.
TransferEncoding
]
val
chunked
=
transferEncoding
==
"chunked"
val
chunked
=
transferEncoding
==
"chunked"
val
connectionType
=
ConnectionOptions
.
parse
(
rawResponse
.
headers
[
HttpHeaders
.
Connection
])
val
connectionType
=
ConnectionOptions
.
parse
(
rawResponse
.
headers
[
HttpHeaders
.
Connection
])
val
headers
=
CIOHeaders
(
rawResponse
.
headers
)
callContext
[
Job
]
?.
invokeOnCompletion
{
rawResponse
.
release
()
}
shouldClose
=
(
connectionType
==
ConnectionOptions
.
Close
)
shouldClose
=
(
connectionType
==
ConnectionOptions
.
Close
)
...
@@ -90,7 +95,7 @@ internal class ConnectionPipeline(
...
@@ -90,7 +95,7 @@ internal class ConnectionPipeline(
}
else
ByteReadChannel
.
Empty
}
else
ByteReadChannel
.
Empty
val
response
=
CIOHttpResponse
(
val
response
=
CIOHttpResponse
(
task
.
request
,
requestTime
,
task
.
request
,
headers
,
requestTime
,
body
,
body
,
rawResponse
,
rawResponse
,
coroutineContext
=
callContext
coroutineContext
=
callContext
...
@@ -99,19 +104,13 @@ internal class ConnectionPipeline(
...
@@ -99,19 +104,13 @@ internal class ConnectionPipeline(
task
.
response
.
complete
(
response
)
task
.
response
.
complete
(
response
)
responseChannel
?.
use
{
responseChannel
?.
use
{
try
{
parseHttpBody
(
parseHttpBody
(
contentLength
,
contentLength
,
transferEncoding
,
transferEncoding
,
connectionType
,
connectionType
,
networkInput
,
networkInput
,
this
this
)
)
}
finally
{
callContext
[
Job
]
?.
invokeOnCompletion
{
rawResponse
.
release
()
}
}
}
}
skipTask
?.
join
()
skipTask
?.
join
()
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/Endpoint.kt
Просмотр файла @
e8de451d
package
io.ktor.client.engine.cio
package
io.ktor.client.engine.cio
import
io.ktor.client.features.websocket.*
import
io.ktor.client.request.*
import
io.ktor.client.request.*
import
io.ktor.client.response.*
import
io.ktor.http.*
import
io.ktor.http.*
import
io.ktor.http.cio.*
import
io.ktor.http.cio.*
import
io.ktor.http.cio.websocket.*
import
io.ktor.network.sockets.*
import
io.ktor.network.sockets.*
import
io.ktor.network.sockets.Socket
import
io.ktor.network.sockets.Socket
import
io.ktor.network.tls.*
import
io.ktor.network.tls.*
import
io.ktor.util.*
import
io.ktor.util.*
import
io.ktor.util.date.*
import
io.ktor.util.date.*
import
kotlinx.atomicfu.*
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
import
kotlinx.coroutines.channels.*
import
kotlinx.coroutines.channels.*
import
kotlinx.coroutines.io.*
import
kotlinx.coroutines.io.*
import
java.io.*
import
java.io.*
import
java.net.*
import
java.net.*
import
java.util.concurrent.atomic.*
import
kotlin.coroutines.*
import
kotlin.coroutines.*
internal
class
Endpoint
(
internal
class
Endpoint
(
...
@@ -25,14 +28,13 @@ internal class Endpoint(
...
@@ -25,14 +28,13 @@ internal class Endpoint(
override
val
coroutineContext
:
CoroutineContext
,
override
val
coroutineContext
:
CoroutineContext
,
private
val
onDone
:
()
->
Unit
private
val
onDone
:
()
->
Unit
)
:
CoroutineScope
,
Closeable
{
)
:
CoroutineScope
,
Closeable
{
private
val
address
=
InetSocketAddress
(
host
,
port
)
private
val
connections
:
AtomicInt
=
atomic
(
0
)
private
val
tasks
:
Channel
<
RequestTask
>
=
Channel
(
Channel
.
UNLIMITED
)
private
val
tasks
:
Channel
<
RequestTask
>
=
Channel
(
Channel
.
UNLIMITED
)
private
val
deliveryPoint
:
Channel
<
RequestTask
>
=
Channel
()
private
val
deliveryPoint
:
Channel
<
RequestTask
>
=
Channel
()
private
val
maxEndpointIdleTime
=
2
*
config
.
endpoint
.
connectTimeout
@Volatile
private
val
maxEndpointIdleTime
:
Long
=
2
*
config
.
endpoint
.
connectTimeout
private
var
connectionsHolder
:
Int
=
0
private
val
address
=
InetSocketAddress
(
host
,
port
)
private
val
postman
=
launch
(
start
=
CoroutineStart
.
LAZY
)
{
private
val
postman
=
launch
(
start
=
CoroutineStart
.
LAZY
)
{
try
{
try
{
...
@@ -64,8 +66,8 @@ internal class Endpoint(
...
@@ -64,8 +66,8 @@ internal class Endpoint(
}
}
}
}
suspend
fun
execute
(
request
:
Default
HttpRequest
,
callContext
:
CoroutineContext
):
CIO
HttpResponse
{
suspend
fun
execute
(
request
:
HttpRequest
,
callContext
:
CoroutineContext
):
HttpResponse
{
val
result
=
CompletableDeferred
<
CIO
HttpResponse
>(
parent
=
callContext
[
Job
])
val
result
=
CompletableDeferred
<
HttpResponse
>(
parent
=
callContext
[
Job
])
val
task
=
RequestTask
(
request
,
result
,
callContext
)
val
task
=
RequestTask
(
request
,
result
,
callContext
)
tasks
.
offer
(
task
)
tasks
.
offer
(
task
)
return
result
.
await
()
return
result
.
await
()
...
@@ -74,7 +76,7 @@ internal class Endpoint(
...
@@ -74,7 +76,7 @@ internal class Endpoint(
private
suspend
fun
makePipelineRequest
(
task
:
RequestTask
)
{
private
suspend
fun
makePipelineRequest
(
task
:
RequestTask
)
{
if
(
deliveryPoint
.
offer
(
task
))
return
if
(
deliveryPoint
.
offer
(
task
))
return
val
connections
=
C
onnections
.
get
(
this
@Endpoint
)
val
connections
=
c
onnections
.
value
if
(
connections
<
config
.
endpoint
.
maxConnectionsPerRoute
)
{
if
(
connections
<
config
.
endpoint
.
maxConnectionsPerRoute
)
{
try
{
try
{
createPipeline
()
createPipeline
()
...
@@ -114,18 +116,20 @@ internal class Endpoint(
...
@@ -114,18 +116,20 @@ internal class Endpoint(
val
contentLength
=
rawResponse
.
headers
[
HttpHeaders
.
ContentLength
]
?.
toString
()
?.
toLong
()
?:
-
1L
val
contentLength
=
rawResponse
.
headers
[
HttpHeaders
.
ContentLength
]
?.
toString
()
?.
toLong
()
?:
-
1L
val
transferEncoding
=
rawResponse
.
headers
[
HttpHeaders
.
TransferEncoding
]
val
transferEncoding
=
rawResponse
.
headers
[
HttpHeaders
.
TransferEncoding
]
val
connectionType
=
ConnectionOptions
.
parse
(
rawResponse
.
headers
[
HttpHeaders
.
Connection
])
val
connectionType
=
ConnectionOptions
.
parse
(
rawResponse
.
headers
[
HttpHeaders
.
Connection
])
val
headers
=
CIOHeaders
(
rawResponse
.
headers
)
val
body
=
when
{
callContext
[
Job
]
!!
.
invokeOnCompletion
{
status
==
HttpStatusCode
.
SwitchingProtocols
.
value
->
{
rawResponse
.
headers
.
release
()
val
content
=
request
.
content
as
?
ClientUpgradeContent
}
?:
error
(
"Invalid content type: UpgradeContent required"
)
if
(
status
==
HttpStatusCode
.
SwitchingProtocols
.
value
)
{
val
session
=
RawWebSocket
(
input
,
output
,
masking
=
true
,
coroutineContext
=
callContext
)
response
.
complete
(
WebSocketResponse
(
callContext
,
requestTime
,
session
))
return
@launch
}
launch
{
content
.
pipeTo
(
output
)
}.
invokeOnCompletion
(
::
closeConnection
)
input
val
body
=
when
{
}
request
.
method
==
HttpMethod
.
Head
->
{
request
.
method
==
HttpMethod
.
Head
->
{
closeConnection
()
closeConnection
()
ByteReadChannel
.
Empty
ByteReadChannel
.
Empty
...
@@ -140,12 +144,12 @@ internal class Endpoint(
...
@@ -140,12 +144,12 @@ internal class Endpoint(
}
}
}
}
response
.
complete
(
val
result
=
CIOHttpResponse
(
CIOHttpResponse
(
request
,
headers
,
requestTime
,
body
,
rawResponse
,
request
,
requestTime
,
body
,
rawResponse
,
coroutineContext
=
callContext
coroutineContext
=
callContext
)
)
)
response
.
complete
(
result
)
}
catch
(
cause
:
Throwable
)
{
}
catch
(
cause
:
Throwable
)
{
response
.
completeExceptionally
(
cause
)
response
.
completeExceptionally
(
cause
)
}
}
...
@@ -168,7 +172,7 @@ internal class Endpoint(
...
@@ -168,7 +172,7 @@ internal class Endpoint(
val
retryAttempts
=
config
.
endpoint
.
connectRetryAttempts
val
retryAttempts
=
config
.
endpoint
.
connectRetryAttempts
val
connectTimeout
=
config
.
endpoint
.
connectTimeout
val
connectTimeout
=
config
.
endpoint
.
connectTimeout
C
onnections
.
incrementAndGet
(
this
)
c
onnections
.
incrementAndGet
()
try
{
try
{
repeat
(
retryAttempts
)
{
repeat
(
retryAttempts
)
{
...
@@ -187,23 +191,28 @@ internal class Endpoint(
...
@@ -187,23 +191,28 @@ internal class Endpoint(
address
.
hostName
address
.
hostName
)
)
}
}
}
catch
(
t
:
Throwable
)
{
}
catch
(
cause
:
Throwable
)
{
try
{
connection
.
close
()
}
catch
(
_
:
Throwable
)
{
}
connectionFactory
.
release
()
connectionFactory
.
release
()
throw
t
throw
cause
}
}
}
}
}
catch
(
cause
:
Throwable
)
{
}
catch
(
cause
:
Throwable
)
{
C
onnections
.
decrementAndGet
(
this
)
c
onnections
.
decrementAndGet
()
throw
cause
throw
cause
}
}
C
onnections
.
decrementAndGet
(
this
)
c
onnections
.
decrementAndGet
()
throw
ConnectException
()
throw
ConnectException
()
}
}
private
fun
releaseConnection
()
{
private
fun
releaseConnection
()
{
connectionFactory
.
release
()
connectionFactory
.
release
()
C
onnections
.
decrementAndGet
(
this
)
c
onnections
.
decrementAndGet
()
}
}
override
fun
close
()
{
override
fun
close
()
{
...
@@ -213,12 +222,8 @@ internal class Endpoint(
...
@@ -213,12 +222,8 @@ internal class Endpoint(
init
{
init
{
postman
.
start
()
postman
.
start
()
}
}
companion
object
{
private
val
Connections
=
AtomicIntegerFieldUpdater
.
newUpdater
(
Endpoint
::
class
.
java
,
Endpoint
::
connectionsHolder
.
name
)
}
}
}
@KtorExperimentalAPI
@KtorExperimentalAPI
@Suppress
(
"KDocMissingDocumentation"
)
class
ConnectException
:
Exception
(
"Connect timed out or retry attempts exceeded"
)
class
ConnectException
:
Exception
(
"Connect timed out or retry attempts exceeded"
)
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/EngineTasks.kt
Просмотр файла @
e8de451d
package
io.ktor.client.engine.cio
package
io.ktor.client.engine.cio
import
io.ktor.client.request.*
import
io.ktor.client.request.*
import
io.ktor.client.response.*
import
io.ktor.http.*
import
io.ktor.http.*
import
io.ktor.util.date.*
import
io.ktor.util.date.*
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
import
kotlin.coroutines.*
import
kotlin.coroutines.*
internal
data class
RequestTask
(
internal
data class
RequestTask
(
val
request
:
Default
HttpRequest
,
val
request
:
HttpRequest
,
val
response
:
CompletableDeferred
<
CIO
HttpResponse
>,
val
response
:
CompletableDeferred
<
HttpResponse
>,
val
context
:
CoroutineContext
val
context
:
CoroutineContext
)
)
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/engine/cio/utils.kt
Просмотр файла @
e8de451d
...
@@ -9,7 +9,7 @@ import io.ktor.http.content.*
...
@@ -9,7 +9,7 @@ import io.ktor.http.content.*
import
kotlinx.coroutines.io.*
import
kotlinx.coroutines.io.*
import
kotlin.coroutines.*
import
kotlin.coroutines.*
internal
suspend
fun
Default
HttpRequest
.
write
(
output
:
ByteWriteChannel
,
callContext
:
CoroutineContext
)
{
internal
suspend
fun
HttpRequest
.
write
(
output
:
ByteWriteChannel
,
callContext
:
CoroutineContext
)
{
val
builder
=
RequestResponseBuilder
()
val
builder
=
RequestResponseBuilder
()
val
contentLength
=
headers
[
HttpHeaders
.
ContentLength
]
?:
content
.
contentLength
?.
toString
()
val
contentLength
=
headers
[
HttpHeaders
.
ContentLength
]
?:
content
.
contentLength
?.
toString
()
...
...
ktor-client/ktor-client-cio/jvm/src/io/ktor/client/features/websocket/buildersCio.kt
0 → 100644
Просмотр файла @
e8de451d
package
io.ktor.client.features.websocket
import
io.ktor.client.*
import
io.ktor.client.request.*
import
io.ktor.http.*
suspend
fun
HttpClient
.
webSocketRawSession
(
method
:
HttpMethod
=
HttpMethod
.
Get
,
host
:
String
=
"localhost"
,
port
:
Int
=
DEFAULT_PORT
,
path
:
String
=
"/"
,
block
:
HttpRequestBuilder
.()
->
Unit
=
{}
):
ClientWebSocketSession
=
request
{
this
.
method
=
method
url
(
"ws"
,
host
,
port
,
path
)
block
()
}
suspend
fun
HttpClient
.
webSocketRaw
(
method
:
HttpMethod
=
HttpMethod
.
Get
,
host
:
String
=
"localhost"
,
port
:
Int
=
DEFAULT_PORT
,
path
:
String
=
"/"
,
request
:
HttpRequestBuilder
.()
->
Unit
=
{},
block
:
suspend
ClientWebSocketSession
.()
->
Unit
):
Unit
{
val
session
=
webSocketRawSession
(
method
,
host
,
port
,
path
)
{
url
.
protocol
=
URLProtocol
.
WS
url
.
port
=
port
request
()
}
try
{
session
.
block
()
}
catch
(
cause
:
Throwable
)
{
session
.
close
(
cause
)
}
finally
{
session
.
close
()
}
}
suspend
fun
HttpClient
.
wsRaw
(
method
:
HttpMethod
=
HttpMethod
.
Get
,
host
:
String
=
"localhost"
,
port
:
Int
=
DEFAULT_PORT
,
path
:
String
=
"/"
,
request
:
HttpRequestBuilder
.()
->
Unit
=
{},
block
:
suspend
ClientWebSocketSession
.()
->
Unit
):
Unit
=
webSocketRaw
(
method
,
host
,
port
,
path
,
request
,
block
)
suspend
fun
HttpClient
.
wssRaw
(
method
:
HttpMethod
=
HttpMethod
.
Get
,
host
:
String
=
"localhost"
,
port
:
Int
=
DEFAULT_PORT
,
path
:
String
=
"/"
,
request
:
HttpRequestBuilder
.()
->
Unit
=
{},
block
:
suspend
ClientWebSocketSession
.()
->
Unit
):
Unit
=
webSocketRaw
(
method
,
host
,
port
,
path
,
request
=
{
url
.
protocol
=
URLProtocol
.
WSS
url
.
port
=
port
request
()
},
block
=
block
)
ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClient.kt
Просмотр файла @
e8de451d
...
@@ -52,14 +52,16 @@ fun HttpClient(
...
@@ -52,14 +52,16 @@ fun HttpClient(
* Asynchronous client to perform HTTP requests.
* Asynchronous client to perform HTTP requests.
*
*
* This is a generic implementation that uses a specific engine [HttpClientEngine].
* This is a generic implementation that uses a specific engine [HttpClientEngine].
* @property engine: [HttpClientEngine] for executing requests.
*/
*/
class
HttpClient
(
class
HttpClient
(
private
val
engine
:
HttpClientEngine
,
@InternalAPI
val
engine
:
HttpClientEngine
,
private
val
userConfig
:
HttpClientConfig
<
out
HttpClientEngineConfig
>
=
HttpClientConfig
()
private
val
userConfig
:
HttpClientConfig
<
out
HttpClientEngineConfig
>
=
HttpClientConfig
()
)
:
CoroutineScope
,
Closeable
{
)
:
CoroutineScope
,
Closeable
{
private
val
closed
=
atomic
(
false
)
private
val
closed
=
atomic
(
false
)
override
val
coroutineContext
:
CoroutineContext
get
()
=
engine
.
coroutineContext
override
val
coroutineContext
:
CoroutineContext
get
()
=
engine
.
coroutineContext
/**
/**
* Pipeline used for processing all the requests sent by this client.
* Pipeline used for processing all the requests sent by this client.
*/
*/
...
...
ktor-client/ktor-client-core/common/src/io/ktor/client/call/HttpClientCall.kt
Просмотр файла @
e8de451d
...
@@ -4,6 +4,7 @@ import io.ktor.client.*
...
@@ -4,6 +4,7 @@ import io.ktor.client.*
import
io.ktor.client.features.*
import
io.ktor.client.features.*
import
io.ktor.client.request.*
import
io.ktor.client.request.*
import
io.ktor.client.response.*
import
io.ktor.client.response.*
import
io.ktor.util.*
import
kotlinx.atomicfu.*
import
kotlinx.atomicfu.*
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
import
kotlinx.io.core.*
import
kotlinx.io.core.*
...
@@ -13,9 +14,9 @@ import kotlin.reflect.*
...
@@ -13,9 +14,9 @@ import kotlin.reflect.*
/**
/**
* A class that represents a single pair of [request] and [response] for a specific [HttpClient].
* A class that represents a single pair of [request] and [response] for a specific [HttpClient].
*
*
*
[
client
] -
client that executed the call.
*
@property
client
:
client that executed the call.
*/
*/
class
HttpClientCall
internal
constructor
(
open
class
HttpClientCall
constructor
(
val
client
:
HttpClient
val
client
:
HttpClient
)
:
CoroutineScope
,
Closeable
{
)
:
CoroutineScope
,
Closeable
{
private
val
received
=
atomic
(
false
)
private
val
received
=
atomic
(
false
)
...
@@ -23,7 +24,12 @@ class HttpClientCall internal constructor(
...
@@ -23,7 +24,12 @@ class HttpClientCall internal constructor(
override
val
coroutineContext
:
CoroutineContext
get
()
=
response
.
coroutineContext
override
val
coroutineContext
:
CoroutineContext
get
()
=
response
.
coroutineContext
/**
/**
* Represents the [request] sent by the client.
* Typed [Attributes] associated to this call serving as a lightweight container.
*/
val
attributes
:
Attributes
get
()
=
request
.
attributes
/**
* Represents the [request] sent by the client
*/
*/
lateinit
var
request
:
HttpRequest
lateinit
var
request
:
HttpRequest
internal
set
internal
set
...
@@ -70,6 +76,12 @@ class HttpClientCall internal constructor(
...
@@ -70,6 +76,12 @@ class HttpClientCall internal constructor(
}
}
}
}
/**
* Raw http call produced by engine.
*
* @property request - executed http request.
* @property response - raw http response
*/
data class
HttpEngineCall
(
val
request
:
HttpRequest
,
val
response
:
HttpResponse
)
data class
HttpEngineCall
(
val
request
:
HttpRequest
,
val
response
:
HttpResponse
)
/**
/**
...
@@ -98,6 +110,7 @@ suspend inline fun <reified T> HttpResponse.receive(): T = call.receive(typeInfo
...
@@ -98,6 +110,7 @@ suspend inline fun <reified T> HttpResponse.receive(): T = call.receive(typeInfo
/**
/**
* Exception representing that the response payload has already been received.
* Exception representing that the response payload has already been received.
*/
*/
@Suppress
(
"KDocMissingDocumentation"
)
class
DoubleReceiveException
(
call
:
HttpClientCall
)
:
IllegalStateException
()
{
class
DoubleReceiveException
(
call
:
HttpClientCall
)
:
IllegalStateException
()
{
override
val
message
:
String
=
"Response already received: $call"
override
val
message
:
String
=
"Response already received: $call"
}
}
...
@@ -106,6 +119,7 @@ class DoubleReceiveException(call: HttpClientCall) : IllegalStateException() {
...
@@ -106,6 +119,7 @@ class DoubleReceiveException(call: HttpClientCall) : IllegalStateException() {
* Exception representing fail of the response pipeline
* Exception representing fail of the response pipeline
* [cause] contains origin pipeline exception
* [cause] contains origin pipeline exception
*/
*/
@Suppress
(
"KDocMissingDocumentation"
)
class
ReceivePipelineException
(
class
ReceivePipelineException
(
val
request
:
HttpClientCall
,
val
request
:
HttpClientCall
,
val
info
:
TypeInfo
,
val
info
:
TypeInfo
,
...
@@ -116,6 +130,7 @@ class ReceivePipelineException(
...
@@ -116,6 +130,7 @@ class ReceivePipelineException(
* Exception representing the no transformation was found.
* Exception representing the no transformation was found.
* It includes the received type and the expected type as part of the message.
* It includes the received type and the expected type as part of the message.
*/
*/
@Suppress
(
"KDocMissingDocumentation"
)
class
NoTransformationFoundException
(
from
:
KClass
<
*
>,
to
:
KClass
<
*
>)
:
UnsupportedOperationException
()
{
class
NoTransformationFoundException
(
from
:
KClass
<
*
>,
to
:
KClass
<
*
>)
:
UnsupportedOperationException
()
{
override
val
message
:
String
?
=
"No transformation found: $from -> $to"
override
val
message
:
String
?
=
"No transformation found: $from -> $to"
}
}
...
@@ -125,4 +140,5 @@ class NoTransformationFoundException(from: KClass<*>, to: KClass<*>) : Unsupport
...
@@ -125,4 +140,5 @@ class NoTransformationFoundException(from: KClass<*>, to: KClass<*>) : Unsupport
ReplaceWith
(
"NoTransformationFoundException"
),
ReplaceWith
(
"NoTransformationFoundException"
),
DeprecationLevel
.
ERROR
DeprecationLevel
.
ERROR
)
)
@Suppress
(
"KDocMissingDocumentation"
)
typealias
NoTransformationFound
=
NoTransformationFoundException
typealias
NoTransformationFound
=
NoTransformationFoundException
ktor-client/ktor-client-core/common/src/io/ktor/client/call/utils.kt
Просмотр файла @
e8de451d
...
@@ -9,6 +9,10 @@ import io.ktor.http.content.*
...
@@ -9,6 +9,10 @@ import io.ktor.http.content.*
class
UnsupportedContentTypeException
(
content
:
OutgoingContent
)
:
class
UnsupportedContentTypeException
(
content
:
OutgoingContent
)
:
IllegalStateException
(
"Failed to write body: ${content::class}"
)
IllegalStateException
(
"Failed to write body: ${content::class}"
)
class
UnsupportedUpgradeProtocolException
(
url
:
Url
)
:
IllegalArgumentException
(
"Unsupported upgrade protocol exception: $url"
)
/**
/**
* Constructs a [HttpClientCall] from this [HttpClient] and
* Constructs a [HttpClientCall] from this [HttpClient] and
* with the specified HTTP request [builder].
* with the specified HTTP request [builder].
...
...
ktor-client/ktor-client-core/common/src/io/ktor/client/features/HttpSend.kt
Просмотр файла @
e8de451d
...
@@ -61,7 +61,7 @@ class HttpSend(
...
@@ -61,7 +61,7 @@ class HttpSend(
do
{
do
{
callChanged
=
false
callChanged
=
false
passInterceptors@
for
(
interceptor
in
feature
.
interceptors
)
{
passInterceptors@
for
(
interceptor
in
feature
.
interceptors
)
{
val
transformed
=
interceptor
(
sender
,
currentCall
)
val
transformed
=
interceptor
(
sender
,
currentCall
)
if
(
transformed
===
currentCall
)
continue
@passInterceptors
if
(
transformed
===
currentCall
)
continue
@passInterceptors
...
@@ -77,7 +77,7 @@ class HttpSend(
...
@@ -77,7 +77,7 @@ class HttpSend(
}
}
private
class
DefaultSender
(
private
val
maxSendCount
:
Int
,
private
val
client
:
HttpClient
)
:
Sender
{
private
class
DefaultSender
(
private
val
maxSendCount
:
Int
,
private
val
client
:
HttpClient
)
:
Sender
{
private
var
sentCount
=
0
private
var
sentCount
:
Int
=
0
override
suspend
fun
execute
(
requestBuilder
:
HttpRequestBuilder
):
HttpClientCall
{
override
suspend
fun
execute
(
requestBuilder
:
HttpRequestBuilder
):
HttpClientCall
{
if
(
sentCount
>=
maxSendCount
)
throw
SendCountExceedException
(
"Max send count $maxSendCount exceeded"
)
if
(
sentCount
>=
maxSendCount
)
throw
SendCountExceedException
(
"Max send count $maxSendCount exceeded"
)
...
...
ktor-client/ktor-client-core/common/src/io/ktor/client/request/Content.kt
Просмотр файла @
e8de451d
...
@@ -5,7 +5,7 @@ import io.ktor.http.*
...
@@ -5,7 +5,7 @@ import io.ktor.http.*
import
kotlinx.coroutines.io.*
import
kotlinx.coroutines.io.*
abstract
class
ClientUpgradeContent
:
OutgoingContent
.
NoContent
()
{
abstract
class
ClientUpgradeContent
:
OutgoingContent
.
NoContent
()
{
private
val
content
:
ByteChannel
=
ByteChannel
()
private
val
content
:
ByteChannel
by
lazy
{
ByteChannel
()
}
val
output
:
ByteWriteChannel
get
()
=
content
val
output
:
ByteWriteChannel
get
()
=
content
...
...
Пред
1
2
3
4
След
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать