### Install MkDocs and Plugins Source: https://github.com/foso/ktorfit/blob/master/CONTRIBUTING.md Installs MkDocs and necessary plugins using pip. Ensure Python and pip are installed and up-to-date. ```bash python3 -m pip install --upgrade pip # install pip python3 -m pip install mkdocs # install MkDocs python3 -m pip install mkdocs-material # install material theme python3 -m pip install mkdocs-git-revision-date-localized-plugin python3 -m pip install mkdocs-minify-plugin python3 -m pip install mkdocs-macros-plugin ``` -------------------------------- ### Define a GET request with a path parameter Source: https://github.com/foso/ktorfit/blob/master/docs/converters/requestparameterconverter.md This example shows how to define a GET request with a path parameter and specify the expected type for conversion using @RequestType. ```kotlin @GET("posts/{postId}/comments") suspend fun getCommentsById(@RequestType(Int::class) @Path("postId") postId: String): List ``` -------------------------------- ### Serve MkDocs Documentation Source: https://github.com/foso/ktorfit/blob/master/CONTRIBUTING.md Starts the MkDocs local development server. Changes to documentation files will be automatically reflected in the browser. ```bash mkdocs serve ``` -------------------------------- ### Ktor Client JSON Content Negotiation Setup Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Configure the Ktor client to handle JSON serialization by installing the ContentNegotiation feature with the json plugin. This setup enables lenient parsing and ignoring unknown keys. ```kotlin val ktorClient = HttpClient() { install(ContentNegotiation) { json(Json { isLenient = true; ignoreUnknownKeys = true }) } } ``` -------------------------------- ### Create Custom Authentication Plugin Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Example of creating a custom Ktor client plugin for authentication, checking for @AuthRequired annotations and appending an Authorization header. ```kotlin val MyAuthPlugin = createClientPlugin("MyAuthPlugin", ::MyAuthPluginConfig) { onRequest { request, _ -> val auth = request.annotations.filterIsInstance().firstOrNull() ?: return@onRequest val token = this@createClientPlugin.pluginConfig.token if (!auth.optional && token == null) throw Exception("Need to be logged in") token?.let { request.headers.append("Authorization", "Bearer $it") } } } class MyAuthPluginConfig { var token: String? = null } ``` -------------------------------- ### Configure Ktorfit Builder and Create API Implementation Source: https://github.com/foso/ktorfit/blob/master/docs/quick-start.md Use Ktorfit.Builder to set the base URL and build the Ktorfit instance. Then, use the generated extension function to get an implementation of your API interface. ```kotlin val ktorfit = Ktorfit.Builder().baseUrl("https://swapi.dev/api/").build() val exampleApi = ktorfit.createExampleApi() ``` -------------------------------- ### Basic GET Request Annotation Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Use @GET to define a GET request. The annotation value is appended to the baseUrl or used as an absolute URL if it starts with http/https. ```kotlin @GET("posts") fun getPosts(): List ``` -------------------------------- ### Generated Ktorfit Implementation Class Source: https://github.com/foso/ktorfit/blob/master/docs/architecture.md This is an example of the Ktorfit-generated implementation class for the `ExampleApi` interface. It handles the network request logic. ```kotlin @OptIn(InternalKtorfitApi::class) public class _ExampleApiImpl( private val _baseUrl: String, private val _helper: KtorfitConverterHelper, ) : ExampleApi { override suspend fun exampleGet(): People { val _ext: HttpRequestBuilder.() -> Unit = { method = HttpMethod.parse("GET") url{ takeFrom(_baseUrl + "/test") } } val _typeData = TypeData.createTypeData( typeInfo = typeInfo(), ) return _helper.suspendRequest(_typeData,_ext)!! } } ``` ```kotlin public class _ExampleApiProvider : ClassProvider { override fun create(_ktorfit: Ktorfit): ExampleApi = _ExampleApiImpl(_ktorfit.baseUrl, KtorfitConverterHelper(_ktorfit)) } ``` ```kotlin public fun Ktorfit.createExampleApi(): ExampleApi = _ExampleApiImpl(this.baseUrl, KtorfitConverterHelper(this)) ``` -------------------------------- ### Query Parameters with @Query, @QueryName, @QueryMap Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Add query parameters to a request using @Query for single parameters, @QueryName for the parameter name, and @QueryMap for a map of parameters. The example shows a request to 'comments?postId=3'. ```kotlin @GET("comments") suspend fun getCommentsById( @Query("postId") postId: String, @QueryName queryName: String, @QueryMap headerMap : Map ): List ``` ```kotlin @GET("comments") suspend fun getCommentsById(@Query("postId") postId: String): List ``` -------------------------------- ### Execute GET Request and Print Response Source: https://github.com/foso/ktorfit/blob/master/docs/quick-start.md Call the suspend function defined in your API interface to make the GET request. The response text is then printed to the console. ```kotlin val response = exampleApi.getPerson() println(response) ``` -------------------------------- ### Define API Interface with GET Request Source: https://github.com/foso/ktorfit/blob/master/docs/quick-start.md Define a Kotlin interface for your API. Use the @GET annotation to specify the HTTP method and relative URL path. Functions must be suspend functions. ```kotlin interface ExampleApi { @GET("people/1/") suspend fun getPerson(): String } ``` -------------------------------- ### GET Request with Absolute URL Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Specify an absolute URL directly in the @GET annotation, overriding the baseUrl. ```kotlin @GET("https://example.com/posts") fun getPosts(): List ``` -------------------------------- ### JSON Serialization Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Ktorfit does not handle JSON parsing directly. You need to install the ContentNegotiation plugin with a JSON serializer (like `kotlinx.serialization`) to your Ktor client. ```APIDOC ## JSON Serialization Ktorfit does not parse JSON by itself. You must install the `ContentNegotiation` feature to the Ktor `HttpClient` that you provide to Ktorfit. See [Add your own Ktor client](../configuration/#add-your-own-ktor-client) and the [Ktor Serialization documentation](https://ktor.io/docs/serialization-client.html) for more details. ### Example Ktor Client Configuration ```kotlin val ktorClient = HttpClient() { install(ContentNegotiation) { json(Json { isLenient = true; ignoreUnknownKeys = true }) } } ``` ``` -------------------------------- ### Define API Interface with Ktorfit Annotations Source: https://github.com/foso/ktorfit/blob/master/docs/architecture.md Define your API interface using Ktorfit annotations like @GET. This interface serves as a contract for your network requests. ```kotlin package com.example import com.example.model.People import de.jensklingenberg.ktorfit.http.GET interface ExampleApi { @GET("/test") suspend fun exampleGet(): People } ``` -------------------------------- ### Use Ktorfit-lib-light Source: https://github.com/foso/ktorfit/blob/master/docs/installation.md Consider using 'de.jensklingenberg.ktorfit:ktorfit-lib-light' if you need finer control over Ktor client engines. This option excludes platform dependencies, requiring you to add them manually. ```kotlin implementation("de.jensklingenberg.ktorfit:ktorfit-lib-light:$ktorfitVersion") ``` -------------------------------- ### Configure HttpClient for Ktorfit Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Sets up a basic HttpClient with ContentNegotiation and HttpTimeout plugins. Expect success is set to false to handle non-2xx responses. ```kotlin val jvmClient = HttpClient() { install(ContentNegotiation) { // register(ContentType.Application.Any, CustomJsonConverter()) // json(Json { isLenient = true; ignoreUnknownKeys = true }) } install(HttpTimeout) { } expectSuccess = false } ``` -------------------------------- ### Ktorfit create function usage Source: https://github.com/foso/ktorfit/blob/master/ktorfit-compiler-plugin/Readme.md Shows the original usage of the `create` function before transformation by the compiler plugin. ```kotlin val api = jvmKtorfit.create() ``` -------------------------------- ### Create API Service Instance Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Creates an instance of a defined API service interface (e.g., GithubService, StarWarsApi) using the Ktorfit client. ```kotlin val githubApi = jvmKtorfit.create() ``` ```kotlin val starWarsApi = jvmKtorfit.create() ``` -------------------------------- ### Initialize Ktorfit Client Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Initializes Ktorfit with a base URL and the configured HttpClient. This client is then used to create API service interfaces. ```kotlin val jvmKtorfit = Ktorfit(baseUrl = "http://localhost:8080/", jvmClient) ``` -------------------------------- ### Upload File with Ktorfit Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Demonstrates uploading a file using Ktorfit's `formData` builder. It appends the file content with appropriate Content-Type and Content-Disposition headers. ```kotlin val test = githubApi.upload("Ktor logo", formData { append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) }) ``` -------------------------------- ### Default Ktorfit create() Function Source: https://github.com/foso/ktorfit/blob/master/docs/architecture.md The default implementation of the `create()` function in the Ktorfit library. It requires the Gradle plugin to be enabled to avoid an `IllegalArgumentException`. ```kotlin public fun create(data: T? = null): T { if (data == null) { throw IllegalArgumentException(ENABLE_GRADLE_PLUGIN) } return data } ``` -------------------------------- ### Execute Network Request and Print Response Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Executes a network request using the created API service and prints the response. Includes a delay to allow for asynchronous operations. ```kotlin runBlocking { // println(de.jensklingenberg.ktorfit.demo.getStarWarsApi.getPersonById(1).name) val test = githubApi.upload("Ktor logo", formData { append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) }) // println(secondApi.getStream().get(1)) println(test) delay(3000) } ``` -------------------------------- ### Headers with @Headers, @Header, @HeaderMap Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Configure request headers using @Headers for static headers, @Header for individual headers, and @HeaderMap for a map of headers. ```kotlin @Headers("Accept: application/json") @GET("comments") suspend fun requestWithHeaders( @Header("Content-Type") name: String, @HeaderMap headerMap : Map ): List ``` -------------------------------- ### ResponseConverter with Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/converters/migration.md This demonstrates an equivalent implementation of ResponseConverter using a Converter.Factory. This factory pattern allows for cleaner integration and management of response conversion logic within Ktorfit. ```kotlin public class CallConverterFactory : Converter.Factory { override fun responseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.ResponseConverter? { if (typeData.typeInfo.type == Call::class) { return object : Converter.ResponseConverter> { override fun convert(getResponse: suspend () -> HttpResponse): Call { return object : Call { override fun onExecute(callBack: Callback) { ktorfit.httpClient.launch { try { val response = getResponse() val data = response.call.body(typeData.typeArgs.first().typeInfo) callBack.onResponse(data, response) } catch (ex: Exception) { println(ex) callBack.onError(ex) } } } } } } } return null } } ``` -------------------------------- ### Add Ktorfit Gradle Plugins Source: https://github.com/foso/ktorfit/blob/master/docs/installation.md Apply the KSP and Ktorfit Gradle plugins in your build script. Ensure you use the correct versions for KSP and the Ktorfit plugin. ```kotlin plugins { id("com.google.devtools.ksp") version "CURRENT_KSP_VERSION" id("de.jensklingenberg.ktorfit") version "{{ktorfit.release}}" } ``` -------------------------------- ### Use Next Converter for Envelope Type Source: https://github.com/foso/ktorfit/blob/master/docs/converters/example1.md Alternatively, use `ktorfit.nextSuspendResponseConverter()` to delegate the conversion of the `Envelope` type to the next available converter, then extract the user. ```kotlin override suspend fun convert(result: KtorfitResult): Any { val typeData = TypeData.createTypeData("com.example.model.Envelope", typeInfo()) val envelope = ktorfit.nextSuspendResponseConverter(null, typeData)?.convert(result) as? Envelope return envelope.user } ``` -------------------------------- ### Add Custom Ktor Client to Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/configuration.md Integrate your own pre-configured Ktor `HttpClient` instance into the Ktorfit builder. This allows for centralized configuration of your HTTP client. ```kotlin val myClient = HttpClient() val ktorfit = Ktorfit.Builder().httpClient(myClient).build() ``` -------------------------------- ### HTTP Method Annotations Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Ktorfit supports standard HTTP methods through annotations. You can also define custom methods using the @HTTP annotation. ```APIDOC ## HTTP Method Annotations Ktorfit supports the following HTTP method annotations: * `@GET` * `@POST` * `@PUT` * `@DELETE` * `@HEAD` * `@OPTIONS` * `@PATCH` Or you can set your custom method to `@HTTP`. ### Example ```kotlin @GET("posts") fun getPosts(): List ``` The value of the HTTP annotation will be appended to the `baseUrl` set in the Ktorfit builder. If the value starts with `http` or `https`, that URL will be used instead of `baseUrl`. ### Example with Absolute URL ```kotlin @GET("https://example.com/posts") fun getPosts(): List ``` ``` -------------------------------- ### Multipart Upload with @Multipart and @Part Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Upload multipart data using the @Multipart annotation on the function and @Part on parameters. All @Part parameters are combined into MultiPartFormDataContent. ```kotlin @Multipart @POST("upload") suspend fun uploadFile(@Part("description") description: String, @Part("") file: List): String ``` ```kotlin val multipart = formData { append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) } exampleApi.upload("Ktor logo",multipart) ``` -------------------------------- ### Add Ktorfit Gradle Plugin Source: https://github.com/foso/ktorfit/blob/master/ktorfit-gradle-plugin/Readme.md Apply the Ktorfit Gradle plugin from the Gradle plugin portal to your project. ```kotlin plugins { id "de.jensklingenberg.ktorfit" version "LATEST_VERSION" } ``` -------------------------------- ### Include Ktorfit-lib Dependency Source: https://github.com/foso/ktorfit/blob/master/docs/installation.md Add the Ktorfit-lib dependency to your common module's dependencies. Replace '{{ktorfit.release}}' with the desired Ktorfit version. ```kotlin val ktorfitVersion = "{{ktorfit.release}}" sourceSets { val commonMain by getting{ dependencies{ implementation("de.jensklingenberg.ktorfit:ktorfit-lib:$ktorfitVersion") } } } ``` -------------------------------- ### Headers Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Configure request headers using @Headers, @Header, or @HeaderMap annotations. ```APIDOC ## Headers You can use `@Headers`, `@Header`, or `@HeaderMap` to configure headers for your request. ### @Headers (Static Headers) ```kotlin @Headers("Accept: application/json") @GET("comments") suspend fun requestWithStaticHeaders(): List ``` ### @Header (Dynamic Header) ```kotlin @GET("comments") suspend fun requestWithDynamicHeader(@Header("Content-Type") contentType: String): List ``` ### @HeaderMap (Map of Headers) ```kotlin @GET("comments") suspend fun requestWithHeaderMap(@HeaderMap headers: Map): List ``` ``` -------------------------------- ### Ktorfit create() Function Transformation Source: https://github.com/foso/ktorfit/blob/master/docs/architecture.md The compiler plugin transforms the Ktorfit `create()` function call to inject the generated implementation class, ensuring proper instantiation. ```kotlin val api = jvmKtorfit.create() ``` ```kotlin val api = jvmKtorfit.create(_ExampleApiImpl(jvmKtorfit)) ``` -------------------------------- ### Default TypeData Creation Source: https://github.com/foso/ktorfit/blob/master/docs/configuration.md Illustrates the default creation of `TypeData` without a qualified type name. ```kotlin val _typeData = TypeData.createTypeData( typeInfo = typeInfo>(), ) ``` -------------------------------- ### Generated Ktorfit Implementation with @NoDelegation Source: https://github.com/foso/ktorfit/blob/master/docs/generation.md Illustrates the generated implementation class structure when an interface is annotated with @NoDelegation, showing no delegation for specified interfaces. ```kotlin public class _TestServiceImpl( private val _ktorfit: Ktorfit, ) : TestService, SuperTestService1 by com.example.api._SuperTestService1Impl(_ktorfit) { // No delegation for SuperTestService1 and SuperTestService2 } ``` -------------------------------- ### Multipart Upload with @Body and MultiPartFormDataContent Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Upload multipart data using @Body with a MultiPartFormDataContent parameter. The method should be annotated with @POST or @PUT. ```kotlin interface ExampleService { @POST("upload") suspend fun upload(@Body map: MultiPartFormDataContent) } ``` ```kotlin val multipart = MultiPartFormDataContent(formData { append("description", "Ktor logo") append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) }) exampleApi.upload(multipart) ``` -------------------------------- ### Create a Custom Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/converters/example1.md Extend `Converter.Factory` to create a custom converter. This factory will be responsible for providing the appropriate converter for specific types. ```kotlin class UserFactory : Converter.Factory { } ``` -------------------------------- ### Configure Ktorfit Gradle Plugin Source: https://github.com/foso/ktorfit/blob/master/ktorfit-gradle-plugin/Readme.md Configure the Ktorfit Gradle plugin to pass data to the compiler. This block is optional and used for advanced customization. ```kotlin configure { } ``` -------------------------------- ### Customize Requests with @ReqBuilder Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Add a parameter with @ReqBuilder ext: HttpRequestBuilder.() -> Unit to your function to apply custom configurations to the HTTP request. The RequestBuilder is applied last. ```kotlin @GET("comments") suspend fun getCommentsById( @Query("postId") name: String, @ReqBuilder ext: HttpRequestBuilder.() -> Unit ): List ``` ```kotlin val result = secondApi.getCommentsById("3") { onDownload { bytesSentTotal, contentLength -> println(bytesSentTotal) } } ``` -------------------------------- ### RequestBuilder API Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Demonstrates how to use the @ReqBuilder annotation to add custom configurations to HTTP requests, such as setting download callbacks. ```APIDOC ## RequestBuilder ### Description Use the `@ReqBuilder ext: HttpRequestBuilder.() -> Unit` parameter to set extra configurations on your request. This builder is applied last after all other Ktorfit configurations. ### Method GET ### Endpoint comments #### Query Parameters - **postId** (String) - Required - The ID of the post to get comments for. ### Request Example ```kotlin val result = secondApi.getCommentsById("3") { onDownload { bytesSentTotal, contentLength -> println(bytesSentTotal) } } ``` ### Response #### Success Response (200) - **List** - A list of comments associated with the post. ``` -------------------------------- ### SuspendResponseConverter with Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/converters/migration.md This demonstrates an equivalent implementation of SuspendResponseConverter using a Converter.Factory. This approach is useful for creating reusable converter logic that can be applied across multiple Ktorfit services. ```kotlin public class CallConverterFactory : Converter.Factory { override fun suspendResponseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.SuspendResponseConverter? { if (typeData.typeInfo.type == Call::class) { return object: Converter.SuspendResponseConverter> { override suspend fun convert(response: HttpResponse): Call { return object : Call { override fun onExecute(callBack: Callback) { ktorfit.httpClient.launch { try { val data = response.call.body(typeData.typeArgs.first().typeInfo) callBack.onResponse(data!!, response) } catch (ex: Exception) { callBack.onError(ex) } } } } } } } return null } } ``` -------------------------------- ### Add Custom Converter Factory to Ktorfit Builder Source: https://github.com/foso/ktorfit/blob/master/docs/converters/example1.md Instantiate your custom `UserFactory` and add it to the `converterFactories` list when building your `Ktorfit` instance. ```kotlin Ktorfit.Builder().converterFactories(UserFactory()).baseUrl("foo").build() ``` -------------------------------- ### Query Parameters Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Add query parameters to your requests using @Query, @QueryName, or @QueryMap annotations. ```APIDOC ## Query Parameters You can use `@Query`, `@QueryName`, or `@QueryMap` to set queries to your request. ### @Query ```kotlin @GET("comments") suspend fun getCommentsById(@Query("postId") postId: String): List ``` **Example Request:** A request with `getCommentsById(3)` will result in the relative URL `comments?postId=3`. ### @QueryName Used to specify the query name dynamically. ### @QueryMap Used to pass a map of query parameters. ```kotlin @GET("comments") suspend fun getComments(@QueryMap queries: Map): List ``` ``` -------------------------------- ### Add Response Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/migration.md Add this converter factory to your Ktorfit instance when migrating from Response? usage. ```kotlin .addConverterFactory(ResponseConverterFactory()) ``` -------------------------------- ### URL Handling Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Dynamically set the request URL using the @Url annotation or by providing absolute URLs in HTTP method annotations. ```APIDOC ## URL Handling ### Dynamic URL with @Url Can be used to set a URL dynamically as a function parameter. ```kotlin @GET("") suspend fun getPosts(@Url url: String): List ``` ### Absolute URLs in HTTP Annotations The value of the HTTP annotation can be an absolute URL. ```kotlin @GET("https://example.com/posts") fun getPosts(): List ``` ``` -------------------------------- ### Path Parameters Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Dynamically replace parts of the URL path using the @Path annotation. ```APIDOC ## Path Parameters When you want to dynamically replace a part of the URL, you can use the `@Path` annotation. ### Example ```kotlin interface ExampleApi { @GET("people/{peopleId}/") suspend fun getPerson(@Path("peopleId") id: String): String } ``` Just write a part of your URL path in curly braces. Then you need to annotate a parameter with `@Path`. The value of `@Path` needs to match one of the curly brace parts in your URL path. **Example Request:** On a request with `getPerson(1)`, `{peopleId}` will be replaced with the argument `1`, and the relative URL will become `people/1/`. ``` -------------------------------- ### Implement FlowConverterFactory Source: https://github.com/foso/ktorfit/blob/master/docs/converters/responseconverter.md Create a custom converter factory to handle Flow return types. This involves extending Converter.Factory and overriding responseConverter or suspendResponseConverter. ```kotlin class FlowConverterFactory : Converter.Factory { } ``` ```kotlin override fun responseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.ResponseConverter? { // ... implementation ... } ``` ```kotlin override fun suspendResponseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.SuspendResponseConverter? { if (typeData.typeInfo.type == Flow::class) { // ... return converter ... } return null } ``` ```kotlin if (typeData.typeInfo.type == User::class) { val requestType = typeData.typeArgs.first() return object : Converter.ResponseConverter> { override fun convert(getResponse: suspend () -> HttpResponse): Flow { return flow { try { val response = getResponse() if (requestType.typeInfo.type == HttpResponse::class) { emit(response) } else { val data = ktorfit.nextSuspendResponseConverter(this@FlowConverterFactory, requestType) ?.convert(response) emit(data) } } catch (exception: Exception) { throw exception } } } } } ``` -------------------------------- ### Dynamic URL with @Url Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Use the @Url annotation on a function parameter to set the URL dynamically. This is useful when the URL is not known at compile time. ```kotlin @GET("") suspend fun getPosts(@Url url: String): List ``` -------------------------------- ### Path Parameters with @Path Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Dynamically replace parts of a URL path using the @Path annotation. The annotation value must match the placeholder in curly braces in the URL. ```kotlin interface ExampleApi { @GET("people/{peopleId}/") suspend fun getPerson(@Path("peopleId") id: String): String } ``` -------------------------------- ### Implement a custom RequestParameterConverter factory Source: https://github.com/foso/ktorfit/blob/master/docs/converters/requestparameterconverter.md Implement a Converter.Factory to create custom RequestParameterConverter instances. This factory is responsible for providing converters for specific parameter types. ```kotlin class StringToIntRequestConverterFactory : Converter.Factory { override fun requestParameterConverter( parameterType: KClass<*>, requestType: KClass<*> ): Converter.RequestParameterConverter? { return object : Converter.RequestParameterConverter { override fun convert(data: Any): Any { //convert the data } } } } ``` -------------------------------- ### Handle Call response with Callback Source: https://github.com/foso/ktorfit/blob/master/docs/converters/responseconverter.md Implement the Callback interface to process the response or handle errors when using the Call type for API requests. ```kotlin exampleApi.getPersonById(3).onExecute(object : Callback { override fun onResponse(call: People, response: HttpResponse) { //Do something with Response } override fun onError(exception: Exception) { //Do something with exception } }) ``` -------------------------------- ### Add Flow Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/migration.md Add this converter factory to your Ktorfit instance when migrating from Flow? usage. ```kotlin .addConverterFactory(FlowConverterFactory()) ``` -------------------------------- ### Streaming API Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md This section explains how to handle streaming responses using the @Streaming annotation and HttpStatement. It's useful for large file downloads or real-time data feeds. ```APIDOC ## Streaming ### Description To receive streaming data, annotate a function with `@Streaming` and ensure the return type is `HttpStatement`. ### Method GET ### Endpoint docs/response.html#streaming ### Request Example ```kotlin exampleApi.getPostsStreaming().execute { response -> //Do something with response } ``` ### Response #### Success Response (200) - **HttpStatement** - Represents a statement that can be executed to retrieve streaming data. ``` -------------------------------- ### Define a Custom Response Wrapper Class Source: https://github.com/foso/ktorfit/blob/master/docs/converters/suspendresponseconverter.md Define a sealed class to hold either a successful response or an error. This class will be used to wrap the Ktorfit response. ```kotlin sealed class MyOwnResponse { data class Success(val data: T) : MyOwnResponse() class Error(val ex: Throwable) : MyOwnResponse() companion object { fun success(data: T) = Success(data) fun error(ex: Throwable) = Error(ex) } } ``` -------------------------------- ### Add Ktorfit Call Adapters Source: https://github.com/foso/ktorfit/blob/master/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/uploadFile.txt Adds various call adapters to the Ktorfit instance to handle different response types like Flow, RxJava, or Ktorfit's default call. ```kotlin jvmKtorfit.addAdapter(FlowCallAdapter()) jvmKtorfit.addAdapter(RxCallAdapter()) jvmKtorfit.addAdapter(KtorfitCallAdapter()) ``` -------------------------------- ### Original API Function Signature Source: https://github.com/foso/ktorfit/blob/master/docs/converters/suspendresponseconverter.md This is the original function signature before implementing the custom response wrapper. It directly returns a list of comments. ```kotlin @GET("posts/{postId}/comments") suspend fun getCommentsByPostId(@Path("postId") postId: Int): List ``` -------------------------------- ### Add ResponseConverterFactory Dependency Source: https://github.com/foso/ktorfit/blob/master/docs/converters/converters.md Include this dependency to use the ResponseConverterFactory for handling HTTP response conversions. ```kotlin implementation("de.jensklingenberg.ktorfit:ktorfit-converters-response:$CONVERTER_VERSION") ``` -------------------------------- ### Register the custom converter factory with Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/converters/requestparameterconverter.md Register your custom converter factory with Ktorfit to enable the custom parameter type conversions defined within it. ```kotlin ktorfit.converterFactories(StringToIntRequestConverterFactory()) ``` -------------------------------- ### Implement Suspend Response Converter Source: https://github.com/foso/ktorfit/blob/master/docs/migration.md Implement this suspend function to handle KtorfitResult for migration to 1.8.1. Handle both Success and Failure cases. ```kotlin public suspend fun convert(result: KtorfitResult): T { return when (result) { is KtorfitResult.Failure -> { throw result.throwable // Or do something with the throwable } is KtorfitResult.Success -> { val response = result.response //Put the code that was in your other convert function here } } } ``` -------------------------------- ### Register the custom ResponseConverter with Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/responseconverter.md Add the implemented `MyOwnResponseConverter` to your Ktorfit client instance to enable response wrapping. ```kotlin ktorfit.responseConverter(MyOwnResponseConverter()) ``` -------------------------------- ### Handle Streaming Responses with @Streaming Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Annotate functions with @Streaming and return HttpStatement to receive streaming data. Use the execute block to process the response. ```kotlin @Streaming @GET("docs/response.html#streaming") suspend fun getPostsStreaming(): HttpStatement ``` ```kotlin exampleApi.getPostsStreaming().execute { response -> //Do something with response } ``` -------------------------------- ### ResponseConverter Implementation Source: https://github.com/foso/ktorfit/blob/master/docs/converters/migration.md This snippet shows a direct implementation of ResponseConverter for handling non-suspend responses. It's used to wrap and process HTTP responses before they are delivered to the callback. ```kotlin override fun wrapResponse( typeData: TypeData, requestFunction: suspend () -> Pair, ktorfit: Ktorfit ): Any { return object : Call { override fun onExecute(callBack: Callback) { ktorfit.httpClient.launch { val deferredResponse = async { requestFunction() } try { val (info, response) = deferredResponse.await() val data = response!!.body(info) as RequestType callBack.onResponse(data, response) } catch (ex: Exception) { callBack.onError(ex) } } } } } override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean { return typeData.qualifiedName == "de.jensklingenberg.ktorfit.Call" } ``` -------------------------------- ### Implement a custom ResponseConverter Source: https://github.com/foso/ktorfit/blob/master/docs/responseconverter.md Implement the `ResponseConverter` interface to intercept Ktor responses. This converter wraps the successful response body in `MyOwnResponse.success` or catches exceptions to return `MyOwnResponse.error`. ```kotlin class MyOwnResponseConverter : ResponseConverter { override suspend fun wrapResponse( typeData: TypeData, requestFunction: suspend () -> Pair, ktorfit: Ktorfit ): Any { return try { val (info, response) = requestFunction() MyOwnResponse.success(response.body(info)) } catch (ex: Throwable) { MyOwnResponse.error(ex) } } override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean { return typeData.qualifiedName == "com.example.model.MyOwnResponse" } } ``` -------------------------------- ### Add Call Converter Factory Source: https://github.com/foso/ktorfit/blob/master/docs/migration.md Add this converter factory to your Ktorfit instance when migrating from Call? usage. ```kotlin .addConverterFactory(CallConverterFactory()) ``` -------------------------------- ### Custom Annotations Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Explains how to use and process custom annotations like @AuthRequired within Ktorfit requests, including how to access them via the HttpRequest object. ```APIDOC ## Annotations ### Description Function annotations are available in the request object with their respective values via the `annotation` extension (`HttpRequest.annotations` or `HttpRequestBuilder.annotations`). Note that `OptIn` and Ktorfit annotations are not included. ### Method POST ### Endpoint comments #### Query Parameters - **issue** (String) - Required - The issue identifier. - **message** (String) - Required - The comment message. ### Request Example ```kotlin @AuthRequired(optional = true) @POST("comments") suspend fun postComment( @Query("issue") issue: String, @Query("message") message: String, ): List ``` ### Custom Plugin Example ```kotlin val MyAuthPlugin = createClientPlugin("MyAuthPlugin", ::MyAuthPluginConfig) { onRequest { request, _ -> val auth = request.annotations.filterIsInstance().firstOrNull() ?: return@onRequest val token = this@createClientPlugin.pluginConfig.token if (!auth.optional && token == null) throw Exception("Need to be logged in") token?.let { request.headers.append("Authorization", "Bearer $it") } } } class MyAuthPluginConfig { var token: String? = null } ``` ### Response #### Success Response (200) - **List** - A list of comments. ``` -------------------------------- ### Add Custom Converter Factory to Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/converters/suspendresponseconverter.md Register your custom converter factory with the Ktorfit instance. This ensures that your converter is used for handling responses. ```kotlin ktorfit.converterFactories(MyOwnResponseConverterFactory()) ``` -------------------------------- ### Handle Call Response with Callback Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Implement the Callback interface to handle the response or errors from a Call API request. This is used when the CallResponseConverter is configured. ```kotlin exampleApi.getPersonById(3).onExecute(object : Callback{ override fun onResponse(call: People, response: HttpResponse) { //Do something with Response } override fun onError(exception: Exception) { //Do something with exception } }) ``` -------------------------------- ### Implement SuspendResponseConverter for Custom Wrapper Source: https://github.com/foso/ktorfit/blob/master/docs/converters/suspendresponseconverter.md Implement SuspendResponseConverter to intercept Ktorfit responses and wrap them in your custom MyOwnResponse class. This converter handles both success and failure cases. ```kotlin class MyOwnResponseConverterFactory : Converter.Factory{ override fun suspendResponseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.SuspendResponseConverter? { if(typeData.typeInfo.type == MyOwnResponse::class) { return object : Converter.SuspendResponseConverter { override suspend fun convert(result: KtorfitResult): Any { return when (result) { is KtorfitResult.Failure -> { MyOwnResponse.error(result.throwable) } is KtorfitResult.Success -> { MyOwnResponse.success(result.response.body(typeData.typeArgs.first().typeInfo)) } } } } } return null } } ``` -------------------------------- ### Workaround for Unresolved API Reference in Single-Target KMP Source: https://github.com/foso/ktorfit/blob/master/docs/knownissues.md When using Ktorfit in a Kotlin Multiplatform project with only one target, IntelliJ may show the generated API extension function as unresolved. Use this explicit generic syntax as a workaround, even though it is deprecated. ```kotlin ktorfit.create() ``` -------------------------------- ### TypeData Creation with QualifiedTypeName Source: https://github.com/foso/ktorfit/blob/master/docs/configuration.md Shows `TypeData` creation when `generateQualifiedTypeName` is enabled, including the qualified type name. ```kotlin val _typeData = TypeData.createTypeData( typeInfo = typeInfo>(), qualifiedTypename = "de.jensklingenberg.ktorfit.Call" ) ``` -------------------------------- ### Define API endpoint returning Flow Source: https://github.com/foso/ktorfit/blob/master/docs/converters/responseconverter.md Use this when your API endpoint should return a Kotlin Flow. Ensure your Ktorfit instance is configured with a FlowConverterFactory. ```kotlin @GET("/user") fun getUser(): Flow> ``` -------------------------------- ### Implement a Custom SuspendResponseConverter Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Implement the SuspendResponseConverter interface to create your own custom response converter. This allows you to handle the conversion from suspend functions to your desired asynchronous code. ```kotlin class MyOwnResponseConverter : SuspendResponseConverter { ... } ``` -------------------------------- ### Implement SuspendResponseConverter for User Type Source: https://github.com/foso/ktorfit/blob/master/docs/converters/example1.md Override `suspendResponseConverter` in your factory to return a `SuspendResponseConverter` when the target type is `User`. This converter handles the transformation of the HTTP response. ```kotlin override fun suspendResponseConverter( typeData: TypeData, ktorfit: Ktorfit ): Converter.SuspendResponseConverter? { if (typeData.typeInfo.type == User::class) { return object : Converter.SuspendResponseConverter { override suspend fun convert(result: KtorfitResult): Any { // Conversion logic here } } } return null } ``` -------------------------------- ### Redirect Deprecated Convert Function Source: https://github.com/foso/ktorfit/blob/master/docs/migration.md Redirect the deprecated convert function to the new suspend function that handles KtorfitResult. ```kotlin override suspend fun convert(response: HttpResponse): Any { return convert(KtorfitResult.Success(response)) } ``` -------------------------------- ### Add FlowConverterFactory Dependency Source: https://github.com/foso/ktorfit/blob/master/docs/converters/converters.md Include this dependency to use the FlowConverterFactory for handling Kotlin Flow conversions. ```kotlin implementation("de.jensklingenberg.ktorfit:ktorfit-converters-flow:$CONVERTER_VERSION") ``` -------------------------------- ### SuspendResponseConverter Implementation Source: https://github.com/foso/ktorfit/blob/master/docs/converters/migration.md This snippet shows a direct implementation of SuspendResponseConverter for handling suspend functions. It's used when you need to intercept and process suspend responses before they are returned to the callback. ```kotlin override suspend fun wrapSuspendResponse( typeData: TypeData, requestFunction: suspend () -> Pair, ktorfit: Ktorfit ): Any { return object : Call { override fun onExecute(callBack: Callback) { ktorfit.httpClient.launch { val deferredResponse = async { requestFunction() } val (data, response) = deferredResponse.await() try { val res = response.call.body(data) callBack.onResponse(res as RequestType, response) } catch (ex: Exception) { callBack.onError(ex) } } } } } override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean { return typeData.qualifiedName == "de.jensklingenberg.ktorfit.Call" } ``` -------------------------------- ### Request Body with @Body Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Send data in the request body using the @Body annotation. This is applicable to HTTP methods that support a request body. ```kotlin interface ExampleService { @POST("upload") suspend fun upload(@Body data: String) } ``` -------------------------------- ### Add CallConverterFactory Dependency Source: https://github.com/foso/ktorfit/blob/master/docs/converters/converters.md Include this dependency to use the CallConverterFactory for handling call-related conversions. ```kotlin implementation("de.jensklingenberg.ktorfit:ktorfit-converters-call:$CONVERTER_VERSION") ``` -------------------------------- ### Configure Ktorfit Error Checking Source: https://github.com/foso/ktorfit/blob/master/docs/configuration.md Set Ktorfit's error checking mode to NONE to disable all Ktorfit-related compile-time error checks. Other options include ERROR (default) and WARNING. ```kotlin ktorfit{ errorCheckingMode = ErrorCheckingMode.NONE } ``` -------------------------------- ### Multipart Data Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Send multipart data using either @Body with MultiPartFormDataContent or @Multipart with @Part annotations. ```APIDOC ## Multipart Data To send Multipart data, you have two options: ### 1) Using @Body with MultiPartFormDataContent ```kotlin interface ExampleService { @POST("upload") suspend fun upload(@Body data: MultiPartFormDataContent): String } ``` To upload MultiPartFormData, you need a parameter of type `MultiPartFormDataContent` annotated with `@Body`. The method must be annotated with `@POST` or `@PUT`. **Example Usage:** ```kotlin val multipart = MultiPartFormDataContent(formData { append("description", "Ktor logo") append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) }) exampleApi.upload(multipart) ``` ### 2) Using @Multipart and @Part ```kotlin @Multipart @POST("upload") suspend fun uploadFile( @Part("description") description: String, @Part("") file: List ): String ``` You can annotate a function with `@Multipart`. Then, you can annotate parameters with `@Part`. **Example Usage:** ```kotlin val multipart = formData { append("image", File("ktor_logo.png").readBytes(), Headers.build { append(HttpHeaders.ContentType, "image/png") append(HttpHeaders.ContentDisposition, "filename=ktor_logo.png") }) } exampleApi.uploadFile("Ktor logo", multipart) ``` All parameters annotated with `@Part` will be combined and sent as `MultiPartFormDataContent`. ``` -------------------------------- ### Define a Call API Call Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Define a Ktorfit API method that returns a Call. This is used in conjunction with the CallResponseConverter to handle responses asynchronously. ```kotlin @GET("people/{id}/") fun getPersonById(@Path("id") peopleId: Int): Call ``` -------------------------------- ### Use Call return type with Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/converters/responseconverter.md Configure Ktorfit with CallConverterFactory to use the Call type for API methods, allowing responses to be handled via callbacks. ```kotlin ktorfit.converterFactories(CallConverterFactory()) ``` ```kotlin @GET("people/{id}/") fun getPersonById(@Path("id") peopleId: Int): Call ``` -------------------------------- ### Define Data Models for API Response Source: https://github.com/foso/ktorfit/blob/master/docs/converters/example1.md Define Kotlin data classes that match the structure of your API's JSON response. Ensure these classes are marked with `@Serializable` if using Kotlin Serialization. ```kotlin @kotlinx.serialization.Serializable data class Envelope(val success: Boolean, val user: User) @kotlinx.serialization.Serializable data class User(val id: Int, val name: String) ``` -------------------------------- ### Add FlowConverterFactory to Ktorfit Builder Source: https://github.com/foso/ktorfit/blob/master/docs/converters/responseconverter.md Configure your Ktorfit instance to use the custom FlowConverterFactory by adding it to the converterFactories list during builder configuration. ```kotlin Ktorfit.Builder().converterFactories(FlowConverterFactory()).baseUrl("foo").build() ``` -------------------------------- ### Access Annotations in Request Object Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Function annotations are available in the request object via the `annotation` extension. OptIn and Ktorfit annotations are excluded. ```kotlin @AuthRequired(optional = true) @POST("comments") suspend fun postComment( @Query("issue") issue: String, @Query("message") message: String, ): List ``` -------------------------------- ### Tagging Requests with @Tag Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Add a tag to a request using the @Tag annotation. This tag can be accessed from the Ktor HttpClientCall attributes. ```kotlin @GET("posts") fun getPosts(@Tag("myTag") tag: String): List ``` -------------------------------- ### Add CallResponseConverter to Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Add the CallResponseConverter to your Ktorfit instance to enable the use of Call for API responses. This allows you to receive responses via a Callback. ```kotlin ktorfit.responseConverter(CallResponseConverter()) ``` -------------------------------- ### Define a Flow API Call Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Define a Ktorfit API method that returns a Kotlin Flow. This is used in conjunction with the FlowResponseConverter. ```kotlin @GET("comments") fun getCommentsById(@Query("postId") postId: String): Flow> ``` -------------------------------- ### Update API Function to Return Custom Wrapper Source: https://github.com/foso/ktorfit/blob/master/docs/converters/suspendresponseconverter.md Modify your API function's return type to use the custom MyOwnResponse wrapper. This change allows the function to return either a successful response or an error wrapped in your custom class. ```kotlin @GET("posts/{postId}/comments") suspend fun getCommentsByPostId(@Path("postId") postId: Int): MyOwnResponse> ``` -------------------------------- ### Enable Qualified Type Name Generation Source: https://github.com/foso/ktorfit/blob/master/docs/configuration.md Set `generateQualifiedTypeName` to true in the Ktorfit config to include the fully qualified type name in the generated code for `TypeData`. This is false by default. ```kotlin ktorfit { generateQualifiedTypeName = true } ``` -------------------------------- ### Form Data Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Send form-urlencoded data using @Field or @FieldMap, and annotate the method with @FormUrlEncoded. ```APIDOC ## Form Data To send FormData, you can use `@Field` or `@FieldMap`. Your function needs to be annotated with `@FormUrlEncoded`. ### @Field ```kotlin @POST("signup") @FormUrlEncoded suspend fun signup( @Field("username") username: String, @Field("email") email: String, @Field("password") password: String, @Field("confirmation") confirmation: String ): String ``` ### @FieldMap ```kotlin @POST("signup") @FormUrlEncoded suspend fun signup(@FieldMap fields: Map): String ``` ``` -------------------------------- ### Form Data with @FormUrlEncoded and @Field Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Send form-urlencoded data using @Field for individual fields and @FieldMap for a map of fields. The function must be annotated with @FormUrlEncoded. ```kotlin @POST("signup") @FormUrlEncoded suspend fun signup( @Field("username") username: String, @Field("email") email: String, @Field("password") password: String, @Field("confirmation") confirmation: String ): String ``` -------------------------------- ### Request Body Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Send data in the request body using the @Body annotation. Suitable for methods that support a request body. ```APIDOC ## Request Body `@Body` can be used as a parameter to send data in a request body. It can only be used with HTTP Methods that have a request body (e.g., POST, PUT). ### Example ```kotlin interface ExampleService { @POST("upload") suspend fun upload(@Body data: String): String } ``` ``` -------------------------------- ### Add FlowResponseConverter to Ktorfit Source: https://github.com/foso/ktorfit/blob/master/docs/suspendresponseconverter.md Add the FlowResponseConverter to your Ktorfit instance to enable Kotlin Flow support. This allows you to use Flow as a return type for your API calls. ```kotlin ktorfit.responseConverter(FlowResponseConverter()) ``` -------------------------------- ### Tag Annotation Source: https://github.com/foso/ktorfit/blob/master/docs/requests.md Add a tag to a request using the @Tag annotation, which can be accessed from the HttpClientCall attributes. ```APIDOC ## Tag Annotation Tag can be used to add a tag to a request. ### Example ```kotlin @GET("posts") fun getPosts(@Tag("myTag") tag: String): List ``` You can then access the tag from the attributes of a Ktor `HttpClientCall`: ```kotlin val myTag = response.call.attributes[AttributeKey("myTag")] ``` ```