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

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

Further tidy up of existing code: remove History, cart and selection templates
and remove leftPanel template function and its references. Also remove selection.py
and tabs.py and clear out any associated code.

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