A Python WSGI middleware for HTTP method override functionality
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file method_override-0.3.0.tar.gz.
File metadata
- Download URL: method_override-0.3.0.tar.gz
- Upload date:
- Size: 6.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.11.13 Linux/6.11.0-1015-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
231994c736875c7959ba03b8120be7de2be3d6be344725b92888972d827bd16e
|
|
| MD5 |
bde21036ab149396b220778f7dd3a083
|
|
| BLAKE2b-256 |
e93d5b8083166cb211e74466839dd65cc0e08f5277b85d385518fc3a318cb113
|
File details
Details for the file method_override-0.3.0-py3-none-any.whl.
File metadata
- Download URL: method_override-0.3.0-py3-none-any.whl
- Upload date:
- Size: 7.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.11.13 Linux/6.11.0-1015-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc521bcb5f7cf91c6d7420320065d171e619fdc181e5e965cbaa37a98ceb945c
|
|
| MD5 |
55ec1f4d93e7eaa1c556c56657988aa6
|
|
| BLAKE2b-256 |
255d8b7355c608ec1ddeab3a15fbaeedcf8e015dfb5d1c0b148c5ea1e58f1f51
|