Skip to content

Instantly share code, notes, and snippets.

@theon
Created February 19, 2013 18:12
Show Gist options
  • Save theon/4988370 to your computer and use it in GitHub Desktop.
Save theon/4988370 to your computer and use it in GitHub Desktop.
import akka.actor.ActorRef
import akka.util.Timeout
import concurrent.{Promise, Future, ExecutionContext}
import spray.http.{HttpMethods, HttpResponse, HttpRequest}
import spray.client.pipelining._
import spray.http.StatusCodes.Redirection
import concurrent.Promise._
import spray.http.HttpMethods._
import scala.concurrent.duration._
/**
* Work around for this: https://github.com/spray/spray/issues/132
*
* Use sendReceiveFollowRedirect in place of spray.client.pipelining#sendReceive in your pipelines. Like so:
* val pipeline = (
* addHeader("blah", "blah")
* ~> sendReceiveFollowRedirect(httpClient)
* ~> unmarshal[AccountResponse]
* )
*/
object FollowRedirectWorkaround {
val MAX_REDIRECTS = 5
def sendReceiveFollowRedirect(transport: ActorRef, futureTimeout: Timeout = 30 seconds span)
(implicit ec: ExecutionContext): HttpRequest => Future[HttpResponse] = {
sendReceiveFollowRedirectInternal(transport, 0, futureTimeout)
}
private def sendReceiveFollowRedirectInternal(transport: ActorRef, depth:Int, futureTimeout: Timeout = 30 seconds span)
(implicit ec: ExecutionContext): HttpRequest => Future[HttpResponse] = {
request => {
sendReceive(transport, futureTimeout).apply(request).flatMap(x => {
val location = x.headers.find(_.lowercaseName == "location")
if(x.status.isInstanceOf[Redirection] && location.isDefined && depth < MAX_REDIRECTS) {
val newReq = request.copy(uri = location.get.value, method = GET)
sendReceiveFollowRedirectInternal(transport, depth+1, futureTimeout).apply(newReq)
} else {
successful(x).future
}
})
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment