Prototyping end to end workflow and UpstreamFilter and Tests

This commit is contained in:
Will Kimeria 2014-12-10 15:04:29 -08:00
parent d414806664
commit 25496ef520
23 changed files with 364 additions and 347 deletions

View File

@ -0,0 +1,29 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response, RoutedRequest}
import com.twitter.finagle.{Filter, Service}
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/11/14.
*/
trait AuthFilter extends Filter[RoutedRequest, FinagleResponse, RoutedRequest, FinagleResponse]
class AuthFilterSimple extends AuthFilter {
def apply(request: RoutedRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println("----------------------------- AuthFilterSimple ------------------------------>")
val r = service(request)
println("<----------------------------- AuthFilterSimple ------------------------------")
r
}
}
class AuthFilterCond(uService: Service[RoutedRequest, FinagleResponse]) extends AuthFilter {
def apply(request: RoutedRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println("----------------------------- AuthFilterCond ------------------------------>")
val r = uService(request)
println("<----------------------------- AuthFilterCond ------------------------------")
r
}
}

View File

@ -0,0 +1,20 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response}
import com.twitter.finagle.Service
import com.twitter.util.Future
import org.jboss.netty.handler.codec.http._
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/11/14.
*/
class AuthService extends Service[HttpRequest, FinagleResponse] {
def apply(request: HttpRequest) = {
println("----------------------------- AuthService------------------------------>")
val result: FinagleResponse = new Response(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
val r = Future.value(result)
println("<----------------------------- AuthService------------------------------")
r
}
}

View File

@ -1,59 +1,54 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.routing._
import com.lookout.borderpatrol.auth._
import com.lookout.borderpatrol.sessions._
import com.twitter.finagle.{Filter, _}
import com.twitter.finagle.builder.ClientBuilder
import java.net.{InetAddress, InetSocketAddress}
import com.twitter.finagle.builder.{Server, ServerBuilder}
import com.twitter.server.TwitterServer
import com.twitter.util._
import org.jboss.netty.handler.codec.http._
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
object BorderPatrolApp extends TwitterServer {
val sessionStore = new SessionStore
val sessionIDFilter = new SessionIDFilter(sessionStore)
val routingFilter = new RoutingFilter
val sessionStoreFilter = new SessionStoreFilter(sessionStore)
val authFilter = new AuthFilter
val authService = new AuthService
val orchestratorFilter: Filter[HttpRequest, HttpResponse, HttpRequest, HttpResponse] =
sessionIDFilter andThen routingFilter andThen sessionStoreFilter andThen authFilter
val service = new Service[HttpRequest, HttpResponse] {
def apply(request: HttpRequest) = {
log.info("Service: Received a request at " + Time.now + ". Calling upstream =" + request.getUri())
val newUri = request.getUri.split("/").toSeq match {
case Seq() => "/"
case x => x.tail.tail.mkString("/", "/", "")
}
log.info("new uri: " + newUri)
request.setUri(newUri)
//call upstream
val client: Service[HttpRequest, HttpResponse] = ClientBuilder()
.codec(com.twitter.finagle.http.Http())
.hosts(request.getHeader("HOST")) // If >1 host, client does simple load-balancing
.hostConnectionLimit(1)
.build()
val clientWithTokenFilter = new TokenFilter(sessionStore) andThen client
clientWithTokenFilter(request)
//TODO: Flesh this out
class Session {
def token(name: String): Option[String] = {
val tokens = Map("flexd" -> "DEADBEEF", "mtp" -> "LIVEKALE")
tokens.get(name)
}
}
val orchestratorService: Service[HttpRequest, HttpResponse] =
orchestratorFilter andThen service
//A Request with Routing and Session Information
class RoutedRequest(val httpRequest: HttpRequest, val session: Session)
extends FinagleRequest {
override val remoteSocketAddress: InetSocketAddress = new InetSocketAddress(InetAddress.getLoopbackAddress, 0) //TODO: This is wrong
}
//Unsuccessful Response
case class NeedsAuthResponse (httpResponse: HttpResponse) extends FinagleResponse //with BorderPatrolResponse
//Successful response
case class Response (httpResponse: HttpResponse) extends FinagleResponse //with BorderPatrolResponse
val sessionFilter = new SessionFilter
val upstreamService = new UpstreamService
val upstreamFilter = new UpstreamFilter(None, None)
val routingFilter = new RoutingFilter
val loginFilter = new LoginFilter
val loginService = new LoginService
var authService = new AuthService
val authFilter = new AuthFilterCond(authService)
val upstreamCombination = upstreamFilter andThen upstreamService
val loginCombination = loginFilter andThen authFilter
val upStreamFilterWithLeft = new UpstreamFilter(Some(loginCombination andThen upstreamFilter andThen upstreamService), Some(upstreamService))
val orchestratorService = routingFilter andThen sessionFilter andThen upStreamFilterWithLeft andThen upstreamService
def main() {
val server = Http.serve(":8080", orchestratorService)
onExit {
server.close()
}
Await.ready(httpServer)
val server: Server = ServerBuilder()
.codec(Http())
.bindTo(new InetSocketAddress(8080))
.name("BorderPatrol")
.build(orchestratorService)
}
}

View File

@ -0,0 +1,17 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response, RoutedRequest}
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/11/14.
*/
class LoginFilter
extends SimpleFilter[RoutedRequest, FinagleResponse] {
def apply(request: RoutedRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println("----------------------------- LoginFilter------------------------------>")
val r = service(request)
println("<----------------------------- LoginFilter------------------------------")
r
}
}

View File

@ -0,0 +1,20 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response, RoutedRequest}
import com.twitter.finagle.Service
import com.twitter.util.Future
import org.jboss.netty.handler.codec.http._
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/11/14.
*/
class LoginService extends Service[RoutedRequest, Response] {
def apply(request: RoutedRequest) = {
println("----------------------------- LoginService------------------------------>")
val r = Future.value(new Response(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)))
println("<----------------------------- LoginService------------------------------")
r
}
}

View File

@ -0,0 +1,26 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp._
import com.twitter.finagle.{Filter, Service}
import com.twitter.util.{Future}
import org.jboss.netty.handler.codec.http._
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
class RoutingFilter
extends Filter[HttpRequest, FinagleResponse, RoutedRequest, FinagleResponse] {
def apply(request: HttpRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println(request.getUri + "-------- RoutingFilter ------------------------------>")
val r =
if(request.getUri() == "/notfound" || request.getUri() == "/favicon.ico"){
val result: FinagleResponse = new Response(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND))
Future.value(result)
}else{
val rRequest = new RoutedRequest(request, new Session())
service(rRequest)
}
println("<----------------------------- RoutingFilter ------------------------------")
r
}
}

View File

@ -0,0 +1,18 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response, RoutedRequest}
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/10/14.
*/
class SessionFilter
extends SimpleFilter[RoutedRequest, FinagleResponse] {
def apply(request: RoutedRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println("----------------------------- SessionFilter ------------------------------>")
val r = service(request)
println("<----------------------------- SessionFilter ------------------------------")
r
}
}

View File

@ -0,0 +1,121 @@
package com.lookout.borderpatrol
/**
* The UpstreamFilter is responsible for calling the UpstreamsService and returning non 401 responses
* back up the chain. For 401 responses, it calls an optional Service in line to get an Authorization
* token for the upstream service that returned the 401. If that succeeeds, it makes a call back to
* the service once more with the Authorization Token
*/
import com.lookout.borderpatrol.BorderPatrolApp._
import com.twitter.finagle.{Filter, SimpleFilter, Service}
import com.twitter.util.{Await}
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
*
* @param next Service to call if we get a 401 from the Upstream Service
* @param uService Service to call instead of calling the service passed in the apply. We do this to accommodate the
* need to have another service called after the Upstream Service.
*/
class UpstreamFilter(next: Option[Service[RoutedRequest, FinagleResponse]], uService: Option[Service[RoutedRequest, FinagleResponse]])
extends SimpleFilter[RoutedRequest, FinagleResponse] {
def apply(request: RoutedRequest, service: Service[RoutedRequest, FinagleResponse]) = {
println("----------------------------- UpstreamFilter ------------------------------>")
val responseFuture = uService match {
case None => service(request)
case Some(t) => {
val authorizedRequest = addRequiredHeaders(addAuthHeader(request, None))
t(authorizedRequest)
}
}
val response = Await.result(responseFuture)
val r = response match {
case NeedsAuthResponse(_) => {
next match {
case None => responseFuture
case Some(s) => {
val respFuture = s(request)
val response = Await.result(respFuture)
val authorizedRequest = addRequiredHeaders(addAuthHeader(request, Option(response)))
val responseFuture = uService match {
case None => service(request)
case Some(t) => {
t(authorizedRequest)
}
}
}
}
responseFuture
}
case Response(_) => {
responseFuture
}
}
println("<----------------------------- UpstreamFilter ------------------------------")
r
}
/**
* Update Session tokens with tokens returned in response
* @param rq RoutedRequest
* @param response Response
* @return New RoutedRequest
*/
def updateSession(rq: RoutedRequest, response: FinagleResponse):RoutedRequest = {
//TODO: Get tokens from Response
val request = new RoutedRequest(rq.httpRequest, rq.session)
request
}
/**
* Add Authorization Header to the RoutedRequest.
* @param rq RoutedRequest
* @param responseOpt Optional Response
* @return New RoutedRequest
*/
def addAuthHeader(rq: RoutedRequest, responseOpt: Option[FinagleResponse]): RoutedRequest = {
val request = responseOpt match {
case None => {
val request = rq.session.token("flexd") match {
case None => new RoutedRequest(rq.httpRequest, rq.session)
case Some(t) => {
val r = new RoutedRequest(rq.httpRequest, rq.session)
r.headers().remove("Auth-Token")
r.headers().add("Auth-Token", t)
r
}
}
request
}
case Some(resp) =>{
val request = updateSession(rq, resp)
request.headers().remove("Auth-Token")
val token = rq.session.token("flexd") match {
case None => Nil
case Some(t) => t
}
request.headers().add("Auth-Token", token)
request
}
}
request
}
/**
* Add required headers in order to call upstream service
* @param rq RoutedRequest
* @return New RoutedRequest
*/
def addRequiredHeaders(rq:RoutedRequest): RoutedRequest = {
//TODO: Figure out a better way of setting headers
val request = new RoutedRequest(rq.httpRequest, rq.session)
//val request = RequestBuilder(rq).withHeaders(("Via","Borderpatrol"))
//request.headers().clear()
//TODO: Figure out what headers we need to pass and whether we need to clear all headers beforehand
request.headers().remove("Via")
request.headers().add("Via", "Borderpatrol")
request
}
}

View File

@ -0,0 +1,31 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp.{Response, NeedsAuthResponse}
import com.twitter.finagle.Service
import com.twitter.util.Future
import org.jboss.netty.handler.codec.http._
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/10/14.
*/
class UpstreamService extends Service[HttpRequest, FinagleResponse] {
def apply(request: HttpRequest) = {
println("----------------------------- UpstreamService ------------------------------>")
var it = request.headers().entries().iterator()
while(it.hasNext){
println(it.next().toString)
}
println("HEADERS --------> " + request.headers().toString)
val r =
if(request.getUri() == "/good"){
val result: Response = new Response(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
Future.value(result)
}else{
val result: FinagleResponse = new NeedsAuthResponse(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED))
Future.value(result)
}
println("<----------------------------- UpstreamService ------------------------------")
r
}
}

View File

@ -1,28 +0,0 @@
package com.lookout.borderpatrol.auth
import org.jboss.netty.buffer._
import org.jboss.netty.handler.codec.http.{HttpRequest, HttpResponse, HttpResponseStatus}
import com.twitter.finagle.{SimpleFilter, Service}
import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer
import org.jboss.netty.util.CharsetUtil.UTF_8
/**
* Transforms an upstream responses 401 UNAUTHORIZED into a 301 Redirect to Checkpoint
*
* Created by akuhnhausen on 6/11/14.
*/
class AuthFilter extends SimpleFilter[HttpRequest, HttpResponse] {
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
// When the upstream have us a 401, transform it to a 302 and return the auth URL.
service(request).onSuccess(resp => {
if(resp.getStatus == HttpResponseStatus.UNAUTHORIZED) {
resp.setStatus(HttpResponseStatus.MOVED_PERMANENTLY)
// TODO: this URL should come from the RoutingService
resp.setContent(copiedBuffer("", UTF_8))
resp.setHeader("Content-Length", "0")
resp.setHeader("Location", "/a")
}
})
}
}

View File

@ -1,17 +0,0 @@
package com.lookout.borderpatrol.auth
import com.twitter.finagle._
import com.twitter.util.Future
import org.jboss.netty.handler.codec.http.{HttpResponseStatus, DefaultHttpResponse, HttpRequest, HttpResponse}
/**
* Invokes the Authentication service to turn a master session token into a token for a specific service.
*
* Created by akuhnhausen on 6/11/14.
*/
class AuthService extends Service[HttpRequest, HttpResponse] {
def apply(request: HttpRequest) = {
val response = new DefaultHttpResponse(request.getProtocolVersion, HttpResponseStatus.OK)
Future.value(response)
}
}

View File

@ -1,39 +0,0 @@
package com.lookout.borderpatrol.auth
import com.lookout.borderpatrol.sessions.SessionStore
import com.twitter.finagle.{Service, SimpleFilter}
import org.jboss.netty.handler.codec.http.{HttpResponseStatus, HttpMethod, HttpRequest, HttpResponse}
/**
* Created by svij on 6/12/14.
*/
class TokenFilter(sessionStore: SessionStore) extends SimpleFilter[HttpRequest, HttpResponse]{
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
System.out.println("Inside token filter. Uri="+ request.getUri())
//TODO: append the service token if exists
//get the master token
val sessionId = request.getHeader("BORDER_PATROL_SESSION_ID")
val session = sessionStore.session(sessionId)
session.masterToken map {
request.addHeader("master_token", _)
}
var f_response = service(request)
if (request.getUri().contains("auth") && request.getMethod() == HttpMethod.POST) {
System.out.println("Inside token filter: extracting master token")
// reassign the response future as we are running this function onSuccess
f_response = f_response onSuccess { resp: HttpResponse =>
if (resp.getStatus() == HttpResponseStatus.OK) {
//take the master token and store
val master_token = resp.getHeader("master_token")
System.out.println("Inside token filter: extracted the master token="+master_token + "; session-id="+sessionId)
session.masterToken = master_token
resp.removeHeader("master_token")
resp.setStatus(HttpResponseStatus.MOVED_PERMANENTLY)
resp.setHeader("Content-Length", "0")
resp.setHeader("Location", "/b/home")
}
}
}
f_response
}
}

View File

@ -1,8 +0,0 @@
package com.lookout.borderpatrol
/**
* Created by akuhnhausen on 6/11/14.
*/
package object auth {
}

View File

@ -1,60 +0,0 @@
package com.lookout.borderpatrol.routing
import java.io.Serializable
import com.twitter.finagle.http.Request
import com.twitter.finagle.http.Response
import com.twitter.finagle.Service
import com.twitter.finagle.SimpleFilter
import com.twitter.finagle.Service
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.SimpleFilter
import scala.collection.immutable.HashMap
import org.jboss.netty.handler.codec.http._
import scala.util.matching.Regex
class RoutingFilter
extends SimpleFilter[HttpRequest, HttpResponse] {
// Ideally the route would map a string to a new object with
// details like service name and host information etc. For demo purposes we are going for
// a string to string mapping of service names. "b" => "smb", "c" => "flexd" but we are hardcoding it
// to SERVICE_NAME for simplicity
//
val routes = HashMap[String, HashMap[String, String]](
"/b"->HashMap[String,String]("service_name"->"smb","host"->"localhost","port"->"9292"),
"/a"->HashMap[String,String]("service_name"->"checkpoint","host"->"localhost","port"->"4567"),
"default"->HashMap[String,String]("service_name"->"flexd","host"->"localhost","port"->"8080"))
val pattern = new Regex("^/([^/]+)")
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
// Ideally we would have a RoutingService looking up possible routes and not
// have a static lookup table.
val req = injectHeaderAndModifyUri(request)
service(req)
}
def extractServiceFromUri(uri: String): Serializable = {
val result = pattern.findFirstIn(uri).getOrElse("default")
val serviceUri = {
routes.getOrElse(result , "")
}
serviceUri
}
def injectHeaderAndModifyUri(request: HttpRequest): HttpRequest = {
println("INITIAL HEADERS : "+ request.getHeaders)
val service = extractServiceFromUri(request.getUri).asInstanceOf[HashMap[String,String]]
request.addHeader("SERVICE_NAME", service.get("service_name").getOrElse("SERVICE_NAME"))
request.addHeader("ORIGINAL_HOST", request.getHeader("HOST"))
request.setHeader("HOST", service.get("host").getOrElse("localhost")+":"+service.get("port").getOrElse("8080"))
request.setUri(request.getUri)
println("HEADERS AFTER REROUTE : "+ request.getHeaders)
request
}
}

View File

@ -1,8 +0,0 @@
package com.lookout.borderpatrol.routing
/**
* Created by akuhnhausen on 6/11/14.
*/
class RoutingService {
}

View File

@ -1,8 +0,0 @@
package com.lookout.borderpatrol
/**
* Created by akuhnhausen on 6/11/14.
*/
package object routing {
}

View File

@ -1,59 +0,0 @@
package com.lookout.borderpatrol.sessions
import com.twitter.finagle.SimpleFilter
import com.twitter.finagle.Service
import org.jboss.netty.handler.codec.http._
import java.util.UUID.randomUUID
import org.jboss.netty.handler.codec.http.DefaultCookie
import scala.collection.JavaConversions._
import com.twitter.logging.Logging
import com.twitter.util.Try
class SessionIDFilter(sessionStore: SessionStore) extends SimpleFilter[HttpRequest, HttpResponse] {
val cookieKey = "border_session"
val maxAge = 24 * 60 * 60
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
val id = getIDFromRequest(request) getOrElse generateNewID
request.setHeader("BORDER_PATROL_SESSION_ID", id)
System.out.println("Session ID: %s".format(id))
service(request) onSuccess (setCookie(_, id))
}
def generateNewID: String = {
val id = randomUUID.toString
sessionStore.addSession(id)
id
}
def getIDFromRequest(request: HttpRequest): Option[String] = {
Option(request.getHeader(HttpHeaders.Names.COOKIE)) flatMap {
getIDFromValidCookie(_)
}
}
def getIDFromValidCookie(cookieHeader: String): Option[String] = {
val cookies = new CookieDecoder().decode(cookieHeader).toSet
val cookie: Option[Cookie] = cookies find {
validCookie(_)
}
cookie map {
_.getValue
}
}
def validCookie(cookie: Cookie): Boolean = {
cookie.getName == cookieKey
}
def setCookie(response: HttpResponse, sessionId: String): Unit = {
val cookie = new DefaultCookie(cookieKey, sessionId)
cookie.setMaxAge(maxAge)
cookie.setDomain("lookout.com")
cookie.setSecure(true)
response.setHeader(HttpHeaders.Names.SET_COOKIE, cookie)
}
}

View File

@ -1,39 +0,0 @@
package com.lookout.borderpatrol.sessions
import scala.collection.mutable.Map
class SessionStore {
/*
{
<session_id>: {
<master_token>: String,
<destination>: String,
<service1>: String, ...
}
}
*/
private var store = Map[String, Map[String, String]]()
def session(id: String) = new Session(id)
def addSession(id: String) = store += (id -> Map[String,String]())
class Session(id: String) {
var sessionStore = store get id
def masterToken_= (token: String): Unit = sessionStore.get += ("master_token" -> token)
def masterToken = store get id flatMap { _ get "master_token" }
def serviceToken_= (t: (String, String)) = sessionStore.get += (t._1 -> t._2)
def serviceToken = store get id
def destination_= (destination: String) = sessionStore.get += ("destination" -> destination)
def destination = store get id flatMap { _ get "destination" }
}
}

View File

@ -1,24 +0,0 @@
package com.lookout.borderpatrol.sessions
import com.twitter.finagle.Service
import com.twitter.finagle.SimpleFilter
import com.twitter.finagle.Service
import com.twitter.finagle.SimpleFilter
import org.jboss.netty.handler.codec.http._
import scala.collection.immutable.{Map, HashMap}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
class SessionStoreFilter(sessionStore: SessionStore) extends SimpleFilter[HttpRequest, HttpResponse] {
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
val serviceName = request.getHeader("SERVICE_NAME")
val sessionId = request.getHeader("BORDER_PATROL_SESSION_ID")
val session = sessionStore.session(sessionId)
session.serviceToken map { _ get serviceName } map {
request.setHeader("Auth-Token", _)
}
System.out.println("Auth-Token: %s".format(request.getHeader("Auth-Token")))
service(request)
}
}

View File

@ -1,8 +0,0 @@
package com.lookout.borderpatrol
/**
* Created by akuhnhausen on 6/11/14.
*/
package object sessions {
}

View File

@ -0,0 +1,36 @@
package com.lookout.borderpatrol
import com.lookout.borderpatrol.BorderPatrolApp._
import com.twitter.finagle.{Filter, Service}
import com.twitter.util.{Future, Await}
import org.jboss.netty.handler.codec.http._
import org.scalatest.{Matchers, FlatSpec}
import com.twitter.finagle.http.{Http, Request => FinagleRequest, Response => FinagleResponse}
/**
* Created by wkimeria on 12/12/14.
*/
class UpstreamFilterSpec extends FlatSpec with Matchers{
def mockUpstreamService(response: String) = new Service[HttpRequest, String] {
def apply(request: HttpRequest) = Future.value(response)
}
def mockRequest = new RoutedRequest(new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,"/upstream"), new Session())
def mockUpService200 = new Service [HttpRequest, FinagleResponse]{
def apply(request: HttpRequest) = {
Future.value(new Response(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)))
}
}
def mockUpService403 = new Service [HttpRequest, FinagleResponse]{
def apply(request: HttpRequest) = {
Future.value(new NeedsAuthResponse(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN)))
}
}
"An UpstreamFilter" should "route appropriately" in {
Await.result(new UpstreamFilter(None, Some(mockUpService200)).apply(mockRequest, mockUpService200)) shouldBe a [Response]
Await.result(new UpstreamFilter(None, Some(mockUpService403)).apply(mockRequest, mockUpService403)) shouldBe a [NeedsAuthResponse]
}
}

View File

@ -9,7 +9,7 @@ This module includes dummy integration test services for Border Patrol.
#### Darwin
* bundle install
* god load borderpatrol
* god -Dbc borderpatrol.god
[God](http://godrb.com) to run 4 processes, on the following ports
@ -18,4 +18,7 @@ This module includes dummy integration test services for Border Patrol.
* `9083` Mock downstream service B
* `9084` Mock Account Service
To stop the integration services, run god stop borderpatrol
To stop the integration services, kill god and shotgun
pkill -9 -f shotgun; pkill -9 -f god

View File

@ -9,8 +9,7 @@ object BorderPatrol extends Build {
organization := "com.lookout",
scalaVersion := "2.10.3",
libraryDependencies ++= Seq(
"com.twitter" %% "twitter-server" % "1.0.2",
"org.scalatest" % "scalatest_2.11" % "2.2.0" % "test"
"com.twitter" % "twitter-server_2.10" % "1.8.0"
),
scalacOptions ++= Seq("-encoding", "utf8"),