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).

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

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

Middleware Chains

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)

WSGI and Paste学习笔记的更多相关文章

  1. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  2. Java学习笔记--Swing用户界面组件

    很多与AWT类似. 事件处理参考:Java学习笔记--AWT事件处理 1.设计模式: 模型:存储内容视图:显示内容控制器:处理用户输入· 2. 文本输入常用组件 2.1 文本域: JLabel lab ...

  3. shell学习笔记

    shell学习笔记 .查看/etc/shells,看看有几个可用的Shell . 曾经用过的命令存在.bash_history中,但是~/.bash_history记录的是前一次登录前记录的所有指令, ...

  4. openstack学习笔记一 虚拟机启动过程代码跟踪

    openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...

  5. Django 学习笔记(三)模板导入

    本章内容是将一个html网页放进模板中,并运行服务器将其展现出来. 平台:windows平台下Liunx子系统 目前的目录: hello ├── manage.py ├── hello │ ├── _ ...

  6. R学习笔记(4): 使用外部数据

    来源于:R学习笔记(4): 使用外部数据 博客:心内求法 鉴于内存的非持久性和容量限制,一个有效的数据处理工具必须能够使用外部数据:能够从外部获取大量的数据,也能够将处理结果保存.R中提供了一系列的函 ...

  7. Django学习笔记(4)——Django连接数据库

    前言 在MVC或者MTV设计模式中,模型(M)代表对数据库的操作.那么如何操作数据库呢?本小节就认真学习一下.首先复习一下Django的整个实现流程 ,然后再实现一下使用数据库的整个流程,最后学习一下 ...

  8. Python Flask学习笔记之Hello World

    Python Flask学习笔记之Hello World 安装virtualenv,配置Flask开发环境 virtualenv 虚拟环境是Python解释器的一个私有副本,在这个环境中可以安装私有包 ...

  9. 鸟哥Linux私房菜基础学习篇学习笔记2

    鸟哥Linux私房菜基础学习篇学习笔记2 第九章 文件与文件系统的压缩打包: Linux下的扩展名没有什么特殊的意义,仅为了方便记忆. 压缩文件的扩展名一般为: *.tar, *.tar.gz, *. ...

随机推荐

  1. 避免切换横竖屏Fragment的重复加载导致UI混乱

    当我们切换横竖屏时 Activity的生命周期就会重走一遍,自然 其中的Fragment的生命周期也就重新走了一遍,实践证明 当熄屏 再开屏时 Fragment的生命周期也会重走一遍 解决方案: an ...

  2. 两个Integer比较

    两个Integer类型比较不能使用==,要使用equals,   == 在-127~128是可以用的,超出这个范围就不行 public static void main(String[] args) ...

  3. centos 防火墙端口开放

    开放端口 永久的开放需要的端口 sudo firewall-cmd --zone=public --add-port=3000/tcp --permanent sudo firewall-cmd -- ...

  4. mongodb参数

    启动命令 : mongod -port --dbpath data/ --logpath log/mongodb.log --fork ps -ef | grep momgod (查看是否启动成功) ...

  5. HTML5-盒子的使用

    一. border-color border-width border-style 属性用法遵循顺时针顺序. border-top- border-left- border-bottom- borde ...

  6. openstack-HTTP exception thrown: Maximum number of ports exceeded错误解决方案

    最近几天什么都没动无法创建云主机了,经过一番查询 1.查日志 /data/jumpserver/logs 得到错误 HTTP exception thrown: Maximum number of p ...

  7. odoo8 元素简介

    一:模型module: 1. 字段类型 (1)可控字段: fileds.char() fileds.Boolean() fileds.Date() (2)保留字段:(系统自动生成) id (Id) t ...

  8. HttpServletRequest字符集问题

    post中文处理 1post在spring里的设置web.xml文件 <!-- 字符处理 UTF8 --> <filter> <filter-name>encodi ...

  9. mysql 外网访问

    --修改用户Root 可以外网访问 update user set host='%' where user='root'; --查询修改结果 select user,host from user; - ...

  10. ThinkPHP 3.2.3+ORACLE插入数据BUG修复及支持获取自增Id的上次记录

    TP+ORACLE插入数据BUG修复以及获取自增Id支持getLastInsID方法 这些天在做Api接口时候,发现用TP操作Oracle数据库,发现查询修改删除都能执行, 但一旦执行插入操作老是报错 ...