Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/tags/cherrypy-2.1.0-rc1/cherrypy/_cpwsgi.py

Revision 626 (checked in by rdelon, 3 years ago)

Implemented ticket #90 (still need to write docs though)

Line 
1 """
2 Copyright (c) 2005, CherryPy Team (team@cherrypy.org)
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright notice,
11       this list of conditions and the following disclaimer in the documentation
12       and/or other materials provided with the distribution.
13     * Neither the name of the CherryPy Team nor the names of its contributors
14       may be used to endorse or promote products derived from this software
15       without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 """
28
29 """
30 A WSGI application interface (see PEP 333).
31 """
32
33 import sys
34 import cherrypy
35 from cherrypy import _cputil, _cphttptools
36 from cherrypy._cpwsgiserver import CherryPyWSGIServer as server
37
38
39 def requestLine(environ):
40     """Rebuild first line of the request (e.g. "GET /path HTTP/1.0")."""
41    
42     resource = environ.get('SCRIPT_NAME', '') + environ.get('PATH_INFO', '')
43     if not (resource == "*" or resource.startswith("/")):
44         resource = "/" + resource
45    
46     qString = environ.get('QUERY_STRING')
47     if qString:
48         resource += '?' + qString
49    
50     resource = resource.replace(" ", "%20")
51    
52     return ('%s %s %s' % (environ['REQUEST_METHOD'],
53                           resource or '/',
54                           environ['SERVER_PROTOCOL']
55                           )
56             )
57
58 headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
59                'CONTENT_LENGTH': 'Content-Length',
60                'CONTENT_TYPE': 'Content-Type',
61                'REMOTE_HOST': 'Remote-Host',
62                'REMOTE_ADDR': 'Remote-Addr',
63                }
64
65 def translate_headers(environ):
66     """Translate CGI-environ header names to HTTP header names."""
67     for cgiName in environ:
68         translatedHeader = headerNames.get(cgiName.upper())
69         if translatedHeader:
70             yield translatedHeader, environ[cgiName]
71         elif cgiName.upper().startswith("HTTP_"):
72             # Hackish attempt at recovering original header names.
73             translatedHeader = cgiName[5:].replace("_", "-")
74             yield translatedHeader, environ[cgiName]
75
76
77 class NullWriter(object):
78    
79     def write(self, data):
80         pass
81
82
83 def wsgiApp(environ, start_response):
84     """The WSGI 'application object' for CherryPy."""
85    
86     # Trap screen output from BaseHTTPRequestHandler.log_message()
87     if not cherrypy.config.get('server.logToScreen'):
88         sys.stderr = NullWriter()
89    
90     try:
91         # LOGON_USER is served by IIS, and is the name of the
92         # user after having been mapped to a local account.
93         # Both IIS and Apache set REMOTE_USER, when possible.
94         cherrypy.request.login = (environ.get('LOGON_USER')
95                                   or environ.get('REMOTE_USER') or None)
96         cherrypy.request.multithread = environ['wsgi.multithread']
97         cherrypy.request.multiprocess = environ['wsgi.multiprocess']
98         clientAddr = (
99             environ.get('REMOTE_ADDR', ''),
100             int(environ.get('REMOTE_PORT', -1))
101         )
102         cherrypy.server.request(clientAddr,
103                                 environ.get('REMOTE_ADDR', ''),
104                                 requestLine(environ),
105                                 translate_headers(environ),
106                                 environ['wsgi.input'],
107                                 environ['wsgi.url_scheme'],
108                                 )
109     except:
110         tb = _cputil.formatExc()
111         cherrypy.log(tb)
112         defaultOn = (cherrypy.config.get('server.environment') == 'development')
113         if not cherrypy.config.get("server.showTracebacks", defaultOn):
114             tb = ""
115         s, h, b = _cphttptools.bareError(tb)
116         exc = sys.exc_info()
117     else:
118         response = cherrypy.response
119         s, h, b = response.status, response.headers, response.body
120         exc = None
121    
122     try:
123         start_response(s, h, exc)
124         for chunk in b:
125             # WSGI requires all data to be of type "str". This coercion should
126             # not take any time at all if chunk is already of type "str".
127             # If it's unicode, it could be a big performance hit (x ~500).
128             chunk = str(chunk)
129             yield chunk
130     except:
131         tb = _cputil.formatExc()
132         cherrypy.log(tb)
133         s, h, b = _cphttptools.bareError()
134         # CherryPy test suite expects bareError body to be output,
135         # so don't call start_response (which, according to PEP 333,
136         # may raise its own error at that point).
137         for chunk in b:
138             yield str(chunk)
139
140
141
142 # Server components.
143
144 class WSGIServer(server):
145    
146     """Wrapper for _cpwsgiserver.CherryPyWSGIServer.
147     
148     _cpwsgiserver has been designed to not reference CherryPy in any way,
149     so that it can be used in other frameworks and applications. Therefore,
150     we wrap it here.
151     
152     """
153    
154     def __init__(self):
155         conf = cherrypy.config.get
156         server.__init__(self,
157                         (conf("server.socketHost"), conf("server.socketPort")),
158                         wsgiApp,
159                         conf("server.threadPool"),
160                         conf("server.socketHost"),
161                         config = cherrypy.config
162                         )
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets