zoukankan      html  css  js  c++  java
  • WSGI and Paste学习笔记

    The Problem

    • Lots of web frameworks Zope, Quixote, Webware, SkunkWeb and Twisted Web etc
    • Applications written for one framework often weren't compatible with the server components of the others

    HTTP Basics

    • When you request a page the browser sends an HTTP request
    • When the server receives that request it will perform some action, (typically running an application) and return an HTTP response

    WSGI application

    • It is a callable (in this case a simple function) taking environ and start_response as positional parameters
    • It calls start_response() with a status code and a list of tuple pairs of headers
    • It returns a value.
    • It should only be called once.
    • The response it returns is an iterable (in this case a list with just one string).

    image 

    The environ Dictionary :

    A dictionary of strings

    • CGI strings
    • WSGI strings: wsgi.version, wsgi.url_scheme, wsgi.input, wsgi.errors, wsgi.multithread, wsgi.multiprocess, wsgi.run_once
    • Server extension strings

    easy_install WSGIUtils

    image

    Middleware

    Component that acts like an application from the server's point of view

    • It is a callable that accepts environ and start_response
    • Calls start_repsonse once with status and headers etc
    • Returns an iterable

    with mddleware, you can do the following

    • Provide more functionality by adding a key to the environ dictionary
    • Change the status
    • Intercepting an error
    • Adding/removing/changing headers
    • Change a response

    image

    Middleware Chains

    image

    Use Paste

    例子一

    • app.py

    from webob import Response

    from webob.dec import wsgify

    from paste import httpserver

    from paste.deploy import loadapp

    @wsgify

    def application(req):

    return Response('Hello World')

    def app_factory(global_config, **local_config):

    return application

    wsgi_app = loadapp('config:/root/paste.ini')

    httpserver.serve(wsgi_app, host='127.0.0.1', port=8080)

    • paste.ini

    [app:main]

    paste.app_factory = app:app_factory

    例子二

    • app.py

    from webob import Response

    from webob.dec import wsgify

    from paste import httpserver

    from paste.deploy import loadapp

    @wsgify

    def application(req):

    return Response('Hello World')

    @wsgify.middleware()

    def my_filter(req, app):

    # just print a message to the console

    print('my_filter was called')

    return app(req)

    def app_factory(global_config, **local_config):

    return application

    def filter_factory(global_config, **local_config):

    return my_filter

    wsgi_app = loadapp('config:/root/paste.ini')

    httpserver.serve(wsgi_app, host='127.0.0.1', port=8080)

    • paste.ini

    [pipeline:main]

    pipeline = myfilter myapp

    [app:myapp]

    paste.app_factory = app:app_factory

    [filter:myfilter]

    paste.filter_factory = app:filter_factory

    Paste Deploy

    • Paste Deployment is a system for finding and configuring WSGI applications and servers.
    • For WSGI application consumers:
      • it provides a single, simple function (loadapp) for loading a WSGI application from a configuration file or a Python Egg.
    • For WSGI application providers
      • it only asks for a single, simple entry point to your application
    • two URI formats currently supported:
    • Global and Local Configurations
      • Global configuration to apply to every application defined in a file should go in a special section named [DEFAULT].

    [DEFAULT]

    admin_email = webmaster@example.com

      • Configuration is done through keys besides use

    [app:blog]

    use = egg:MyBlog

    database = mysql://localhost/blogdb

    blogname = This Is My Blog!

    • Tree types of sections:
      • Applications
      • Composite Applications
      • Filter Composition
    • Application section: There’s two ways to indicate the Python code for the application.
      • The first is to refer to another URI or name:

    #points to application section in other config files

    [app:myapp]

    use = config:another_config_file.ini#app_name

    # or any URI:

    [app:myotherapp]

    use = egg:MyApp

    # or a callable from a module:

    [app:mythirdapp]

    use = call:my.project:myapplication

    # or even another section:

    [app:mylastapp]

    use = myotherapp

      • The other way to define an application is to point exactly to some Python code:

    [app:myapp]

    paste.app_factory = myapp.modulename:app_factory

    • Composite Applications
      • “Composite” applications are things that act like applications, but are made up of other applications.
      • One example would be a URL mapper, where you mount applications at different URL paths.

    [composite:main]

    use = egg:Paste#urlmap

    / = mainapp

    /files = staticapp

    [app:mainapp]

    use = egg:MyApp

    [app:staticapp]

    use = egg:Paste#static

    document_root = /path/to/docroot

    • Filter Composition: several ways to apply filters to applications:
      • The first way is to use the filter-with setting

    [app:main]

    use = egg:MyEgg

    filter-with = printdebug

    [filter:printdebug]

    use = egg:Paste#printdebug

    # and you could have another filter-with here, and so on...

      • filter-app defines a filter, and then a special key next which points to the application to apply the filter to.

    [composite:main]

    use = egg:Paste#urlmap

    / = home

    /blog = blog

    /wiki = wiki

    /cms = config:cms.ini

    [app:home]

    use = egg:Paste#static

    document_root = %(here)s/htdocs

    [filter-app:blog]

    use = egg:Authentication#auth

    next = blogapp

    roles = admin

    htpasswd = /home/me/users.htpasswd

    [app:blogapp]

    use = egg:BlogApp

    database = sqlite:/home/me/blog.db

    [app:wiki]

    use = call:mywiki.main:application

    database = sqlite:/home/me/wiki.db

      • pipeline: is used when you need apply a number of filters.

    [pipeline:main]

    pipeline = filter1 egg:FilterEgg#filter2 filter3 app

    [filter:filter1]

    ...

    • Factories
      • paste.app_factory
      • paste.composite_factory
      • paste.filter_factory
      • paste.server_factory
    • keystoneclient/middleware/auth_token.py

    class AuthProtocol(object):

        """Auth Middleware that handles authenticating client calls."""

        def __init__(self, app, conf):

            ……

        def __call__(self, env, start_response):

            """Handle incoming request.

            Authenticate send downstream on success. Reject request if we can't authenticate.

    def filter_factory(global_conf, **local_conf):

        """Returns a WSGI filter app for use with paste.deploy."""

        conf = global_conf.copy()

        conf.update(local_conf)

        def auth_filter(app):

            return AuthProtocol(app, conf)

        return auth_filter

    def app_factory(global_conf, **local_conf):

        conf = global_conf.copy()

        conf.update(local_conf)

        return AuthProtocol(None, conf)

    [composite:rootapp]

    paste.composite_factory = glance.api:root_app_factory

    /: apiversions

    /v1: apiv1app

    /v2: apiv2app

    def root_app_factory(loader, global_conf, **local_conf):

        if not CONF.enable_v1_api:

            del local_conf['/v1']

        if not CONF.enable_v2_api:

            del local_conf['/v2']

        return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)

  • 相关阅读:
    idea git 操作
    1
    python 迭代器/生成器/迭代对象
    python 中的type
    systemd 配置文件
    python 中类的初始化过程
    mysql主从错误180301
    从零开始搭建k8s-20180301
    kubernetes role
    Java程序员毕业两年自述
  • 原文地址:https://www.cnblogs.com/popsuper1982/p/3800430.html
Copyright © 2011-2022 走看看