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, you need to include the ktor-server-method-override artifact in the 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 the application, pass it to the install function in the specified module. The code snippets below show how to install XHttpMethodOverride...
... inside the embeddedServer function call.
... inside the explicitly defined module, which is an extension function of the Application class.
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.
20 October 2025