Skip to main content

Overview

The methodoverride middleware allows HTML forms to use HTTP methods other than GET and POST. Since HTML forms only support GET and POST, this middleware lets you override the method using a header or form field.

Installation

import "github.com/go-mizu/mizu/middlewares/methodoverride"

Quick Start

app := mizu.New()
app.Use(methodoverride.New())

Configuration

OptionTypeDefaultDescription
Headerstring"X-HTTP-Method-Override"Override header
FormFieldstring"_method"Form field name
Methods[]string["PUT", "PATCH", "DELETE"]Allowed override methods

Examples

HTML Form with PUT

<form method="POST" action="/users/123">
    <input type="hidden" name="_method" value="PUT">
    <input type="text" name="name" value="John">
    <button type="submit">Update</button>
</form>
app.Use(methodoverride.New())
app.Put("/users/:id", updateUser)  // Handles the form above

DELETE via Form

<form method="POST" action="/users/123">
    <input type="hidden" name="_method" value="DELETE">
    <button type="submit">Delete</button>
</form>

Header Override (AJAX)

fetch('/users/123', {
    method: 'POST',
    headers: {
        'X-HTTP-Method-Override': 'PUT',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({name: 'John'})
});

Custom Configuration

app.Use(methodoverride.WithOptions(methodoverride.Options{
    Header:    "X-Method",
    FormField: "method",
    Methods:   []string{"PUT", "DELETE"}, // Only allow PUT/DELETE
}))

How It Works

  1. Only processes POST requests
  2. Checks header, then query, then form field for override value
  3. If valid method found, changes request method
  4. Subsequent handlers see the overridden method

API Reference

func New() mizu.Middleware
func WithOptions(opts Options) mizu.Middleware

Technical Details

Implementation Overview

The method override middleware works by intercepting POST requests and checking for method override indicators in the following priority order:
  1. Header Check: First checks the override header (default: X-HTTP-Method-Override)
  2. Query Parameter: If no header is found, checks the query parameter with the form field name
  3. Form Field: For form submissions (content types application/x-www-form-urlencoded or multipart/form-data), checks the form field value

Method Validation

  • Override values are converted to uppercase for case-insensitive matching
  • Only methods specified in the Methods configuration are allowed (default: PUT, PATCH, DELETE)
  • Invalid or disallowed methods are silently ignored, leaving the original POST method intact
  • The allowed methods are stored in a map for O(1) lookup performance

Request Processing

The middleware only processes POST requests. Any other HTTP method (GET, PUT, DELETE, etc.) passes through unchanged, even if override headers or parameters are present. This prevents potential security issues from unexpected method changes.

Content Type Handling

Form field checking only occurs when the request has an appropriate content type:
  • application/x-www-form-urlencoded
  • multipart/form-data
This ensures form parsing is only attempted for actual form submissions, avoiding unnecessary processing for JSON or other content types.

Best Practices

Use CSRF Protection

Always combine method override with CSRF protection when handling form submissions:
app.Use(csrf.New())
app.Use(methodoverride.New())

Restrict Allowed Methods

Only enable the HTTP methods your application actually needs:
app.Use(methodoverride.WithOptions(methodoverride.Options{
    Methods: []string{"PUT", "DELETE"}, // Exclude PATCH if not needed
}))

Header Priority

When using AJAX requests, prefer the header approach for cleaner code and better separation from form data.

Testing

The middleware includes comprehensive test coverage for all override scenarios:
Test CaseDescriptionExpected Behavior
Header OverridePOST request with X-HTTP-Method-Override: PUT headerMethod changed to PUT
Query OverridePOST request with ?_method=DELETE query parameterMethod changed to DELETE
Form OverridePOST request with _method=PATCH form fieldMethod changed to PATCH
Non-POST IgnoredGET request with override headerMethod remains GET, override ignored
Invalid MethodPOST request with X-HTTP-Method-Override: INVALIDMethod remains POST, invalid override ignored
Custom HeaderPOST request with custom header name (X-Method: PUT)Method changed to PUT using custom header
Custom Methods - AllowedPOST request with allowed custom method (GET)Method changed to GET
Custom Methods - BlockedPOST request with non-allowed method (DELETE) when only GET/HEAD allowedMethod remains POST
Case InsensitivePOST request with lowercase override value (delete)Method changed to DELETE (uppercase)

Security Notes

  • Only POST requests can be overridden
  • Only allowed methods (PUT, PATCH, DELETE by default) can be used
  • Use with CSRF protection for forms
  • csrf - Form protection