Skip to content

HTTP Methods API

The methods module defines constants and helper functions for handling HTTP methods in Plinx applications. This module provides a clean way to work with HTTP methods throughout your application.

HTTP Method Constants

plinx.methods.HTTPMethods

Bases: Enum

Enumeration of HTTP methods supported by the Plinx framework.

This enum defines the standard HTTP methods as defined in RFC 7231 and RFC 5789, categorized by their safety and idempotency properties.

Safe methods (should not modify resources): - GET: Retrieve a representation of a resource - HEAD: Same as GET but returns only headers, no body

Idempotent methods (multiple identical requests have same effect as single request): - PUT: Replace a resource with the request payload - DELETE: Remove the specified resource - OPTIONS: Describe the communication options for the target resource

Non-idempotent methods (multiple identical requests may have different effects): - POST: Submit data to be processed, typically creating a new resource - PATCH: Apply partial modifications to a resource

Usage
from plinx.methods import HTTPMethods

# Check if a method is GET
if method == HTTPMethods.GET:
    # handle GET request

# Get the string value of a method
method_str = HTTPMethods.POST.value  # "POST"
Source code in plinx/methods.py
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class HTTPMethods(Enum):
    """
    Enumeration of HTTP methods supported by the Plinx framework.

    This enum defines the standard HTTP methods as defined in RFC 7231 and RFC 5789,
    categorized by their safety and idempotency properties.

    Safe methods (should not modify resources):
    - GET: Retrieve a representation of a resource
    - HEAD: Same as GET but returns only headers, no body

    Idempotent methods (multiple identical requests have same effect as single request):
    - PUT: Replace a resource with the request payload
    - DELETE: Remove the specified resource
    - OPTIONS: Describe the communication options for the target resource

    Non-idempotent methods (multiple identical requests may have different effects):
    - POST: Submit data to be processed, typically creating a new resource
    - PATCH: Apply partial modifications to a resource

    Usage:
        ```python
        from plinx.methods import HTTPMethods

        # Check if a method is GET
        if method == HTTPMethods.GET:
            # handle GET request

        # Get the string value of a method
        method_str = HTTPMethods.POST.value  # "POST"
        ```
    """

    # Safe methods
    GET = "GET"
    HEAD = "HEAD"

    # Idempotent methods
    PUT = "PUT"
    DELETE = "DELETE"
    OPTIONS = "OPTIONS"

    # Non-idempotent methods
    POST = "POST"
    PATCH = "PATCH"

Method Handling Functions

plinx.methods.is_valid_method(method)

Check if the given method is a valid HTTP method.

Parameters:

Name Type Description Default
method str

The HTTP method to check

required

Returns:

Name Type Description
bool bool

True if the method is valid, False otherwise

Source code in plinx/methods.py
51
52
53
54
55
56
57
58
59
60
61
def is_valid_method(method: str) -> bool:
    """
    Check if the given method is a valid HTTP method.

    Args:
        method: The HTTP method to check

    Returns:
        bool: True if the method is valid, False otherwise
    """
    return method in HTTPMethods.__members__.values()

plinx.methods.get_handler_name_for_method(method)

Get the handler name for a given HTTP method.

Parameters:

Name Type Description Default
method str

The HTTP method to get the handler name for

required

Returns:

Name Type Description
str str

The handler name corresponding to the HTTP method

Source code in plinx/methods.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def get_handler_name_for_method(method: str) -> str:
    """
    Get the handler name for a given HTTP method.

    Args:
        method: The HTTP method to get the handler name for

    Returns:
        str: The handler name corresponding to the HTTP method
    """
    if not is_valid_method(method):
        raise ValueError(f"Invalid HTTP method: {method}")

    return method.lower()

Examples

Checking for Valid HTTP Methods

from plinx.methods import is_valid_method

# Check if a method is supported
if is_valid_method("GET"):
    print("GET is a valid HTTP method")

if not is_valid_method("CUSTOM"):
    print("CUSTOM is not a valid HTTP method")

Working with HTTP Method Constants

from plinx import Plinx
from plinx.methods import HTTPMethods

app = Plinx()

@app.route("/example")
def handler(request, response):
    if request.method == HTTPMethods.GET:
        response.text = "This is a GET request"
    elif request.method == HTTPMethods.POST:
        response.text = "This is a POST request"
    else:
        response.text = f"This is a {request.method} request"

Finding Handler Method Names

from plinx.methods import get_handler_name_for_method

# For class-based views, this function maps HTTP methods to method names
handler_name = get_handler_name_for_method("GET")  # Returns "get"
handler_name = get_handler_name_for_method("POST")  # Returns "post"

Method Handling in Class-Based Views

In class-based views, HTTP methods are automatically mapped to methods with lowercase names:

from plinx import Plinx

app = Plinx()

@app.route("/resource")
class ResourceHandler:
    def get(self, request, response):
        response.text = "Handling GET request"

    def post(self, request, response):
        response.text = "Handling POST request"

    def put(self, request, response):
        response.text = "Handling PUT request"

    def delete(self, request, response):
        response.text = "Handling DELETE request"

    def patch(self, request, response):
        response.text = "Handling PATCH request"

    def head(self, request, response):
        # HEAD requests don't return a body
        pass

    def options(self, request, response):
        response.headers["Allow"] = "GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS"

When a request comes in, Plinx will call the appropriate method based on the HTTP method of the request.

Custom Method Handlers

You can implement custom method handling by overriding the default behavior:

from plinx import Plinx
from plinx.methods import get_handler_name_for_method

# Custom function to map HTTP methods to handler names
def custom_method_mapper(method):
    method_map = {
        "GET": "handle_get",
        "POST": "handle_post",
        "PUT": "handle_put",
        "DELETE": "handle_delete"
    }
    return method_map.get(method, "handle_default")

app = Plinx()

@app.route("/custom")
class CustomMethodHandler:
    def handle_get(self, request, response):
        response.text = "Custom GET handler"

    def handle_post(self, request, response):
        response.text = "Custom POST handler"

    def handle_put(self, request, response):
        response.text = "Custom PUT handler"

    def handle_delete(self, request, response):
        response.text = "Custom DELETE handler"

    def handle_default(self, request, response):
        response.text = f"Default handler for {request.method}"

    # Override the default method handling
    def __getattr__(self, name):
        if name == get_handler_name_for_method(request.method):
            # Use our custom mapper instead
            handler_name = custom_method_mapper(request.method)
            return getattr(self, handler_name)
        raise AttributeError(f"{self.__class__.__name__} has no attribute {name}")

Method Not Allowed Handling

Plinx automatically handles requests with methods not supported by your handler:

from plinx import Plinx

app = Plinx()

@app.route("/limited")
class LimitedHandler:
    def get(self, request, response):
        response.text = "GET is allowed"

    # No other methods defined
    # POST, PUT, etc. will receive a 405 Method Not Allowed response

# For function handlers, the default behavior allows all methods
@app.route("/allow-all")
def all_methods_handler(request, response):
    response.text = f"Handling {request.method} request"

Method Override

Sometimes it's useful to override the HTTP method, especially when working with HTML forms that only support GET and POST:

from plinx import Plinx
from plinx.middleware import Middleware

class MethodOverrideMiddleware(Middleware):
    def process_request(self, request):
        # Check for X-HTTP-Method-Override header
        override = request.headers.get("X-HTTP-Method-Override")

        # Check for _method form field (common in HTML forms)
        if not override and request.method == "POST":
            override = request.POST.get("_method")

        # Override the method if specified
        if override and override.upper() in ["PUT", "DELETE", "PATCH"]:
            request.method = override.upper()

app = Plinx()
app.add_middleware(MethodOverrideMiddleware)

This allows HTML forms to simulate PUT, DELETE, and PATCH requests by including a form field named _method or by setting the X-HTTP-Method-Override header.

Best Practices

  1. Use HTTP methods semantically: Follow RESTful conventions (GET for retrieval, POST for creation, etc.)
  2. Handle OPTIONS requests: Especially important for CORS support
  3. Return appropriate status codes: 405 Method Not Allowed for unsupported methods
  4. Support idempotent methods: GET, PUT, and DELETE should be idempotent
  5. Consider method overrides: If supporting HTML forms that can only use GET and POST
  6. Document supported methods: Make it clear which methods are supported by each endpoint