diff --git a/akka-http-tests/src/test/scala/akka/http/server/directives/RespondWithDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/server/directives/RespondWithDirectivesSpec.scala new file mode 100644 index 0000000000..711a1497a1 --- /dev/null +++ b/akka-http-tests/src/test/scala/akka/http/server/directives/RespondWithDirectivesSpec.scala @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.server.directives + +import akka.http.model._ +import MediaTypes._ +import headers._ +import StatusCodes._ + +import akka.http.server._ + +class RespondWithDirectivesSpec extends RoutingSpec { + + "overrideStatusCode" should { + "set the given status on successful responses" in { + Get() ~> { + overrideStatusCode(Created) { completeOk } + } ~> check { response shouldEqual HttpResponse(Created) } + } + "leave rejections unaffected" in { + Get() ~> { + overrideStatusCode(Created) { reject } + } ~> check { rejections shouldEqual Nil } + } + } + + val customHeader = RawHeader("custom", "custom") + val customHeader2 = RawHeader("custom2", "custom2") + val existingHeader = RawHeader("custom", "existing") + + "respondWithHeader" should { + val customHeader = RawHeader("custom", "custom") + "add the given header to successful responses" in { + Get() ~> { + respondWithHeader(customHeader) { completeOk } + } ~> check { response shouldEqual HttpResponse(headers = customHeader :: Nil) } + } + } + "respondWithHeaders" should { + "add the given headers to successful responses" in { + Get() ~> { + respondWithHeaders(customHeader, customHeader2) { completeOk } + } ~> check { response shouldEqual HttpResponse(headers = customHeader :: customHeader2 :: Nil) } + } + } + "respondWithDefaultHeader" should { + def route(extraHeaders: HttpHeader*) = respondWithDefaultHeader(customHeader) { + respondWithHeaders(extraHeaders: _*) { + completeOk + } + } + + "add the given header to a response if the header was missing before" in { + Get() ~> route() ~> check { response shouldEqual HttpResponse(headers = customHeader :: Nil) } + } + "don't change a response if the header already existed" in { + Get() ~> route(existingHeader) ~> check { response shouldEqual HttpResponse(headers = existingHeader :: Nil) } + } + } + "respondWithDefaultHeaders" should { + def route(extraHeaders: HttpHeader*) = respondWithDefaultHeaders(customHeader, customHeader2) { + respondWithHeaders(extraHeaders: _*) { + completeOk + } + } + + "add the given headers to a response if the header was missing before" in { + Get() ~> route() ~> check { response shouldEqual HttpResponse(headers = customHeader :: customHeader2 :: Nil) } + } + "don't update an existing header" in { + Get() ~> route(existingHeader) ~> check { + response shouldEqual HttpResponse(headers = existingHeader :: customHeader2 :: Nil) + } + } + } +} diff --git a/akka-http/src/main/scala/akka/http/server/Directives.scala b/akka-http/src/main/scala/akka/http/server/Directives.scala index a70e732c5e..5681610fee 100644 --- a/akka-http/src/main/scala/akka/http/server/Directives.scala +++ b/akka-http/src/main/scala/akka/http/server/Directives.scala @@ -27,7 +27,7 @@ trait Directives extends RouteConcatenation //with ParameterDirectives with PathDirectives //with RangeDirectives - //with RespondWithDirectives + with RespondWithDirectives with RouteDirectives with SchemeDirectives //with SecurityDirectives diff --git a/akka-http/src/main/scala/akka/http/server/directives/RespondWithDirectives.scala b/akka-http/src/main/scala/akka/http/server/directives/RespondWithDirectives.scala new file mode 100644 index 0000000000..fa1b400db1 --- /dev/null +++ b/akka-http/src/main/scala/akka/http/server/directives/RespondWithDirectives.scala @@ -0,0 +1,53 @@ +package akka.http.server +package directives + +import akka.http.model._ +import scala.collection.immutable + +trait RespondWithDirectives { + import BasicDirectives._ + + /** + * Overrides the given response status on all HTTP responses of its inner Route. + */ + def overrideStatusCode(responseStatus: StatusCode): Directive0 = + mapResponse(_.copy(status = responseStatus)) + + /** + * Unconditionally adds the given response header to all HTTP responses of its inner Route. + */ + def respondWithHeader(responseHeader: HttpHeader): Directive0 = respondWithHeaders(responseHeader) + + /** + * Adds the given response header to all HTTP responses of its inner Route, + * if the response from the inner Route doesn't already contain a header with the same name. + */ + def respondWithDefaultHeader(responseHeader: HttpHeader): Directive0 = respondWithDefaultHeaders(responseHeader) + + /** + * Unconditionally adds the given response headers to all HTTP responses of its inner Route. + */ + def respondWithHeaders(responseHeaders: HttpHeader*): Directive0 = + respondWithHeaders(responseHeaders.toVector) + + /** + * Unconditionally adds the given response headers to all HTTP responses of its inner Route. + */ + def respondWithHeaders(responseHeaders: immutable.Seq[HttpHeader]): Directive0 = + mapResponseHeaders(responseHeaders ++ _) + + /** + * Adds the given response headers to all HTTP responses of its inner Route, + * if a header already exists it is not added again. + */ + def respondWithDefaultHeaders(responseHeaders: HttpHeader*): Directive0 = + respondWithDefaultHeaders(responseHeaders.toVector) + + /* Adds the given response headers to all HTTP responses of its inner Route, + * if a header already exists it is not added again. + */ + def respondWithDefaultHeaders(responseHeaders: immutable.Seq[HttpHeader]): Directive0 = + mapResponse(_.withDefaultHeaders(responseHeaders)) +} + +object RespondWithDirectives extends RespondWithDirectives