Metadata-Version: 1.1
Name: aio.web.server
Version: 0.0.5
Summary: Aio web server
Home-page: http://github.com/phlax/aio.web.server
Author: Ryan Northey
Author-email: ryan@3ca.org.uk
License: GPL
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>
        
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.4
Classifier: Topic :: Software Development :: Libraries :: Python Modules
