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

Benedikt Kaiser

03/23/2023, 2:48 PM
hi, i am currently testing kmm and i am building a small app with a simple api request generated with openapi generator. the get request was pretty straight forward now i am trying to implement a post request and i always get the error "java.lang.IllegalStateException: Fail to prepare request body for sending. " despite the correct declaration in the openapi file. does anybody know if i need to change the openapi file in order to work properly with ktor or if there is a special setting i need for the generation? Openapi file is in the thread
Copy code
openapi: 3.0.2
info:
  title: *****************
  version: 1.0.0
servers:
  - url: *******************
paths:
  /login:
    post:
      summary: User Login
      description: Logs in a user and returns a token.
      requestBody:
        description: User credentials for login
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCredentials'
      responses:
        '200':
          $ref: '#/components/responses/AuthSuccessful'
        '401':
          $ref: '#/components/responses/InvalidCredentials'
Error: The body type is: class openapitools.client.models.UserCredentialsDto (Kotlin reflection is not available), with Content-Type: null. i installed content-negotiation in the commonMain sourceSet
c

Casey Brooks

03/23/2023, 3:16 PM
I’m pretty sure the Ktor OpenApi generator is not maintained, the docs show it still using the 1.6.7 version of Ktor, which is not compatible with recent 2.x versions
t

Thomas Urbanitsch

03/23/2023, 3:31 PM
is that your entire yaml? isn’t it missing the components definition you are refering to in the document? which ktor client openapi generator are we talking about specifically? (assuming the OpenAPITools one using Kotlin+multiplatform?)
p

Paul Holze

05/03/2023, 8:48 PM
I had the same problem. For anyone else coming across this problem:. It seems to help to pass a httpClientConfig to the ApiClient (in this case AuthApi) which contains the header for ContentType. Otherwise the generated HttpClient will send a request without Content Header. But I'm also seeing other errors, therefore I will probably switch to an alternative Client Code Generator for now.
Copy code
val setupConfig: (HttpClientConfig<*>) -> Unit = { config -> clientConfig(config) }

    val auth = AuthApi(
        baseUrl = "<http://localhost:8005>",
        httpClientConfig = setupConfig,
        // httpClientEngine = null,
        jsonSerializer = kotlinx.serialization.json.Json
    )
    
    public fun login(username: String, password: String) : String?  {
        var error: String? = null
        runBlocking {
            try {
                auth.apiAuthLoginPost(LoginUserDTO(username, password))
            } catch (e: Exception) {
                error = e.message
            }
        }
        return error
    }

    private fun clientConfig(config: HttpClientConfig<*>) {
        config.install(makeClient())
        config.defaultRequest { headers.appendIfNameAbsent(HttpHeaders.ContentType, "application/json") }
    }

    private fun makeClient(): HttpClient {
        return HttpClient {
            install(ContentNegotiation) {
                json(Json {
                    prettyPrint = true
                    isLenient = true
                    ignoreUnknownKeys = true
                })
            }
        }
    }
61 Views