Method Override Middleware
A Python WSGI middleware that allows HTTP method override via form parameters or headers. This enables HTML forms to use HTTP methods other than GET and POST by providing a method override mechanism.
Features
- 🔄 Override HTTP methods via form parameters (
_method) or custom headers - 🛡️ Security-focused: Only allows overrides from POST requests
- 🎯 Configurable allowed methods and parameters
- 📝 Comprehensive logging for debugging and monitoring
- 🚀 Compatible with any WSGI application (Flask). Coming soon Django, FastAPI and etc
- ⚡ Zero dependencies - uses only Python standard library
Installation
Install using pip:
pip install method-override
Or using Poetry:
poetry add method-override
Quick Start
Basic Usage
from method_override import MethodOverrideMiddleware
# Wrap your WSGI application
app = MethodOverrideMiddleware(your_wsgi_app)
Flask Example
from flask import Flask
from method_override import MethodOverrideMiddleware
app = Flask(__name__)
# Apply the middleware
app.wsgi_app = MethodOverrideMiddleware(app.wsgi_app)
@app.put('/users/<int:user_id>')
def edit_user(user_id):
return f"Updating user {user_id}"
@app.delete('/users/<int:user_id>')
def delete_user(user_id):
return f"Deleting user {user_id}"
HTML Form Usage
<!-- HTML forms can now use PUT, PATCH, DELETE methods -->
<form method="POST" action="/users/123">
<input type="hidden" name="_method" value="PUT">
<input type="text" name="name" placeholder="User name">
<button type="submit">Update User</button>
</form>
<form method="POST" action="/users/123">
<input type="hidden" name="_method" value="DELETE">
<button type="submit">Delete User</button>
</form>
AJAX/Header Usage
// You can also use the X-HTTP-Method-Override header
fetch('/users/123', {
method: 'POST',
headers: {
'X-HTTP-Method-Override': 'PUT',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John Doe' })
});
Configuration
Advanced Configuration
from method_override import MethodOverrideMiddleware
app = MethodOverrideMiddleware(
your_wsgi_app,
allowed_methods=['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], # Allowed override methods
bodyless_methods=['GET', 'HEAD', 'OPTIONS', 'DELETE'], # Methods without body
override_param='_method', # Form parameter name
header_override='X-HTTP-Method-Override' # Header name for override
)
Configuration Options
| Parameter | Type | Default | Description |
|---|---|---|---|
allowed_methods |
Iterable[str] |
['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] |
HTTP methods that can be used as overrides |
bodyless_methods |
Iterable[str] |
['GET', 'HEAD', 'OPTIONS', 'DELETE'] |
Methods that should not have a request body |
override_param |
str |
'_method' |
Form parameter name used for method override |
header_override |
str |
'X-HTTP-Method-Override' |
HTTP header name for method override |
Security
This middleware implements several security measures:
- POST-only overrides: Method override is only allowed from POST requests
- Whitelist approach: Only explicitly allowed methods can be used as overrides
- No self-override: Cannot override a method to itself
- Body handling: Automatically removes body content for bodyless methods
How It Works
- The middleware intercepts incoming WSGI requests
- Checks if the original request method is POST
- Looks for override method in:
- HTTP headers (
X-HTTP-Method-Overrideby default) - checked first for performance - Form data (
_methodparameter by default) - only for POST requests
- HTTP headers (
- Validates the override method against allowed methods
- Updates the
REQUEST_METHODin the WSGI environ - Handles body content appropriately for bodyless methods
Technical Implementation
The middleware uses a clean, zero-dependency approach:
- Direct WSGI environ manipulation: No external dependencies required
- Stream handling: Carefully reads and reconstructs the request body stream to avoid conflicts
- Header parsing: Efficiently extracts HTTP headers from WSGI environ variables
- Form parsing: Uses Python's built-in
urllib.parse.parse_qsfor form data processing - Error resilience: Gracefully handles malformed requests without breaking the application
Use Cases
- RESTful APIs: Enable full REST verb support in HTML forms
- Legacy browser support: Support for older browsers that only support GET/POST
- Form-based applications: Build rich web applications with proper HTTP semantics
- API consistency: Maintain consistent API design across different client types
Development
Setup
# Clone the repository
git clone https://github.com/marcuxyz/method-override.git
cd method-override
# Install dependencies
poetry install
Running Tests
# Run tests
poetry run pytest
# Run tests with coverage
poetry run pytest --cov=src/wsgi_method_override
Code Formatting
# Format code
poetry run black .
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
v0.3.0
- 📦 Better Package Name: Renamed from
wsgi-method-overridetomethod-overridefor better discoverability
v0.2.1
- 🚀 Zero Dependencies: Completely removed Werkzeug dependency - now uses only Python standard library
- 🧹 Code Simplification: Major refactor for better readability and maintainability
- 🐛 Bug Fix: Resolved browser hanging issue when accessing
request.formin WSGI applications - ⚡ Performance: Faster form parsing with direct stream handling
- 📖 Better Documentation: Improved code comments and documentation in Portuguese for better understanding
- 🔧 Improved Error Handling: More robust error handling with graceful fallbacks
- 🎯 Cleaner API: Simplified internal methods with clear, descriptive names
- 💡 Better Debugging: Enhanced logging for troubleshooting middleware issues
v0.2.0
- Python Compatibility: Expanded Python version support from 3.12.4 to >=3.10.0
- Broader Compatibility: Now supports Python 3.10, 3.11, and 3.12+
- Improved Accessibility: Makes the package available to more users with different Python versions
v0.1.0
- Initial release
- Basic method override functionality
- Support for form parameters and headers
- Comprehensive test suite
- Security measures implemented
Support
If you encounter any issues or have questions, please:
- Check the documentation
- Search existing issues
- Create a new issue if needed
Authors
- Marcus Almeida - Initial work - marcuxyz
Acknowledgments
- Inspired by similar middleware implementations in other web frameworks
- Built with Python standard library for maximum compatibility
- Follows WSGI standards and best practices
Release files for method-override 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| method_override-0.3.0.tar.gz | 6.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| method_override-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.2 kB
Release files / method_override-0.3.0.tar.gz
| Download URL | method_override-0.3.0.tar.gz |
|---|---|
| Size | 6.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
231994c736875c7959ba03b8120be7de2be3d6be344725b92888972d827bd16e
|
|
BLAKE2b-256 checksum How to use checksums |
e93d5b8083166cb211e74466839dd65cc0e08f5277b85d385518fc3a318cb113
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.11.13 Linux/6.11.0-1015-azure
|
Release files / method_override-0.3.0-py3-none-any.whl
| Download URL | method_override-0.3.0-py3-none-any.whl |
|---|---|
| Size | 7.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc521bcb5f7cf91c6d7420320065d171e619fdc181e5e965cbaa37a98ceb945c
|
|
BLAKE2b-256 checksum How to use checksums |
255d8b7355c608ec1ddeab3a15fbaeedcf8e015dfb5d1c0b148c5ea1e58f1f51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.11.13 Linux/6.11.0-1015-azure
|