🌐 Section 6 · Question #16

What is Content-Type header

The Content-Type HTTP entity header (RFC 9110, Section 8.3) specifies the media format (MIME / Media Type) of the data payload transmitted in the body of an HTTP request or HTTP...


🟢 Junior Level

The Content-Type HTTP entity header (RFC 9110, Section 8.3) specifies the media format (MIME / Media Type) of the data payload transmitted in the body of an HTTP request or HTTP response.

Fundamental Operating Principle

HTTP transports message bodies as unformatted streams of raw binary octets. The Content-Type header instructs the receiver (web server, mobile client, or browser) which parser and deserialization rules must be applied to interpret those bytes:

POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json; charset=utf-8

{"name": "Alice", "age": 30}

Without Content-Type, the recipient cannot determine whether incoming bytes represent plaintext, JSON, XML, or binary PDF data.


Core Distinction: Content-Type vs. Accept

  • Content-Type: Informs the recipient of the format of the data currently being sent in the immediate message body.
  • Accept: Informs the recipient of the data formats the sender is willing to accept in the resulting response payload (Content Negotiation).
[Client] ── POST /users (Content-Type: JSON, Accept: XML) ──► [Server parses JSON, responds with XML]

Standard MIME Media Types in REST

MIME Media Type Semantic Meaning Common REST Application
application/json JavaScript Object Notation (RFC 8259) Standard default for modern REST APIs
application/xml Extensible Markup Language Enterprise legacy REST & SOAP services
application/x-www-form-urlencoded URL-encoded key-value tuples Standard HTML form submissions
multipart/form-data Multi-part payload with distinct boundaries Mixed file uploads and form metadata
text/plain / text/html Unformatted text or HTML documents Simple health checks or rendered views
application/octet-stream Arbitrary binary byte stream Raw binary file downloads

🟡 Middle Level

Spring MVC HttpMessageConverter Resolution Pipeline

In Spring Web / Spring Boot, the Content-Type header determines which HttpMessageConverter bean deserializes the request body into Java DTOs:

                  Incoming Request (`Content-Type: application/json`)
                                          │
                                          ▼
                                  DispatcherServlet
                                          │
                                          ▼
                        RequestResponseBodyMethodProcessor
                                          │
                         Iterates registered converters:
                         ├── ByteArrayHttpMessageConverter   ──> canRead()? false
                         ├── StringHttpMessageConverter      ──> canRead()? false
                         └── MappingJackson2HttpMessageConverter ──> canRead()? TRUE!
                                          │
                                          ▼
                          Jackson `ObjectMapper` deserializes InputStream
  1. Spring evaluates registered converters in priority order.
  2. For each converter, it evaluates canRead(targetClass, mediaType).
  3. The first converter returning true reads the InputStream.
  4. If no registered converter supports the provided Content-Type, Spring throws HttpMediaTypeNotSupportedException, which translates directly to 415 Unsupported Media Type.

Restricting Consumed Formats (consumes)

Controllers explicitly restrict supported incoming formats using the consumes attribute:

@PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserResponseDto> createUser(@RequestBody CreateUserRequest request) {
    // ...
}

If a client issues a request with Content-Type: application/xml, Spring MVC rejects it immediately with 415 Unsupported Media Type before executing any controller or business logic.


Header Parameters: charset and boundary

  1. The charset Parameter: Under RFC 8259, UTF-8 is the mandatory default encoding for application/json. Supplying charset=utf-8 on JSON is redundant. However, for text/plain or text/html, specifying charset=utf-8 is critical to prevent legacy clients from defaulting to ISO-8859-1.
  2. The boundary Parameter in multipart/form-data:
    Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
    

    The boundary token is a unique delimiter string generated by the client that partitions individual parts (e.g., separating JSON metadata from raw binary file streams) within a single continuous HTTP stream.


Security: MIME Sniffing & X-Content-Type-Options: nosniff

Historically, web browsers attempted to infer (“sniff”) a payload’s true file type by inspecting its magic bytes, ignoring the declared Content-Type. This enabled Cross-Site Scripting (XSS):

  • An attacker uploads an avatar image (avatar.png) containing hidden JavaScript (<script>alert('XSS')</script>).
  • The server serves the file with Content-Type: image/png.
  • A sniffing browser detects HTML/JS tokens and executes the script within the victim’s session.

The Production Fix: Servers must return the security header:

X-Content-Type-Options: nosniff

This forces the browser to strictly honor the declared Content-Type, disabling speculative execution.


🔴 Senior Level

Specialized MIME Types in Enterprise Architectures

Production-grade REST services utilize fine-grained, standardized media types:

  • application/problem+json (RFC 9457): Standardized error structure supported out of the box in Spring Boot 3 via ProblemDetail.
  • application/merge-patch+json (RFC 7386): Identifies declarative delta updates for PATCH operations.
  • application/json-patch+json (RFC 6902): Identifies atomic transactional mutation instruction arrays.
  • application/vnd.company.user.v2+json: Vendor-specific media types for schema versioning via Content Negotiation.

High-Throughput Binary Serialization (Protobuf, Avro, CBOR)

In latency-critical microservice backplanes, swapping application/json for binary MIME formats reduces egress bandwidth by $50\%\text{–}80\%$ and accelerates serialization by $5\times\text{–}10\times$ by eliminating string tokenization:

  • application/x-protobuf: Google Protocol Buffers with compiled binary schemas.
  • application/avro: Apache Avro with embedded schema registries.
  • application/cbor: Concise Binary Object Representation (RFC 8949).

Production Spring Boot 3 Implementation: Multipart File & JSON Ingestion

package com.example.controller;

import com.example.dto.DocumentMetadataDto;
import com.example.service.DocumentService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@RestController
@RequestMapping("/api/v1/documents")
public class DocumentUploadController {

    private final DocumentService documentService;

    public DocumentUploadController(DocumentService documentService) {
        this.documentService = documentService;
    }

    // Consumes mixed multipart/form-data containing JSON metadata and binary file
    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<Void> uploadDocument(
            @RequestPart("metadata") DocumentMetadataDto metadata,
            @RequestPart("file") MultipartFile file) throws IOException {

        // Validate internal payload Content-Type
        String fileContentType = file.getContentType();
        if (fileContentType == null || !fileContentType.equals(MediaType.APPLICATION_PDF_VALUE)) {
            return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).build(); // 415
        }

        documentService.save(metadata, file.getBytes());
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }
}

4 Tricky Questions

1. What HTTP status code must the server return if a client sends an XML payload to an endpoint that consumes only JSON?

Answer: The server must return 415 Unsupported Media Type.

  • Returning 400 Bad Request in this situation is a protocol error: the request is not necessarily syntactically corrupt; rather, the server does not support the declared Content-Type format.
  • Returning 415 clearly indicates to the client that it must transcode its payload into an accepted format (e.g., application/json).

2. Why is the boundary parameter required in the Content-Type of a multipart/form-data request?

Answer: A multipart/form-data request encapsulates multiple distinct entities (e.g., text form fields, JSON metadata, and binary file byte streams) within a single continuous HTTP TCP connection.

  • The boundary parameter defines an unambiguous, unique character string acting as a delimiter between parts.
  • The receiving server relies on this exact boundary marker to split the stream and pass each sub-payload to its respective parser.

3. Is specifying charset=utf-8 mandatory for application/json?

Answer: No. Under RFC 8259 Section 8.1, JSON text exchanged between systems must be encoded in UTF-8 by specification default.

  • Appending ; charset=utf-8 to application/json is redundant and discouraged by modern IETF standards.
  • In contrast, text formats such as text/plain, text/csv, or text/html require explicit charset declaration; otherwise, receivers may default to ISO-8859-1, corrupting non-ASCII characters.

4. What is MIME Sniffing, and what security vulnerability does X-Content-Type-Options: nosniff prevent?

Answer: MIME Sniffing is an algorithmic feature where browsers inspect the initial byte stream of a response to infer its format, overriding the server’s declared Content-Type.

  • The Exploit: An attacker uploads a file named avatar.png containing malicious JavaScript. If served by a vulnerable server, the browser sniffs the script tags and executes the payload as HTML/JS, causing Cross-Site Scripting (XSS).
  • The Protection: Supplying X-Content-Type-Options: nosniff strictly disables browser sniffing, ensuring the browser treats the file solely as the declared MIME type.

🎯 Interview Cheat Sheet

30-Second Elevator Pitch

Content-Type (RFC 9110) is an entity header declaring the media format (MIME type) of the payload transmitted in the HTTP request or response body. It guides the recipient on which deserializer to invoke (e.g., Jackson for application/json).

Unlike Accept (which states what format is expected in return), Content-Type states what is being sent right now.

In Spring MVC, it drives HttpMessageConverter selection; an unsupported type returns 415 Unsupported Media Type. In production, security requires attaching X-Content-Type-Options: nosniff to prevent MIME-sniffing XSS attacks.


Red Flags (What NOT to Say)

  • ❌ “Content-Type and Accept are synonyms.” (Content-Type describes the sent body; Accept requests the response format).
  • ❌ “GET requests must include Content-Type: application/json.” (Requests without a body must not include a Content-Type header).
  • ❌ “If a client sends an unsupported media type, the server should guess the format.” (The server must return 415 Unsupported Media Type).
  • ❌ “X-Content-Type-Options: nosniff improves JSON parsing speed.” (It is a security header designed to eliminate MIME sniffing XSS attacks).