avolkmann
06/10/2018, 11:13 AMskipWhen
flag, which according to doc: If there is no filters, authentication is required. If any filter returns true, authentication is not required.
Meaning that when it returns true, auth is optional. But it seems more like it completely skips the auth process.dave08
06/13/2018, 12:42 PMcoder82
06/13/2018, 9:16 PMdave08
06/14/2018, 4:18 PMcoder82
06/14/2018, 8:52 PMvincent.brule
06/15/2018, 9:44 AMNathan Hartwell
06/15/2018, 1:36 PMAccept
header? I'm not seeing an obvious way to configure the module to use a default, and also have not been able to figure out a way to mutate / replace the request headers before the ContentNegotiation module looks at them to fake it out.Axel
06/16/2018, 8:16 AMkatokay
06/17/2018, 12:58 AMfun main(args: Array<String>) {
val server = embeddedServer(Netty, port = 9000) {
intercept(ApplicationCallPipeline.Infrastructure){
val requestId = UUID.randomUUID()
MDC.putCloseable("req.Id", requestId.toString()).use {
<http://this.context.application.log.info|this.context.application.log.info>("Interceptor")
proceed()
}
}
routing {
get("/") {
<http://call.application.log.info|call.application.log.info>("Inside /")
call.respondText("Hello World!", ContentType.Text.Plain)
}
}
}
server.start(wait = true)
}
I tested using wrk -t6 -c200 -d15s <http://localhost:9000/>
just to get a little bit of concurrency.
Added context:
https://github.com/Kotlin/kotlinx.coroutines/issues/119christophsturm
06/17/2018, 12:54 PMcoder82
06/18/2018, 7:53 AMcoder82
06/18/2018, 11:54 AMSlackbot
06/18/2018, 12:58 PMvincent.brule
06/18/2018, 1:26 PMDeactivated User
06/18/2018, 2:05 PMcoder82
06/18/2018, 3:00 PMpike
06/19/2018, 3:59 AMpike
06/19/2018, 5:49 AMjozefdransfield
06/19/2018, 9:03 PMvincent.brule
06/20/2018, 7:24 AMDeactivated User
06/20/2018, 1:34 PMvincent.brule
06/20/2018, 1:38 PMavolkmann
06/21/2018, 6:47 AMdefault
to specify a default file, shouldn't it be served, when I call an otherwise unhandled endpoint?Matt
06/21/2018, 12:06 PMinstall(CORS) { anyHost() }
just when I'm running locally in developer mode -- is there a standard way to check that programatically?mkporwit
06/21/2018, 5:33 PMval result = client.get<HttpResponse> { /* your code here */ }
val data = result.content.readRemaining().readText()
vincent.brule
06/22/2018, 8:35 AMmkporwit
06/26/2018, 4:16 AM0.9.3-alpha-6
, that would be great with me 🙂Matt
06/26/2018, 11:37 AMwithTestApplication
to test my microservice, and wanted to send it data classes rather than JSON strings, and receive unmarshalled data classes as responses (rather than raw JSON strings from HTTP response bodies). Is it a case of just using Jackson directly, or is there any special support available in Ktor for this?cy
06/26/2018, 12:30 PM0.9.3
has been released
* Improved WebSocket API
* Websocket header Sec-WebSocket-Key
is now optional
* Fixed client cookies rendering to avoid x-enc
* Fixed plain text client reader (#392)
* Added EC support in CIO TLS (#394: ECDHE_RSA_AES256_SHA384, ECDHE_RSA_AES128_SHA256)
* Fix client certificate validation
* Introduced optional authentication
* Added ApplicationCall
as receiver for auth validate
functions
* Introduced call.respondBytes
(#395)
* Improved JWT support: multiple schemes, nullable issuer
* Conversion service enum type diagnostics improved (#403)
* Avoided using apos entity in HTML escaping as IE doesn't support it (#400)
* Converter support for java big numbers
* Ability to add auth methods to existing feature on the fly
* Improved auth header scheme and contents validation (#415)
* Default charset for BasicAuth is now UTF-8 (#420)
* Added ByteArrayContent.contentLength
(#421)
* Fixed headersOf
case insensitive issue (#426)
* Client deserialization improved by using type token
* Ability to disable client default transformers
* Explicit Accept
header in client request
* Turn on masking in client websockets (#423)
* Fixed inverted PartialContent.Configuration.maxRangeCount
check (#440)
* Fixed uncaught UnsupportedMediaTypeException
from receiveOrNull()
(#442)
* Fix multipart boundary header parsing
* Upgraded jwks/jwt, applied RSA256 by default if unspecified (#434, #435)
* Upgrade coroutine version to 0.23.3
* Upgrade Jetty version to 9.4.11.v20180605
* Add client-mock-engine
for testing purpose
* Use default available engine by deafult
* Upgrade kotlin to 1.2.50
Move ktor-samples to a separate repository (#340). https://github.com/ktorio/ktor-samples
See http://ktor.io/quickstart/migration/0.9.3.html for migration stepsrocketraman
06/26/2018, 2:08 PMInputStream
. Oddly, this doesn't appear to be a built-in function? I've created this class which I'm passing to call.respond
, but can someone comment on whether I'm missing something here?
class InputStreamContent(
private val stream: InputStream,
etag: String?,
override val contentLength: Long?,
override val contentType: ContentType): OutgoingContent.ReadChannelContent() {
init {
if (etag != null) versions += EntityTagVersion(etag)
}
override fun readFrom(): ByteReadChannel = stream.toByteReadChannel()
}
rocketraman
06/26/2018, 2:08 PMInputStream
. Oddly, this doesn't appear to be a built-in function? I've created this class which I'm passing to call.respond
, but can someone comment on whether I'm missing something here?
class InputStreamContent(
private val stream: InputStream,
etag: String?,
override val contentLength: Long?,
override val contentType: ContentType): OutgoingContent.ReadChannelContent() {
init {
if (etag != null) versions += EntityTagVersion(etag)
}
override fun readFrom(): ByteReadChannel = stream.toByteReadChannel()
}
cy
06/26/2018, 2:34 PMInputStream
is blocking so it may cause problems once the stream
get stuckrocketraman
06/26/2018, 2:39 PMAsynchronousSocketChannel
or something.cy
06/26/2018, 2:51 PMDeactivated User
06/26/2018, 2:52 PMrocketraman
06/26/2018, 2:53 PMcy
06/26/2018, 2:59 PMrocketraman
06/26/2018, 3:08 PMSingle
or Observable
to deal with.Deactivated User
06/26/2018, 3:20 PMwriter
from kotlinx.coroutines-io to custom generate a ByteReadChannel
. If you have a callback function receiving ByteBuffer chunks, you can create a channel and pass to that writer jobrocketraman
06/26/2018, 3:23 PMcy
06/26/2018, 4:15 PMrocketraman
06/26/2018, 4:23 PMFlowable<ByteBuffer>
to a ByteReadChannel
via `writer`:
suspend fun Flowable<ByteBuffer>.toByteReadChannel(parent: Job = Job()) = writer(Unconfined, parent = parent, autoFlush = true) {
try {
this@toByteReadChannel.consumeEach {
channel.writeFully(it)
}
} catch (e: Throwable) {
channel.close(e)
}
}.channel
I haven't fully explored whether this is doing all the right things under the hood, but it seems to work. If I put a breakpoint at the writeFully
line I see the client getting bytes a chunk at a time, as each breakpoint is hit and run.Flowable
that is being consumed by a suspendable.cy
06/27/2018, 8:19 AMthis@toByteReadChannel.consumeEach
what does it do? Does Flowable have consumeEach
? Where it is implemented?rocketraman
06/27/2018, 2:14 PMByteReadChannel
to a Flowable<ByteBuffer>
. I ended up with this:
suspend fun ByteReadChannel.toFlowable(): Flowable<ByteBuffer> {
return rxFlowable {
this@toFlowable.lookAheadSuspend {
consumeEachRemaining {
// we have to make a copy otherwise the ByteBuffer gets recycled by ktor and the Flowable items get corrupted
this@rxFlowable.channel.send(it.copy())
true
}
this@rxFlowable.close()
}
}
}
Note the copy()
in there on the ByteBuffer
from ktor. Without that, the upload contained garbage. I'm pretty sure its due to concurrent ByteBuffer recycling by ktor, which corrupts the Flowable. Is there a better approach to this?cy
06/27/2018, 2:17 PMrocketraman
06/27/2018, 2:20 PMByteReadChannel
API I should use to split it up into `ByteBuffer`'s I can send to a Flowable
? Btw, rxFlowable
here also comes from the same rx2 coroutines adapter lib.cy
06/27/2018, 3:08 PMrocketraman
06/27/2018, 3:18 PM