Created
February 12, 2012 02:14
-
-
Save justinholmes/1805815 to your computer and use it in GitHub Desktop.
finagle reverse proxy - do not use in production
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.nascency.incipit | |
import com.twitter.finagle.{Service, SimpleFilter} | |
import org.jboss.netty.handler.codec.http._ | |
import org.jboss.netty.handler.codec.http.HttpResponseStatus._ | |
import org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1 | |
import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer | |
import org.jboss.netty.util.CharsetUtil.UTF_8 | |
import com.twitter.util.Future | |
import java.net.InetSocketAddress | |
import com.twitter.finagle.builder.{Server, ServerBuilder} | |
import com.twitter.finagle.http.Http | |
import com.twitter.finagle.builder.ClientBuilder | |
import org.jboss.netty.util.CharsetUtil | |
import scala.collection.JavaConverters._ | |
import com.google.common.collect.HashMultimap | |
import com.google.common.collect.Multimap | |
import com.google.common.collect.Multimaps | |
object LoadBalancer { | |
def main(args: Array[String]) = { | |
val respond = new Respond | |
// compose the Filters and Service together: | |
val myService: Service[HttpRequest, HttpResponse] = respond | |
val server: Server = ServerBuilder() | |
.codec(Http()) | |
.bindTo(new InetSocketAddress(8080)) | |
.name("httpserver") | |
.build(myService) | |
} | |
val mappings : Multimap[String,String] = Multimaps.synchronizedMultimap(HashMultimap.create()); | |
List(("localhost:8080", "localhost:9000"),("localhost","localhost:9001")).map(e => mappings.put(e._1, e._2)) | |
class Respond extends Service[HttpRequest, HttpResponse] { | |
def apply(request: HttpRequest) = { | |
val hostname = request.containsHeader("Host") match{case true => request.getHeader("Host").toString() ; case false => { val response = new DefaultHttpResponse(HTTP_1_1, OK) | |
response.setContent(copiedBuffer( "LB server error", UTF_8)) | |
Future.value(response)}} | |
var returns = "" | |
val searchForDestination = mappings.get(hostname.toString()) | |
searchForDestination.asScala.toList.foreach{d=>returns += d+","} | |
//println(returns) | |
val hosts = returns | |
val method = request.getMethod() | |
val path = request.getUri() | |
try{ | |
val clientWithoutErrorHandling: Service[HttpRequest, HttpResponse] = ClientBuilder() | |
.codec(Http()) | |
.hosts(hosts) | |
.hostConnectionLimit(1) | |
.retries(2) | |
.build() | |
val authorizedRequest = new DefaultHttpRequest( | |
HttpVersion.HTTP_1_1, method, path) | |
for (req <- request.getHeaders().asScala.toList){ | |
//println(req.getKey(),req.getValue()) | |
if (! "Connection".equals(req.getKey())) { | |
authorizedRequest.setHeader(req.getKey(),req.getValue()) | |
} | |
} | |
authorizedRequest.addHeader("Host",request.getHeader("Host")) | |
// if(request.getHeader("Cookie") != null) authorizedRequest.addHeader("Cookie",request.getHeader("Cookie")) | |
authorizedRequest.setMethod(method) | |
if (request.isChunked()) { | |
println("Chunked") | |
} | |
authorizedRequest.setChunked(false) | |
authorizedRequest.setContent(request.getContent()) | |
authorizedRequest.setUri(path) | |
clientWithoutErrorHandling(authorizedRequest) onSuccess { | |
response => | |
val client: Service[HttpRequest, HttpResponse] = clientWithoutErrorHandling | |
val response2 = new DefaultHttpResponse(HTTP_1_1, response.getStatus()) | |
for (req <- response.getHeaders().asScala.toList){ | |
response2.setHeader(req.getKey(),req.getValue()) | |
} | |
response2.setContent(response.getContent()) | |
response2.setStatus(response.getStatus()) | |
response2.setHeader("Server","Incipit LB") | |
response2.setChunked(true) | |
if(response.getHeader("Cookie") != null)response2.setHeader("Cookie",response.getHeader("Cookie")) | |
Future.value(response2) | |
}}catch { | |
case e => { | |
//e.printStackTrace() | |
val response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR) | |
response.setContent(copiedBuffer( """ | |
The application could not route your request | |
""", UTF_8)) | |
Future.value(response) | |
} | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment