Created
September 5, 2013 12:38
-
-
Save fsarradin/6449549 to your computer and use it in GitHub Desktop.
A Web Framework in Scala From Scratch
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 scalawebapp | |
import com.sun.net.httpserver.{HttpExchange, HttpHandler, HttpServer} | |
import java.net.InetSocketAddress | |
import scala.concurrent.Future | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import scala.util.{Failure, Success} | |
class MyHttpServer(port: Int = 8080) { | |
type HttpFunction = String => Future[(Int, String)] | |
val httpServer = HttpServer.create(new InetSocketAddress(port), 0) | |
def withContext(root: String)(httpFunction: HttpFunction) = { | |
def send(httpExchange: HttpExchange, responseCode: Int, content: String) { | |
val response = content.getBytes | |
httpExchange.sendResponseHeaders(responseCode, response.length) | |
httpExchange.getResponseBody.write(response) | |
httpExchange.close() | |
} | |
httpServer.createContext("/", new HttpHandler { | |
def handle(httpExchange: HttpExchange) { | |
println(Thread.currentThread()) | |
val path: String = httpExchange.getRequestURI.getPath | |
val futureResponse = httpFunction(path) | |
futureResponse onComplete { | |
case Success((responseCode, content)) => send(httpExchange, responseCode, content) | |
case Failure(e) => send(httpExchange, 500, s"Internal Server Error ${e.getMessage}") | |
} | |
} | |
}) | |
this | |
} | |
def start() { | |
httpServer.start() | |
} | |
def stop() { | |
httpServer.stop(0) | |
} | |
} | |
object MyHttpServer { | |
implicit def intString2Future(response: (Int, String)) = Future(response) | |
def main(args: Array[String]) { | |
new MyHttpServer() | |
.withContext("/") { | |
case "/hello" => Future { | |
println(Thread.currentThread()) | |
(200, "hello") | |
} | |
case "/world" => (200, "world") | |
case badPath => (404, s"Not Found $badPath") | |
} | |
.start() | |
} | |
} |
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 scalawebapp | |
import org.scalatest.{BeforeAndAfterAll, FunSuite} | |
import scala.io.Source | |
import org.scalatest.matchers.MustMatchers | |
import java.io.FileNotFoundException | |
class MyHttpServerTest extends FunSuite with MustMatchers with BeforeAndAfterAll { | |
import MyHttpServer.intString2Future | |
val server = new MyHttpServer(9242) | |
.withContext("/") { | |
case "/hello" => (200, "hello") | |
case "/world" => (200, "world") | |
case badPath => (404, s"Not Found $badPath") | |
} | |
override def beforeAll() { | |
server.start() | |
} | |
override def afterAll() { | |
server.stop() | |
} | |
test("it should say hello when /hello") { | |
val result = Source.fromURL("http://localhost:9242/hello").mkString | |
result must be("hello") | |
} | |
test("it should say world when /world") { | |
val result = Source.fromURL("http://localhost:9242/world").mkString | |
result must be("world") | |
} | |
test("it should complain when /whatever") { | |
evaluating { | |
Source.fromURL("http://localhost:9242/whatever") | |
} must produce[FileNotFoundException] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment