Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: disable server-side HTTP pipelining by default #3321

Merged
merged 1 commit into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions akka-http-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ akka.http {
# connection can be "open" (i.e. being processed by the application) at any
# time. Set to higher values to enable HTTP pipelining.
# This value must be > 0 and <= 1024.
pipelining-limit = 16
pipelining-limit = 1

# Enables/disables the addition of a `Remote-Address` header
# holding the clients (remote) IP address.
Expand Down Expand Up @@ -535,7 +535,7 @@ akka.http {

# Allows overriding settings per host. The setting must be a list in which each entry
# is an object with a `host-pattern` entry that specifies for which hosts the overrides
# should take effect. All other entries have the same syntax as entries in the
# should take effect. All other entries have the same syntax as entries in the
# `host-connection-pool` section.
#
# The `host-pattern` can have these forms:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ class HttpServerSpec extends AkkaSpec(
headers = List(Host("example.com")),
entity = HttpEntity.Strict(ContentTypes.`application/octet-stream`, ByteString("abcdefghijkl")))

simpleResponse()

send("""POST /next-strict HTTP/1.1
|Host: example.com
|Content-Length: 12
Expand Down Expand Up @@ -267,6 +269,8 @@ class HttpServerSpec extends AkkaSpec(
dataProbe.expectComplete()
}

simpleResponse()

send("""POST /next-strict HTTP/1.1
|Host: example.com
|Content-Length: 5
Expand Down Expand Up @@ -306,6 +310,8 @@ class HttpServerSpec extends AkkaSpec(
dataProbe.expectComplete()
}

simpleResponse()

send("""POST /next-strict HTTP/1.1
|Host: example.com
|Content-Length: 5
Expand Down Expand Up @@ -412,6 +418,8 @@ class HttpServerSpec extends AkkaSpec(

val whenComplete = expectRequest().entity.dataBytes.runWith(Sink.ignore)
whenComplete.futureValue should be(akka.Done)

simpleResponse()
}
shutdownBlueprint()
})
Expand Down Expand Up @@ -1219,7 +1227,6 @@ class HttpServerSpec extends AkkaSpec(
error shouldEqual EntityStreamSizeException(limit, Some(actualSize))
error.getMessage should include("exceeded size limit")

responses.expectRequest()
responses.sendError(error.asInstanceOf[Exception])

expectResponseWithWipedDate(
Expand All @@ -1244,7 +1251,6 @@ class HttpServerSpec extends AkkaSpec(
error shouldEqual EntityStreamSizeException(limit, None)
error.getMessage should include("exceeded size limit")

responses.expectRequest()
responses.sendError(error.asInstanceOf[Exception])

expectResponseWithWipedDate(
Expand All @@ -1264,6 +1270,8 @@ class HttpServerSpec extends AkkaSpec(
sendStrictRequestWithLength(10)
expectRequest().expectEntity[HttpEntity.Strict](10)

simpleResponse()

// entities that would be strict but have a Content-Length > the configured maximum are delivered
// as single element Default entities!
sendStrictRequestWithLength(11)
Expand All @@ -1274,6 +1282,8 @@ class HttpServerSpec extends AkkaSpec(
sendDefaultRequestWithLength(10)
expectRequest().expectEntity[HttpEntity.Default](10)

simpleResponse()

sendDefaultRequestWithLength(11)
expectRequest().expectDefaultEntityWithSizeError(limit = 10, actualSize = 11)
}
Expand All @@ -1282,6 +1292,8 @@ class HttpServerSpec extends AkkaSpec(
sendChunkedRequestWithLength(10)
expectRequest().expectEntity[HttpEntity.Chunked](10)

simpleResponse()

sendChunkedRequestWithLength(11)
expectRequest().expectChunkedEntityWithSizeError(limit = 10)
}
Expand All @@ -1290,6 +1302,7 @@ class HttpServerSpec extends AkkaSpec(
sendStrictRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Strict](10)

simpleResponse()
// entities that would be strict but have a Content-Length > the configured maximum are delivered
// as single element Default entities!
sendStrictRequestWithLength(11)
Expand All @@ -1300,6 +1313,8 @@ class HttpServerSpec extends AkkaSpec(
sendDefaultRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Default](10)

simpleResponse()

sendDefaultRequestWithLength(11)
expectRequest().mapEntity(_ withSizeLimit 10).expectDefaultEntityWithSizeError(limit = 10, actualSize = 11)
}
Expand All @@ -1308,6 +1323,8 @@ class HttpServerSpec extends AkkaSpec(
sendChunkedRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Chunked](10)

simpleResponse()

sendChunkedRequestWithLength(11)
expectRequest().mapEntity(_ withSizeLimit 10).expectChunkedEntityWithSizeError(limit = 10)
}
Expand All @@ -1318,6 +1335,8 @@ class HttpServerSpec extends AkkaSpec(
sendStrictRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Default](10)

simpleResponse()

sendStrictRequestWithLength(11)
expectRequest().mapEntity(_ withSizeLimit 10).expectDefaultEntityWithSizeError(limit = 10, actualSize = 11)
}
Expand All @@ -1326,6 +1345,8 @@ class HttpServerSpec extends AkkaSpec(
sendDefaultRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Default](10)

simpleResponse()

sendDefaultRequestWithLength(11)
expectRequest().mapEntity(_ withSizeLimit 10).expectDefaultEntityWithSizeError(limit = 10, actualSize = 11)
}
Expand All @@ -1334,6 +1355,8 @@ class HttpServerSpec extends AkkaSpec(
sendChunkedRequestWithLength(10)
expectRequest().mapEntity(_ withSizeLimit 10).expectEntity[HttpEntity.Chunked](10)

simpleResponse()

sendChunkedRequestWithLength(11)
expectRequest().mapEntity(_ withSizeLimit 10).expectChunkedEntityWithSizeError(limit = 10)
}
Expand All @@ -1346,6 +1369,8 @@ class HttpServerSpec extends AkkaSpec(
sendDefaultRequestWithLength(10)
expectRequest().mapEntity(nameDataSource("foo")).expectEntity[HttpEntity.Default](10)

simpleResponse()

sendDefaultRequestWithLength(11)
expectRequest().mapEntity(nameDataSource("foo")).expectDefaultEntityWithSizeError(limit = 10, actualSize = 11)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,23 @@ abstract class HttpServerTestSetupBase {

def closeNetworkInput(): Unit = netIn.sendComplete()

def simpleResponse(): Unit = {
responses.sendNext(HttpResponse())
expectResponseWithWipedDate(
"""HTTP/1.1 200 OK
|Server: akka-http/test
|Date: XXXX
|Content-Length: 0
|
|"""
)
}

def shutdownBlueprint(): Unit = {
netIn.sendComplete()
requests.expectComplete()

responses.sendComplete()
netOut.expectBytes(ByteString("HTT")) // ???
netOut.expectComplete()
netOut.cancel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ This can save bandwidth in some cases, but is also counter-intuitive when you ac
and may increase resource usage in cases where the logic behind the `GET` request is heavy. For this reason we have changed
the default value of `akka.http.server.transparent-head-requests` to `off`, making this feature opt-in.

### Server-side HTTP pipelining now disabled by default

HTTP pipelining is now disabled by default. It is not used commonly by clients because it suffers from
head-of-line blocking. It is recommended to use pooled connections or HTTP/2 instead.

HTTP pipelining is still supported and can be re-enabled by setting `pipelining-limit = n` with a value of `n > 1`.

### X-Real-Ip now takes precedence over Remote-Address in extractClientIP

The @ref[extractClientIP](../routing-dsl/directives/misc-directives/extractClientIP.md) now returns the value of the
Expand Down