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
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 slashespathSingleSlash, which matches the path only when it ends with a slashpathEndOrSingleSlash, 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.
Also:
PathMatcher.Slashreplaces the oldPathMatcher.Slash_!which matches exactly one slash.PathMatcher.PathEndnow matches exactly the end of the path (before: an optional slash as well).PathMatcher.Segmentsalso doesn’t match a trailing slash any more.PathMatcher.Emptywas renamed toPathMatcher.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.
(Un)marshalling
(TODO)
- 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.
spray-can
Server-side changes:
- Http handlers must answer
ChunkedRequestStartmessage withRegisterChunkHandlercommand (see chunking support) [d738e54]ServerSettingstimeout settings were moved into a separate class [9193318].
Client-side changes:
- new member
HostConnectorSettings.maxRedirectsto enable automatic redirection handling on the client side [98365ff]spray.can.client.user-agent-headervs. specifying a customUser-Agentheader behavior changed: a customUser-Agentheader 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.connectionSettingsare now read fromspray.can.clientinstead of fromspray.can.host-connector.client[9abbcf6].spray.can.client.ssl-encryptionis gone. Instead,Http.Connectgot a newsslEncryptionparameter replacing the global setting. [e922cd4].HostConnectorSetupmust now be created from hostname and port. Before it was created from anInetSocketAddresswhich wasn’t enough to distinguish virtual hosts [a47f3b0].
Other changes:
keepOpenOnPeerClosedis not supported for Http and was removed fromHttp.Register[f6b0292].ClientConnectionSettingsandServerSettingsgot a new membermaxEncryptionChunkSize[0b5ef36].- Lots of formerly public types belonging to spray’s private API were marked as such [da29cdf].
spray.can.server.response-size-hintwas adapted tospray.can.server.response-header-size-hint. The same forspray.can.client.request-size-hint[ba1ae77].Content-Length.lengthis now aLongvalue. Alsospray.can.server.parsing.max-content-lengthandincoming-auto-chunking-threshold-size[b2fee8d].SetIdleTimeoutcommand now always resets the timeout [ab17f00].SslTlsSupportpipeline stage now publishes aSSLSessionEstablishedevent with session details [80982d4].- New
ParserSettings.sslSessionInfoHeadersetting which enables the automatic addition of a syntheticSSL-Session-Infoheader to a request/response with SSL session information [e486900].ClientConnectionSettings.userAgentHeaderis now modelled directly by anOption[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 |
spray-http
Access-Control-Allow-OriginandOriginheader models now have members of newly introduced typeHttpOrigininstead of the previousUriwhich didn’t completely match the model [015f3c6].Renderer.seqRendererand related signatures changed [e058a43].- in
Uri.Querya'='is rendered even for empty values unless the special valueQuery.EmptyValueis used. Also, a query parsed from?key=will now be rendered the same way (previously, a trailing'='was always stripped) [d2b8bba].(Multipart)FormData.fieldsare now represented asSeqto be able to model duplicate fields [ad593d1].HttpMessage.entityAcceptedwas renamed toHttpMessage.isEntityAccepted[5d78dae].- Replacement of HttpBody by HttpData [c6f49cc].
- Many charsets in
HttpCharsetsare not any more available as static values. UseHttpCharset.getForKey("windows-1252")to access a particular charset [f625b5a].Uri.Query.applyandUri.Host.applyhave a newcharsetparameter [88a25f7].Uri.Queryhas a new subtypeUri.Query.Rawwhich will be generated when parsing with modeUri.ParsingMode.RelaxedWithRawQuery[d8a9ee4].MediaRanges.customwas renamed toMediaRange.custom[a915b8f].HttpSuccessandHttpFailureare not public API any more. UseStatusCode.isSuccessinstead [a9e0d2c].HttpIpwas replaced byRemoteAddresswhich also supports “unknown” addresses.X-Forwarded-For.ipsmember was renamed toaddresses.Remote-Address.ipmember 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 |
spray-routing
RequestContext.completeoverloads were removed in favor of using the marshalling infrastructure (see (Un)marshalling) [4d787dc].CompletionMagnetis gone in favor of the newToResponseMarshallerinfrastructure [7a36de5].FieldDefMagnetAux,ParamDefMagnetAux, andAnyParamDefMagnetAuxare gone and replaced by a simpler construct [d86cb80].RequestContext.marshallingContextis gone.producedirective loses itsstatusandheaderparameter which can be replaced by using an appropriateToResponseMarshaller[b145ced].AuthenticationFailedRejectionnow directly contains challenge headers to return. There’s no need to implement a (fake)HttpAuthenticatorto make use of the rejection (see Authentication) [9c9b976].FileAndResourceDirectives.withTrailingSlashandfileSystemPathare now private [ab35761].decompressRequestandcompressResponsenow always need parentheses. Also, encoding directives like thecompressResponseautomatically use theautoChunkFileBytesdirectives to avoid having to load potentially huge files into memory [e3defb4].(h)requiredirectives can now take several rejections instead of an Option of only one [9c11228].detachTois gone in favor ofdetach()which always needs parentheses. The underlying implementation is now Future-based and needs an (implicit or explicit)ExecutionContextorActorRefFactoryin scope [ead4a70].PathMatcher.(flat)Mapwere renamed toPathMatcher.h(flat)Map.mapandflatMapwere reintroduced forPathMatcher1instances [8c91851].AuthenticationFailedRejectionandAuthenticationRequiredRejectionwere merged and remodelled. [034779d]PathMatchers.Emptywas renamed toPathMatchers.Neutral[ee7fe47].Slash_!is gone andSlashgot its semantics.PathEndnow just matches the end of the path.PathDirectiveswere adapted to have the same semantics as before [1480e73].UserPassAuthenticator.cachedwas renamed toCachedUserPassAuthenticator.apply[1326046].PathMatcher.applynow takes aPathprefix instead of aString[3ff3471].PathMatcher.Segmentsdoesn’t match trailing slashes anymore. Implicit infrastructure forPathMatcher.?was changed [8ee49d7].pathEndand pathEndOrSingleSlash were introduced to replace the formerpath("")(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 |
spray-httpx
(TODO)
| [ae17d18] | create FormFile as an easy way to access uploaded file information for forms, fixes #327 |
| [9d27559] | rename BodyPart.getName -> BodyPart.name, add BodyPart.dispositionParameterValue |
| [fad2ff2] | polish MediaType model, fix tests, smaller improvements |
| [f8f5b6d] | support content negotiation, fixes #167 |
| [ebaa580] | enable FEOU and FSOD to be interchanged in the usual cases, fixes #426 |
| [ebe3e97] | remove MetaUnmarshallers.scala, fold only member into FormDataUnmarshallers.scala |
| [dd51be5] | change default charset for application/x-www-form-urlencoded to utf8, fixes #526 |
| [f5b1535] | decode should remove Content-Encoding header from message |
| [adf9170] | move unmarshal and unmarshalUnsafe to Unmarshaller and add unmarshaller method |
| [f5997f8] | flexibilize RequestBuilding and ResponseTransformation by generalizing the ~> operator |
spray-io
(TODO)
| [01c4aa9] | major refactoring of SslTlsSupport, fixes #544 |
| [5f23219] | improve DynamicPipelines trait |
| [76345ba] | abort connection on idle-timeout, fixes #539 |
| [2c77d8f] | add support for compound write commands (Tcp.CompoundWrite) |
spray-testkit
(TODO)
| [6a99cb7] | move result.awaitResult call from injectIntoRoute into check, fixes #205 |
| [72c9397] | in RouteTests always convert URIs into absolute ones, fixes #464 |
| [680fde0] | enable custom ExceptionHandlers in routing tests |
| [3b4ac55] | small clean-up, remove duplication with httpx RequestBuilding |