Set a parameter in a Java HttpServletRequest
The HttpServletRequest interface in Java is a fundamental part of Jakarta Servlets formerly Java Servlets, providing a way for servlets to interact with client requests. The ability to intercept and modify incoming HTTP requests before they reach the application holds significant value. Filters provide an elegant solution to preprocess these requests dynamically. In this article, we will delve into the creation of a filter that intercepts an HttpServletRequest
, leveraging a custom HttpServletRequestWrapper
for parameter sanitization. The ultimate goal is to showcase how such a filter can enrich the request with custom parameters, providing an understanding of its applications in building robust web applications.
1. Understanding HttpServletRequest, HttpServletRequestWrapper, and Filters
Before getting involved in setting parameters, let’s briefly understand the HttpServletRequest interface and the concept of Parameters, HttpServletRequestWrapper, and Filters.
1.1 HttpServletRequest Interface
The HttpServletRequest interface is part of the Java Servlet API and is used to represent an HTTP request made by a client. It provides methods to obtain information about the request, such as headers, parameters, and session details.
We utilize HttpServletRequest to engage with client requests and customize our servlets accordingly.
1.2 Parameters
Parameters are key-value
pairs sent by clients in the HTTP request. These can be part of the query string in the URL for GET requests or included in the request body for POST requests. Servlets use parameters to retrieve client data and perform necessary actions.
1.3 HttpServletRequestWrapper
As we navigate the intricacies of request processing, we might encounter scenarios demanding modification of the original request. HttpServletRequestWrapper
is a powerful class that extends HttpServletRequest
to facilitate dynamic modification.
This wrapper empowers us to customize request objects, dynamically altering their behavior. We can create a custom HttpServletRequestWrapper
for tasks such as parameter sanitization.
1.4 Filters
Filters are components that provide a mechanism to intercept and process requests and responses as they pass through the servlet container. Filters sit between the client’s request and the servlet, allowing us to perform pre-processing and post-processing tasks on a request, a response, or both.
Multiple filters can be chained together to create a sequence of processing steps. Each filter in the chain can contribute to the overall processing of the request and response. Filters have a defined lifecycle with methods like init
, doFilter
, and destroy
, allowing us to initialize resources, perform filtering logic, and release resources when the filter is no longer needed.
2. Maven Dependencies
For our servlet-based web application, we need to include the dependencies related to the Java Servlet API and Jetty Servlet container. We can achieve this by adding the following entries to the <dependencies>
section of the pom.xml
file:
<dependencies> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- Jetty Servlet Container --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.43.v20210629</version> </dependency> <!-- Jetty Servlet API --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.4.43.v20210629</version> </dependency> </dependencies>
3. Example: Parameter Sanitization
Filters empower us to sanitize incoming parameters, guarding against injection attacks and ensuring data integrity. In the context of parameter sanitization, filters assume the role of protectors, carefully inspecting and purifying incoming parameters.
In this example, we explore the Filter
interface and its lifecycle, delving into the creation of a filter dedicated to parameter sanitization. We will also observe how filters complement HttpServletRequest
and HttpServletRequestWrapper
.
3.1 Create SanitizedRequestWrapper
Let’s update the application to use HttpServletRequestWrapper
to sanitize the request parameters. We will create a custom wrapper class named SanitizedRequestWrapper
to override the getParameter
method and sanitize the parameter values. The filter will then use this wrapper to process the incoming request.
public class SanitizedRequestWrapper extends HttpServletRequestWrapper { public SanitizedRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { // Override the getParameter method to sanitize parameter values String originalValue = super.getParameter(name); return sanitize(originalValue); } @Override public Map<String, String[]> getParameterMap() { // Override getParameterMap to sanitize all parameter values return super.getParameterMap().entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, entry -> sanitize(entry.getValue()))); } private String[] sanitize(String[] values) { // Sanitize each value in the array return Arrays.stream(values).map(this::sanitize).toArray(String[]::new); } private String sanitize(String value) { // Implement your sanitization logic here // For simplicity, let's say we're removing any digits from the parameter values return value.replaceAll("\\d", ""); } }
Here is a break down the key elements of this code:
- Constructor:
public SanitizedRequestWrapper(HttpServletRequest request)
constructor takes anHttpServletRequest
as a parameter and calls the constructor of the superclass (HttpServletRequestWrapper
) with the provided request. This establishes the connection between the wrapper and the original request. - Overridden
getParameter
Method: This method overrides thegetParameter
method from the superclass. It calls the originalgetParameter
method to retrieve the parameter value. The retrieved value is then passed to thesanitize
method, which performs the sanitization logic. - Overridden
getParameterMap
Method: This method overrides thegetParameterMap
method from the superclass. It retrieves the original parameter map usingsuper.getParameterMap()
. It uses Java Stream API to iterate over the entries of the map and applies thesanitize
method to each array of values. The sanitized map is then returned. sanitize
Methods: These methods perform the actual sanitization.- The
sanitize(String[])
method uses Java Streams to sanitize each value in the array. - The
sanitize(String)
method, in this example, removes any digits from the parameter values using a regular expression
- The
3.2 Create a ParameterSettingFilter to use SanitizedRequestWrapper
@WebFilter(filterName = "ParameterSettingFilter", urlPatterns = {"/*"}) public class ParameterSettingFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Wrap the request with the SanitizedRequestWrapper HttpServletRequest sanitizedRequest = new SanitizedRequestWrapper((HttpServletRequest) request); // Continue with the sanitized request chain chain.doFilter(sanitizedRequest, response); } }
Here, we create a filter that intercepts the incoming request. We use the doFilter
method in the ParameterSettingFilter
to wrap the original request with SanitizedRequestWrapper
. This ensures that the sanitized request will be used downstream.
3.3 Create a Servlet to Access the Parameter
Next, create a servlet to access the newly added parameters.
@WebServlet(name = "DisplayParametersServlet", urlPatterns = {"/displayparams"}) public class DisplayParametersServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { SanitizedRequestWrapper sanitizedRequest = new SanitizedRequestWrapper(req); // Retrieve sanitized parameter values String sanitizedParam = sanitizedRequest.getParameter("userInput"); // Output the sanitized parameter value resp.setContentType("text/plain"); resp.getWriter().println(""); resp.getWriter().println("Sanitize Parameters Example"); resp.getWriter().write("Sanitized Parameter Value: " + sanitizedParam); resp.getWriter().println(""); } }
In this servlet, An instance of the SanitizedRequestWrapper
class is created by passing the original HttpServletRequest
(req
) to its constructor. This SanitizedRequestWrapper
is used to retrieve a parameter called userInput
, and the sanitized value is then outputted to the response.
To test the servlet, we need to deploy this servlet in our servlet container (in this article – Eclipse Jetty) and access it through a web browser or a tool like cURL.
To test the servlet using cURL
, we can make a GET request and observe the response. Here’s an example cURL
command:
curl http://localhost:8080/displayparams?userInput=123abc456def
This command sends a GET request to the specified URL with a query parameter named userInput
. The provided value is 123abc456def
. The servlet, in turn, processes this request and uses the SanitizedRequestWrapper
to retrieve and sanitize the parameter value.
The output is:
The output when we access the servlet URL on a web browser at http://localhost:8080/displayparams?userInput=123abc456def
is:
4. Modify Request Parameters: Adding and Removing in Action
To demonstrate adding a new parameter and removing one from the original request, we need to modify/enhance the code.
Create a new class named EnhancedRequestWrapper
that extends the HttpServletRequestWrapper
with the following code:
4.1 EnhancedRequestWrapper Class
public class EnhancedRequestWrapper extends HttpServletRequestWrapper { private final Map<String, String[]> modifiedParameters; public EnhancedRequestWrapper(HttpServletRequest request) { super(request); this.modifiedParameters = new HashMap<>(request.getParameterMap()); // Adding a new parameter this.modifiedParameters.put("newParameter", new String[]{"javacodegeeks"}); // Removing an existing parameter this.modifiedParameters.remove("userInput"); } @Override public String getParameter(String name) { // Retrieve the parameter from the modified parameters String[] values = modifiedParameters.get(name); return (values != null && values.length > 0) ? values[0] : null; } @Override public Map<String, String[]> getParameterMap() { // Return an unmodifiable map to prevent modification return Collections.unmodifiableMap(modifiedParameters); } @Override public Enumeration<String> getParameterNames() { // Return enumeration of parameter names return Collections.enumeration(modifiedParameters.keySet()); } @Override public String[] getParameterValues(String name) { // Retrieve the parameter values from the modified parameters return modifiedParameters.get(name); } }
In this modification, we added a new parameter named newParameter with a value of javacodegeeks and removed the existing userInput parameter from the original request. The get
methods are updated to retrieve parameters from the modified set.
We can use this enhanced wrapper EnhancedRequestWrapper
in our servlet just as before. The servlet code remains the same:
@WebServlet(name = "DisplayParametersServlet", urlPatterns = {"/displayparams"}) public class DisplayParametersServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Creating an instance of EnhancedRequestWrapper to sanitize and modify parameters EnhancedRequestWrapper enhancedRequest = new EnhancedRequestWrapper(req); // Retrieve parameters String newParamValue = enhancedRequest.getParameter("newParameter"); String removedParamValue = enhancedRequest.getParameter("userInput"); // Output the parameters resp.setContentType("text/plain"); resp.getWriter().println(""); resp.getWriter().println("Enhanced Request Parameters Example"); resp.getWriter().write("New Parameter Value: " + newParamValue); resp.getWriter().println(""); resp.getWriter().write("Removed Parameter Value: " + removedParamValue); resp.getWriter().println(""); } }
4.2 Modify ParameterSettingFilter to use EnhancedRequestWrapper
Next, we need to modify the doFilter
method in the ParameterSettingFilter
to wrap the original request with EnhancedRequestWrapper
.
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest enhancedRequest = new EnhancedRequestWrapper((HttpServletRequest) request); // Continue with the sanitized request chain chain.doFilter(enhancedRequest, response); }
4.3 Access the Servlet and Inspect the Output
To use cURL to make a simple GET request to the servlet, assuming the servlet is running on http://localhost:8080/displayparams
, we can use the following command:
curl http://localhost:8080/displayparams?userInput=modifyparameters
Now, when we access the servlet, we should see the output reflecting the addition of the new parameter and the removal of the existing one. The servlet is configured to output parameter values, including the new parameter and the removed parameter. The example output is:
Enhanced Request Parameters Example New Parameter Value: javacodegeeks Removed Parameter Value: null
5. Conclusion
In this article, we explored key Servlet components essential for Java web application development to manage incoming client requests. These components include:
- HttpServletRequest: The central stage, where information from the client’s browser arrives – parameters, headers, cookies, and more.
- HttpServletRequestWrapper: Wrapping the request to fit your specific needs – modifying and adding parameters.
- Filter: Used for intercepting requests before they reach their destination, filtering sensitive information, performing validations, or redirecting traffic.
6. Download the Source Code
This was an example of how to set parameter in a Java servlet request.
You can download the full source code of this example here: java servlet request set parameter