# Ktor: Altering served content

DevFeed: [Ktor: Altering served content](<https://devfeed.tech/articles/ktor-altering-served-content-21773.md>)

Original publisher: [Read original article](<https://enoent.fr/posts/ktor-altering-served-content/>)

Author: Marc Plano-Lesay

Published: 2022-09-06T04:00:00Z

Content type: tutorial

Language: en

Sources: [Marc Plano-Lesay](<https://devfeed.tech/sources/marc-plano-lesay.md>)

Topics: [Web Development](<https://devfeed.tech/topics/web-development.md>), [Netty](<https://devfeed.tech/topics/netty.md>), [HTTP](<https://devfeed.tech/topics/http.md>), [servers](<https://devfeed.tech/topics/servers.md>)

Tags: [configuration](<https://devfeed.tech/tags/configuration.md>), [html](<https://devfeed.tech/tags/html.md>), [http](<https://devfeed.tech/tags/http.md>), [js](<https://devfeed.tech/tags/js.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [ktor](<https://devfeed.tech/tags/ktor.md>), [plugin](<https://devfeed.tech/tags/plugin.md>), [plugins](<https://devfeed.tech/tags/plugins.md>), [script](<https://devfeed.tech/tags/script.md>), [server](<https://devfeed.tech/tags/server.md>), [web](<https://devfeed.tech/tags/web.md>)

## AI overview

A tutorial on creating a Ktor plugin that injects a configured script element into the head of served HTML files. It uses Ktor response-pipeline hooks to transform HTML while leaving other file formats unchanged, with Jsoup handling the HTML modification.

## Source excerpt

When serving files with Ktor, there might be times when you need to alter those files. For example, you might want to inject a script in every served HTML file. For this purpose, we can leverage plugins. Plugins can hook at different stages of the request/response pipeline: graph LR Request --> Plugin1[Plugin] Plugin1 --> Handler Handler --> Plugin2[Plugin] Plugin2 --> Response Ktor request/response pipeline Let's write a plugin that transforms a specific type of files - going with the previous example of injecting a script to every served HTML file. Our plugin needs to: Take a script URL as an input. If not provided, it won't do anything. Add that script as a <script> element in the <head> of any HTML file served by this Ktor server. Obviously, not interfere with any other file format. Let's start by defining an empty plugin and its configuration: class PluginConfiguration { var scriptUrl: String? = null } val ScriptInjectionPlugin = createApplicationPlugin( name = "ScriptInjectionPlugin", createConfiguration = ::PluginConfiguration, ) { val scriptUrl = pluginConfig.scriptUrl // The rest of our plugin goes here. } With this simple definition, we can add our plugin to a Ktor server: embeddedServer(Netty, port = 8080) { install(ScriptInjectionPlugin) { scriptUrl = "http://foo.bar/my/injected/script.js" } } Now, let's see how we can transform the body. Ktor offers a few handlers to hook into the pipeline shown above. The main ones are: onCall is fairly high level, and is mostly useful to get information about a request (e.g. to log a request). onCallReceive allows to transform data received from the client before it's processed. onCallRespond allows to transform data before sending it to the client. That's the one we're after. There are a few other handlers for specific use-cases, detailed here. Let's hook into onCallRespond, and its helper transformBody. We also need to check if the content type we're sending is HTML, otherwise, we just forward the response body as-i