HTTP Request Handler 📇
There are various abstractions in the form of routers and filters provided by Play to be integrated into your application. However, having all the configurations, including the complex settings, is not possible. So, Play provides a method to customize the settings using the HttpRequestHandler API. Scala developers can use the HttpRequestHandler to provide custom implementation to their web applications.

Note that using the HttpRequestHandler should be the last option. The first option is to leverage routers or filters to offer configuration settings.
To learn more about APIs, visit Introduction to API and its usage – Coding Ninjas Blog
Implementation of a Custom Request Handler 🚀
The HttpRequestHandler has a method called the handlerForRequest that can be used to get the handlers for your requests. It returns a tuple of RequestHeader and a Handler. RequestHeader is used to store the routing information for the request. This helps monitor the requests by connecting them with their routing information.

Example 📃
import javax.inject.Inject
import play.api.mvc._
import play.api.http._
import play.api.routing.Router
class MyHttpRequestHandler @Inject() (router: Router, action: DefaultActionBuilder) extends HttpRequestHandler {
def handlerForRequest(request: RequestHeader) = {
router.routes.lift(request) match {
case Some(handler) => (request, handler)
case None => (request, action(Results.NotFound))
}
}
}
Let’s now discuss how you can extend the default request handler.
Extending the Default Request Handler 📃
If you want to create a new request handler, you can extend the DefaultHttpRequestHandler instead of building a new one from scratch. You can override the methods of the DefaultHttpRequestHandler that you want to customize. This minimizes the efforts of writing your methods that don’t require any changes and are available in the DefaultHttpRequestHandler.
Configuring the HTTP request handler 📍📟
If you're building your app with BuiltInComponents, you should override the httpRequestHandler method of the Application class to return the custom handler.

If you are customizing your application by runtime dependency injection, the request handler will be loaded dynamically at run time. This can be achieved by creating a class RequestHandler that executes HttpRequestHandler.
Essential Actions 📌
The EssentialAction in Play is a simpler type of underlying Action[A]. To understand the concept of essential actions better, you first have to understand the Play Architecture.
Play is a very small framework with a large set of helping APIs and services that provide different functionalities to Play-developed applications. These APIs and services are the reason why web development is easier and faster with Play.
The Play’s Action API has the following type:
First, it takes the request header stored in RequestHeader, then the request body is shared and stored in Array[Byte], and finally, a Result is produced.
RequestHeader -> Array[Byte] -> Result
The problem with the above computation is that the entire request body is kept in memory. Now there may be cases where we want to shift this to a cloud service, say AWS S3, or maybe want to compute a part of the request body and not the whole. To achieve this, we want a mechanism that takes the request body in pieces, processes them, and produces results.
To ensure that the request body is taken in chunks and not as a whole, we can use the Accumulator, which takes 2 parameters. In Accumulator[E, R], the two parameters are type parameters where E is the type of inputs and R is the type of results generated.
The chunks or pieces of input are a ByteString, and the result is of type Result. So, with this, we can rewrite the computation as:
RequestHeader => Accumulator[ByteString, Result]
This can also be written as:
RequestHeader => ByteString ==> Result
This is how the EssentialActions are defined in Play
trait EssentialAction extends (RequestHeader => Accumulator[ByteString, Result])
The Result type also contains the ResponseHeader as the header and ByteString as the body. Following is how you define the Result type:
case class Result(header: ResponseHeader, body: ByteString)
But here also, the problem of sending the entire response body as a ByteString persists. We need to define the type such that the response body is not of type ByteString but pieces of ByteString. To do so, we have Source[E, _ ], which produces pieces of type E (in our case, E is ByteString). so by using this, our Result type becomes:
case class Result(header: ResponseHeader, body: Source[ByteString, _ ])
HTTP Filters 📋
The Play framework provided the filter API that the Scala developers can use to apply global filters to each request.
Filters 🆚 Action Composition
The filter API is meant for concerns that are applied uniformly to all routes. Some use cases of filters include Logging/metrics collection, Security headers, and GZIP encoding.
Whereas the purpose of action composition is to address route-specific problems, including caching, authentication and authorization. If you want to apply filters to specific routes, actions should be used instead of filters. Also, Play allows you to customize the actions according to your needs.
How to Use Filters ❔
The easiest way to use the filters is to define their implementation into the root package. If you are customizing your application using the runtime dependency injection, then to use filers, you can extend the DefaultHttpFilters class and pass the filters as arguments to the var args constructor.
Following is an example of how you can do this:
import javax.inject.Inject
import play.api.http.DefaultHttpFilters
import play.api.http.EnabledFilters
import play.filters.gzip.GzipFilter
class Filters @Inject() (
defaultFilters: EnabledFilters,
gzip: GzipFilter,
log: LoggingFilter
) extends DefaultHttpFilters(defaultFilters.filters :+ gzip :+ log: _*)
If you use the BuiltInComponents for customizing by compile time dependency injection, you may override the httpFilters lazy val.
Frequently Asked Questions
What is Scala?
Scala is an open-source, general purpose, multiple paradigm programming languages. It supports both functional and object-oriented programming principles.
What is Play?
Play is one of the web development frameworks written in Scala. It is a small framework consisting of many APIs to provide various functionalities to your web application.
Can you customize the implementation of DefaultHttpRequestHandler in Play?
Yes. Play provides a method to customize the settings using the HttpRequestHandler API. Scala developers can use the HttpRequestHandler to provide custom implementation to their web applications.
What is Source[E, _ ] type in Play?
Source[E, _ ] is a type in Play that produces pieces of type E. You can replace E with the type of data you are dealing with. In the case of the Result type, we replaced E with ByteString because our input is of type ByteString, and we want to take inputs in chunks.
What exactly does a Scala developer do??
A Scala developer is responsible for designing, developing, and managing scala-based web applications. They should be familiar with the concepts of Scala knowledge, including but not limited to functional and object-oriented programming paradigms.
Conclusion 🔚
In this article, we discussed application settings for Scala developers. We also discussed the concepts of HTTP request handlers, Essential actions, and HTTP filters.
To read interview questions related to Scala, visit Scala Interview Questions - Coding Ninjas Coding Ninjas Studio.
I hope you would have gained a better understanding of these topics now!
Are you planning to ace the interviews of reputed product-based companies like Amazon, Google, Microsoft, and more?
Attempt our Online Mock Test Series on Coding Ninjas Studio now!
Happy Coding!