XHttpMethodOverride
The XHttpMethodOverride plugin enables the capability to tunnel HTTP verbs inside the X-HTTP-Method-Override header. This might be useful if your server API handles multiple HTTP verbs (GET, PUT, POST, DELETE, and so on), but the client can only use a limited set of verbs (for example, GET and POST) due to specific limitations. For instance, if the client sends a request with the X-Http-Method-Override header set to DELETE, Ktor will process this request using the delete route handler.
Add dependencies
To use XHttpMethodOverride, add the ktor-server-method-override artifact to your build script:
implementation("io.ktor:ktor-server-method-override:$ktor_version")
implementation "io.ktor:ktor-server-method-override:$ktor_version"
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-server-method-override-jvm</artifactId>
<version>${ktor_version}</version>
</dependency>
Install XHttpMethodOverride
To install the XHttpMethodOverride plugin to your application, pass it to the install function in the specified module. The following examples show how to install XHttpMethodOverride:
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.application.*
import io.ktor.server.plugins.methodoverride.*
fun main() {
embeddedServer(Netty, port = 8080) {
install(XHttpMethodOverride)
// ...
}.start(wait = true)
}
import io.ktor.server.application.*
import io.ktor.server.plugins.methodoverride.*
// ...
fun Application.module() {
install(XHttpMethodOverride)
// ...
}
By default, XHttpMethodOverride checks the X-Http-Method-Override header to determine the route that should handle the request. You can customize a header name using the headerName property.
Example
The HTTP request below uses the POST verb with the X-Http-Method-Override header set to DELETE:
POST http://0.0.0.0:8080/customer/3
X-Http-Method-Override: DELETE
To handle such requests using the delete route handler, you need to install XHttpMethodOverride:
package com.example
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.plugins.methodoverride.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import io.ktor.server.util.getValue
@Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String)
fun Application.main() {
val customerStorage = mutableListOf<Customer>()
customerStorage.addAll(
arrayOf(
Customer(1, "Jane", "Smith"),
Customer(2, "John", "Smith"),
Customer(3, "Jet", "Brains")
)
)
install(XHttpMethodOverride)
install(ContentNegotiation) {
json(Json)
}
routing {
get("/customer/{id}") {
val id: Int by call.parameters
val customer: Customer = customerStorage.find { it.id == id }!!
call.respond(customer)
}
delete("/customer/{id}") {
val id: Int by call.parameters
customerStorage.removeIf { it.id == id }
call.respondText("Customer is removed", status = HttpStatusCode.NoContent)
}
}
}
You can find the full example here: json-kotlinx-method-override.
24 April 2026