All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatra.ScalatraServlet.scala Maven / Gradle / Ivy

package org.scalatra

import org.scalatra.ServletCompat._
import org.scalatra.ServletCompat.http._

import org.apache.commons.text.StringEscapeUtils
import org.scalatra.servlet.ServletBase
import org.scalatra.util.RicherString._

import scala.util.control.Exception.catching

/**
 * An implementation of the Scalatra DSL in a servlet.  This is the recommended
 * base trait 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
 */
trait ScalatraServlet
  extends HttpServlet
  with ServletBase
  with Initializable {

  override def service(request: HttpServletRequest, response: HttpServletResponse): Unit = {
    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.
   */
  val RequestPathKey = "org.scalatra.ScalatraServlet.requestPath"

  def requestPath(implicit request: HttpServletRequest): String = {
    require(request != null, "The request can't be null for getting the request path")
    def startIndex(r: HttpServletRequest) =
      r.getContextPath.blankOption.map(_.length).getOrElse(0) + r.getServletPath.blankOption.map(_.length).getOrElse(0)
    def getRequestPath(r: HttpServletRequest) = {
      val u = (catching(classOf[NullPointerException]) opt { r.getRequestURI } getOrElse "/")
      requestPath(u, startIndex(r))
    }

    request.get(RequestPathKey) map (_.toString) getOrElse {
      val rp = getRequestPath(request)
      request(RequestPathKey) = rp
      rp
    }
  }

  def requestPath(uri: String, idx: Int): String = {
    if (uri.length == 0) {
      "/"
    } else {
      val pos = uri.indexOf(';')
      val u1 = if (pos >= 0) uri.substring(0, pos) else uri
      val u2 = if (decodePercentEncodedPath) UriDecoder.decode(u1) else u1
      u2.substring(idx).blankOption.getOrElse("/")
    }
  }

  protected def routeBasePath(implicit request: HttpServletRequest): String = {
    require(config != null, "routeBasePath requires the servlet to be initialized")
    require(request != null, "routeBasePath requires an active request to determine the servlet path")

    servletContext.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()(implicit request: HttpServletRequest, response: HttpServletResponse): 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()(implicit request: HttpServletRequest, response: HttpServletResponse): 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(StringEscapeUtils.escapeHtml4(request.getPathInfo)) getOrElse "/",
        request.getServletPath,
        routes.entryPoints.mkString("
  • ", "
  • ", "
")) } } type ConfigT = ServletConfig override def init(config: ServletConfig): Unit = { super.init(config) initialize(config) // see Initializable.initialize for why } override def initialize(config: ServletConfig): Unit = { super.initialize(config) } override def destroy(): Unit = { shutdown() super.destroy() } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy