Skip to content

Commit 9b6478a

Browse files
author
Eun Woo Song
committed
Merge branch 'master' of github.com:codeport/scala-http
2 parents 794875a + 981e4b5 commit 9b6478a

File tree

1 file changed

+73
-78
lines changed

1 file changed

+73
-78
lines changed

src/main/scala/common/main.scala

Lines changed: 73 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* la-scala http server
33
* source from http://doc.akka.io/docs/akka/2.1.0/scala/io.html
4-
*/
4+
*/
55

66
/*
77
* This software is licensed under the Apache 2 license, quoted below.
@@ -63,7 +63,7 @@ object HttpIteratees {
6363
body <- readBody(headers)
6464
} yield Request(meth, path, query, httpver, headers, body)
6565
}
66-
66+
6767
def ascii(bytes: ByteString): String = bytes.decodeString("US-ASCII").trim
6868

6969
def readRequestLine = {
@@ -74,25 +74,17 @@ object HttpIteratees {
7474
httpver <- IO takeUntil CRLF
7575
} yield (ascii(meth), uri, ascii(httpver))
7676
}
77-
78-
def readRequestURI = IO peek 1 flatMap {
79-
case PATH => {
80-
for {
81-
path <- readPath
82-
query <- readQuery
83-
} yield (path, query)
84-
}
85-
86-
case _ => {
87-
sys.error("Not Implemented")
77+
78+
def readRequestURI = {
79+
IO peek 1 flatMap {
80+
case PATH =>
81+
for {
82+
path <- readPath
83+
query <- readQuery
84+
} yield (path, query)
85+
case _ => sys.error("Not Implemented")
8886
}
8987
}
90-
91-
def readBody(headers: List[Header]) =
92-
if (headers.exists(header => header.name == "Content-Length" || header.name == "Transfer-Encoding"))
93-
IO.takeAll map (Some(_))
94-
else
95-
IO Done None
9688

9789
def readPath = {
9890
def step(segments: List[String]): IO.Iteratee[List[String]] = IO peek 1 flatMap {
@@ -104,30 +96,36 @@ object HttpIteratees {
10496
}
10597
step(Nil)
10698
}
107-
108-
def readQuery: IO.Iteratee[Option[String]] = IO peek 1 flatMap {
109-
case QUERY => IO drop 1 flatMap (_ => readUriPart(querychar) map (Some(_)))
110-
case _ => IO Done None
99+
100+
def readQuery: IO.Iteratee[Option[String]] = {
101+
IO peek 1 flatMap {
102+
case QUERY => IO drop 1 flatMap (_ => readUriPart(querychar) map (Some(_)))
103+
case _ => IO Done None
104+
}
111105
}
112-
106+
113107
val alpha = Set.empty ++ ('a' to 'z') ++ ('A' to 'Z') map (_.toByte)
114108
val digit = Set.empty ++ ('0' to '9') map (_.toByte)
115109
val hexdigit = digit ++ (Set.empty ++ ('a' to 'f') ++ ('A' to 'F') map (_.toByte))
116110
val subdelim = Set('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=') map (_.toByte)
117111
val pathchar = alpha ++ digit ++ subdelim ++ (Set(':', '@') map (_.toByte))
118112
val querychar = pathchar ++ (Set('/', '?') map (_.toByte))
119113

120-
def readUriPart(allowed: Set[Byte]): IO.Iteratee[String] = for {
121-
str <- IO takeWhile allowed map ascii
122-
pchar <- IO peek 1 map (_ == PERCENT)
123-
all <- if (pchar) readPChar flatMap (ch => readUriPart(allowed) map (str + ch + _)) else IO Done str
124-
} yield all
114+
def readUriPart(allowed: Set[Byte]): IO.Iteratee[String] = {
115+
for {
116+
str <- IO takeWhile allowed map ascii
117+
pchar <- IO peek 1 map (_ == PERCENT)
118+
all <- if (pchar) readPChar flatMap (ch => readUriPart(allowed) map (str + ch + _)) else IO Done str
119+
} yield all
120+
}
125121

126-
def readPChar = IO take 3 map {
127-
case Seq('%', rest @ _*) if rest forall hexdigit =>
128-
java.lang.Integer.parseInt(rest map (_.toChar) mkString, 16).toChar
122+
def readPChar = {
123+
IO take 3 map {
124+
case Seq('%', rest @ _*) if rest forall hexdigit =>
125+
java.lang.Integer.parseInt(rest map (_.toChar) mkString, 16).toChar
126+
}
129127
}
130-
128+
131129
def readHeaders = {
132130
def step(found: List[Header]): IO.Iteratee[List[Header]] = {
133131
IO peek 2 flatMap {
@@ -139,22 +137,23 @@ object HttpIteratees {
139137
}
140138

141139
def readHeader = {
142-
for {
140+
for {
143141
name <- IO takeUntil COLON
144142
value <- IO takeUntil CRLF flatMap readMultiLineValue
145143
} yield Header(ascii(name), ascii(value))
146144
}
147145

148-
def readMultiLineValue(initial: ByteString): IO.Iteratee[ByteString] = {
149-
IO peek 1 flatMap {
150-
case SP => IO takeUntil CRLF flatMap (bytes => readMultiLineValue(initial ++ bytes))
151-
}
146+
def readMultiLineValue(initial: ByteString): IO.Iteratee[ByteString] = IO peek 1 flatMap {
147+
case SP => IO takeUntil CRLF flatMap (bytes => readMultiLineValue(initial ++ bytes))
148+
case _ => IO Done initial
149+
}
150+
151+
def readBody(headers: List[Header]) = {
152+
if (headers.exists(header => header.name == "Content-Length" || header.name == "Transfer-Encoding")) IO.takeAll map (Some(_))
153+
else IO Done None
152154
}
153155
}
154156

155-
/**
156-
* ok 응답
157-
*/
158157
object OKResponse {
159158
import HttpConstants.CRLF
160159

@@ -176,74 +175,70 @@ object OKResponse {
176175
date ++= ByteString(new java.util.Date().toString) ++= CRLF ++=
177176
server ++= CRLF ++=
178177
contentLength ++= ByteString(rsp.body.length.toString) ++= CRLF ++=
179-
connection ++= (if (rsp.keepAlive) keepAlive else close) ++= CRLF ++=
180-
CRLF ++= rsp.body result
178+
connection ++= (if (rsp.keepAlive) keepAlive else close) ++= CRLF ++= CRLF ++= rsp.body result
181179
}
182180
}
183181

184182
case class OKResponse(body: ByteString, keepAlive: Boolean)
185183

186184
/**
187-
* http server companion object
188-
*/
185+
* http server companion object
186+
*/
189187
object HttpServer {
190-
import HttpIteratees._
191-
192-
def processRequest(socket: IO.SocketHandle): IO.Iteratee[Unit] = {
193-
IO repeat {
194-
for {
195-
request <- readRequest
196-
} yield {
197-
val rsp = request match {
198-
case Request("GET", "ping" :: Nil, _, _, headers, _) => {
199-
OKResponse(ByteString("<p>pong</p>"), request.headers.exists {
200-
case Header(n, v) => n.toLowerCase == "connection" && v.toLowerCase == "keep-alive" })
188+
import HttpIteratees._
189+
190+
def processRequest(socket: IO.SocketHandle): IO.Iteratee[Unit] = {
191+
IO repeat {
192+
for {
193+
request <- readRequest
194+
} yield {
195+
val rsp = request match {
196+
case Request("GET", "ping" :: Nil, _, _, headers, _) => {
197+
OKResponse(ByteString("<p>pong</p>"), request.headers.exists { case Header(n, v) => n.toLowerCase == "connection" && v.toLowerCase == "keep-alive" })
201198
}
202-
case req => {
203-
OKResponse(ByteString("<p>" + req.toString + "</p>"), request.headers.exists {
204-
case Header(n, v) => n.toLowerCase == "connection" && v.toLowerCase == "keep-alive" })
199+
case req => {
200+
OKResponse(ByteString("<p>" + req.toString + "</p>"), request.headers.exists { case Header(n, v) => n.toLowerCase == "connection" && v.toLowerCase == "keep-alive" })
205201
}
206-
}
207-
socket write OKResponse.bytes(rsp).compact
208-
if (!rsp.keepAlive) socket.close()
209-
}
210-
}
202+
}
203+
socket write OKResponse.bytes(rsp).compact
204+
if (!rsp.keepAlive) socket.close()
205+
}
206+
}
211207
}
212208
}
213209

214210
/**
215211
* http server main
216212
*/
217213
class HttpServer(port: Int) extends Actor {
218-
val state = IO.IterateeRef.Map.async[IO.Handle]()(context.dispatcher)
214+
val state = IO.IterateeRef.Map.async[IO.Handle]()(context.dispatcher)
219215

220-
override def preStart {
221-
IOManager(context.system) listen new InetSocketAddress(port)
222-
}
216+
override def preStart {
217+
IOManager(context.system) listen new InetSocketAddress(port)
218+
}
223219

224-
def receive = {
225-
case IO.NewClient(server) => {
220+
def receive = {
221+
case IO.NewClient(server) => {
226222
val socket = server.accept()
227223
state(socket) flatMap (_ => HttpServer.processRequest(socket))
228224
}
229-
230-
case IO.Read(socket, bytes) => {
225+
226+
case IO.Read(socket, bytes) => {
231227
state(socket)(IO Chunk bytes)
232228
}
233229

234-
case IO.Closed(socket, cause) => {
230+
case IO.Closed(socket, cause) => {
235231
state(socket)(IO EOF)
236232
state -= socket
237233
}
238-
}
234+
}
239235
}
240236

241-
242237
/**
243238
* Main
244239
*/
245240
object Main extends App {
246-
val port = Option(System.getenv("PORT")) map (_.toInt) getOrElse 8080
247-
val system = ActorSystem()
248-
val server = system.actorOf(Props(new HttpServer(port)))
241+
val port = Option(System.getenv("PORT")) map (_.toInt) getOrElse 8080
242+
val system = ActorSystem()
243+
val server = system.actorOf(Props(new HttpServer(port)))
249244
}

0 commit comments

Comments
 (0)