Skip to content

Commit cf806ca

Browse files
committed
Prevent cask from responding with 405 for an undefined route.
Fixes #51. Prior to this commit, `prepareRouteTries` created a mapping from method-name to DispatchTrie (Map[String, DispatchTrie[…]]). This commit instead creates a DispatchTrie[Map[String, …]], basically an inversion of the previous result. The updated tests in minimalApplication and minimalApplication2 have been updated to cover the differences.
1 parent 156ddff commit cf806ca

File tree

3 files changed

+22
-26
lines changed

3 files changed

+22
-26
lines changed

cask/src/cask/main/Main.scala

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ abstract class Main{
7474
}
7575

7676
object Main{
77-
class DefaultHandler(routeTries: Map[String, DispatchTrie[(Routes, EndpointMetadata[_])]],
77+
class DefaultHandler(routeTries: DispatchTrie[Map[String, (Routes, EndpointMetadata[_])]],
7878
mainDecorators: Seq[Decorator[_, _, _]],
7979
debugMode: Boolean,
8080
handleNotFound: () => Response.Raw,
@@ -101,16 +101,10 @@ object Main{
101101
(r: Any) => Main.writeResponse(exchange, r.asInstanceOf[Response.Raw])
102102
)
103103

104-
val dispatchTrie: DispatchTrie[(Routes, EndpointMetadata[_])] = routeTries.get(effectiveMethod) match {
105-
case None =>
106-
Main.writeResponse(exchange, handleMethodNotAllowed())
107-
return
108-
case Some(trie) => trie
109-
}
110-
111-
dispatchTrie.lookup(Util.splitPath(exchange.getRequestPath).toList, Map()) match {
104+
routeTries.lookup(Util.splitPath(exchange.getRequestPath).toList, Map()) match{
112105
case None => Main.writeResponse(exchange, handleNotFound())
113-
case Some(((routes, metadata), routeBindings, remaining)) =>
106+
case Some((methodMap, routeBindings, remaining)) if methodMap.contains(effectiveMethod) =>
107+
val (routes, metadata) = methodMap(effectiveMethod)
114108
Decorator.invoke(
115109
Request(exchange, remaining),
116110
metadata.endpoint,
@@ -128,8 +122,8 @@ object Main{
128122
)
129123
None
130124
}
125+
case _ => Main.writeResponse(exchange, handleMethodNotAllowed())
131126
}
132-
// println("Completed Request: " + exchange.getRequestPath)
133127
}catch{case e: Throwable =>
134128
e.printStackTrace()
135129
}
@@ -149,23 +143,25 @@ object Main{
149143
)
150144
}
151145

152-
def prepareRouteTries(allRoutes: Seq[Routes]): Map[String, DispatchTrie[(Routes, EndpointMetadata[_])]] = {
153-
val routeList = for{
146+
def prepareRouteTries(allRoutes: Seq[Routes]): DispatchTrie[Map[String, (Routes, EndpointMetadata[_])]] = {
147+
val flattenedRoutes = for {
154148
routes <- allRoutes
155-
route <- routes.caskMetadata.value.map(x => x: EndpointMetadata[_])
156-
} yield (routes, route)
149+
metadata <- routes.caskMetadata.value
150+
} yield {
151+
val segments = Util.splitPath(metadata.endpoint.path)
152+
val methodMap = metadata.endpoint.methods.map(_ -> (routes, metadata: EndpointMetadata[_])).toMap
153+
(segments, methodMap, metadata.endpoint.subpath)
154+
}
157155

158-
val allMethods: Set[String] =
159-
routeList.flatMap(_._2.endpoint.methods).map(_.toLowerCase).toSet
156+
val dispatchInputs = flattenedRoutes.groupBy(_._1).map { case (segments, values) =>
157+
val methodMap = values.map(_._2).flatten.toMap
158+
val hasSubpath = values.map(_._3).contains(true)
159+
(segments, methodMap, hasSubpath)
160+
}.toSeq
160161

161-
allMethods
162-
.map { method =>
163-
method -> DispatchTrie.construct[(Routes, EndpointMetadata[_])](0,
164-
for ((route, metadata) <- routeList if metadata.endpoint.methods.contains(method))
165-
yield (Util.splitPath(metadata.endpoint.path): collection.IndexedSeq[String], (route, metadata), metadata.endpoint.subpath)
166-
)
167-
}.toMap
162+
DispatchTrie.construct(0, dispatchInputs)
168163
}
164+
169165
def writeResponse(exchange: HttpServerExchange, response: Response.Raw) = {
170166
response.data.headers.foreach{case (k, v) =>
171167
exchange.getResponseHeaders.put(new HttpString(k), v)

example/minimalApplication/app/test/src/ExampleTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object ExampleTests extends TestSuite{
2727

2828
requests.post(s"$host/do-thing", data = "hello").text() ==> "olleh"
2929

30-
requests.get(s"$host/do-thing", check = false).statusCode ==> 404
30+
requests.delete(s"$host/do-thing", check = false).statusCode ==> 405
3131
}
3232
}
3333
}

example/minimalApplication2/app/test/src/ExampleTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object ExampleTests extends TestSuite{
2727

2828
requests.post(s"$host/do-thing", data = "hello").text() ==> "olleh"
2929

30-
requests.get(s"$host/do-thing", check = false).statusCode ==> 404
30+
requests.delete(s"$host/do-thing", check = false).statusCode ==> 405
3131
}
3232
}
3333
}

0 commit comments

Comments
 (0)