Ktor 3.0.0 Help

Forwarded headers

The ForwardedHeaders and XForwardedHeaders plugins allow you to handle reverse proxy headers to get information about the original request when a Ktor server is placed behind a reverse proxy. This might be useful for logging purposes.

  • ForwardedHeaders handles the Forwarded header (RFC 7239)

  • XForwardedHeaders handles the following X-Forwarded- headers:

    • X-Forwarded-Host/X-Forwarded-Server

    • X-Forwarded-For

    • X-Forwarded-By

    • X-Forwarded-Proto/X-Forwarded-Protocol

    • X-Forwarded-SSL/Front-End-Https

Add dependencies

To use the ForwardedHeaders/XForwardedHeaders plugins, you need to include the ktor-server-forwarded-header artifact in the build script:

implementation("io.ktor:ktor-server-forwarded-header:$ktor_version")
implementation "io.ktor:ktor-server-forwarded-header:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-forwarded-header-jvm</artifactId> <version>${ktor_version}</version> </dependency>

Install plugins

To install the ForwardedHeaders plugin to the application, pass it to the install function in the specified module. The code snippets below show how to install ForwardedHeaders...

  • ... 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.forwardedheaders.* fun main() { embeddedServer(Netty, port = 8080) { install(ForwardedHeaders) // ... }.start(wait = true) }
import io.ktor.server.application.* import io.ktor.server.plugins.forwardedheaders.* // ... fun Application.module() { install(ForwardedHeaders) // ... }

To install the XForwardedHeaders plugin to the application, pass it to the install function in the specified module. The code snippets below show how to install XForwardedHeaders...

  • ... 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.forwardedheaders.* fun main() { embeddedServer(Netty, port = 8080) { install(XForwardedHeaders) // ... }.start(wait = true) }
import io.ktor.server.application.* import io.ktor.server.plugins.forwardedheaders.* // ... fun Application.module() { install(XForwardedHeaders) // ... }

After installing ForwardedHeaders/XForwardedHeaders, you can get information about the original request using the call.request.origin property.

Get request information

Proxy request information

To get information about the proxy request, use the call.request.local property inside the route handler. The code snippet below shows how to obtain information about the proxy address and the host to which the request was made:

get("/hello") { val remoteHost = call.request.local.remoteHost val serverHost = call.request.local.serverHost }

Original request information

To read information about the original request, use the call.request.origin property:

get("/hello") { val originRemoteHost = call.request.origin.remoteHost val originServerHost = call.request.origin.serverHost }

The table below shows the values of different properties exposed by call.request.origin depending on whether ForwardedHeaders/XForwardedHeaders is installed or not.

Request diagram

Property

Without ForwardedHeaders

With ForwarderHeaders

origin.localHost

web-server

web-server

origin.localPort

8080

8080

origin.serverHost

web-server

proxy

origin.serverPort

8080

80

origin.remoteHost

proxy

client

origin.remotePort

32864

32864

Configure ForwardedHeaders

You may need to configure ForwardedHeaders/XForwardedHeaders if a request goes through multiple proxies. In this case, X-Forwarded-For contains all the IP addresses of each successive proxy, for example:

X-Forwarded-For: <client>, <proxy1>, <proxy2>

By default, XForwardedHeader assigns the first entry in X-Forwarded-For to the call.request.origin.remoteHost property. You can also supply custom logic for selecting an IP address. XForwardedHeadersConfig exposes the following API for this:

  • useFirstProxy and useLastProxy allow you to take the first or last value from the list of IP addresses, respectively.

  • skipLastProxies skips the specified number of entries starting from the right and takes the next entry. For example, if the proxiesCount parameter is equal to 3, origin.remoteHost will return 10.0.0.123 for the header below:

    X-Forwarded-For: 10.0.0.123, proxy-1, proxy-2, proxy-3
  • skipKnownProxies removes the specified entries from the list and takes the last entry. For example, if you pass listOf("proxy-1", "proxy-3") to this function, origin.remoteHost will return proxy-2 for the header below:

    X-Forwarded-For: 10.0.0.123, proxy-1, proxy-2, proxy-3
  • extractEdgeProxy allows you to provide custom logic for extracting the value from the X-Forward-* headers.

Last modified: 02 April 2024