Working with Request Headers and Response Headers in Java Servlets
Course: Advanced Java Training
Topic: Working with Request Headers and Response Headers
Course Link: Advanced Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction to HTTP Headers
HTTP headers are important components of HTTP communication between a client and a server. They provide additional information about a request or response, including content types, accepted formats, caching rules, authentication information, language preferences, and security policies.
In Java web applications, the HttpServletRequest interface allows servlets to read incoming request headers, while the HttpServletResponse interface allows servlets to configure outgoing response headers.
For example, when a browser requests a webpage, it may send headers describing its preferred response formats and supported languages. The servlet can inspect these headers and return an appropriate response with headers describing the content type and caching behavior.
2. Learning Objectives
- Understand HTTP headers and their purpose.
- Differentiate between request headers and response headers.
- Retrieve request headers using
HttpServletRequest.
- Read individual header values using
getHeader().
- Retrieve multiple header values using
getHeaders().
- Enumerate request headers using
getHeaderNames().
- Create and modify response headers using
HttpServletResponse.
- Understand common headers such as Content-Type, Accept, Cache-Control, and Authorization.
- Configure response content types and security-related headers.
- Apply header-handling techniques in practical servlet applications.
3. What Are HTTP Headers?
HTTP headers are name-value pairs included in HTTP requests and responses. They provide metadata that helps the client and server interpret the message correctly.
Example of an HTTP Request
GET /MyApp/products HTTP/1.1
Host: localhost:8080
Accept: text/html, application/json
Accept-Language: en-US
User-Agent: ExampleBrowser/1.0
Explanation
GET specifies the HTTP method.
Host identifies the requested host and may include a port.
Accept describes response media types the client can accept.
Accept-Language indicates preferred languages.
User-Agent provides information about the client software.
Example of an HTTP Response
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Cache-Control: no-store
X-Content-Type-Options: nosniff
<html>
<body>
<h1>Welcome to the Application</h1>
</body>
</html>
The response includes a status code, headers describing the returned content and its handling, and an HTML response body.
4. Request Headers vs. Response Headers
| Feature |
Request Headers |
Response Headers |
| Direction |
Sent from the client to the server. |
Sent from the server to the client. |
| Purpose |
Describe the request and client preferences. |
Describe the response and how it should be handled. |
| Servlet interface |
HttpServletRequest |
HttpServletResponse |
| Reading values |
getHeader() |
getHeader() for headers configured on the response. |
| Setting values |
Clients ordinarily supply request headers. |
Servlets configure them using setHeader() or addHeader(). |
| Examples |
Accept, User-Agent, Accept-Language |
Content-Type, Cache-Control, Location |
5. Understanding HttpServletRequest
HttpServletRequest is an interface in the Servlet API that represents an incoming HTTP request. It provides methods for accessing request headers, parameters, attributes, cookies, and other request information.
The servlet container creates and supplies the request object when a request is processed.
Important Request Header Methods
| Method |
Description |
getHeader(String name) |
Returns the first value of the specified header, or null if absent. |
getHeaders(String name) |
Returns an enumeration of all values for a header. |
getHeaderNames() |
Returns an enumeration of request header names. |
getIntHeader(String name) |
Reads a header as an integer when its value is valid. |
getDateHeader(String name) |
Reads a date-valued header as milliseconds since the Unix epoch. |
getMethod() |
Returns the HTTP request method, such as GET or POST. |
getRequestURI() |
Returns the request URI path. |
6. Retrieving a Single Request Header Using getHeader()
The getHeader() method retrieves the value associated with a specified request header. The method accepts the header name and returns its first value as a string.
Syntax
String headerValue = request.getHeader("Header-Name");
Example: Reading the User-Agent Header
String userAgent = request.getHeader("User-Agent");
if (userAgent != null) {
System.out.println("Client software: " + userAgent);
} else {
System.out.println("User-Agent header is unavailable.");
}
Explanation
- The servlet requests the value of the
User-Agent header.
- If the header exists, its value is returned as a string.
- If the header is absent, the method returns
null.
- The servlet can use the value for diagnostics or logging, subject to privacy and security requirements.
Important: Header values supplied by clients are untrusted. Do not use the User-Agent header as proof of a browser's identity, device security, or user authorization.
7. Reading Common Request Headers
Applications frequently inspect request headers to understand client preferences, identify accepted content formats, or process conditional requests.
Example
String accept = request.getHeader("Accept");
String language = request.getHeader("Accept-Language");
String userAgent = request.getHeader("User-Agent");
String contentType = request.getHeader("Content-Type");
System.out.println("Accepted formats: " + accept);
System.out.println("Preferred languages: " + language);
System.out.println("Client software: " + userAgent);
System.out.println("Request content type: " + contentType);
Common Request Headers
| Header |
Purpose |
Example |
Accept |
Lists media types acceptable in the response. |
application/json, text/html |
Accept-Language |
Indicates preferred response languages. |
en-US,en;q=0.9 |
User-Agent |
Describes the client software. |
ExampleBrowser/1.0 |
Content-Type |
Describes the media type of the request body. |
application/json |
Authorization |
Carries credentials or authorization information. |
Bearer example-token |
Cookie |
Carries cookies previously stored by the client. |
sessionId=example |
If-Modified-Since |
Supports conditional retrieval based on modification time. |
An HTTP date |
Origin |
Identifies the origin of a cross-origin request where applicable. |
https://example.com |
Some headers may be absent, repeated, or handled by the container or intermediary infrastructure. Always design code to handle missing or unexpected values.
8. Retrieving Multiple Header Values Using getHeaders()
Some request headers can contain multiple values. The getHeaders() method returns an Enumeration containing all values associated with the specified header name.
Syntax
Enumeration<String> values = request.getHeaders("Header-Name");
Example
import java.util.Enumeration;
Enumeration<String> languages =
request.getHeaders("Accept-Language");
while (languages.hasMoreElements()) {
String value = languages.nextElement();
System.out.println("Accepted language: " + value);
}
If a request contains multiple Accept-Language header fields, the enumeration allows the servlet to inspect their individual values. Some headers may instead combine several values in one field, depending on the HTTP header's rules.
9. Retrieving All Request Header Names
The getHeaderNames() method returns an enumeration of the request header names. It can be useful for diagnostic tools, request inspection, and debugging.
Example
import java.util.Enumeration;
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name + ": " + value);
}
}
This example reads the first value of each header. It does not necessarily print every value for repeated headers. Use getHeaders(name) when all values are required.
Do not log all headers indiscriminately in production. Headers such as Authorization, Cookie, and other credential-bearing fields may contain sensitive information.
10. Reading Integer and Date Headers
The Servlet API provides convenience methods for reading headers that represent integers or HTTP dates.
Reading an Integer Header
int contentLength = request.getIntHeader("Content-Length");
if (contentLength >= 0) {
System.out.println("Content length: " + contentLength);
} else {
System.out.println("Content length is unavailable.");
}
If the header is missing, getIntHeader() returns -1. If its value cannot be converted to an integer, an IllegalArgumentException may be thrown.
Reading a Date Header
long modifiedSince =
request.getDateHeader("If-Modified-Since");
if (modifiedSince != -1L) {
System.out.println("Client modification timestamp: "
+ modifiedSince);
}
The date is returned as milliseconds since January 1, 1970, UTC. A missing header returns -1, while an invalid date value can cause an IllegalArgumentException.
11. Understanding HttpServletResponse
HttpServletResponse is an interface that represents the HTTP response generated by a servlet. It allows the servlet to set the response status, content type, headers, cookies, and body content.
Response headers provide instructions and metadata to the client. They may describe the returned content, define caching behavior, specify a redirect destination, or communicate security policies.
Important Response Header Methods
| Method |
Description |
setHeader(name, value) |
Sets a header value, replacing existing values for that header. |
addHeader(name, value) |
Adds another value for a header. |
setIntHeader(name, value) |
Sets a header with an integer value. |
addIntHeader(name, value) |
Adds an integer header value. |
setDateHeader(name, date) |
Sets a header containing a formatted date. |
addDateHeader(name, date) |
Adds a date-valued header. |
containsHeader(name) |
Checks whether the response contains a named header. |
getHeader(name) |
Reads a header value configured on the response. |
getHeaders(name) |
Returns all configured values for a response header. |
getHeaderNames() |
Returns the names of configured response headers. |
12. Setting Response Headers Using setHeader()
The setHeader() method assigns a value to a response header. If the header already has values, this method replaces them with the specified value.
Syntax
response.setHeader("Header-Name", "Header-Value");
Example
response.setHeader("Cache-Control", "no-store");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Content-Language", "en");
Explanation
Cache-Control: no-store instructs caches not to store the response.
X-Content-Type-Options: nosniff helps prevent browsers from interpreting content as a different media type through MIME sniffing.
Content-Language: en indicates that the intended language of the representation is English.
Choose response headers based on the application's requirements. Security headers must be configured consistently, and cache directives should match the sensitivity and intended caching behavior of the returned content.
13. Adding Multiple Header Values Using addHeader()
The addHeader() method adds another value for a response header rather than replacing previously configured values.
Example
response.addHeader("X-Demo-Info", "Servlet");
response.addHeader("X-Demo-Info", "Advanced Java");
These calls add two values for the same header name. Whether a particular header supports multiple values and how those values are interpreted depends on the header's specification. Do not use addHeader() as a substitute for understanding the semantics of the header being configured.
Difference Between setHeader() and addHeader()
| Feature |
setHeader() |
addHeader() |
| Purpose |
Sets or replaces a header value. |
Adds another header value. |
| Existing values |
Replaces existing values for that name. |
Preserves existing values and adds another. |
| Typical use |
Setting Content-Type or Cache-Control. |
Adding values when the header specification permits it. |
14. Setting the Response Content Type
The response content type tells the client what kind of representation is being returned. The servlet commonly sets it using setContentType(), which configures the response media type and may include a character encoding.
Example: HTML Response
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println(
"<h1>Welcome to the Servlet Application</h1>"
);
Example: Plain Text Response
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Request processed successfully.");
Example: JSON Response
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(
"{\"status\":\"success\",\"message\":\"Data received\"}"
);
Important: The content type should accurately describe the response body. Do not label HTML as JSON or return unescaped user input as executable HTML. For complex JSON responses, use a JSON library rather than manually building strings.
15. Complete Example: Reading Request Headers and Setting Response Headers
The following servlet demonstrates how to retrieve selected request headers and configure response headers before returning an HTML page.
Java Servlet Code
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/headers")
public class HeaderServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String userAgent = request.getHeader("User-Agent");
String accept = request.getHeader("Accept");
String language = request.getHeader("Accept-Language");
response.setContentType("text/html;charset=UTF-8");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Cache-Control", "no-store");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html><head>");
out.println("<title>HTTP Header Details</title>");
out.println("</head><body>");
out.println("<h1>Request Header Information</h1>");
out.println("<p>User-Agent: "
+ escapeHtml(userAgent) + "</p>");
out.println("<p>Accept: "
+ escapeHtml(accept) + "</p>");
out.println("<p>Accept-Language: "
+ escapeHtml(language) + "</p>");
out.println("</body></html>");
}
}
private String escapeHtml(String value) {
if (value == null) {
return "Not provided";
}
return value.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace(""", """)
.replace("'", "'");
}
}
How the Program Works
- The client sends a GET request to the servlet mapped to
/headers.
- The servlet reads the User-Agent, Accept, and Accept-Language request headers.
- The response content type is set to HTML with UTF-8 encoding.
- The servlet adds a cache-control header and a content-type protection header.
- Missing header values are handled without causing a null-pointer error.
- Header values are escaped before they are inserted into the HTML response.
- The servlet writes the HTML body and completes the response.
How to Run
- Create a Java web application in your IDE.
- Add the Servlet API provided by your Jakarta-compatible container.
- Save the class as
HeaderServlet.java.
- Deploy the application to a compatible server, such as Tomcat 10 or later.
- Open
http://localhost:8080/YourApp/headers, replacing YourApp with your application's context path.
- Inspect the generated page and the HTTP response headers in your browser's developer tools.
For older Java EE environments, use the corresponding javax.servlet imports instead of jakarta.servlet.
16. Setting Integer and Date Response Headers
The Servlet API provides methods for setting integer and date headers without requiring the application to format every value manually.
Integer Header Example
response.setIntHeader("X-Record-Count", 25);
This example sets a custom header containing an integer. Custom headers should be documented if other application components depend on them.
Date Header Example
long currentTime = System.currentTimeMillis();
response.setDateHeader("Last-Modified", currentTime);
The setDateHeader() method accepts milliseconds since the Unix epoch and formats the value as an HTTP date. In a real application, the Last-Modified value should represent the actual modification time of the returned resource, not simply the current time.
17. Understanding Cache-Control Headers
HTTP caching allows browsers and intermediary caches to reuse responses. Proper cache directives can improve performance while preventing sensitive information from being stored in inappropriate locations.
| Directive |
Meaning |
Typical Use |
no-store |
Instructs caches not to store the response. |
Sensitive account or personal information. |
no-cache |
Requires revalidation before a stored response is reused. |
Content that may be stored but must be checked before reuse. |
max-age=60 |
Defines a freshness lifetime of 60 seconds. |
Content that can be cached briefly. |
private |
Restricts storage to private caches rather than shared caches. |
Responses intended for an individual user. |
Example
response.setHeader("Cache-Control", "no-store");
Cache behavior should be selected according to the data being returned. A cache directive does not replace authentication, authorization, or protection of data in transit.
18. Security Headers in Java Servlets
Response security headers can help browsers apply additional protections. The correct set depends on whether the application serves HTML, APIs, embedded content, or other resources.
Example
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Content-Security-Policy",
"default-src 'self'; object-src 'none'; base-uri 'self'");
response.setHeader("Referrer-Policy",
"strict-origin-when-cross-origin");
Purpose of These Headers
- X-Content-Type-Options: The
nosniff value helps prevent MIME-type sniffing in supported browser contexts.
- Content-Security-Policy: Defines permitted sources and other rules for resources used by the page. The policy shown is an example and may need adjustment for scripts, styles, images, and other application requirements.
- Referrer-Policy: Controls how much referrer information browsers send when navigating to another resource.
Security headers should be configured and tested for the entire application. A restrictive Content Security Policy can break pages if it does not account for required resources. Applications using HTTPS should also configure appropriate transport-security policies at the correct deployment layer.
19. Understanding the Authorization Request Header
The Authorization header is commonly used to carry authentication credentials, including bearer tokens. A servlet may read this header as part of an authentication workflow, but reading the value alone does not authenticate a user.
Example
String authorization = request.getHeader("Authorization");
if (authorization == null || authorization.isBlank()) {
response.sendError(
HttpServletResponse.SC_UNAUTHORIZED,
"Authorization information is required.");
return;
}
// Validate the credentials with an appropriate
// authentication mechanism before granting access.
A production application must validate credentials using an appropriate security framework or authentication mechanism. Do not print, expose, or store bearer tokens unnecessarily. Use HTTPS and apply suitable token expiration, revocation, and authorization controls.
20. Response Headers and Redirects
A servlet can redirect a client to another URL using sendRedirect(). The container typically generates a redirect response with a Location header and an appropriate status code.
Example
response.sendRedirect("dashboard");
Alternatively, a servlet can configure a redirect response manually, but the status code and Location header must be set correctly and before the response is committed.
response.setStatus(HttpServletResponse.SC_FOUND);
response.setHeader("Location", "dashboard");
Use trusted redirect destinations or validate them carefully. Allowing arbitrary user-provided redirect URLs can create open-redirect vulnerabilities.
21. When Can Response Headers Be Set?
Response headers should be configured before the response is committed. A response may become committed when its buffer is flushed, filled and sent, or when an operation such as a redirect or error response commits it.
Correct Approach
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-store");
response.getWriter().println("<h1>Hello</h1>");
Potentially Incorrect Approach
response.getWriter().println("<h1>Hello</h1>");
response.flushBuffer();
response.setHeader("Cache-Control", "no-store");
In the second example, the response has already been committed. The servlet container may ignore the later header change. Configure the status and headers before writing or flushing response content whenever possible.
22. Common Errors and Troubleshooting
| Problem |
Possible Cause |
Solution |
getHeader() returns null. |
The client did not send the specified header. |
Check for null and avoid assuming every header exists. |
| Header value is unexpected. |
The value is client-controlled or formatted differently than expected. |
Validate and parse it according to the header's rules. |
| Only one header value is displayed. |
The code uses getHeader() for a repeated header. |
Use getHeaders() to retrieve all values. |
| Response header does not appear. |
The response was committed or another component changed the response. |
Set headers early and inspect the final network response. |
| Browser caches sensitive content. |
Cache directives are missing or unsuitable. |
Choose suitable Cache-Control directives and verify browser behavior. |
| JSON response is interpreted incorrectly. |
The content type does not match the body. |
Set the correct media type before writing the body. |
| Security header breaks the page. |
The configured policy blocks required resources. |
Review and test the policy against application dependencies. |
| Header parsing throws an exception. |
A numeric or date header has an invalid value. |
Handle parsing exceptions and validate the value. |
23. Best Practices for Working with HTTP Headers
- Use
HttpServletRequest to inspect incoming request headers.
- Use
HttpServletResponse to configure outgoing response headers.
- Handle absent headers safely.
- Use
getHeaders() when multiple values matter.
- Never trust request headers as proof of identity or authorization.
- Avoid exposing authentication tokens and cookies in logs.
- Set the correct content type and character encoding.
- Configure headers before the response is committed.
- Choose cache directives according to the sensitivity of the response.
- Use security headers that fit the application's requirements.
- Validate redirect destinations to avoid open-redirect vulnerabilities.
- Test actual HTTP responses with browser developer tools or an HTTP client.
- Keep security configuration consistent across controllers, servlets, filters, and reverse proxies.
24. Practical Exercises
Exercise 1: Display Request Headers
Create a servlet that reads the User-Agent, Accept, and Accept-Language headers and displays their values safely on an HTML page.
Exercise 2: Enumerate All Headers
Use getHeaderNames() to display the request header names. For repeated headers, retrieve all values using getHeaders().
Exercise 3: Configure Response Headers
Create a servlet that returns an HTML response and sets the content type, Cache-Control, and X-Content-Type-Options headers.
Exercise 4: JSON Response
Create an endpoint that returns a valid JSON response with the correct content type and a suitable HTTP status code.
Exercise 5: Authentication Header
Read an Authorization header and demonstrate how an application should delegate credential verification to a proper authentication component. Never treat the presence of a header as proof of authentication.
Exercise 6: Inspect Cache Behavior
Compare responses using Cache-Control: no-store and Cache-Control: max-age=60. Inspect the response headers and observe how browser caching behavior differs.
25. Interview Questions and Answers
Q1. What are HTTP headers?
Answer: HTTP headers are name-value pairs that carry metadata about an HTTP request or response.
Q2. What is the difference between request headers and response headers?
Answer: Request headers are sent by the client to provide request metadata and preferences. Response headers are returned by the server to describe the response and its handling.
Q3. What is the purpose of getHeader()?
Answer: It retrieves the first value of a named request header as a string, returning null when the header is absent.
Q4. What is the difference between getHeader() and getHeaders()?
Answer: getHeader() retrieves the first value, while getHeaders() returns an enumeration of all values for the specified request header.
Q5. What is the difference between setHeader() and addHeader()?
Answer: setHeader() replaces existing values for a response header name, while addHeader() adds another value.
Q6. What does Content-Type specify?
Answer: It identifies the media type of the message body, such as text/html, text/plain, or application/json.
Q7. What is the purpose of Cache-Control?
Answer: It specifies caching directives that guide browsers and intermediary caches in storing, reusing, and revalidating responses.
Q8. Can a servlet change response headers after writing content?
Answer: It may be possible before the response is committed, but header changes generally have no effect after commitment. Headers should be configured early.
Q9. Why should request headers be treated as untrusted?
Answer: Clients can modify or fabricate headers. Their values should not be used as the sole basis for authentication, authorization, or security decisions.
Q10. What is the purpose of X-Content-Type-Options?
Answer: The nosniff value helps prevent browsers from interpreting a response as a media type different from the one declared.
Q11. What is the Authorization header?
Answer: It carries authentication credentials or tokens that a server or security component can validate.
Q12. How can response headers be tested?
Answer: Use browser developer tools, an HTTP client, or automated integration tests to inspect the response status, headers, and body.
26. Quick Revision
- HTTP headers carry metadata in requests and responses.
HttpServletRequest is used to access incoming request headers.
getHeader() retrieves the first value of a request header.
getHeaders() retrieves all values for a request header.
getHeaderNames() enumerates request header names.
HttpServletResponse is used to configure outgoing response headers.
setHeader() replaces existing values for a response header.
addHeader() adds another response header value.
setContentType() configures the response media type and can specify character encoding.
- Configure headers before the response is committed.
- Never trust client-supplied headers as authentication proof.
- Use appropriate caching and security headers for the application.
27. Conclusion
Working with request headers and response headers is an important skill in Java Servlet development. Request headers help applications understand client preferences and request metadata, while response headers communicate content information, caching instructions, redirect destinations, and security policies.
By mastering HttpServletRequest methods such as getHeader(), getHeaders(), and getHeaderNames(), along with response methods such as setHeader(), addHeader(), and setContentType(), developers can build more reliable and secure web applications.
Always validate untrusted header values, avoid exposing credentials, choose suitable response policies, and configure headers before the response is committed.
Learn Advanced Java with JustAcademy
Build practical knowledge of Java Servlets, HTTP communication, request processing, response handling, JDBC, JSP, and enterprise web application development.
Explore the Advanced Java Training Course
Register for a Course Demo
Visit the JustAcademy Website