Created
May 19, 2012 04:11
-
-
Save tototoshi/2729029 to your computer and use it in GitHub Desktop.
finagle-http で Hello, world.
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.github.tototoshi.finagle_hack | |
import java.net.InetSocketAddress | |
import com.twitter.finagle.{Service, SimpleFilter} | |
import com.twitter.util.Future | |
import com.twitter.finagle.builder.{Server, ServerBuilder} | |
import com.twitter.finagle.http._ | |
import com.twitter.finagle.http.path._ | |
object HTTPServer { | |
def main(args: Array[String]) = { | |
val service = new Service[Request, Response] { | |
def apply(request: Request) = { | |
val response = Response() | |
Path(request.path) match { | |
case Root / "name" / name => | |
response.setContentString("Hello, %s!".format(name)) | |
case _ => | |
response.setContentString("Hello, world!") | |
} | |
Future.value(response) | |
} | |
} | |
val server: Server = { | |
val port = 8080 | |
val _server = ServerBuilder() | |
.codec(RichHttp[Request](Http())) | |
.bindTo(new InetSocketAddress(port)) | |
.name("Finagle hack!") | |
.build(service) | |
println("Server start up! port: %d".format(port)) | |
_server | |
} | |
} | |
} | |
/* | |
$ curl localhost:8080 | |
Hello, world! | |
$ curl localhost:8080/name/toshi | |
Hello, toshi!% | |
*/ |
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.github.tototoshi.finagle_hack | |
import java.net.{ InetSocketAddress, URL } | |
import java.util.concurrent.ScheduledThreadPoolExecutor | |
import com.twitter.finagle.{Service, SimpleFilter} | |
import com.twitter.util.{ Future, FuturePool } | |
import com.twitter.finagle.builder.{Server, ServerBuilder} | |
import com.twitter.finagle.builder._ | |
import com.twitter.finagle.http._ | |
import com.twitter.finagle.http.path._ | |
import com.twitter.finagle.http.service._ | |
import org.jboss.netty.buffer.ChannelBuffers._ | |
import scalax.io._ | |
import com.github.tototoshi.selector.Selector | |
object GreetService extends Service[Request, Response] { | |
val futurePool = FuturePool(new ScheduledThreadPoolExecutor(3)) | |
def apply(request: Request) = { | |
futurePool { | |
val response = Response() | |
Path(request.path) match { | |
case Root / "name" / name => response.setContentString("Hello, %s!".format(name)) | |
case _ => response.setStatusCode(500) | |
} | |
response | |
} | |
} | |
} | |
object defaultService extends Service[Request, Response] { | |
val futurePool = FuturePool(new ScheduledThreadPoolExecutor(3)) | |
def apply(request: Request) = { | |
futurePool { | |
val response = Response() | |
response.setContentString("Hello, world!") | |
response | |
} | |
} | |
} | |
object jigokuService extends Service[Request, Response] with ResponseTransformer { | |
def apply(request: Request): Future[Response] = { | |
val id = Path(request.path) match { | |
case Root / "jigoku" / id => id.toInt //TODO | |
case _ => throw new IllegalStateException | |
} | |
for { | |
img <- JigokunoClient.get(id) | |
} yield { | |
val res = Response() | |
res.setContent(copiedBuffer(responseToByteArray(img))) | |
res | |
} | |
} | |
} | |
object HTTPServer extends ResponseTransformer { | |
def main(args: Array[String]) = { | |
val router = RoutingService.byPathObject { | |
case Root / "name" / name => GreetService | |
case Root / "jigoku" / id => jigokuService | |
case _ => defaultService | |
} | |
val server: Server = { | |
val port = 8080 | |
val _server = ServerBuilder() | |
.codec(RichHttp[Request](Http())) | |
.bindTo(new InetSocketAddress(port)) | |
.name("Finagle hack!") | |
.build(router) | |
println("Server start up! port: %d".format(port)) | |
_server | |
} | |
} | |
} | |
object SimpleHttpClient { | |
private def clientWithoutErrorHandling(host: String): Service[Request, Response] = ClientBuilder() | |
.codec(RichHttp[Request](Http())) | |
.hosts(new InetSocketAddress(host, 80)) | |
.hostConnectionLimit(1) | |
.build() | |
private def requestGet(url: String) = Request( | |
RequestBuilder().url(new URL(url)).buildGet() | |
) | |
def GET(url: String): Future[Response] = { | |
val reg = """http://(.+?)/.*""".r | |
url match { | |
case reg(host) => clientWithoutErrorHandling(host)(requestGet(url)) | |
case _ => throw new Exception | |
} | |
} | |
} | |
object JigokunoClient extends ResponseTransformer { | |
def get(i: Int): Future[Response] = { | |
for { | |
res1 <- SimpleHttpClient.GET("http://jigokuno.com/?cid=" + i) | |
imgUrl = HtmlParser.parse(responseToString(res1)) | |
res2 <- SimpleHttpClient.GET(imgUrl) | |
} yield { | |
res2 | |
} | |
} | |
} | |
// utilities | |
class HtmlParseException(message: String) extends Exception(message) | |
object HtmlParser { | |
import net.liftweb.util.Html5 | |
def parse(html: String): String = { | |
val xml = Html5.parse(html).open_! //TODO | |
val $ = new Selector(xml) | |
if (($("div.entry img") \\ "@src").isEmpty) { | |
throw new HtmlParseException("Parse failed") | |
} else { | |
($("div.entry img") \\ "@src" ).head.text | |
} | |
} | |
} | |
trait ResponseTransformer { | |
def responseToByteArray(response: Response): Array[Byte] = | |
Resource.fromInputStream(response.getInputStream).byteArray | |
def responseToString(response: Response): String = | |
Resource.fromInputStream(response.getInputStream).slurpString | |
} |
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
object SimpleHttpClient { | |
private val clientWithoutErrorHandling: Service[Request, Response] = ClientBuilder() | |
.codec(RichHttp[Request](Http())) | |
.hosts(new InetSocketAddress(80)) | |
.hostConnectionLimit(1) | |
.build() | |
private def requestGet(url: String) = Request( | |
RequestBuilder().url(new URL(url)).buildGet() | |
) | |
def GET(url: String): Future[Response] = clientWithoutErrorHandling(requestGet(url)) | |
} |
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.github.tototoshi.finagle_hack | |
import java.net.InetSocketAddress | |
import com.twitter.finagle.{Service, SimpleFilter} | |
import com.twitter.util.Future | |
import com.twitter.finagle.builder.{Server, ServerBuilder} | |
import com.twitter.finagle.http._ | |
import com.twitter.finagle.http.path._ | |
import com.twitter.finagle.http.service._ | |
object HTTPServer { | |
def main(args: Array[String]) = { | |
val nameService = new Service[Request, Response] { | |
def apply(request: Request) = { | |
val response = Response() | |
Path(request.path) match { | |
case Root / "name" / name => | |
response.setContentString("Hello, %s!".format(name)) | |
case _ => response.setContentString("Oops!") | |
} | |
Future.value(response) | |
} | |
} | |
val defaultService = new Service[Request, Response] { | |
def apply(request: Request) = { | |
val response = Response() | |
Path(request.path) match { | |
case _ => response.setContentString("Hello, world!") | |
} | |
Future.value(response) | |
} | |
} | |
val router = RoutingService.byPath { | |
case path if path.startsWith("/name") => nameService | |
case _ => defaultService | |
} | |
val server: Server = { | |
val port = 8080 | |
val _server = ServerBuilder() | |
.codec(RichHttp[Request](Http())) | |
.bindTo(new InetSocketAddress(port)) | |
.name("Finagle hack!") | |
.build(router) | |
println("Server start up! port: %d".format(port)) | |
_server | |
} | |
} | |
} | |
/* | |
$ curl localhost:8080 | |
Hello, world! | |
$ curl localhost:8080/name/toshi | |
Hello, toshi!% | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment