Question 16 · Section 6

What is Content-Type header?

The server needs to know how to read data from the request. Without Content-Type, the server won't know how to deserialize the bytes.

Language versions: English Russian Ukrainian

Junior Level

Content-Type is an HTTP header that tells the server in what format the data is being sent.

Examples:

Content-Type: application/json        — data in JSON format
Content-Type: application/xml         — data in XML format
Content-Type: text/plain              — plain text
Content-Type: multipart/form-data     — form with files

Why is this needed?

The server needs to know how to read data from the request. Without Content-Type, the server won’t know how to deserialize the bytes.

Request example:

POST /users
Content-Type: application/json

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

Common media types:

| Type | Description | | ———————————– | —————– | | application/json | JSON data | | application/xml | XML data | | text/html | HTML page | | multipart/form-data | Form with files | | application/x-www-form-urlencoded | Form data |


Middle Level

Content-Type in Spring MVC

HttpMessageConverter is responsible for handling Content-Type:

  1. Request arrives with Content-Type: application/json
  2. Spring iterates through converters (Jackson, Gson, etc.)
  3. The canRead(clazz, mediaType) method returns true
  4. Reading and mapping to a Java object begins

Security and MIME Sniffing

X-Content-Type-Options: nosniff

Browsers sometimes try to “guess” the content type, ignoring the header. MIME Sniffing — a browser mechanism: it tries to determine content type by content, ignoring Content-Type. Useful for backward compatibility, but creates XSS vulnerabilities.

Risk: A user uploaded an image that is actually JavaScript. The browser may execute it.

Solution: Always return X-Content-Type-Options: nosniff.

Boundary in Multipart

With multipart/form-data, the header contains a unique delimiter:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

This delimiter is used to parse the request body into separate parts.

Edge Cases

  • Missing Content-Type: If the client didn’t send the header — return 415 Unsupported Media Type. Don’t try to guess the type
  • Custom MIME Types: For versioning, use your own types: application/vnd.mycompany.v1+json

Performance

  • Charset: For application/json, UTF-8 is the default per RFC 8259, so charset=utf-8 is optional. For text/* types, specifying charset is mandatory, as the default is iso-8859-1.
  • Binary Formats: In Highload systems, application/x-protobuf or application/octet-stream is used — Protobuf is typically 3-10x faster than JSON for parsing (depends on payload size and language). Binary format doesn’t require lexical parsing, no string-key parsing — numeric field tags.

Senior Level

When Content-Type can be omitted

GET requests without a body, DELETE without a body. For requests with a body (POST, PUT, PATCH) — it’s mandatory.

Converter selection process

In Spring MVC, HttpMessageConverter is selected based on:

  1. The Content-Type header from the request
  2. Registered converters in the application
  3. The canRead(clazz, mediaType) method

Multipart/Related vs Multipart/Form-Data

  • Multipart/Form-Data: For uploading files via forms
  • Multipart/Related: When you need to send an object (JSON) and a related binary file (image) in a single request. More efficient than two separate requests

Performance and Highload

  • Charset Overhead: Specifying encoding prevents proxies from attempting to re-encode text
  • Binary Formats: Protobuf is typically 3-10x faster than JSON for parsing (depends on payload size and language). Binary format doesn’t require lexical parsing, no string-key parsing — numeric field tags.
  • Multipart/Related: More efficient for sending JSON + binary file in a single request

Diagnostics

  • Curl Debugging: curl -v -H "Content-Type: application/json" -d '{"key":"val"}' ... — the basics for API diagnostics
  • Postman/Insomnia Pitfalls: These tools often add Content-Type automatically. When testing a “raw” API, disable auto-fill
  • 415 Unsupported Media Type: If the server doesn’t support the sent type — return 415, don’t try to guess

Interview Cheat Sheet

Must know:

  • Content-Type tells the server the format of data in the request body: application/json, application/xml, multipart/form-data
  • Content-Type is mandatory for requests with a body (POST, PUT, PATCH); not needed for GET/DELETE without body
  • In Spring MVC, HttpMessageConverter handles processing (Jackson, Gson, etc.)
  • X-Content-Type-Options: nosniff prevents MIME Sniffing and XSS attacks
  • multipart/form-data uses a boundary delimiter to parse the body into parts
  • Missing Content-Type → return 415 Unsupported Media Type, don’t guess
  • Binary Formats (Protobuf) are 3-10x faster than JSON for parsing

Common follow-up questions:

  • Why is X-Content-Type-Options: nosniff needed? — Prevents MIME Sniffing, where the browser “guesses” the type and executes JS
  • How does Spring choose a converter? — By request Content-Type → checks canRead(clazz, mediaType) → first match
  • When can Content-Type be omitted? — For GET and DELETE without body; for POST/PUT/PATCH — mandatory
  • What is Multipart/Related? — Sending JSON + related binary file in one request, more efficient than two requests

Red flags (DO NOT say):

  • “Content-Type and Accept are the same” — Content-Type = what I’m sending, Accept = what I want to receive
  • “Content-Type is needed for GET requests” — GET without body doesn’t require Content-Type
  • “The server can guess the content type” — should return 415, not guess
  • “charset=utf-8 is mandatory for JSON” — UTF-8 is the default per RFC 8259, optional

Related topics:

  • [[What is Accept header]]
  • [[How to organize REST API versioning]]
  • [[What is REST]]
  • [[What HTTP status codes do you know]]
  • [[What is RESTful API design]]