ktorio / ktor Goto Github PK
View Code? Open in Web Editor NEWFramework for quickly creating connected applications in Kotlin with minimal effort
Home Page: https://ktor.io
License: Apache License 2.0
Framework for quickly creating connected applications in Kotlin with minimal effort
Home Page: https://ktor.io
License: Apache License 2.0
RFC4627 Section 3 specifies that the default encoding of application/json
is UTF-8. Ktor falls back to ISO-8859-1 (see RequestContent.kt:11).
Further, the application/json entry on IANA has the note:
Note: No "charset" parameter is defined for this registration.
Adding one really has no effect on compliant recipients.
Ktor doesn't comply here to the standard and is to be considered as non-compliant server. See discussions on this issue e.g. on request/request#383.
Please fallback on application/json
to UTF-8.
When you compiling something with gradle dependency to ktor-core, you got this warning, but if you try to build fatJar you gonna build fail.
Sample gradle file
version '0.1-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.0.3'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
sourceCompatibility = 1.8
repositories {
maven {
url 'http://dl.bintray.com/kotlin/ktor'
}
mavenCentral()
jcenter()
}
dependencies {
compile 'org.jetbrains.ktor:ktor-core:0.2.2'
compile 'org.jetbrains.ktor:ktor-netty:0.2.2'
}
task fatJar(type: Jar) {
manifest {
attributes "Main-Class": "MainClass"
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':fatJar'.
> Could not expand ZIP '/<somePath>/kotlinx-support-jdk8-0.1-alpha-2.pom'.
Hi, I would like to have some documentation of ktor before using it. The Wiki has some links with empty content.
As a rookie I have no idea how to run the hello world sample from the command line. Can you maybe add that to the docs? I suppose its a simple command
No quite sure why it happened but should be handled somehow.
java.lang.IllegalArgumentException: endInclusive shouldn't be less than start but start = 0, endInclusive = -1
at org.jetbrains.ktor.nio.FileReadChannel.<init>(FileReadChannel.kt:16)
at org.jetbrains.ktor.nio.FileReadChannel.<init>(FileReadChannel.kt:8)
at org.jetbrains.ktor.nio.FileReadChannelKt.asyncReadOnlyFileChannel(FileReadChannel.kt:84)
at org.jetbrains.ktor.nio.FileReadChannelKt.asyncReadOnlyFileChannel(FileReadChannel.kt:85)
at org.jetbrains.ktor.nio.FileReadChannelKt.asyncReadOnlyFileChannel$default(FileReadChannel.kt:85)
at org.jetbrains.ktor.content.LocalFileContent.channel(StaticContent.kt:31)
at org.jetbrains.ktor.content.LocalFileContent.channel(StaticContent.kt:15)
at org.jetbrains.ktor.content.FinalContent$ChannelContent.startContent(FinalContent.kt:28)
at org.jetbrains.ktor.host.BaseApplicationCall$1.invoke(BaseApplicationCall.kt:64)
at org.jetbrains.ktor.host.BaseApplicationCall$1.invoke(BaseApplicationCall.kt:11)
at org.jetbrains.ktor.pipeline.PipelineBlock.call(PipelineBlock.kt:9)
at org.jetbrains.ktor.pipeline.PipelineMachine.proceed(PipelineMachine.kt:34)
at org.jetbrains.ktor.pipeline.PipelineExecution.proceed(PipelineExecution.kt:18)
at org.jetbrains.ktor.pipeline.AsyncKt.continuePipeline(Async.kt:104)
at org.jetbrains.ktor.transform.TransformationSupport$transform$1$1.invoke(TransformIntercept.kt:39)
at org.jetbrains.ktor.transform.TransformationSupport$transform$1$1.invoke(TransformIntercept.kt:11)
at org.jetbrains.ktor.pipeline.PipelineMachine.proceed(PipelineMachine.kt:86)
at org.jetbrains.ktor.pipeline.PipelineMachine.execute(PipelineMachine.kt:15)
at org.jetbrains.ktor.transform.TransformationSupport.transform(TransformIntercept.kt:48)
at org.jetbrains.ktor.transform.TransformationSupport.access$transform(TransformIntercept.kt:11)
at org.jetbrains.ktor.transform.TransformationSupport$install$1$1.invoke(TransformIntercept.kt:23)
at org.jetbrains.ktor.transform.TransformationSupport$install$1$1.invoke(TransformIntercept.kt:11)
at org.jetbrains.ktor.pipeline.PipelineBlock.call(PipelineBlock.kt:9)
at org.jetbrains.ktor.pipeline.PipelineMachine.proceed(PipelineMachine.kt:34)
at org.jetbrains.ktor.pipeline.PipelineMachine.execute(PipelineMachine.kt:15)
at org.jetbrains.ktor.pipeline.AsyncKt$executeOn$1.run(Async.kt:23)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
If an application/x-www-form-urlencoded
POST contains invalid data like foo=foo+%+bar
ktor will create threads stuck in an infinite loop at org.jetbrains.ktor.http.CodecsKt.decode(Codecs.kt:37)
.
Perhaps a fuzzer should be used in the test suite to ensure ktor is resilient to this sort of problem.
I see a bunch of broken links and missing documentation. Is this project officially supported by jetbrains?
It would be great to be able to write twig
templates (not a fan of freemarker :)
I have a long running request (>1min). At some point the server just crashes with the following breakpoint.
Even if I just put a "thread only" suspending breakpoint in the post
body it crashes
java.lang.IllegalStateException: ReadListener already set
at org.eclipse.jetty.server.HttpInput.setReadListener(HttpInput.java:600) ~[jetty-server-9.3.13.v20161014.jar:9.3.13.v20161014]
at org.jetbrains.ktor.servlet.ServletReadChannel.read(ServletReadChannel.kt:45) ~[ktor-servlet-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.nio.AsyncReadChannelAdapterStream.read(Channels.kt:114) ~[ktor-core-0.2.3.jar:0.2.3]
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) ~[na:1.8.0_60]
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) ~[na:1.8.0_60]
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[na:1.8.0_60]
at java.io.InputStreamReader.read(InputStreamReader.java:184) ~[na:1.8.0_60]
at java.io.Reader.read(Reader.java:140) ~[na:1.8.0_60]
at kotlin.io.TextStreamsKt.copyTo(ReadWrite.kt:116) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at kotlin.io.TextStreamsKt.copyTo$default(ReadWrite.kt:113) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at kotlin.io.TextStreamsKt.readText(ReadWrite.kt:100) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at org.jetbrains.ktor.request.RequestContent$contentAsString$2.invoke(RequestContent.kt:11) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.request.RequestContent$contentAsString$2.invoke(RequestContent.kt:10) ~[ktor-core-0.2.3.jar:0.2.3]
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at org.jetbrains.ktor.request.RequestContent.getContentAsString(RequestContent.kt) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.request.RequestContent.get(RequestContent.kt:37) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.request.RequestContent$computedValuesMap$2.invoke(RequestContent.kt:49) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.request.RequestContent$computedValuesMap$2.invoke(RequestContent.kt:10) ~[ktor-core-0.2.3.jar:0.2.3]
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at org.jetbrains.ktor.request.RequestContent.getComputedValuesMap(RequestContent.kt) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.request.RequestContent.get(RequestContent.kt:38) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.host.BaseApplicationCall$parameters$2.invoke(BaseApplicationCall.kt:185) ~[ktor-hosts-common-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.host.BaseApplicationCall$parameters$2.invoke(BaseApplicationCall.kt:13) ~[ktor-hosts-common-0.2.3.jar:0.2.3]
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131) ~[kotlin-stdlib-1.0.5.jar:1.0.5]
at org.jetbrains.ktor.host.BaseApplicationCall.getParameters(BaseApplicationCall.kt) ~[ktor-hosts-common-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.routing.Routing.interceptor(Routing.kt:10) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.routing.Routing.access$interceptor(Routing.kt:7) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.routing.Routing$Feature$install$1.invoke(Routing.kt:28) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.routing.Routing$Feature$install$1.invoke(Routing.kt:23) ~[ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.PipelineMachine.runAction(PipelineMachine.kt:113) [ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.PipelineMachine.loop(PipelineMachine.kt:105) [ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.PipelineMachine.proceed(PipelineMachine.kt:25) [ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.PipelineMachine.execute(PipelineMachine.kt:16) [ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.AsyncKt$executeOn$1.get(Async.kt:30) [ktor-core-0.2.3.jar:0.2.3]
at org.jetbrains.ktor.pipeline.AsyncKt$executeOn$1.get(Async.kt) [ktor-core-0.2.3.jar:0.2.3]
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) [na:1.8.0_60]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_60]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_60]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_60]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
import org.jetbrains.ktor.application.call
import org.jetbrains.ktor.http.ContentType
import org.jetbrains.ktor.netty.embeddedNettyServer
import org.jetbrains.ktor.response.respondText
import org.jetbrains.ktor.routing.get
import org.jetbrains.ktor.routing.routing
fun main(args: Array<String>) {
embeddedNettyServer {
routing {
get("/") {
call.respondText(ContentType.Text.Plain, "Hello, world!")
}
}
}
}
And here's the logging output:
"C:\Program Files\Java\jdk1.8.0_112\bin\java" -Didea.launcher.port=7538 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_112\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\rt.jar;D:\Desktop\CheatLife-Web\build\classes\main;D:\Desktop\CheatLife-Web\build\resources\main;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.1-M03\1c4aa4b0dab7b4c111934f34e6506812d7e974a2\kotlin-stdlib-1.1-M03.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlinx\kotlinx.html.jvm\0.5.12\3da1a90368af646a445193dc31da6a4d9c5f0458\kotlinx.html.jvm-0.5.12.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.ktor\ktor-netty\0.2.4\3af06c53d0be9f5052eaffde1013613c14a87d5f\ktor-netty-0.2.4.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-runtime\1.1-M03\4069ca5d11d19708ad18b0266bb77af0c54a47a8\kotlin-runtime-1.1-M03.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlinx\kotlinx.html.shared\0.5.12\5cb67c768cfef3c12f0d2f98916b1a0eae124ec8\kotlinx.html.shared-0.5.12-jvm.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.ktor\ktor-hosts-common\0.2.4\9b36e5b96bf0d3e4e743471826ed6ff43e77da83\ktor-hosts-common-0.2.4.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.5.Final\6568f4fefc2ce0a8761e5bc14d95a6ba1758be29\netty-codec-http2-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.eclipse.jetty.alpn\alpn-api\1.1.3.v20160715\a1bf3a937f91b4c953acd13e8c9552347adc2198\alpn-api-1.1.3.v20160715.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.ktor\ktor-core\0.2.4\cdb24fa130d4636e793971105603f98af040e14c\ktor-core-0.2.4.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.0.5-2\b20effae1385355c5216c647300efe35f97aa2ae\kotlin-reflect-1.0.5-2.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlinx\kotlinx-support-jdk8\0.3\5fe4a54228199cd21454469fb1e9ccc354c500a8\kotlinx-support-jdk8-0.3.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\1.7.21\139535a69a4239db087de9bab0bee568bf8e0b70\slf4j-api-1.7.21.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.1.2\b316e9737eea25e9ddd6d88eaeee76878045c6b2\logback-classic-1.1.2.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\com.typesafe\config\1.2.1\f771f71fdae3df231bcd54d5ca2d57f0bf93f467\config-1.2.1.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.5.Final\87bda1b9ec7e3f75ca721fc87735cbedad2aa1a\netty-codec-http-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.5.Final\6262900ee9487e62560030a136160df953b1cd6b\netty-handler-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\com.googlecode.json-simple\json-simple\1.1.1\c9ad4a0850ab676c5c64461a05ca524cdfff59f1\json-simple-1.1.1.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlinx\kotlinx-support-jdk7\0.3\3313e3973024cd6ca92c4b2a06fb3a7110743126\kotlinx-support-jdk7-0.3.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.1.2\2d23694879c2c12f125dac5076bdfd5d771cc4cb\logback-core-1.1.2.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.5.Final\66bbf9324fa36467d041083f89328e2a24ec4f67\netty-codec-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.5.Final\b5fb6bccda4d63d4a74c9faccdf32f77ab66abc1\netty-buffer-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.5.Final\37126b370722ff9631ee13c91139aacec0a71d1d\netty-transport-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\junit\junit\4.10\e4f1766ce7404a08f45d859fb9c226fc9e41a861\junit-4.10.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.5.Final\607f8433d8782445e72abe34e43a7e57e86a5e6c\netty-common-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.5.Final\5f367bedcdc185a727fda3296b9a18014cdc22c4\netty-resolver-4.1.5.Final.jar;C:\Users\Jire\.gradle\caches\modules-2\files-2.1\org.hamcrest\hamcrest-core\1.1\860340562250678d1a344907ac75754e259cdb14\hamcrest-core-1.1.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain life.cheat.www.MainKt
19:50:56.518 [main] DEBUG i.n.u.i.l.InternalLoggerFactory - Using SLF4J as the default logging framework
19:50:56.526 [main] DEBUG i.n.c.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 8
19:50:56.543 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
19:50:56.544 [main] DEBUG i.n.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
19:50:56.545 [main] DEBUG i.n.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
19:50:56.545 [main] DEBUG i.n.util.internal.PlatformDependent0 - direct buffer constructor: available
19:50:56.546 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true
19:50:56.546 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.<init>(long, int): available
19:50:56.547 [main] DEBUG io.netty.util.internal.Cleaner0 - java.nio.ByteBuffer.cleaner(): available
19:50:56.547 [main] DEBUG i.n.util.internal.PlatformDependent - Platform: Windows
19:50:56.547 [main] DEBUG i.n.util.internal.PlatformDependent - Java version: 8
19:50:56.547 [main] DEBUG i.n.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
19:50:56.547 [main] DEBUG i.n.util.internal.PlatformDependent - sun.misc.Unsafe: available
19:50:56.548 [main] DEBUG i.n.util.internal.PlatformDependent - -Dio.netty.noJavassist: false
19:50:56.548 [main] DEBUG i.n.util.internal.PlatformDependent - Javassist: unavailable
19:50:56.548 [main] DEBUG i.n.util.internal.PlatformDependent - You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes. Please check the configuration for better performance.
19:50:56.549 [main] DEBUG i.n.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\Jire\AppData\Local\Temp (java.io.tmpdir)
19:50:56.549 [main] DEBUG i.n.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
19:50:56.549 [main] DEBUG i.n.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
19:50:56.549 [main] DEBUG i.n.util.internal.PlatformDependent - io.netty.maxDirectMemory: 3804758016 bytes
19:50:56.563 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
19:50:56.563 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
19:50:56.565 [main] DEBUG i.n.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 8
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 8
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.tinyCacheSize: 512
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
19:50:56.712 [main] DEBUG i.n.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
Process finished with exit code 0
My error was to use /static/*
as the route instead of /static
. Because of this the path
variable was empty and it crashed.
Maybe there should be a way to prevent this kind of user error. Documenting StaticContent would be a first step.
Also don't try to read the basePath
folder as a file when path
is empty.
When I have following code fragments:
fun main(args: Array<String>) {
embeddedNettyServer(8080) {
get("/test") {
authentication {
println("authentication...")
basicAuthentication("ktor") {
println("within basic ...")
authenticate(it)
}
}
call.respond("Hello")
}
}.start(wait = true)
}
fun authenticate(user: UserPasswordCredential): Principal? {
println(user)
return users[user.name]?.let {
if (it == user.password)
UserIdPrincipal(user.name)
else null
}
}
I can call curl abosch@localhost:8080/test
and get "Hello" prompt on first call. Following calls show me correctly that no password is specified and "Hello" is not returned.
Is it a bug or do I not understand how to use the authentication :) ?
Ensure there is a test for flush/stream.
On an ApplicationCall
there are
response
property which is ApplicationResponserespond
property which is ResponsePipelinerespond
function which executes a subject on a pipelineWe need to figure our better non-confusing APIs.
It seems the bintray profile needs to be activated. e.g.
mvn clean package -P dev,bintray
Maybe bintray
could be activated by default or some note added in the readme for building.
I've been playing with this over the weekend and have got it running in an embedded context and using the org.jetbrains.ktor.jetty.DevelopmentHost
The next step was to deploy to a Jetty instance, and that's where I'm running into this problem. It's been a while since I've played with a WAR, so maybe I'm doing something obviously wrong.
2017-02-12 18:46:56.210:WARN:oejs.HttpChannel:qtp4076014-11: /homeseer-brains/
javax.servlet.ServletException: org.eclipse.jetty.servlet.ServletHolder$1: java.lang.IllegalStateException: ServletConfig has not been initialized
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:138)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:122)
at org.eclipse.jetty.util.thread.strategy.ExecutingExecutionStrategy.invoke(ExecutingExecutionStrategy.java:58)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:201)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:133)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
Caused by:
org.eclipse.jetty.servlet.ServletHolder$1: java.lang.IllegalStateException: ServletConfig has not been initialized
at org.eclipse.jetty.servlet.ServletHolder.makeUnavailable(ServletHolder.java:596)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:648)
at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:498)
at org.eclipse.jetty.servlet.ServletHolder.ensureInstance(ServletHolder.java:785)
at org.eclipse.jetty.servlet.ServletHolder.prepare(ServletHolder.java:770)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:538)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1584)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1228)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:481)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1553)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1130)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:118)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
Caused by:
java.lang.IllegalStateException: ServletConfig has not been initialized
at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:199)
at org.jetbrains.ktor.servlet.ServletApplicationHost$loader$2.invoke(ServletApplicationHost.kt:15)
at org.jetbrains.ktor.servlet.ServletApplicationHost$loader$2.invoke(ServletApplicationHost.kt:13)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130)
at org.jetbrains.ktor.servlet.ServletApplicationHost.getLoader(ServletApplicationHost.kt)
at org.jetbrains.ktor.servlet.ServletApplicationHost.<init>(ServletApplicationHost.kt:36)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at org.eclipse.jetty.server.handler.ContextHandler$Context.createInstance(ContextHandler.java:2510)
at org.eclipse.jetty.servlet.ServletContextHandler$Context.createServlet(ServletContextHandler.java:1326)
at org.eclipse.jetty.servlet.ServletHolder.newInstance(ServletHolder.java:1273)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:614)
at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:498)
at org.eclipse.jetty.servlet.ServletHolder.ensureInstance(ServletHolder.java:785)
at org.eclipse.jetty.servlet.ServletHolder.prepare(ServletHolder.java:770)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:538)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1584)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1228)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:481)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1553)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1130)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:118)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
In readme in testable is mention TestHost, please add link to that library.
Unhandled exceptions are usually printed (afaik) but the IllegalArgumentException
here isnt. My guess would be it should always be printed.
class Blocking(environment: ApplicationEnvironment) : Application(environment) {
init {
routing {
method(HttpMethod.Post){
route("/exception") {
handle {
println("exception")
throw IllegalArgumentException()
}
}
route("/exception2") {
handle {
println("exception2")
subject.respondWrite {
throw IllegalArgumentException()
}
}
}
}
}
}
}
class ExceptionEater {
@Test
fun foo(){
val port = 44003
val appHostConfig = applicationHostConfig { connector { this.port = port } }
val appEnv = BasicApplicationEnvironment(javaClass.classLoader, SLF4JApplicationLog("KTorTest"), MapApplicationConfig(
"ktor.application.class" to Blocking::class.qualifiedName!!
))
val jetty = JettyApplicationHost(appHostConfig, appEnv)
jetty.start()
val paths = listOf("exception", "exception2")
val e = Executors.newCachedThreadPool()
paths.map { path ->
e.submit(Callable {
val c = URL("http://localhost:$port/$path").openConnection() as HttpURLConnection
c.doOutput = true
c.outputStream.apply {
write("Foo".toByteArray(StandardCharsets.UTF_8))
flush()
}
c.inputStream.bufferedReader().readLine().apply {
println("Done")
}
})
}
TimeUnit.SECONDS.sleep(10)
}
}
I tried to get it working with both the Netty and Jetty embedded server. I am using Ktor 0.2.4 and Kotlin 1.1-M03.
import org.jetbrains.ktor.application.call
import org.jetbrains.ktor.application.install
import org.jetbrains.ktor.features.DefaultHeaders
import org.jetbrains.ktor.jetty.embeddedJettyServer
import org.jetbrains.ktor.logging.CallLogging
import org.jetbrains.ktor.response.respondText
import org.jetbrains.ktor.routing.Routing
import org.jetbrains.ktor.routing.get
fun main(args: Array<String>) = embeddedJettyServer {
install(DefaultHeaders)
install(CallLogging)
install(Routing) {
get("/") {
call.respondText("Hello, World!")
}
}
}.start()
2016-12-09 20:23:11.000 [main] INFO org.eclipse.jetty.util.log - Logging initialized @426ms
2016-12-09 20:23:11.064 [main] TRACE embedded - Starting server...
2016-12-09 20:23:11.065 [main] INFO org.eclipse.jetty.server.Server - jetty-9.3.13.v20161014
2016-12-09 20:23:11.126 [main] INFO o.e.jetty.server.AbstractConnector - Started ServerConnector@69a10787{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-16, h2c-15, h2c-14]}{0.0.0.0:80}
2016-12-09 20:23:11.126 [main] INFO org.eclipse.jetty.server.Server - Started @555ms
2016-12-09 20:23:11.126 [main] TRACE embedded - Server running.
2016-12-09 20:23:13.826 [ktor-pool-1-thread-1] ERROR embedded - null: GET - /
java.lang.IncompatibleClassChangeError: class kotlin.reflect.jvm.internal.KFunctionImpl has interface kotlin.jvm.internal.FunctionImpl as super class
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_112]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_112]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_112]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_112]
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_112]
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_112]
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_112]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_112]
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_112]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_112]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_112]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_112]
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$visitor$1.visitFunctionDescriptor(KDeclarationContainerImpl.kt:68) ~[kotlin-reflect-1.0.5-2.jar:1.0.5-2]
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$visitor$1.visitFunctionDescriptor(KDeclarationContainerImpl.kt:52) ~[kotlin-reflect-1.0.5-2.jar:1.0.5-2]
at kotlin.reflect.jvm.internal.impl.descriptors.impl.FunctionDescriptorImpl.accept(FunctionDescriptorImpl.java:613) ~[kotlin-reflect-1.0.5-2.jar:1.0.5-2]
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$2.invoke(KDeclarationContainerImpl.kt:81) ~[kotlin-reflect-1.0.5-2.jar:1.0.5-2]
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$2.invoke(KDeclarationContainerImpl.kt:33) ~[kotlin-reflect-1.0.5-2.jar:1.0.5-2]
at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:137) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:98) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:121) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:97) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:121) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:533) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:557) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:550) ~[kotlin-stdlib-1.1-M03.jar:1.1-M03]
at kotlin.reflect.KClasses.getMemberProperties(KClasses.kt:142) ~[kotlin-reflect-1.0.5-2.jar:1.1-M03]
at org.jetbrains.ktor.http.HttpStatusCode.<clinit>(HttpStatusCode.kt:65) ~[ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.host.BaseApplicationCall.commit(BaseApplicationCall.kt:24) ~[ktor-hosts-common-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.host.BaseApplicationCall.handleFinalContent(BaseApplicationCall.kt:87) ~[ktor-hosts-common-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.host.BaseApplicationCall$1.invoke(BaseApplicationCall.kt:47) ~[ktor-hosts-common-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.host.BaseApplicationCall$1.invoke(BaseApplicationCall.kt:13) ~[ktor-hosts-common-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.PipelineMachine.runAction(PipelineMachine.kt:111) [ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.PipelineMachine.loop(PipelineMachine.kt:103) [ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.PipelineMachine.proceed(PipelineMachine.kt:25) [ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.PipelineMachine.execute(PipelineMachine.kt:16) [ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.AsyncKt$executeOn$1.get(Async.kt:30) [ktor-core-0.2.4.jar:0.2.4]
at org.jetbrains.ktor.pipeline.AsyncKt$executeOn$1.get(Async.kt) [ktor-core-0.2.4.jar:0.2.4]
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) [na:1.8.0_112]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_112]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_112]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_112]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_112]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_112]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_112]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]
A number of ktor gradle artifacts specify logback-classic as a dependency, however best practice for libraries is to include something like sl4j-api, but not any specific logging implementation - to prevent an application's logs from being filled up with logging generated by a library.
The workaround is to do something like this:
compile ('org.jetbrains.ktor:ktor-core:0.3.0') {
exclude group : 'ch.qos.logback', module : 'logback-classic'
}
The wiki page says "For now watch keys are just strings that are matched with contains
against path to classes/jars of the loaded application." To me, that wording suggests I could use the pathname of a class or a package.
If I try to watch
using a substring from a package name (eg "web" from org.example.web
), it doesn't work (unless that substring happens to be part of the classpath entry), with this misleading warning:
Application.Loader - No ktor.deployment.watch patterns specified: hot reload is disabled
I think this would be clearer (in the wiki):
"For now watch
keys are just substrings that are matched with contains
against classpath entries of the loaded application, such as a jar name or a project directory name."
If I want a URL to look like this:
/?novalue
The best I can come up with is:
@Location("/") class SomeLocation private constructor(val novalue:String){
constructor():this("")
}
Which give:
/?novalue=
If exception happens in ktor and is not handled by an interceptor such as StatusPages, it should propagate up to host and be handled there without using any ktor facilities like response pipeline. The reason is that we don't know which part of the system were at fault and it could very well be response pipeline itself. So unhandled exception should be propagated to the host-specific facilities and responded with 500 status code natively there.
Note, that it would make 500 Internal Server Error
status produced in this case not interceptable by StatusPage
feature on a per code basis, but exception filter in the same feature can be installed on Throwable
and do pretty much any custom handling there. At this moment exception would be considered handled and won't be part of this issue.
The Readme.md indicates an Automatic HEAD response. It's not as automatic as one could expect. It needs the installation of HeadRequestSupport feature AND the routing of HEAD requests.
This feature:
As a workaround to set up the Head routing for every Get mapping, you can add this extension method:
fun Route.getOrHead(path: String, body: PipelineContext<ApplicationCall>.(ApplicationCall) -> Unit): Route {
val selector = OrRouteSelector(HttpMethodRouteSelector(HttpMethod.Get),HttpMethodRouteSelector(HttpMethod.Head))
return select(selector).route(path) { handle(body) }
}
and replace the get calls by this new function.
install(HeadRequestSupport)
routing {
getOrHead("/foo") {
call.respondText("Bar")
}
}
RequestContent
API is designed to be pluggable, but currently there is no way to install custom transformation. Consider abstracting/reusing Transform
engine to install different converters, like json->entity.
At the moment you cannot create hrefs from a location with trailing /:
/somepath/
as it would end up being /somepath
This should of cause also work for nested Locations, so i could do:
@location("/somepath/") class SomeLocation{
@location("/nested/") class Nested
}
and get /somepath/
and /somepath/nested/
From spec https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
If no Accept header field is present, then it is assumed that the client accepts all media types.
отдает статические файлы очень медленно, или происходит отваливание по таймауту.
Собирал из main и pipeline веток.
Проверяю на embedded jetty.
На windows 10 пару тройку файлов выдает с лагами, на Mac Os облом).
вариант вызова
server = embeddedJettyServer(9090) {
serveClasspathResources("/public")
}
и
server = embeddedJettyServer(9090) {
serveFileSystem(File(fullpath+"/build/resources/main/public"))
}
When trying to install ktor through gradle, it is unable to resolve dependencies:
gradle output:
$ gradle --stacktrace
:compileKotlin
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all dependencies for configuration ':compile'.
> Could not find org.jetbrains.kotlinx:kotlinx-support-jdk8:0.1-alpha-2.
Searched in the following locations:
https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
http://dl.bintray.com/kotlin/ktor/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
http://dl.bintray.com/kotlin/ktor/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
Required by:
:kotlin-blog:unspecified > org.jetbrains.ktor:ktor-core:0.2.2
* Try:
Run with --info or --debug option to get more log output.
* Exception is:
org.gradle.api.artifacts.ResolveException: Could not resolve all dependencies for configuration ':compile'.
at org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration.rethrowFailure(DefaultLenientConfiguration.java:52)
at org.gradle.api.internal.artifacts.ivyservice.DefaultResolvedConfiguration.rethrowFailure(DefaultResolvedConfiguration.java:36)
at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyResolver$FilesAggregatingResolvedConfiguration.rethrowFailure(SelfResolvingDependencyResolver.java:110)
at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingArtifactDependencyResolver$ErrorHandlingResolvedConfiguration.rethrowFailure(ErrorHandlingArtifactDependencyResolver.java:180)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:467)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:218)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileTreeConverter.convertInto(DefaultFileCollectionResolveContext.java:191)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:103)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileTrees(DefaultFileCollectionResolveContext.java:75)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileTreeConverter.convertInto(DefaultFileCollectionResolveContext.java:182)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:98)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileTrees(DefaultFileCollectionResolveContext.java:75)
at org.gradle.api.internal.file.CompositeFileCollection$1.resolve(CompositeFileCollection.java:88)
at org.gradle.api.internal.file.CompositeFileCollection.getSourceCollections(CompositeFileCollection.java:143)
at org.gradle.api.internal.file.CompositeFileTree.getSourceCollections(CompositeFileTree.java:30)
at org.gradle.api.internal.file.CompositeFileCollection.getFiles(CompositeFileCollection.java:38)
at org.gradle.api.internal.changedetection.state.DefaultFileCollectionSnapshotter.snapshot(DefaultFileCollectionSnapshotter.java:47)
at org.gradle.api.internal.changedetection.rules.TaskUpToDateState.<init>(TaskUpToDateState.java:55)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.getStates(DefaultTaskArtifactStateRepository.java:126)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.isUpToDate(DefaultTaskArtifactStateRepository.java:69)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:50)
at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:27)
at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40)
at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
at org.gradle.launcher.Main.doAction(Main.java:33)
at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: org.gradle.internal.resolve.ModuleVersionNotFoundException: Could not find org.jetbrains.kotlinx:kotlinx-support-jdk8:0.1-alpha-2.
Searched in the following locations:
https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
http://dl.bintray.com/kotlin/ktor/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
http://dl.bintray.com/kotlin/ktor/org/jetbrains/kotlinx/kotlinx-support-jdk8/0.1-alpha-2/kotlinx-support-jdk8-0.1-alpha-2.pom
Required by:
:kotlin-blog:unspecified > org.jetbrains.ktor:ktor-core:0.2.2
at org.gradle.internal.resolve.result.DefaultBuildableComponentResolveResult.notFound(DefaultBuildableComponentResolveResult.java:35)
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainDependencyResolver.resolve(RepositoryChainDependencyResolver.java:86)
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainAdapter.resolve(RepositoryChainAdapter.java:69)
at org.gradle.api.internal.artifacts.ivyservice.clientmodule.ClientModuleResolver.resolve(ClientModuleResolver.java:44)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$ModuleVersionResolveState.resolve(DependencyGraphBuilder.java:576)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$ModuleVersionResolveState.getMetaData(DependencyGraphBuilder.java:586)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$DependencyEdge.calculateTargetConfigurations(DependencyGraphBuilder.java:271)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder$DependencyEdge.attachToTargetConfigurations(DependencyGraphBuilder.java:245)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.traverseGraph(DependencyGraphBuilder.java:155)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.resolveDependencyGraph(DependencyGraphBuilder.java:93)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:83)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver$1.execute(DefaultDependencyResolver.java:125)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver$1.execute(DefaultDependencyResolver.java:90)
at org.gradle.internal.Transformers$4.transform(Transformers.java:137)
at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:61)
at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:39)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver.resolve(DefaultDependencyResolver.java:90)
at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.run(CacheLockingArtifactDependencyResolver.java:42)
at org.gradle.internal.Factories$1.create(Factories.java:22)
at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:192)
at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:175)
at org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:106)
at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.useCache(DefaultCacheFactory.java:187)
at org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager.useCache(DefaultCacheLockingManager.java:64)
at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver.resolve(CacheLockingArtifactDependencyResolver.java:40)
at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyResolver.resolve(SelfResolvingDependencyResolver.java:45)
at org.gradle.api.internal.artifacts.ivyservice.ShortcircuitEmptyConfigsArtifactDependencyResolver.resolve(ShortcircuitEmptyConfigsArtifactDependencyResolver.java:58)
at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingArtifactDependencyResolver.resolve(ErrorHandlingArtifactDependencyResolver.java:47)
at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolve(DefaultConfigurationResolver.java:46)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:263)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getResolvedConfiguration(DefaultConfiguration.java:253)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getResolvedConfiguration(Unknown Source)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:465)
... 60 more
BUILD FAILED
Total time: 8.983 secs
build.gradle:
buildscript {
ext.kotlin_version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = 'blog.MainKt'
defaultTasks 'run'
repositories {
mavenCentral()
maven {
url "http://dl.bintray.com/kotlin/ktor"
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.ktor:ktor-core:0.2.2"
testCompile 'junit:junit:4.11'
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
task wrapper(type: Wrapper) {
gradleVersion = "2.7"
}
2016-12-07 12:06:43.196 [nioEventLoopGroup-3-1] WARN i.n.u.c.AbstractEventExecutor - A task raised an exception. Task: org.jetbrains.ktor.netty.NettyApplicationRequest$close$$inlined$executeInLoop$1@22adee83
java.util.NoSuchElementException: org.jetbrains.ktor.netty.BodyHandlerChannelAdapter
at io.netty.channel.DefaultChannelPipeline.getContextOrDie(DefaultChannelPipeline.java:1089) ~[netty-transport-4.1.5.Final.jar:4.1.5.Final]
at io.netty.channel.DefaultChannelPipeline.remove(DefaultChannelPipeline.java:428) ~[netty-transport-4.1.5.Final.jar:4.1.5.Final]
at org.jetbrains.ktor.netty.NettyApplicationRequest$close$$inlined$executeInLoop$1.run(NettyApplicationRequest.kt:141) ~[classes/:na]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.5.Final.jar:4.1.5.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:418) [netty-common-4.1.5.Final.jar:4.1.5.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:440) [netty-transport-4.1.5.Final.jar:4.1.5.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873) [netty-common-4.1.5.Final.jar:4.1.5.Final]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144) [netty-common-4.1.5.Final.jar:4.1.5.Final]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Reproducible on Login in you-kube sample.
Also support mapping to files by convention, e.g. "404.html"
The contract of the interface of session storages defines that SessiosStorage.lookup should only call the consumer if the session can be found and otherwise fail silently.
The InMemorySessionStorage throws an IllegalArgumentException is the session can not be found and thus crashes the pipeline.
private class InMemorySessionStorage : SessionStorage {
private val sessions = ConcurrentHashMap<String, ByteArray>()
override fun save(id: String, contentProvider: (OutputStream) -> Unit): Future<Unit> {
val baos = ByteArrayOutputStream()
contentProvider(baos)
sessions[id] = baos.toByteArray()
return CompletableFuture.completedFuture(Unit)
}
override fun <R> read(id: String, consumer: (InputStream) -> R): Future<R> = CompletableFuture<R>().apply {
sessions[id]?.let { bytes -> complete(consumer(bytes.inputStream())) } ?: throw IllegalArgumentException("Session $id not found")
}
override fun invalidate(id: String): Future<Unit> {
sessions.remove(id)
return CompletableFuture.completedFuture(Unit)
}
}
Here is a minimal test that that shows how this behavior crashes the pipeline:
https://gist.github.com/audax/ac07afbe225d0d6a04f57a9fa492bffb
ktor 0.2.2
CallLogger fails to properly capture exceptions (NPE, for example) and logs them instead as "trace"s.
PipelineMachine ends up in PipelineState.Succeeded
state. My guess is StatusPagesKt.errorPage creates a new execution with state "Executing", which clears the "Failed" state from the pipeline".
As a side note, that whole "Pipeline" stuff is absolutely incomprehensible and hard to debug. Took me ah hour to understand it's actually an implementation of event loop. I have a bad feeling about this approach (reminds of JavaScript callback hell - highly sharded code hard to follow, complex state management), but at the very least it needs tons, TONS of documentation.
From slack:
https://kotlinlang.slack.com/archives/ktor/p1484960403000468
Julio Cotta [11:00 PM]
class KweetApp : AutoCloseable ...
I understand why KweetApp is autocloseable... it wants to close the database pool when shutting down... I just dont understand is when ktor calls
close()`... the only verification of AutoCloseable is here
fun <A : Pipeline<*>, F : Any> A.uninstallFeature(key: AttributeKey<F>) {
val registry = attributes.getOrNull(ApplicationFeature.registry) ?: return
val instance = registry.getOrNull(key) ?: return
if (instance is AutoCloseable)
instance.close()
registry.remove(key)
}
As I understand... instance.close()
is a feature... does KweetApp
is seem as such?
Ilya Ryzhenkov [JB] [11:04 PM]
Yep, unfinished transformation from Application-as-a-feature to Application-as-a-function. Need to fix that. Could you please file an issue?
Please provide some simple sample project that isn't dependant from the whole repository. For a rookie Getting started isn't enough to start Hello Word. I'm getting this when trying to access http://localhost:8080/ and don't know why
DEBUG org.eclipse.jetty.http.HttpParser - Parse exception: HttpParser{s=END,0 of 0} for HttpChannelOverHttp@37cc43a2{r=1,c=false,a=IDLE,uri=//localhost:8080/}
org.eclipse.jetty.http.BadMessageException: 400: Bad Request
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1464)
at org.eclipse.jetty.server.HttpConnection.parseRequestBuffer(HttpConnection.java:350)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:234)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:122)
at org.eclipse.jetty.util.thread.strategy.ExecutingExecutionStrategy.invoke(ExecutingExecutionStrategy.java:58)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:201)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:133)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.AbstractMethodError: Method org/eclipse/jetty/server/HttpChannelOverHttp.contentComplete()Z is abstract
at org.eclipse.jetty.server.HttpChannelOverHttp.contentComplete(HttpChannelOverHttp.java)
at org.eclipse.jetty.http.HttpParser.handleHeaderContentMessage(HttpParser.java:597)
at org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1115)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1369)
... 12 common frames omitted
install(Routing) {
get("/") {
call.respondText("Hello, World!")
}
get("/{...}") {
if (call.request.uri != "/") {
call.respond(call.request.uri)
}
}
}
Request to /
results 404 Not found instead of 200 OK with "Hello, World!" content
curl 'http://localhost:8080/aa'
/aa
curl 'http://localhost:8080/'
<H1>404 Not Found</H1>Not found: /
I keep getting a RuntimeException in the repo indexing. Some Google results suggest that that is an Intellij IDEA issue. Anyone else had that problem?
I use a 2017 version of Idea, without an external gradle installation. I tried version LATEST as well as some version numbers. Did anyone integrate ktor successfully with Maven/Gradle? I would be grateful for any hint because this seems to be a really useful project.
The current implementation of LocalFileContent :
During active development of a web site, users can have an inconsistent view of the site: pages with old css and js scripts.
I didn't manage to reproduce it in a dev/integration environment but I had it in production.
The Compression feature was taking all CPU. Removing it resolved the problem.
The configuration of the feature was:
install(Compression) {
default()
excludeMimeTypeMatch(ContentType.Video.Any)
}
See above the view of the threads and the profiling of CPU.
Hello,
I am implementing here a ktor version of https://httpbin.org/ HTTP Request & Response Service
It's nowhere done, but I wanted to know if there is some interest that I eventually contribute it as a ktor sample.
Jean-Michel
ApplicationCall.values
(renamed from parameters) should combine them all
The current implementation of html-builder uses an HTMLStreamBuilder to produce html through kotlinx.html library.
HTMLStreamBuilder is a TagConsumer that uses the default onTagError
implementation : https://github.com/Kotlin/kotlinx.html/blob/master/shared/src/main/kotlin/api.kt#L14
In case of an exception in a bloc that produces html, nothing is logged and a empty html page is returned to the client.
To simplify debugging, in case of error or exception a trace should be logged.
If a route is implemented with a Kotlin TODO()
, currently ktor returns a 500 Server Error
. It should return a 501 Not Implemented
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.