Method Override Middleware
Method override middleware that allows HTML forms to simulate PUT, PATCH, and DELETE requests using a hidden form field.
Installation
Function
methodOverride()
Creates middleware that overrides context.method with the value of the method override field.
Signature:
function methodOverride(options?: MethodOverrideOptions): Middleware
Parameters:
options - Optional method override settings
Returns: A middleware that overrides context.method with the value of the method override field.
This middleware must be placed after the formData middleware in the middleware chain, or some other middleware that provides context.get(FormData).
Options
MethodOverrideOptions
interface MethodOverrideOptions {
fieldName?: string
}
fieldName
The name of the form field to check for request method override.
- Type:
string
- Default:
'_method'
Basic Usage
import { createRouter } from 'remix/fetch-router'
import { formData } from 'remix/form-data-middleware'
import { methodOverride } from 'remix/method-override-middleware'
let router = createRouter({
// methodOverride must come AFTER formData middleware
middleware: [formData(), methodOverride()],
})
router.delete('/users/:id', async (context) => {
let userId = context.params.id
// Delete user logic...
return new Response('User deleted')
})
HTML Form:
<form method="POST" action="/users/123">
<input type="hidden" name="_method" value="DELETE" />
<button type="submit">Delete User</button>
</form>
Custom Field Name
import { createRouter } from 'remix/fetch-router'
import { formData } from 'remix/form-data-middleware'
import { methodOverride } from 'remix/method-override-middleware'
let router = createRouter({
middleware: [formData(), methodOverride({ fieldName: '__method__' })],
})
HTML Form:
<form method="POST" action="/users/123">
<input type="hidden" name="__method__" value="PUT" />
<button type="submit">Update User</button>
</form>
RESTful CRUD Example
import { createRouter } from 'remix/fetch-router'
import { formData } from 'remix/form-data-middleware'
import { methodOverride } from 'remix/method-override-middleware'
let router = createRouter({
middleware: [formData(), methodOverride()],
})
// Create
router.post('/posts', async (context) => {
let data = context.get(FormData)
let title = data.get('title')
let content = data.get('content')
// Create post...
return new Response('Post created', { status: 201 })
})
// Update
router.put('/posts/:id', async (context) => {
let postId = context.params.id
let data = context.get(FormData)
// Update post...
return new Response('Post updated')
})
// Partial update
router.patch('/posts/:id', async (context) => {
let postId = context.params.id
let data = context.get(FormData)
// Partially update post...
return new Response('Post updated')
})
// Delete
router.delete('/posts/:id', async (context) => {
let postId = context.params.id
// Delete post...
return new Response('Post deleted')
})
HTML Forms:
<!-- Update form -->
<form method="POST" action="/posts/123">
<input type="hidden" name="_method" value="PUT" />
<input type="text" name="title" value="My Post" />
<textarea name="content">Post content here</textarea>
<button type="submit">Update Post</button>
</form>
<!-- Delete form -->
<form method="POST" action="/posts/123">
<input type="hidden" name="_method" value="DELETE" />
<button type="submit">Delete Post</button>
</form>
How It Works
- Browser submits a POST request with the form data
formData middleware parses the form data
methodOverride middleware reads the _method field value
- If the value is a valid HTTP method (GET, POST, PUT, PATCH, DELETE, etc.), it overrides
context.method
- Router matches the request to the appropriate handler based on the overridden method
Supported Methods
The middleware supports all standard HTTP methods:
- GET
- POST
- PUT
- PATCH
- DELETE
- HEAD
- OPTIONS