summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/docs/writing-tests/python-handlers/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/docs/writing-tests/python-handlers/index.md')
-rw-r--r--testing/web-platform/tests/docs/writing-tests/python-handlers/index.md116
1 files changed, 116 insertions, 0 deletions
diff --git a/testing/web-platform/tests/docs/writing-tests/python-handlers/index.md b/testing/web-platform/tests/docs/writing-tests/python-handlers/index.md
new file mode 100644
index 0000000000..e52e137179
--- /dev/null
+++ b/testing/web-platform/tests/docs/writing-tests/python-handlers/index.md
@@ -0,0 +1,116 @@
+# Python Handlers
+
+Python file handlers are Python files which the server executes in response to
+requests made to the corresponding URL. This is hooked up to a route like
+`("*", "*.py", python_file_handler)`, meaning that any .py file will be
+treated as a handler file (note that this makes it easy to write unsafe
+handlers, particularly when running the server in a web-exposed setting).
+
+The Python files must define a function named `main` with the signature:
+
+ main(request, response)
+
+...where `request` is [a wptserve `Request`
+object](/tools/wptserve/docs/request) and `response` is [a wptserve `Response`
+object](/tools/wptserve/docs/response).
+
+This function must return a value in one of the following four formats:
+
+ ((status_code, reason), headers, content)
+ (status_code, headers, content)
+ (headers, content)
+ content
+
+Above, `headers` is a list of (field name, value) pairs, and `content` is a
+string or an iterable returning strings.
+
+The `main` function may also update the response manually. For example, one may
+use `response.headers.set` to set a response header, and only return the
+content. One may even use this kind of handler, but manipulate the output
+socket directly. The `writer` property of the response exposes a
+`ResponseWriter` object that allows writing specific parts of the request or
+direct access to the underlying socket. If used, the return value of the
+`main` function and the properties of the `response` object will be ignored.
+
+The wptserver implements a number of Python APIs for controlling traffic.
+
+```eval_rst
+.. toctree::
+ :maxdepth: 1
+
+ /tools/wptserve/docs/request
+ /tools/wptserve/docs/response
+ /tools/wptserve/docs/stash
+```
+
+### Importing local helper scripts
+
+Python file handlers may import local helper scripts, e.g. to share logic
+across multiple handlers. To avoid module name collision, however, imports must
+be relative to the root of WPT. For example, in an imaginary
+`cookies/resources/myhandler.py`:
+
+```python
+# DON'T DO THIS
+import myhelper
+
+# DO THIS
+from cookies.resources import myhelper
+```
+
+Only absolute imports are allowed; do not use relative imports. If the path to
+your helper script includes a hyphen (`-`), you can use `import_module` from
+`importlib` to import it. For example:
+
+```python
+import importlib
+myhelper = importlib.import_module('common.security-features.myhelper')
+```
+
+**Note on __init__ files**: Importing helper scripts like this
+requires a 'path' of empty `__init__.py` files in every directory down
+to the helper. For example, if your helper is
+`css/css-align/resources/myhelper.py`, you need to have:
+
+```
+css/__init__.py
+css/css-align/__init__.py
+css/css-align/resources/__init__.py
+```
+
+## Example: Dynamic HTTP headers
+
+The following code defines a Python handler that allows the requester to
+control the value of the `Content-Type` HTTP response header:
+
+```python
+def main(request, response):
+ content_type = request.GET.first('content-type')
+ headers = [('Content-Type', content_type)]
+
+ return (200, 'my status text'), headers, 'my response content'
+```
+
+If saved to a file named `resources/control-content-type.py`, the WPT server
+will respond to requests for `resources/control-content-type.py` by executing
+that code.
+
+This could be used from a [testharness.js test](../testharness) like so:
+
+```html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Demonstrating the WPT server's Python handler feature</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(function() {
+ return fetch('resources/control-content-type.py?content-type=text/foobar')
+ .then(function(response) {
+ assert_equals(response.status, 200);
+ assert_equals(response.statusText, 'my status text');
+ assert_equals(response.headers.get('Content-Type'), 'text/foobar');
+ });
+});
+</script>
+```