/
ScalatraServlet.scala
147 lines (134 loc) · 5.07 KB
/
ScalatraServlet.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package org.scalatra
import servlet.ServletBase
import javax.servlet._
import javax.servlet.http._
import org.scalatra.util.RicherString._
import java.io.File
object ScalatraServlet {
import servlet.ServletApiImplicits._
def requestPath(request: HttpServletRequest) = {
def getRequestPath = request.getRequestURI match {
case requestURI: String =>
var uri = requestURI
if (request.getContextPath != null && request.getContextPath.trim.nonEmpty) uri = uri.substring(request.getContextPath.length)
if (request.getServletPath != null && request.getServletPath.trim.nonEmpty) uri = uri.substring(request.getServletPath.length)
if (uri.isEmpty) {
uri = "/"
} else {
val pos = uri.indexOf(';')
if (pos >= 0) uri = uri.substring(0, pos)
}
UriDecoder.firstStep(uri)
case null => "/"
}
request.get("org.scalatra.ScalatraServlet.requestPath") match {
case Some(uri) => uri.toString
case _ => {
val requestPath = getRequestPath
request.setAttribute("org.scalatra.ScalatraServlet.requestPath", requestPath)
requestPath.toString
}
}
}
}
/**
* An implementation of the Scalatra DSL in a servlet. This is the recommended
* base class for most Scalatra applications. Use a servlet if:
*
* $ - your Scalatra routes run in a subcontext of your web application.
* $ - you want Scalatra to have complete control of unmatched requests.
* $ - you think you want a filter just for serving static content with the
* default servlet; ScalatraServlet can do this too
* $ - you don't know the difference
*
* @see ScalatraFilter
*/
//@deprecated("This aproach uses thread locals which cause headaches in a multi-threading scenario, use org.scalatra.ScalatraApp instead.", "2.2")
abstract class ScalatraServlet
extends HttpServlet
with ServletBase
with Initializable {
override def service(request: HttpServletRequest, response: HttpServletResponse) {
handle(request, response)
}
/**
* Defines the request path to be matched by routers. The default
* definition is optimized for `path mapped` servlets (i.e., servlet
* mapping ends in `/*`). The route should match everything matched by
* the `/*`. In the event that the request URI equals the servlet path
* with no trailing slash (e.g., mapping = `/admin/*`, request URI =
* '/admin'), a '/' is returned.
*
* All other servlet mappings likely want to return request.getServletPath.
* Custom implementations are allowed for unusual cases.
*/
def requestPath = {
def getRequestPath = request.getRequestURI match {
case requestURI: String =>
var uri = requestURI
if (request.getContextPath != null && request.getContextPath.trim.nonEmpty) uri = uri.substring(request.getContextPath.length)
if (request.getServletPath != null && request.getServletPath.trim.nonEmpty) uri = uri.substring(request.getServletPath.length)
if (uri.isEmpty) {
uri = "/"
} else {
val pos = uri.indexOf(';')
if (pos >= 0) uri = uri.substring(0, pos)
}
UriDecoder.firstStep(uri)
case null => "/"
}
request.get("org.scalatra.ScalatraServlet.requestPath") match {
case Some(uri) => uri.toString
case _ => {
val requestPath = getRequestPath
request.setAttribute("org.scalatra.ScalatraServlet.requestPath", requestPath)
requestPath.toString
}
}
}
protected def routeBasePath = {
if (request == null)
throw new IllegalStateException("routeBasePath requires an active request to determine the servlet path")
request.getContextPath + request.getServletPath
}
/**
* Invoked when no route matches. By default, calls `serveStaticResource()`,
* and if that fails, calls `resourceNotFound()`.
*
* This action can be overridden by a notFound block.
*/
protected var doNotFound: Action = () => {
serveStaticResource() getOrElse resourceNotFound()
}
/**
* Attempts to find a static resource matching the request path. Override
* to return None to stop this.
*/
protected def serveStaticResource(): Option[Any] =
servletContext.resource(request) map { _ =>
servletContext.getNamedDispatcher("default").forward(request, response)
}
/**
* Called by default notFound if no routes matched and no static resource
* could be found.
*/
protected def resourceNotFound(): Any = {
response.setStatus(404)
if (isDevelopmentMode) {
val error = "Requesting \"%s %s\" on servlet \"%s\" but only have: %s"
response.getWriter println error.format(
request.getMethod,
Option(request.getPathInfo) getOrElse "/",
request.getServletPath,
routes.entryPoints.mkString("<ul><li>", "</li><li>", "</li></ul>"))
}
}
type ConfigT = ServletConfig
override def init(config: ServletConfig) {
super.init(config)
initialize(config) // see Initializable.initialize for why
}
override def initialize(config: ServletConfig) {
super.initialize(config)
}
}