Migration from M8

Big breaking changes

Replacement of HttpBody by HttpData

HttpBody was completely replaced by HttpData. HttpData is a data structure that abstracts over either ByteString buffers (HttpData.Bytes), data from files (HttpData.FileBytes), and combinations of both (HttpData.Compound). This allows spray-can to combine both heap byte buffers and data from files without ever having to load file data into a heap buffer. The companion object of HttpEntity contains lots of overloaded apply methods to create an HttpEntity without having to deal with HttpData directly.


Authentication rejections were remodelled. There’s now only one rejection type, AuthenticationFailedRejection, that contains a cause (CredentialsMissing or CredentialsRejected) and a list of headers to add to the response as a challenge for the client. Previously, challenge generation wasn’t handled uniformly and challenges weren’t generated at all in some cases. For your custom authenticator, you now have to generate the challenge headers directly in the ContextAuthenticator implementation. HttpAuthenticator now has a new abstract method to implement to return challenge headers.

Chunking support

With request chunk aggregation turned off (spray.can.server.request-chunk-aggregation-limit = 0) spray-can will deliver request chunks as is to the user-level handler. Previously, all chunks of a request came in subsequently without any interaction needed from the handler. Now the ChunkedRequestStart message has to be acknowledged with a RegisterChunkHandler message which contains the ActorRef of an actor to handle the chunks before any actual MessageChunks will be delivered. This allows to separate the handling of multiple incoming request chunk streams to several chunk handlers.

PathMatcher infrastructure

The path matching infrastructure was changed by replacing automatic behavior with more explicit directives. Mainly, this affects uses of nested path("") directives. Previously, path("") would either match 1) nothing, 2) a single slash, or 3) two slashes before the path end. Since the question of whether to deliver identical content under two different URIs (adding a trailing slash to a URI results in a semantically different URI!) is one of continuous discussion (see for example: http://googlewebmastercentral.blogspot.de/2010/04/to-slash-or-not-to-slash.html) we want to make it easy for your to pick your strategy and be consistent about it. With the new version, you can use one of the new directives instead of path("") to be explicit about what to match:

  • pathEnd, which matches just the path end without any trailing slashes
  • pathSingleSlash, which matches the path only when it ends with a slash
  • pathEndOrSingleSlash, which matches in both cases

Directives path and pathPrefix previously matched an optional beginning slash from the (remaining) path. The beginning slash is now required. If that’s not what you want use rawPathPrefix instead.


  • PathMatcher.Slash replaces the old PathMatcher.Slash_! which matches exactly one slash.
  • PathMatcher.PathEnd now matches exactly the end of the path (before: an optional slash as well).
  • PathMatcher.Segments also doesn’t match a trailing slash any more.
  • PathMatcher.Empty was renamed to PathMatcher.Neutral.

It is now easy to create path matchers for optional or repeated matches. Use PathMatcher.? to make a PathMatcher optional. Use PathMatcher.repeat to capture several matches.



  • Introduction of ToResponseMarshaller etc.
  • RequestContext.complete overloads gone
  • CompletionMagnet gone

Comprehensive list of breaking changes

The following list is an annotated version of all commits that were marked as breaking (!) since M8. You may find additional information on how to fix broken code by looking into the linked commits. Changes are often accompanied with test changes that show how code can be fixed.


  • ExpiringLruCache uses Duration instead of Long for timeouts [2394720].
  • LruCache.apply doesn’t allow Duration.Zero any more but Duration.Inf, instead, for not specifying any timeout [2394720].
[2394720](1, 2) use util.Timestamp in ExpiringLruCache


Server-side changes:

  • Http handlers must answer ChunkedRequestStart message with RegisterChunkHandler command (see chunking support) [d738e54]
  • ServerSettings timeout settings were moved into a separate class [9193318].

Client-side changes:

  • new member HostConnectorSettings.maxRedirects to enable automatic redirection handling on the client side [98365ff]
  • spray.can.client.user-agent-header vs. specifying a custom User-Agent header behavior changed: a custom User-Agent header now always overrides any configuration setting. The setting is used when there’s no custom header specified [6fec00c].
  • Connection failure and request timeout now produce dedicated exceptions on the client side [4b48875].
  • HostConnectorSettings.connectionSettings are now read from spray.can.client instead of from spray.can.host-connector.client [9abbcf6].
  • spray.can.client.ssl-encryption is gone. Instead, Http.Connect got a new sslEncryption parameter replacing the global setting. [e922cd4].
  • HostConnectorSetup must now be created from hostname and port. Before it was created from an InetSocketAddress which wasn’t enough to distinguish virtual hosts [a47f3b0].

Other changes:

  • keepOpenOnPeerClosed is not supported for Http and was removed from Http.Register [f6b0292].
  • ClientConnectionSettings and ServerSettings got a new member maxEncryptionChunkSize [0b5ef36].
  • Lots of formerly public types belonging to spray’s private API were marked as such [da29cdf].
  • spray.can.server.response-size-hint was adapted to spray.can.server.response-header-size-hint. The same for spray.can.client.request-size-hint [ba1ae77].
  • Content-Length.length is now a Long value. Also spray.can.server.parsing.max-content-length and incoming-auto-chunking-threshold-size [b2fee8d].
  • SetIdleTimeout command now always resets the timeout [ab17f00].
  • SslTlsSupport pipeline stage now publishes a SSLSessionEstablished event with session details [80982d4].
  • New ParserSettings.sslSessionInfoHeader setting which enables the automatic addition of a synthetic SSL-Session-Info header to a request/response with SSL session information [e486900].
  • ClientConnectionSettings.userAgentHeader is now modelled directly by an Option[User-Agent]. [da12531].
[ab17f00]use util.Timestamp instead of longs for timeout checking
[f6b0292]get rid of Http.Register.keepOpenOnPeerClosed, fixes #401
[0b5ef36]add max-encryption-chunk-size setting to ClientConnectionSettings and ServerSettings
[98365ff]Implement redirection following (issue #132)
[d738e54]require services to respond to ChunkedRequestStart with RegisterChunkHandler, fixes #473
[da29cdf]“privatize” all classes/objects not meant to be part of public API
[6fec00c]only render default User-Agent if no such header was explicit given, fixes #462
[9193318]break out ServerSettings timeout settings into sub case class, closes #489
[ba1ae77]upgrade to new HttpEntity / HttpData model
[b2fee8d]make Content-Length a long value, fixes #443
[4b48875]introduce dedicated exceptions for connection failure and request timeout for host-level API
[9abbcf6]when creating HostConnectorSettings expect client settings at spray.can.client, fixes #408
[e922cd4]move client.ssl-encryption setting from reference.conf into Http.Connect message, fixes #396
[a47f3b0]replace InetSocketAddress in HostConnectorSetup with hostname/port pair, fixes #394
[80982d4]Publish SSLSessionEstablished event from SslTlsSupport upon successful SSL handshaking
[e486900]Add SSLSessionInfo header to requests on server and responses on client
[da12531]model user-agent-header value as User-Agent to fail fast, fixes #458


  • Access-Control-Allow-Origin and Origin header models now have members of newly introduced type HttpOrigin instead of the previous Uri which didn’t completely match the model [015f3c6].
  • Renderer.seqRenderer and related signatures changed [e058a43].
  • in Uri.Query a '=' is rendered even for empty values unless the special value Query.EmptyValue is used. Also, a query parsed from ?key= will now be rendered the same way (previously, a trailing '=' was always stripped) [d2b8bba].
  • (Multipart)FormData.fields are now represented as Seq to be able to model duplicate fields [ad593d1].
  • HttpMessage.entityAccepted was renamed to HttpMessage.isEntityAccepted [5d78dae].
  • Replacement of HttpBody by HttpData [c6f49cc].
  • Many charsets in HttpCharsets are not any more available as static values. Use HttpCharset.getForKey("windows-1252") to access a particular charset [f625b5a].
  • Uri.Query.apply and Uri.Host.apply have a new charset parameter [88a25f7].
  • Uri.Query has a new subtype Uri.Query.Raw which will be generated when parsing with mode Uri.ParsingMode.RelaxedWithRawQuery [d8a9ee4].
  • MediaRanges.custom was renamed to MediaRange.custom [a915b8f].
  • HttpSuccess and HttpFailure are not public API any more. Use StatusCode.isSuccess instead [a9e0d2c].
  • HttpIp was replaced by RemoteAddress which also supports “unknown” addresses. X-Forwarded-For.ips member was renamed to addresses. Remote-Address.ip member was renamed to address [443b0d8].
[015f3c6]add HttpOrigin and use it for Access-Control-Allow-Origin and Origin headers, fixes #579
[e058a43]allow creation of custom MediaTypes with ‘*’ as a subtype when called by the parser, fixes #529
[d2b8bba]introduce a distinction between ”?key=” and ”?key” in queries, fixes #460
[ad593d1]make multipart form-data more flexible but have it adhere to the RFC more strictly
[5d78dae]add CONNECT method and support for custom HTTP methods, closes #428
[c6f49cc]introduce HttpData model replacing the byte array in HttpBody and MessageChunk, closes #365
[f625b5a]add small extensions to Uri model
[88a25f7]make only standard charsets available as constants, fixes #340
[a915b8f]fix raw queries still performing %-decoding and not being rendered as raw, fixes #330
[d8a9ee4]add support for Accept-Header extensions and media-type parameters, closes #310
[a9e0d2c]support for custom status codes, fixes #564
[443b0d8]remodel HttpIp to RemoteAddress, fixes #638


  • RequestContext.complete overloads were removed in favor of using the marshalling infrastructure (see (Un)marshalling) [4d787dc].
  • CompletionMagnet is gone in favor of the new ToResponseMarshaller infrastructure [7a36de5].
  • FieldDefMagnetAux, ParamDefMagnetAux, and AnyParamDefMagnetAux are gone and replaced by a simpler construct [d86cb80].
  • RequestContext.marshallingContext is gone. produce directive loses its status and header parameter which can be replaced by using an appropriate ToResponseMarshaller [b145ced].
  • AuthenticationFailedRejection now directly contains challenge headers to return. There’s no need to implement a (fake) HttpAuthenticator to make use of the rejection (see Authentication) [9c9b976].
  • FileAndResourceDirectives.withTrailingSlash and fileSystemPath are now private [ab35761].
  • decompressRequest and compressResponse now always need parentheses. Also, encoding directives like the compressResponse automatically use the autoChunkFileBytes directives to avoid having to load potentially huge files into memory [e3defb4].
  • (h)require directives can now take several rejections instead of an Option of only one [9c11228].
  • detachTo is gone in favor of detach() which always needs parentheses. The underlying implementation is now Future-based and needs an (implicit or explicit) ExecutionContext or ActorRefFactory in scope [ead4a70].
  • PathMatcher.(flat)Map were renamed to PathMatcher.h(flat)Map. map and flatMap were reintroduced for PathMatcher1 instances [8c91851].
  • AuthenticationFailedRejection and AuthenticationRequiredRejection were merged and remodelled. [034779d]
  • PathMatchers.Empty was renamed to PathMatchers.Neutral [ee7fe47].
  • Slash_! is gone and Slash got its semantics. PathEnd now just matches the end of the path. PathDirectives were adapted to have the same semantics as before [1480e73].
  • UserPassAuthenticator.cached was renamed to CachedUserPassAuthenticator.apply [1326046].
  • PathMatcher.apply now takes a Path prefix instead of a String [3ff3471].
  • PathMatcher.Segments doesn’t match trailing slashes anymore. Implicit infrastructure for PathMatcher.? was changed [8ee49d7].
  • pathEnd and pathEndOrSingleSlash were introduced to replace the former path("") (see PathMatcher infrastructure) [f0cbf25].
[4d787dc]remove superfluous RequestContext::complete overloads
[1480e73]improve PathMatcher infrastructure
[7a36de5]CompletionMagnet: gone, streamlining completion API: accomplished
[d86cb80]remove layer of *Aux classes by type aliases for simplicity
[b145ced]upgrade to new ToResponseMarshaller, closes #293
[9c9b976]AuthenticationFailedRejection now directly contains challenge headers to return, fixes #538
[ab35761]fix getFromDirectory and getFromResourceDirectory not working properly for URIs with encoded chars
[e3defb4]have encodeResponse automatically tie in autoChunkFileBytes
[9c11228]small improvement of require and hrequire modifiers on directives
[ead4a70]Added detach directive which executes its inner route in a future. Removed detachTo directive. Fixes #240.
[8c91851]PathMatcher.(flat)map => h(flat)map, introduce map/flatMap, fixes #274
[034779d]Render WWW-Authenticate header also for rejected credentials, fixes #188
[ee7fe47]redefine PathMatchers.Empty as PathMatchers.Neutral with explicit type annotation, fixes #339
[1326046]move UserPassAuthenticator.cached to CachedUserPassAuthenticator.apply, fixes #352
[3ff3471]change PathMatcher.apply, add PathMatcher.provide method, cosmetic improvements
[8ee49d7]add PathMatcher::repeated modifier, closes #636
[f0cbf25]add pathEnd and pathEndOrSingleSlash directive, closes #628



  • [e234dd9]
  • [b0b90b3]
  • The settings infrastructure was reworked. XxxSettings.apply(config: Config) now takes the root config instead of the subconfig. For the old behavior use the new fromSubConfig instead [78d7e4a].
[e234dd9]remove SprayActorLogging and UtilSettings, simplify LoggingContext, fixes #421
[b0b90b3]Swap Duration.Undefined by Duration.Inf, fixes #440
[78d7e4a]improve *Settings infrastructure