patx/micropie
fully updated index routes ability to accept url path params, with 404 when needed
Commit 8af8853 · patx · 2025-01-25T16:32:21-05:00
Comments
No comments yet.
Diff
diff --git a/MicroPie.py b/MicroPie.py
index c42faab..59d7e54 100644
--- a/MicroPie.py
+++ b/MicroPie.py
@@ -36,6 +36,8 @@ from wsgiref.simple_server import make_server
import time
import uuid
import inspect
+import os
+import mimetypes
from urllib.parse import parse_qs
try:
@@ -210,6 +212,16 @@ class Server:
return False
def wsgi_app(self, environ, start_response):
+ """
+ A WSGI-compatible application method that processes incoming requests,
+ manages sessions, dispatches to the correct handler function,
+ and supports streaming/generator responses.
+ IMPORTANT:
+ - If your route returns (status, body, extra_headers), we handle them
+ in a single call to start_response.
+ - Do NOT call `start_response` in your handler.
+
+ """
self.environ = environ
self.start_response = start_response
@@ -221,10 +233,13 @@ class Server:
func_name = path_parts[0] if path_parts else "index"
self.path_params = path_parts[1:] if len(path_parts) > 1 else []
+ # Get the handler function
+ handler_function = getattr(self, func_name, None)
+
# Special case: If the first segment doesn't match a function, assume index
- if not hasattr(self, func_name):
+ if not handler_function:
self.path_params = path_parts
- func_name = "index"
+ handler_function = getattr(self, "index", None)
# Parse query parameters
self.query_params = parse_qs(environ["QUERY_STRING"])
@@ -285,12 +300,7 @@ class Server:
start_response("400 Bad Request", [("Content-Type", "text/html")])
return [f"400 Bad Request: {str(e)}".encode("utf-8")]
- # Find the requested handler
- handler_function = getattr(self, func_name, None)
- if not handler_function:
- start_response("404 Not Found", [("Content-Type", "text/html")])
- return [b"404 Not Found"]
-
+ # Check if the handler function requires arguments
sig = inspect.signature(handler_function)
func_args = []
@@ -308,6 +318,11 @@ class Server:
start_response("400 Bad Request", [("Content-Type", "text/html")])
return [msg.encode("utf-8")]
+ # If the index method does not take any arguments and the path is not empty, return 404
+ if handler_function == getattr(self, "index", None) and not func_args and path:
+ start_response("404 Not Found", [("Content-Type", "text/html")])
+ return [b"404 Not Found"]
+
try:
response = handler_function(*func_args)
status_code = 200
@@ -358,4 +373,3 @@ class Server:
except:
pass
return [b"500 Internal Server Error"]
-
diff --git a/README.md b/README.md
index 6ec1ae0..2d81252 100644
--- a/README.md
+++ b/README.md
@@ -115,33 +115,6 @@ class MyApp(Server):
- [http://127.0.0.1:8080/profile/456](http://127.0.0.1:8080/profile/456)
- Returns: `User ID: 456, Age: Unknown`
-#### **Other Considerations for GET requests**
-In **MicroPie**, the `index` method serves as the default route handler, which behaves differently compared to other route methods such as `greet` or any custom-defined handlers.
-
-##### Key Differences:
-
-1. **Default Handling:**
- - When the root URL (`/`) is accessed, the framework automatically maps the request to the `index` method.
- - Other methods (e.g., `greet`) must be explicitly accessed via their route, such as `/greet`.
-
-2. **URL Parameter Handling:**
- - The `index` method does **not** receive URL path parameters in the same way as other route methods.
- - Instead, it primarily relies on query parameters (e.g., `/index?name=John`).
- - Other methods can accept parameters directly from the URL path (e.g., `/greet/John`).
-
-##### Example Usage:
-
-| URL | Method Called | Notes |
-|--------------------- |--------------------------|----------------------------------------|
-| `/` | `index()` | Default route, no path parameters. |
-| `/index?name=John` | `index(name="John")` | Query parameters work. |
-| `/greet/John` | `greet("John")` | Path parameters are passed correctly. |
-| `/<dynamic_path>` | **Not supported** | Will result in a 404 error. |
-
-**Note:** Dynamic paths such as `/<dynamic_path>` will not work with the `index` method. Instead, they should be explicitly handled using dedicated route methods.
-
-By understanding this distinction, you can structure your routes effectively when using MicroPie.
-
### **3. Handling POST Requests**
MicroPie supports handling form data submitted via HTTP POST requests. Form data is automatically mapped to method arguments.
diff --git a/examples/streaming/text.py b/examples/streaming/text.py
index a020863..0fd7b66 100644
--- a/examples/streaming/text.py
+++ b/examples/streaming/text.py
@@ -2,6 +2,7 @@ import time
from MicroPie import Server
class Root(Server):
+
def index(self):
# Normal, immediate response (non-streaming)
return "Hello from index!"
diff --git a/examples/streaming/video.mp4 b/examples/streaming/video.mp4
new file mode 100644
index 0000000..9b89f62
Binary files /dev/null and b/examples/streaming/video.mp4 differ
diff --git a/examples/streaming/video1.py b/examples/streaming/video1.py
index ede6965..efd0b72 100644
--- a/examples/streaming/video1.py
+++ b/examples/streaming/video1.py
@@ -81,7 +81,7 @@ class VideoStreamer(Server):
app = VideoStreamer()
# The WSGI entry point Gunicorn will look for
-wsgi_app = app.wsgi_apps
+wsgi_app = app.wsgi_app
if __name__ == "__main__":
app.run()