bobo_handler.py :  » Web-Frameworks » Zope » Zope-2.6.0 » ZServer » medusa » contrib » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Zope 
Zope » Zope 2.6.0 » ZServer » medusa » contrib » bobo_handler.py
"""Bobo handler module
For use with medusa & python object publisher

copyright 1997 amos latteier
(code based on script_handler.py)

Use:

here is a sample fragment from a script to start medusa:

...
hs = http_server.http_server (IP_ADDRESS, HTTP_PORT, rs, lg)
...
sys.path.insert(0,'c:\\windows\\desktop\\medusa2\\www\\bobo')
import bobotest
bh=bobo_handler.bobo_handler(bobotest, debug=1)  #create bobo handler  
hs.install_handler(bh)  #install handler in http server
...

This will install the bobo handler on the http server and give you 
access to the bobotest module via urls like this:

http://myserver.com/bobotest/blah/blah

bobo_handler initalization options: 
* debug: If the debug flag is set then the published module will be reloaded
whenever its source is changed on disk. This is very handy for developement.
* uri_base: If the uri_base isn't specified it defaults to /<module_name>
"""

__version__="1.03"

import cgi_module_publisher
import sys
import regex
import string
import os

try:
    from cStringIO import StringIO
except:
    from StringIO import StringIO
try:
    import thread
    mutex = thread.allocate_lock()
    THREADS = 1
except:
    THREADS = 0
    
import counter
import default_handler
import producers

split_path = default_handler.split_path
unquote    = default_handler.unquote
get_header = default_handler.get_header

CONTENT_LENGTH = regex.compile ('Content-Length: \([0-9]+\)', regex.casefold)


# maps request headers to environment variables
#

header2env={'Content-Length'  : 'CONTENT_LENGTH',
                        'Content-Type'    : 'CONTENT_TYPE',
                        'Referer'      : 'HTTP_REFERER',
                        'User-Agent'    : 'HTTP_USER_AGENT',
                        'Accept'      : 'HTTP_ACCEPT',
                        'Accept-Charset'  : 'HTTP_ACCEPT_CHARSET',
                        'Accept-Language'  : 'HTTP_ACCEPT_LANGUAGE',
                        'Host'        : None,
                        'Connection'    : 'CONNECTION_TYPE',
                        'Pragma'      : None,
                        'Authorization'    : 'HTTP_AUTHORIZATION',
                        'Cookie'      : 'HTTP_COOKIE',
                        }
# convert keys to lower case for case-insensitive matching
#
for (key,value) in header2env.items():
    del header2env[key]
    key=string.lower(key)
    header2env[key]=value
    
    
class bobo_handler:
    "publishes a module via bobo"
    
    def __init__ (self, module, uri_base=None, debug=None):
        self.module = module
        self.debug = debug
        if self.debug:
            self.last_reload=self.module_mtime()
        self.hits = counter.counter()
        
        # if uri_base is unspecified, assume it
        # starts with the published module name
        #
        if not uri_base:  
            uri_base="/%s" % module.__name__
        elif uri_base[-1]=="/":  # kill possible trailing /
            uri_base=uri_base[:-1]
        self.uri_base=uri_base
        
        uri_regex='%s.*' % self.uri_base
        self.uri_regex = regex.compile(uri_regex)
        
        
    def match (self, request):
        uri = request.uri
        if self.uri_regex.match (uri) == len(uri):
            return 1
        else:
            return 0
            
    def handle_request (self, request):
        [path, params, query, fragment] = split_path (request.uri)
        while path and path[0] == '/':
            path = path[1:]
            
        if '%' in path:
            path = unquote (path)
            
        self.hits.increment()
        
        if query:
                # cgi_publisher_module doesn't want the leading '?'
            query = query[1:]
            
        self.env = {}
        self.env['REQUEST_METHOD']  = string.upper(request.command)
        self.env['SERVER_PORT']    = '%s' % request.channel.server.port
        self.env['SERVER_NAME']    = request.channel.server.server_name
        self.env['SERVER_SOFTWARE']  = request['Server']
        self.env['SCRIPT_NAME']    = self.uri_base  # are script_name and path_info ok?
        self.env['QUERY_STRING']  = query
        try:
            path_info=string.split(path,self.uri_base[1:],1)[1]
        except:
            path_info=''
        self.env['PATH_INFO']    = path_info
        self.env['GATEWAY_INTERFACE']='CGI/1.1'      # what should this really be?
        self.env['REMOTE_ADDR']=request.channel.addr[0]
        self.env['REMOTE_HOST']=request.channel.addr[0]  #what should this be?
        
        for header in request.header:
            [key,value]=string.split(header,": ",1)
            key=string.lower(key)
            if header2env.has_key(key):
                if header2env[key]:
                    self.env[header2env[key]]=value
            else:
                key='HTTP_'+string.upper(string.join(string.split(key,"-"),"_"))
                self.env[key]=value
                
                # remove empty environment variables
                #
        for key in self.env.keys():
            if self.env[key]=="" or self.env[key]==None:
                del self.env[key]
                
        if request.command in ["post","put"]:
            request.collector=input_collector(self,request)
            request.channel.set_terminator (None)
        else:
            sin=StringIO('')
            self.continue_request(sin,request)
            
            
    def continue_request(self,sin,request):
        "continue handling request now that we have the stdin"
        
        # if we have threads spawn a new one to publish the module
        # so we dont freeze the server while publishing.
        if THREADS:
            thread.start_new_thread(self._continue_request,(sin,request))
        else:
            self._continue_request(sin,request)
            
            
    def _continue_request(self,sin,request):
        "continue handling request now that we have the stdin"
        sout = StringIO()
        serr = StringIO()
        
        if self.debug:
            m_time=self.module_mtime()
            if m_time> self.last_reload:
                reload(self.module)
                self.last_reload=m_time
        if THREADS:
            mutex.acquire()
        cgi_module_publisher.publish_module(
                self.module.__name__,
                stdin=sin,
                stdout=sout,
                stderr=serr,
                environ=self.env,
                #debug=1
                )
        if THREADS:
            mutex.release()
            
        if serr.tell():
            request.log(serr.getvalue())
            
        response=sout
        response=response.getvalue()
        
        # set response headers
        [headers,html]=string.split(response,"\n\n",1)
        headers=string.split(headers,"\n")
        
        for line in headers:
            [header, header_value]=string.split(line,": ",1)
            if header=="Status":
                [code,message]=string.split(header_value," ",1)
                request.reply_code=string.atoi(code)
            else:
                request[header]=header_value
                
        request.push(html)
        request.done()
        
        
    def module_mtime(self):
        "returns the last modified date for a given module's source file"
        return os.stat(self.module.__file__)[8]
        
    def status (self):
        return producers.simple_producer (
                '<li>Bobo Handler'
                + '<ul>'
                + '  <li><b>Hits:</b> %d' % int(self.hits)
                + '</ul>'
                )
        
        
class input_collector:
    "gathers input for put and post requests"
    
    def __init__ (self, handler, request):
        self.handler  = handler
        self.request  = request
        self.data = StringIO()
        
        # make sure there's a content-length header
        self.cl = get_header (CONTENT_LENGTH, request.header)
        
        if not self.cl:
            request.error(411)
            return
        else:
            self.cl = string.atoi(self.cl)
            
    def collect_incoming_data (self, data):
        self.data.write(data)
        if self.data.tell() >= self.cl:
            self.data.seek(0)
            
            h=self.handler
            r=self.request
            
            # set the terminator back to the default
            self.request.channel.set_terminator ('\r\n\r\n')
            del self.handler
            del self.request
            
            h.continue_request(self.data,r)
            
            
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.