ktorio / ktor

Framework for quickly creating connected applications in Kotlin with minimal effort
https://ktor.io
Apache License 2.0
12.82k stars 1.04k forks source link

Type of request is changed from GET to POST #804

Closed nbaklanov-issart closed 5 years ago

nbaklanov-issart commented 5 years ago

Ktor Version

ktor_version = 1.0.1

Ktor Engine Used(client or server and name)

Ktor Clients

JVM Version, Operating System and Relevant Context

Android API 22

Feedback

Hi, everyone, I have a simple request code :

protected fun sendGetRequest(requestBody:Any = EmptyContent,
                                  parameters:List<Pair<String, String>> = emptyList(),
                                  requestHeaders:List<Pair<String, String>> = emptyList()) {
        GlobalScope.launch(CoroutineContextProvider.provideContext()) {
            try {
                val call = client.request<HttpResponse> {
                    url{
                        protocol = URLProtocol.HTTP
                        //port = serverPort
                        host = serverAddress
                        encodedPath = requestEncodedPath
                    }
                    method = HttpMethod.Get
                    body = requestBody
                    for (currentPair:Pair<String, String> in requestHeaders) {
                        headers.append(currentPair.first, currentPair.second)
                    }
                    for (currentPair:Pair<String, String> in parameters) {
                        parameter(currentPair.first, currentPair.second)
                    }
                }
                requestResponseHandler(call, call.readText())
            } catch (requestException:Exception) {
                requestExceptionHandler(requestException)
            }
        }
    }

It's get request. But when I call this function like this :

        val headers:MutableList<Pair<String, String>> = mutableListOf()
        headers.add(Pair("Authorization", "Bearer $token"))

        val body:ByteArrayContent = ByteArrayContent(fileBytes)
        sendGetRequest(requestBody = body, requestHeaders = headers)

I will get response like : Request method POST not supported. And in proxy logs I see that ktor really sending POST. If I will remove body from request - ktor will send get, but server will not accept this because it's waiting parameters in body.

e5l commented 5 years ago

Hi @nbaklanov-issart. What client engine do you use? (Some engines forces get requests to be without any payload).

nbaklanov-issart commented 5 years ago

Hi, thank you for your answer. I don’t know how to get exact client engine. I am working on multi-platform project and import ktor like :

       commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
                implementation("io.ktor:ktor-client:$ktor_version")
                implementation("io.ktor:ktor-client-json:$ktor_version")
            }
        }

And looks like you right about forcing requests without payloads. I already contacted with our service developer and he confirmed what usually get requests don't use body and it was api mistake. They will change it.

So I guess it's not a bug of engine. Sorry.

nbaklanov-issart commented 5 years ago

Should I do anything with this request? Close or put some mark on it?

e5l commented 5 years ago

Nope. Let's keep it, probably we need an exception or at least a warning here

e5l commented 5 years ago

When you using HttpClient() without engine argument, it uses service loader to find an engine from dependencies.

nbaklanov-issart commented 5 years ago

When you using HttpClient() without engine argument, it uses service loader to find an engine from dependencies.

I am creating HttpClient in this way:

    protected val client = HttpClient {
        expectSuccess = false
    }

So, I guess, it uses engine from dependancies (I posted them before).

e5l commented 5 years ago

Could you also post platform-specific dependencies?

nbaklanov-issart commented 5 years ago

Could you also post platform-specific dependencies?

sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation("io.ktor:ktor-client:$ktor_version")
implementation("io.ktor:ktor-client-json:$ktor_version")
}
}
commonTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
}
androidMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
implementation("io.ktor:ktor-client-android:$ktor_version")
}
}
androidTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
}
iosMain {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
}
}
iosTest {
}
}
e5l commented 5 years ago

Fixed in master.