> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Type

> Content-Type validation and enforcement middleware.

## Overview

The `contenttype` middleware validates and enforces Content-Type headers on requests. It ensures requests have the expected content type and can set default content types for responses.

Use it when you need:

* JSON-only API endpoints
* Form submission validation
* Content-Type enforcement
* Default response types

## Installation

```go theme={null}
import "github.com/go-mizu/mizu/middlewares/contenttype"
```

## Quick Start

```go theme={null}
app := mizu.New()

// Require JSON for all POST/PUT/PATCH requests
app.Use(contenttype.RequireJSON())
```

## Functions

### Request Validation

| Function            | Description                    |
| ------------------- | ------------------------------ |
| `Require(types...)` | Require specific content types |
| `RequireJSON()`     | Require `application/json`     |
| `RequireForm()`     | Require form content types     |
| `Default(type)`     | Set default if missing         |

### Response Headers

| Function            | Description               |
| ------------------- | ------------------------- |
| `SetResponse(type)` | Set response Content-Type |

## Examples

### Require JSON

```go theme={null}
// Only accept JSON requests
app.Use(contenttype.RequireJSON())

app.Post("/api/users", func(c *mizu.Ctx) error {
    // Guaranteed to receive JSON
    var user User
    if err := c.BindJSON(&user); err != nil {
        return err
    }
    return c.JSON(201, user)
})
```

### Require Form Data

```go theme={null}
// Only accept form submissions
app.Post("/contact", contactHandler, contenttype.RequireForm())
```

### Multiple Content Types

```go theme={null}
// Accept either JSON or XML
app.Use(contenttype.Require("application/json", "application/xml"))
```

### Set Default Content-Type

```go theme={null}
// Set default for requests without Content-Type
app.Use(contenttype.Default("application/json"))
```

### Set Response Content-Type

```go theme={null}
// All responses are JSON
app.Use(contenttype.SetResponse("application/json; charset=utf-8"))
```

### Per-Route Configuration

```go theme={null}
// API routes: JSON only
api := app.Group("/api")
api.Use(contenttype.RequireJSON())

// Form routes: Form data only
forms := app.Group("/forms")
forms.Use(contenttype.RequireForm())
```

### Combined Request/Response

```go theme={null}
// Require JSON input, set JSON output
app.Use(contenttype.RequireJSON())
app.Use(contenttype.SetResponse("application/json; charset=utf-8"))
```

## API Reference

### Functions

```go theme={null}
// Require specific content types
func Require(types ...string) mizu.Middleware

// RequireJSON requires application/json
func RequireJSON() mizu.Middleware

// RequireForm requires form content types
func RequireForm() mizu.Middleware

// Default sets default Content-Type if not present
func Default(contentType string) mizu.Middleware

// SetResponse sets response Content-Type
func SetResponse(contentType string) mizu.Middleware
```

## Behavior

* Only validates POST, PUT, PATCH requests (methods with bodies)
* Compares media type only, ignores parameters (charset, boundary)
* Returns 415 Unsupported Media Type on validation failure

## Common Content Types

| Type                                | Description      |
| ----------------------------------- | ---------------- |
| `application/json`                  | JSON data        |
| `application/xml`                   | XML data         |
| `application/x-www-form-urlencoded` | URL-encoded form |
| `multipart/form-data`               | File uploads     |
| `text/plain`                        | Plain text       |

## Technical Details

### Implementation Overview

The contenttype middleware provides Content-Type validation and enforcement through a set of middleware functions that operate on request and response headers.

#### Request Validation (`Require`, `RequireJSON`, `RequireForm`)

The validation middleware follows these steps:

1. **Method Filtering**: Only validates requests with body content (POST, PUT, PATCH). GET, DELETE, and other methods bypass validation.

2. **Header Extraction**: Retrieves the Content-Type header from the incoming request.

3. **Media Type Parsing**: Extracts the base media type by:
   * Finding the semicolon separator (if present)
   * Stripping parameters (charset, boundary, etc.)
   * Trimming whitespace from the result

4. **Case-Insensitive Matching**: Compares the extracted media type against allowed types using case-insensitive comparison.

5. **Error Response**: Returns HTTP 415 (Unsupported Media Type) if:
   * Content-Type header is missing (for methods that require it)
   * The media type doesn't match any allowed types

#### Default Content-Type (`Default`)

Sets a default Content-Type header on the request if none is present. This middleware:

* Checks if the Content-Type header exists
* Sets the header to the specified default value if missing
* Preserves existing headers without modification

#### Response Content-Type (`SetResponse`)

Sets the Content-Type header on the response. This middleware:

* Unconditionally sets the response Content-Type header
* Executes before the handler processes the request
* Can be combined with request validation middleware

### Key Design Decisions

* **Parameter Stripping**: Media type parameters are ignored during validation, allowing `application/json; charset=utf-8` to match `application/json`
* **Method-Specific**: Only methods with request bodies are validated
* **Fail-Fast**: Validation happens before the handler executes
* **Composable**: Multiple middleware can be chained for complex scenarios

## Best Practices

* Use `RequireJSON()` for REST APIs
* Use `RequireForm()` for traditional forms
* Set response Content-Type for consistency
* Combine `Default()` with `Require()` to provide fallback behavior
* Apply validation at the router group level for route-specific rules

## Testing

The contenttype middleware includes comprehensive test coverage for all functions and edge cases.

### Test Cases

| Test Case                    | Description                                                      | Expected Behavior                                                        |
| ---------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------ |
| **Require Middleware**       |                                                                  |                                                                          |
| Allows matching content type | POST request with `application/json` header                      | Request proceeds (200 OK)                                                |
| Allows with charset          | POST request with `application/json; charset=utf-8`              | Request proceeds (200 OK), parameters ignored                            |
| Rejects wrong content type   | POST request with `application/xml` header (not in allowed list) | Returns 415 Unsupported Media Type                                       |
| Rejects missing content type | POST request without Content-Type header                         | Returns 415 Unsupported Media Type                                       |
| Skips GET requests           | GET request without Content-Type header                          | Request proceeds (200 OK), validation skipped                            |
| **RequireJSON Middleware**   |                                                                  |                                                                          |
| Allows JSON                  | POST request with `application/json` header                      | Request proceeds (200 OK)                                                |
| Rejects form                 | POST request with `application/x-www-form-urlencoded` header     | Returns 415 Unsupported Media Type                                       |
| **RequireForm Middleware**   |                                                                  |                                                                          |
| Allows form-urlencoded       | POST request with `application/x-www-form-urlencoded` header     | Request proceeds (200 OK)                                                |
| Allows multipart             | POST request with `multipart/form-data; boundary=----` header    | Request proceeds (200 OK)                                                |
| **Default Middleware**       |                                                                  |                                                                          |
| Sets default when missing    | POST request without Content-Type header                         | Request header set to `application/json`                                 |
| Preserves existing           | POST request with `text/plain` header                            | Existing header preserved as `text/plain`                                |
| **SetResponse Middleware**   |                                                                  |                                                                          |
| Sets response Content-Type   | GET request to endpoint with SetResponse middleware              | Response includes `Content-Type: application/json; charset=utf-8` header |

## Related Middlewares

* [bodylimit](/middlewares/bodylimit) - Body size limits
* [validator](/middlewares/validator) - Request validation
