https://kotlinlang.org logo
#ktor
Title
# ktor
h

Helio

05/20/2022, 1:24 AM
Hello Ktor team 👋🏽 , I’m about to complete the migration from Ktor 1 to 2 but I noticed some weird things in which I’m not sure if this is a behaviour change that I couldn’t find in the documentation, or if these could be indeed an issue. Both of the issues found were around the Unit/Integration tests.
1 - Converting an URL to URI using
io.ktor.http.Url
throws an Exception
java.net.URISyntaxException: Illegal character in query at index
The snippet below works for
Ktor 1.6.8
, but it throws the exception for
Ktor 2.0.1
Copy code
// The input parameters used for testing are:
// baseUrl = <http://bbc-pipelines-build-info.integration.test:8082>
// urlQueryParameters = build-info?workspace-id={5734a707-dc63-47a1-b63f-03e5d80efad5}

private fun buildBuildInfoUrl(baseUrl: String, urlQueryParameters: String) =
    return Url("$baseUrl/$urlQueryParameters").toURI().toString()

The response is:
<http://bbc-pipelines-build-info.integration.test:8082/build-info?workspace-id=%7B5734a707-dc63-47a1-b63f-03e5d80efad5%7D>
Exception thrown by
Ktor 2.0.1
Copy code
java.net.URISyntaxException: Illegal character in query at index 78: <http://bbc-pipelines-build-info.integration.test:8082/build-info?workspace-id={5734a707-dc63-47a1-b63f-03e5d80efad5}>
	at java.base/java.net.URI$Parser.fail(URI.java:2913)
	at java.base/java.net.URI$Parser.checkChars(URI.java:3084)
	at java.base/java.net.URI$Parser.parseHierarchical(URI.java:3172)
	at java.base/java.net.URI$Parser.parse(URI.java:3114)
	at java.base/java.net.URI.<init>(URI.java:600)
	at io.ktor.http.URLUtilsJvmKt.toURI(URLUtilsJvm.kt:54)
2 - Even though I’m using the
defaultRequest
plugin with the HttpClient from my integration tests, when I set the following attributes
host/port/protocol
, during the request time the
host
is replaced from the value I gave with
localhost
.
Looking through the snippet below in which I define my HttpClient I would assume that
host
used for the request should be
bbc-pipelines-build-info.integration.test
.
Copy code
fun buildClient(): HttpClient {
    val buildInfoUrl = URLBuilder("<http://bbc-pipelines-build-info.integration.test:8082>").build()
    return HttpClient(MockEngine) {
        install(ContentNegotiation) {
            json(Json {
                isLenient = true
                ignoreUnknownKeys = true
                useArrayPolymorphism = true
            })
        }
        defaultRequest {
            url {
                protocol = buildInfoUrl.protocol
                port = buildInfoUrl.port
                host = buildInfoUrl.host
            }
            header(HttpHeaderConstants.X_SLAUTH_EGRESS, true)
        }
        bbcPipelinesUrlHandler(buildInfoUrl)
    }
}
However, when I make the request with
url {encodedPath = "build-info"}
the request is done using the host as being
localhost
(see snippet below). When I replace the
url { encodedPath = "build-info"}
with
buildInfoHttpClient.submitForm("build-info",...)
instead of
localhost
, the request is sent to
bbc-pipelines-build-info.integration.test
host.
Copy code
suspend fun getBitbucketPipelineBuildInfo(
        workspaceId: String,
    ): BitbucketBuildInfoResponseModel = retrying {
        buildInfoHttpClient.submitForm(url {encodedPath = "build-info"}, formParameters = Parameters.build {
            append(BitbucketPipelineQueryParameters.WORKSPACE_ID.field, workspaceId)
        }, encodeInQuery = true).body()
    }
Do you reckon you could provide an assistance for these 2 issues, please? Thanks heaps!
p

Paul Woitaschek

05/20/2022, 4:12 AM
That port thing is a bug in 2.0.1 and not present in 2.0.0
h

Helio

05/20/2022, 5:37 AM
Thanks for pointing out. 😃 I wonder if the
host
issue could be related with the bug.
a

Aleksei Tirman [JB]

05/20/2022, 3:56 PM
1. In Ktor 1.6.* we decoded an input URL passed for the
UrlBuilder
and then encoded it when returning a string representation. That led to a loss of original symbols in URL because there are multiple representations for some symbols. In Ktor 2.0.0 that behavior was fixed so we store an original URL string as is.
h

Helio

05/21/2022, 3:20 AM
Thanks for your reply Aleksei! So, from your Ktor expertise, there is no way in which I could only covert the curly braces from the URL using the UrlBuilder anymore?
a

Aleksei Tirman [JB]

05/22/2022, 12:34 PM
So, from your Ktor expertise, there is no way in which I could only covert the curly braces from the URL using the UrlBuilder anymore?
You can add query paramerters to an
UrlBuilder
via the
parameters
property:
Copy code
val uri = URLBuilder().apply {
    host = "bbc-pipelines-build-info.integration.test"
    port = 8082
    encodedPath = "/build-info"
    parameters.append("workspace-id", "{5734a707-dc63-47a1-b63f-03e5d80efad5}")
}.build().toURI()
I wonder if the
host
issue could be related with the bug
Your code should work as expected in Ktor 2.0.2.
🙌🏽 1
h

Helio

05/22/2022, 10:22 PM
Thank you so much!! I will give it a shot.
Hello Aleksei, 👋🏽 I was attempting to migrate another application our team owns with Ktor V2…. But I noticed that some of the mocks we previously had working in Ktor v1 no longer works with Ktor v2. I added an example in #mockk Is there any behaviour change in Ktor v2 regarding the tests that we should be aware of? I tried looking through the migration guide, but nothing that actually caught my attention. Would you be able to tell me if there was any change around test execution that would trigger such behaviour? I have added an example i
a

Aleksei Tirman [JB]

06/16/2022, 6:07 AM
As I see, in your example there is no usage of Ktor API. Could you please give an example where Ktor classes are mocked?
h

Helio

06/16/2022, 6:09 AM
I can certainly show you. Let me prepare some snippets, 1s
a

Aleksei Tirman [JB]

06/16/2022, 6:11 AM
Please create a new thread or file an issue.
h

Helio

06/16/2022, 6:11 AM
Sure! I will do a new thread in a minute. I’ll probably raise a new issue actually. It might be better
4 Views