Skip to main content

Aio web server

Project description

Detailed documentation
**********************

aio.web.server
==============

Web server for the aio_ asyncio framework

.. _aio: https://github.com/phlax/aio



Build status
------------

.. image:: https://travis-ci.org/phlax/aio.web.server.svg?branch=master
:target: https://travis-ci.org/phlax/aio.web.server


Installation
------------
Install with:

.. code:: bash

pip install aio.web.server


Configuration
-------------

Example configuration for a hello world web page

.. code:: ini

[server/test]
factory = aio.web.server.factory
port = 8080

[web/test/page]
match = /
route = my.example.handler

And the corresponding route handler

.. code:: python

import asyncio
import aiohttp

@asyncio.coroutine
def handler(request):
return aiohttp.web.Response(body=b"Hello, web world")


Running
-------

Run with the aio command

.. code:: bash

aio run



aio.web.server usage
-------------


Configuration
-------------

Let's create a config defining a factory method and using the aio.web.server.protocol for the protocol

In the following configuration example a server named "example-1" is set up.

Any sections that start with "web/example-1/" will be treated as route definitions.

The route definition should provide a "match" and a "route" at a minimum.

The route is given a name derived from the section name. In this case "homepage"

>>> web_server_config = """
... [aio]
... log_level: ERROR
...
... [server/example]
... factory = aio.web.server.factory
... port = 7070
...
... [web/example/homepage]
... match = /
... route = aio.web.server.tests._example_handler
... """

>>> import asyncio
>>> import aiohttp
>>> import aio.web.server.tests
>>> from aio.app.runner import runner
>>> from aio.testing import aiofuturetest

>>> @asyncio.coroutine
... def handler(request):
... return aiohttp.web.Response(body=b"Hello, web world")

>>> aio.web.server.tests._example_handler = handler

>>> @aiofuturetest(sleep=1)
... def run_web_server(config, request_page="http://localhost:7070"):
... yield from runner(['run'], config_string=config)
...
... @asyncio.coroutine
... def call_web_server():
... result = yield from (
... yield from aiohttp.request(
... "GET", request_page)).read()
...
... print(result.decode())
...
... return call_web_server

>>> run_web_server(web_server_config)
Hello, web world


Accessing web apps
------------------

You can access a webapp by name

>>> import aio.web.server
>>> aio.web.server.apps['example']
<Application>

>>> aio.web.server.apps['example']['name']
'example'

Let's clear the web apps, this will also call aio.app.clear()

>>> aio.web.server.clear()
>>> aio.web.server.apps
{}

>>> print(aio.app.config, aio.app.signals)
None None


Static directory
----------------

The "web/" section takes a static_url and a static_dir option for hosting static files

>>> config_static = """
... [aio]
... log_level: ERROR
...
... [server/test]
... factory: aio.web.server.factory
... port: 7070
...
... [web/test]
... static_url: /static
... static_dir: %s
... """

>>> import os
>>> import tempfile

>>> with tempfile.TemporaryDirectory() as tmp:
... with open(os.path.join(tmp, "test.css"), 'w') as cssfile:
... res = cssfile.write("body {}")
...
... run_web_server(
... config_static % tmp,
... request_page="http://localhost:7070/static/test.css")
body {}

And clear up...

>>> aio.web.server.clear()


Routes, templates and fragments
-------------------------------

aio.web.server uses jinja2 templates under the hood

On setup aio searches the paths of modules listed in the aio:modules option for folders named "templates" and loads any templates it finds from there

>>> config_template = """
... [aio]
... modules = aio.web.server.tests
... log_level: ERROR
...
... [server/example-2]
... factory: aio.web.server.factory
... port: 7070
...
... [web/example-2/homepage]
... match = /
... route = aio.web.server.tests._example_route_handler
... """


Routes
~~~~~~

By decorating a function with @aio.web.server.route, the function is called with the request and the configuration for the route that is being handled

>>> @aio.web.server.route("test_template.html")
... def route_handler(request, config):
... return {
... 'message': 'Hello, world'}

>>> aio.web.server.tests._example_route_handler = route_handler

>>> run_web_server(config_template)
<html>
<body>
Hello, world
</body>
</html>

>>> aio.web.server.clear()

Templates
~~~~~~~~~

A route handler can defer to other templates, for example according to the path.

The @aio.web.server.route decorator does not require a template, but in that case the decorated function must return an aiohttp.web.StreamResponse object

A route always takes 2 arguments - request and config, a template can take any arguments that it requires

While you can use an @aio.web.template as a route handler, doing so would bypass the normal logging and request handling operations

>>> example_config = """
... [aio]
... modules = aio.web.server.tests
... log_level: ERROR
...
... [server/example-3]
... factory: aio.web.server.factory
... port: 7070
...
... [web/example-3/paths]
... match = /{path:.*}
... route = aio.web.server.tests._example_route_handler
... """

>>> @aio.web.server.template("test_template.html")
... def template_handler_1(request):
... return {'message': "Hello, world from template handler 1"}

>>> @aio.web.server.template("test_template.html")
... def template_handler_2(request):
... return {'message': "Hello, world from template handler 2"}

>>> @aio.web.server.route
... def route_handler(request, config):
...
... if request.path == "/path1":
... return (yield from template_handler_1(request))
...
... elif request.path == "/path2":
... return (yield from template_handler_2(request))

>>> aio.web.server.tests._example_route_handler = route_handler

>>> run_web_server(
... example_config,
... request_page="http://localhost:7070/path1")
<html>
<body>
Hello, world from template handler 1
</body>
</html>

>>> aio.web.server.clear()

>>> run_web_server(
... example_config,
... request_page="http://localhost:7070/path2")
<html>
<body>
Hello, world from template handler 2
</body>
</html>

>>> aio.web.server.clear()

Fragments
~~~~~~~~~

Both routes and templates are expected to return a full html page, or an html response object.

Fragments render a snippet of code, and are not expected to return a full page.

Fragments cannot return an html response object, but can raise an html error if required

>>> example_config = """
... [aio]
... modules = aio.web.server.tests
... log_level: ERROR
...
... [server/example-3]
... factory: aio.web.server.factory
... port: 7070
...
... [web/example-3/paths]
... match = /
... route = aio.web.server.tests._example_route_handler
... """

>>> @aio.web.server.fragment("fragments/test_fragment.html")
... def fragment_handler(request, test_list):
... return {'test_list': test_list}

>>> @aio.web.server.template("test_template.html")
... def template_handler(request, test_list):
... return {'message': (yield from fragment_handler(request, test_list))}

>>> @aio.web.server.route
... def route_handler(request, config):
...
... return (yield from template_handler(request, ["foo", "bar", "baz"]))

>>> aio.web.server.tests._example_route_handler = route_handler

>>> run_web_server(
... example_config,
... request_page="http://localhost:7070/")
<html>
<body>
<ul>
<li>foo</li><li>bar</li><li>baz</li>
</ul>
</body>
</html>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aio.web.server-0.0.2.tar.gz (7.5 kB view details)

Uploaded Source

File details

Details for the file aio.web.server-0.0.2.tar.gz.

File metadata

File hashes

Hashes for aio.web.server-0.0.2.tar.gz
Algorithm Hash digest
SHA256 c721f82154891ab7b632a156c45f69c405cb26b4e537f57cf62aad6802ed1e54
MD5 9e123ef19b62b29d7aff03044224d544
BLAKE2b-256 c37986e63ec7257d0861a0cf416303796d515d178b69ee01b596bc04bae71172

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page