patx/wred
Release Wred 0.14
Commit a4b5964 · patx · 2026-11-01T01:18:17-04:00
Comments
No comments yet.
Diff
diff --git a/README.md b/README.md
index 62a58ba..09e8c1a 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,9 @@ async def update_user(request, user_id):
Different methods can have separate handlers on the same path. Fixed routes
win over dynamic routes for that method; dynamic routes follow registration
order. Registering the same path and method again replaces its handler.
+
+Path parameters must occupy a whole path segment and cannot span slashes.
+
Trailing slashes are ignored when registering and matching routes: `/users`
and `/users/` use the same handler, without a redirect.
Unmatched paths or methods return JSON 404. No automatic HEAD, OPTIONS, or 405.
@@ -106,12 +109,16 @@ Wred 0.9 uses `request.query()`; remove the parentheses when upgrading.
* `request.path` -> Path without the query string
* `request.method` -> HTTP method
-* `request.headers` -> Header dict decoded and cached on first access, with lowercase ASCII names and Latin-1 values; repeated Cookie fields join with `; `, other repeated names keep their last value
+* `request.headers` -> Header dict decoded and cached on first access, with lowercase ASCII names and Latin-1 values; repeated Cookie fields join with `; `, other repeated names join with `, `
* `request.scope` -> Original ASGI scope, including client, scheme, and middleware state
* `request.query` -> Dict of string keys and values, parsed and cached on first access.
* `await request.body()` -> Cached body raw bytes
* `await request.json()` -> Parsed JSON body; an empty body becomes `{}`
+Since Wred 0.14, repeated request header values are joined with `, `, except
+Cookie fields, which join with `; `. Previously, other repeated names kept
+their last value.
+
```python
@app.route('/search')
async def search(request):
diff --git a/wred.py b/wred.py
index 07b7c61..69e0cad 100644
--- a/wred.py
+++ b/wred.py
@@ -3,7 +3,7 @@ Wred: An ultra micro ASGI API framework.
Copyright (c) 2026, Harrison Erd.
"""
__author__, __email__, __license__ = 'Harrison Erd', '[email protected]', 'BSD-3-Clause'
-__version__ = '0.13'
+__version__ = '0.14'
from collections.abc import Awaitable, Callable
from functools import cached_property
from typing import Any
@@ -20,7 +20,7 @@ class Request:
@cached_property
def headers(self) -> dict[str, str]:
- """Decode and cache headers, joining duplicates with commas (semicolons for Cookie)."""
+ """Decode and cache headers, joining duplicates."""
headers: dict[str, str] = {}
for k, v in self.scope.get('headers', []):
k, v = k.decode('ascii').lower(), v.decode('latin-1')