Compression feature adds the ability to compress outgoing content using gzip, deflate or custom encoder and thus reduce the size of the response.
install(Compression)
io.ktor.features.Compression
类中定义,无需任何额外构件。
When the configuration block is omitted, the default configuration is used. It includes the following encoders:
If you want to select specific encoders you need to provide a configuration block:
install(Compression) {
gzip()
}
Each encoder can be configured with a priority and some conditions:
install(Compression) {
gzip {
priority = 1.0
}
deflate {
priority = 10.0
minimumSize(1024) // condition
}
}
Encoders are sorted by specified quality in an Accept-Encoding
header in the HTTP request, and
then by specified priority. First encoder that satisfies all conditions wins.
In the example above when Accept-Encoding
doesn’t specify quality, gzip
will be selected for all contents
less than 1K in size, and all the rest will be encoded with deflate
encoder.
Some typical conditions are readily available:
minimumSize
– minimum size of the response to compressmatchContentType
– one or more content types that should be compressedexcludeContentType
– do not compress these content typesYou can also use a custom condition by providing a predicate:
gzip {
condition {
parameters["e"] == "1"
}
}
HTTPS with any kind of compression is vulnerable to the BREACH attack. This kind of attack allows a malicious attacker to guess a secret (like a session, an auth token, a password, or a credit card) from an encrypted HTTPS page in less than a minute.
You can mitigate this attack by:
Set-Cookie
with a session_id).<!-- 100~500 random_bytes !-->
making it much harder to guess the secret for an attacker in a reasonable time.application.install(Compression) {
gzip {
condition {
// @TODO: Check: this is only effective if your website is completely HTTPS and has HSTS enabled.
request.headers[HttpHeaders.Referrer]?.startsWith("https://my.domain/") == true
}
}
}
TL;DR; Even when HTTPS prevents an eavesdropper to know the content of a request, it does not hide the response length. So one of your users could be connecting to an evil access point, for example by connecting to a public network or one with a well-known password, or a private network with an Evil Twin. That access point can intercept all the encrypted messages and measure the length. Then can modify any non-https connection (or social engineer the user to access an https page controlled by the attacker) to inject a javascript or place images pointing to the vulnerable page mutating an input (get, post or header parameters) that are reflected in either the headers or the response body, then the access point can measure the length of the responses to guess a secret with as little as 100 to 10000 requests that are forced to be done by your browser with either the javascript or image requests without the user ever noticing.
You can provide your own encoder by implementing the CompressionEncoder
interface and providing a configuration function.
Since content can be provided as a ReadChannel
or WriteChannel
, it should be able to compress in both ways.
See GzipEncoder
as an example of an encoder.