russjr08
russjr08

Reputation: 911

Sending a form urlencoded POST request with Ktor Client?

I am wanting to utilize the Ktor client library to interact with a Web API, specifically to authenticate via OAuth, and I'm running into trouble attempting to send a form urlencoded POST request properly. It would appear the actual body is not being sent for some reason.

I've tried looking at similar questions on SO, such as this question but I believe Ktor's API must have changed. I've also taken a look at JetBrains' documentation on this exact type of request here.

I am using the following to send my request:


val response = client.submitForm() {
            url("http://localhost:5555/oauth/token/")
            parameter("code", authData.authCode)
            parameter("grant_type", "authorization_code")
            parameter("client_id", clientId)
            parameter("client_secret", clientSecret)

            header("X-API-Key", getApiKey())
            method = HttpMethod.Post

        }

Which results in the following request being logged from a quick Express.js application I built to mock the request:

----- Body -----
{}
----- Headers -----
{
  host: 'localhost:5555',
  'content-length': '0',
  'x-api-key': 'api_key_here',
  'accept-charset': 'UTF-8',
  accept: '*/*',
  'user-agent': 'Ktor client',
  'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
}

My header is being sent just fine, however the body is empty.

I've tried a few other variations as well, such as:

        val response = client.post("http://localhost:5555/oauth/token/") {
            formData {
                parameter("test", "test")
            }

        }

Which results in:

----- Body -----
{}
----- Headers -----
{
  host: 'localhost:5555',
  'content-length': '0',
  'accept-charset': 'UTF-8',
  accept: '*/*',
  'user-agent': 'Ktor client'
}

as well as:

        val response = client.post("http://localhost:5555/oauth/token/") {
            FormDataContent(Parameters.build {
                append("code", authData.authCode!!)
                append("grant_type", "authorization_code")
                append("client_id", clientId)
                append("client_secret", clientSecret)
            })

            header("X-API-Key", getApiKey())
        }

Which shapes up similar to the first set of logs:

----- Body -----
{}
----- Headers -----
{
  host: 'localhost:5555',
  'content-length': '0',
  'x-api-key': 'api_key_here',
  'accept-charset': 'UTF-8',
  accept: '*/*',
  'user-agent': 'Ktor client'
}

For additional context, I am using the following libraries / versions:

I'm sure it's something simple, but I've had no luck thus far with any of my permutations that I've tried.

Upvotes: 1

Views: 2168

Answers (1)

Aleksei Tirman
Aleksei Tirman

Reputation: 6999

You can set an instance of FormDataContent to a request body to send application/x-www-form-urlencoded request. To create an object of FormDataContent class you need to pass an instance of Parameters to its constructor.

val response: HttpResponse = client.post("http://localhost:5555/oauth/token/") {
    header("X-API-Key", "api key")
    setBody(
        FormDataContent(
            Parameters.build {
                append("code", "code")
                append("grant_type", "authorization_code")
                append("client_id", "client id")
                append("client_secret", "client secret")
            }
        )
    )
}

Upvotes: 4

Related Questions