~ubuntu-branches/ubuntu/natty/flup/natty

« back to all changes in this revision

Viewing changes to flup/server/fcgi_single.py

  • Committer: Bazaar Package Importer
  • Author(s): Kai Hendry
  • Date: 2009-07-28 20:09:00 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090728200900-41mf0fqnsusbrpjl
Tags: 1.0.2-1
* New upstream release (Closes: #517965)
* http://www.saddi.com/software/news/archives/65-flup-1.0.2-on-the-horizon....html
* Debian packaging updated to use debhelper7
* Updated debian/copyright to be machine-interpretable
* Disabled upstream's use of ez_setup since Build-Depends already requires
  python-setuptools

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
 
2
# All rights reserved.
 
3
#
 
4
# Redistribution and use in source and binary forms, with or without
 
5
# modification, are permitted provided that the following conditions
 
6
# are met:
 
7
# 1. Redistributions of source code must retain the above copyright
 
8
#    notice, this list of conditions and the following disclaimer.
 
9
# 2. Redistributions in binary form must reproduce the above copyright
 
10
#    notice, this list of conditions and the following disclaimer in the
 
11
#    documentation and/or other materials provided with the distribution.
 
12
#
 
13
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
14
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
15
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
16
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
17
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
18
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
19
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
20
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
21
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
22
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
23
# SUCH DAMAGE.
 
24
#
 
25
# $Id$
 
26
 
 
27
"""
 
28
fcgi - a FastCGI/WSGI gateway.
 
29
 
 
30
For more information about FastCGI, see <http://www.fastcgi.com/>.
 
31
 
 
32
For more information about the Web Server Gateway Interface, see
 
33
<http://www.python.org/peps/pep-0333.html>.
 
34
 
 
35
Example usage:
 
36
 
 
37
  #!/usr/bin/env python
 
38
  from myapplication import app # Assume app is your WSGI application object
 
39
  from fcgi import WSGIServer
 
40
  WSGIServer(app).run()
 
41
 
 
42
See the documentation for WSGIServer for more information.
 
43
 
 
44
On most platforms, fcgi will fallback to regular CGI behavior if run in a
 
45
non-FastCGI context. If you want to force CGI behavior, set the environment
 
46
variable FCGI_FORCE_CGI to "Y" or "y".
 
47
"""
 
48
 
 
49
__author__ = 'Allan Saddi <allan@saddi.com>'
 
50
__version__ = '$Revision$'
 
51
 
 
52
import os
 
53
 
 
54
from flup.server.fcgi_base import BaseFCGIServer, FCGI_RESPONDER, \
 
55
     FCGI_MAX_CONNS, FCGI_MAX_REQS, FCGI_MPXS_CONNS
 
56
from flup.server.singleserver import SingleServer
 
57
 
 
58
__all__ = ['WSGIServer']
 
59
 
 
60
class WSGIServer(BaseFCGIServer, SingleServer):
 
61
    """
 
62
    FastCGI server that supports the Web Server Gateway Interface. See
 
63
    <http://www.python.org/peps/pep-0333.html>.
 
64
    """
 
65
    def __init__(self, application, environ=None,
 
66
                 bindAddress=None, umask=None, multiplexed=False,
 
67
                 debug=True, roles=(FCGI_RESPONDER,), forceCGI=False, **kw):
 
68
        """
 
69
        environ, if present, must be a dictionary-like object. Its
 
70
        contents will be copied into application's environ. Useful
 
71
        for passing application-specific variables.
 
72
 
 
73
        bindAddress, if present, must either be a string or a 2-tuple. If
 
74
        present, run() will open its own listening socket. You would use
 
75
        this if you wanted to run your application as an 'external' FastCGI
 
76
        app. (i.e. the webserver would no longer be responsible for starting
 
77
        your app) If a string, it will be interpreted as a filename and a UNIX
 
78
        socket will be opened. If a tuple, the first element, a string,
 
79
        is the interface name/IP to bind to, and the second element (an int)
 
80
        is the port number.
 
81
        """
 
82
        BaseFCGIServer.__init__(self, application,
 
83
                                environ=environ,
 
84
                                multithreaded=False,
 
85
                                multiprocess=False,
 
86
                                bindAddress=bindAddress,
 
87
                                umask=umask,
 
88
                                multiplexed=multiplexed,
 
89
                                debug=debug,
 
90
                                roles=roles,
 
91
                                forceCGI=forceCGI)
 
92
        for key in ('jobClass', 'jobArgs'):
 
93
            if kw.has_key(key):
 
94
                del kw[key]
 
95
        SingleServer.__init__(self, jobClass=self._connectionClass,
 
96
                              jobArgs=(self,), **kw)
 
97
        self.capability = {
 
98
            FCGI_MAX_CONNS: 1,
 
99
            FCGI_MAX_REQS: 1,
 
100
            FCGI_MPXS_CONNS: 0
 
101
            }
 
102
 
 
103
    def _isClientAllowed(self, addr):
 
104
        return self._web_server_addrs is None or \
 
105
               (len(addr) == 2 and addr[0] in self._web_server_addrs)
 
106
 
 
107
    def run(self):
 
108
        """
 
109
        The main loop. Exits on SIGHUP, SIGINT, SIGTERM. Returns True if
 
110
        SIGHUP was received, False otherwise.
 
111
        """
 
112
        self._web_server_addrs = os.environ.get('FCGI_WEB_SERVER_ADDRS')
 
113
        if self._web_server_addrs is not None:
 
114
            self._web_server_addrs = map(lambda x: x.strip(),
 
115
                                         self._web_server_addrs.split(','))
 
116
 
 
117
        sock = self._setupSocket()
 
118
 
 
119
        ret = SingleServer.run(self, sock)
 
120
 
 
121
        self._cleanupSocket(sock)
 
122
 
 
123
        return ret
 
124
 
 
125
if __name__ == '__main__':
 
126
    def test_app(environ, start_response):
 
127
        """Probably not the most efficient example."""
 
128
        import cgi
 
129
        start_response('200 OK', [('Content-Type', 'text/html')])
 
130
        yield '<html><head><title>Hello World!</title></head>\n' \
 
131
              '<body>\n' \
 
132
              '<p>Hello World!</p>\n' \
 
133
              '<table border="1">'
 
134
        names = environ.keys()
 
135
        names.sort()
 
136
        for name in names:
 
137
            yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
 
138
                name, cgi.escape(`environ[name]`))
 
139
 
 
140
        form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ,
 
141
                                keep_blank_values=1)
 
142
        if form.list:
 
143
            yield '<tr><th colspan="2">Form data</th></tr>'
 
144
 
 
145
        for field in form.list:
 
146
            yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
 
147
                field.name, field.value)
 
148
 
 
149
        yield '</table>\n' \
 
150
              '</body></html>\n'
 
151
 
 
152
    from wsgiref import validate
 
153
    test_app = validate.validator(test_app)
 
154
    WSGIServer(test_app).run()