source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/base.py @ 3536

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/base.py@3536
Revision 3536, 8.0 KB checked in by cbyrom, 12 years ago (diff)

Upgrade the server code to make consistent with newer pylons codebase - v0.9.6.1.
This mainly involves the replacement of the Response object, and associated methods,
with the inbuild, default response object. Typical changes include:

render_response -> render - with required settings on the response object
made before the render call against the response object

Response(...) -> response.write() - for content + response.headers.. = .. for headers info

  • also included the replacement of depricated functions, as highlighted by

the server logging

Line 
1import urllib
2from urlparse import urlsplit, urlunsplit
3from base64 import urlsafe_b64encode
4from pylons import c, g, cache, request, session, response
5from pylons.controllers import WSGIController
6from pylons.decorators import jsonify, validate
7from pylons.templating import render
8from pylons.controllers.util import abort, redirect_to, etag_cache
9from pylons.i18n import N_, _, ungettext
10from paste.request import construct_url
11import ows_server.models as model
12import ows_server.lib.helpers as h
13from ows_server.lib.security_util import setSecuritySession, LoginServiceQuery
14from ows_common import exceptions as OWS_E
15from ows_common.operations_metadata import OperationsMetadata, Operation, RequestMethod
16from ows_common.get_capabilities import ServiceMetadata
17import ows_common.xml
18
19
20try:
21    from xml.etree import ElementTree as ET
22except ImportError:
23    from elementtree import ElementTree as ET
24
25import logging
26logger = logging.getLogger(__name__)
27
28# Configure
29EXCEPTION_TYPE = request.environ['ndgConfig'].get('OWS_SERVER', 'exception_type', 'ogc').lower()
30
31class BaseController(WSGIController):
32   
33    def __call__(self, environ, start_response):       
34        # Insert any code to be run per request here. The Routes match
35        # is under environ['pylons.routes_dict'] should you want to check
36        # the action or route vars here
37
38        logger.debug("BaseController.__call__ ...")
39       
40        # construct URL picking up setting of server name from config to
41        # avoid exposing absolute URL hidden behind mod_proxy see #857
42        # Also, avoid returning to getCredentials and potentially exposing
43        # username/pass-phrase on URL.
44        # TODO: rework getCredentials get-out for more modular solution
45        pathInfo = urllib.quote(environ.get('PATH_INFO', '')) 
46        if 'getCredentials' in pathInfo:
47            logger.debug(\
48                "Reverting request URL from getCredentials to discovery...")
49            c.requestURL = g.server + '/discovery'       
50        else:
51            c.requestURL = g.server + pathInfo
52            query='&'.join(["%s=%s"%item for item in request.params.items()])
53            if query:
54                c.requestURL += '?' + query
55       
56        # Base 64 encode to enable passing around in 'r' argument of query
57        # string for use with login/logout
58        c.b64encRequestURL = urlsafe_b64encode(c.requestURL)
59
60        if 'h' in request.params:
61            # 'h' corresponds to the setting of a session manager host i.e.
62            # the request has come from a completed login from the login
63            # service
64            logger.debug("Setting security session from URL query args ...")
65           
66            # Copy the query arguments into security session keys
67            setSecuritySession()
68           
69            session.save()
70           
71            # Re-construct the URL removing the security related arguments
72            qs = LoginServiceQuery.stripFromURI()
73
74            logger.debug('Switching from https to http...')
75            cc = g.server + urllib.quote(environ.get('PATH_INFO',''))
76            if qs:
77                cc += "?" + qs
78               
79            logger.debug('URL transport switched to http: "%s"' % cc)
80            h.redirect_to(cc)
81
82               
83        #organise the information needed by pagetabs ...
84        # TODO avoid this for the server controllers ...
85       
86        c.pageTabs=[('Search',g.discoveryURL)]
87        if 'results' in session: 
88            c.pageTabs.append(('Results',session['results']))
89            # make selections tab available once results are shown - to simplify associated business logic
90            c.pageTabs.append(('Selections',h.url_for(controller='selectedItems',action='index')))
91           
92        if 'lastViewed' in session: c.pageTabs.append(('Display',session['lastViewed']))
93        if 'lastViewedWMC' in session: c.pageTabs.append(('View',session['lastViewedWMC']))
94       
95#            c.pageTabs.append(('Visualise',h.url_for(controller='visualise', action='index')))
96#            c.pageTabs.append(('Download','Blah'))
97       
98        return WSGIController.__call__(self, environ, start_response)
99   
100class OwsController(BaseController):
101    def __call__(self, environ, start_response):
102
103        # All OWS parameter names are case insensitive.
104        req = request._current_obj()
105        self.ows_params = {}
106        for k in req.params:
107            self.ows_params[k.lower()] = req.params[k]       
108
109        # If the EXCEPTION_TYPE is 'pylons' let Pylons catch any exceptions.
110        # Otherwise send an OGC exception report for any OWS_E.OwsError
111        if 'pylons' in EXCEPTION_TYPE:
112            self._fixOwsAction(environ)
113            return super(OwsController, self).__call__(environ, start_response)
114        else:
115            try:
116                self._fixOwsAction(environ)
117                return super(OwsController, self).__call__(environ, start_response)
118            except OWS_E.OwsError, e:
119                logger.exception(e)
120
121                response.headers['content-type'] = 'text/xml'
122                return render('exception_report', report=e.report, format='xml')
123
124
125    def _fixOwsAction(self, environ):
126        # Override the Routes action from the request query parameter
127        try:
128            action = self.ows_params['request']
129        except KeyError:
130            raise OWS_E.MissingParameterValue('REQUEST parameter not specified', 'REQUEST')
131
132        # Check action is a method in self
133        if not getattr(self, action):
134            raise OWS_E.InvalidParameterValue('request=%s not supported' % action, 'REQUEST')
135
136        # override routes action with request
137        environ['pylons.routes_dict']['action'] = action
138        del self.ows_params['request']
139
140    def _loadCapabilities(self):
141        """
142        creates an ows_common.get_capabilities.ServiceMetadata object
143        by consulting the paste configuration and annotations in the
144        controller definition.
145
146        """
147        # Deduce ows_endpoint from routes
148        ows_endpoint = h.url_for(controller=request.environ['pylons.routes_dict']['controller'])
149       
150        #Deduce base_url from config
151        base_url =request.environ['ndgConfig'].get('DEFAULT','server')
152
153       
154        # Get the server-level configuration data from an XML file
155        config = request.environ['paste.config']
156        sm_tree = ET.parse(config['ows_common_config'])
157        sm = ows_common.xml.service_metadata(sm_tree.getroot())
158       
159        # Extract service-level parameters and constraint
160        parameters = getattr(self, '_ows_parameters', {})
161        constraints = getattr(self, '_ows_constraints', {})
162        versions = getattr(self, '_ows_versions', [])
163       
164        # Extract operation-level parameters and constraints
165        od = {}
166        for attr in dir(self):
167            op = getattr(self, attr)
168            if hasattr(op, '_ows_name'):
169                p = getattr(op, '_ows_parameters', {})
170                c = getattr(op, '_ows_constraints', {})
171                od[op._ows_name] = Operation(get=RequestMethod(href=base_url+ows_endpoint),
172                                             post=None,
173                                             parameters=p,
174                                             constraints=c,
175                                             name=op._ows_name)
176       
177        sm.operationsMetadata = OperationsMetadata(od, constraints, parameters)
178        sm.serviceIdentification.serviceTypeVersions = versions
179        return sm
180
181    def _renderCapabilities(self, template='ows/get_capabilities'):
182        """
183        The standard way of returning a Capabilities document.
184
185        Each subclass should implement self._load_capabilities() and call
186        this method to return a response object.
187
188        """
189        c.service_metadata = self._loadCapabilities()       
190        response.headers['content-type'] = 'text/xml'
191        return render(template, format='xml')
192
193
194# Include the '_' function in the public names
195__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
196           or __name == '_']
Note: See TracBrowser for help on using the repository browser.