From 2e1fca586f7767673199e2dd739a949533e18d53 Mon Sep 17 00:00:00 2001 From: Dominik Moritz Date: Fri, 26 Oct 2012 12:46:34 +0200 Subject: [PATCH] Resource proxy plugin started --- ckanext/jsonpreview/plugin.py | 17 +++++++----- ckanext/resourceproxy/__init__.py | 0 ckanext/resourceproxy/controller.py | 27 +++++++++++++++++++ ckanext/resourceproxy/plugin.py | 41 +++++++++++++++++++++++++++++ setup.py | 1 + 5 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 ckanext/resourceproxy/__init__.py create mode 100644 ckanext/resourceproxy/controller.py create mode 100644 ckanext/resourceproxy/plugin.py diff --git a/ckanext/jsonpreview/plugin.py b/ckanext/jsonpreview/plugin.py index 8b24d456adc..9e18b26adf9 100644 --- a/ckanext/jsonpreview/plugin.py +++ b/ckanext/jsonpreview/plugin.py @@ -2,6 +2,9 @@ import ckan.plugins as p import ckan.plugins.toolkit as toolkit +import ckan.lib.base as base + +import ckanext.resourceproxy.plugin as proxy log = getLogger(__name__) @@ -17,6 +20,9 @@ class JsonPreview(p.SingletonPlugin): p.implements(p.IConfigurer, inherit=True) p.implements(p.IResourcePreview, inherit=True) + def __init__(self): + self.proxy_enabled = True + def update_config(self, config): ''' Set up the resource library, public directory and template directory for the preview @@ -25,15 +31,12 @@ def update_config(self, config): toolkit.add_template_directory(config, 'theme/templates') toolkit.add_resource('theme/public', 'ckanext-jsonpreview') - def requires_same_orign(self, resource): - ''' json resources have to be from the same origin. jsonp resources don't - ''' - format_lower = resource['format'].lower() - return format_lower in ['json'] - def can_preview(self, resource): format_lower = resource['format'].lower() - return format_lower in ['jsonp', 'json'] + return format_lower in ['jsonp'] or format_lower in ['json'] and self.proxy_enabled + + def setup_template_variables(self, context, data_dict): + base.c.resource['url'] = proxy.get_proxyfied_resource_url(data_dict) def preview_template(self, context): return 'json.html' diff --git a/ckanext/resourceproxy/__init__.py b/ckanext/resourceproxy/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ckanext/resourceproxy/controller.py b/ckanext/resourceproxy/controller.py new file mode 100644 index 00000000000..affa2dc1bd5 --- /dev/null +++ b/ckanext/resourceproxy/controller.py @@ -0,0 +1,27 @@ +import urllib2 +from logging import getLogger + +import ckan.logic as logic +import ckan.lib.base as base + +log = getLogger(__name__) + + +@logic.side_effect_free +def proxy_resource(context, data_dict): + resource_id = data_dict['resource_id'] + log.info('Proxify resource {id}'.format(id=resource_id)) + resource = logic.get_action('resource_show')(context, {'id': resource_id}) + url = resource['url'] + req = urllib2.urlopen(url) + base.response.headers = req.headers + + import shutil + shutil.copyfileobj(req, base.response) + + +class ProxyController(base.BaseController): + def proxy_resource(self, data_dict): + context = {'model': base.model, 'session': base.model.Session, + 'user': base.c.user or base.c.author} + return proxy_resource(context, data_dict) diff --git a/ckanext/resourceproxy/plugin.py b/ckanext/resourceproxy/plugin.py new file mode 100644 index 00000000000..ced7fa3b5f1 --- /dev/null +++ b/ckanext/resourceproxy/plugin.py @@ -0,0 +1,41 @@ +from logging import getLogger + +import ckan.plugins as p +import ckan.lib.base as base + +import controller + +log = getLogger(__name__) + + +def get_proxyfied_resource_url(data_dict): + url = base.h.url_for( + action='proxy_resource', + id=data_dict['package']['name'], + resource_id=data_dict['resource']['id']) + log.info('Proxified url is {0}'.format(url)) + return url + + +class ResourceProxy(p.SingletonPlugin): + """A proxy for CKAN resources to get around the same + origin policy for previews + + This extension implements two interfaces + + - ``IConfigurer`` allows to modify the configuration + - ``IRoutes`` allows to add a route to the proxy action + - ``IActions`` allows to add an action for the proxy + """ + p.implements(p.IConfigurer, inherit=True) + p.implements(p.IRoutes, inherit=True) + p.implements(p.IActions) + + def before_map(self, m): + m.connect('/dataset/{id}/resource/{resource_id}/proxy', + controller='ckanext.resourceproxy.controller:ProxyController', + action='proxy_resource') + return m + + def get_actions(self): + return {'proxy_resource': controller.proxy_resource} diff --git a/setup.py b/setup.py index 2724343e8f1..da9fd72e13d 100644 --- a/setup.py +++ b/setup.py @@ -122,6 +122,7 @@ jsonpreview=ckanext.jsonpreview.plugin:JsonPreview pdfpreview=ckanext.pdfpreview.plugin:PdfPreview reclinepreview=ckanext.reclinepreview.plugin:ReclinePreview + resourceproxy=ckanext.resourceproxy.plugin:ResourceProxy [ckan.system_plugins] domain_object_mods = ckan.model.modification:DomainObjectModificationExtension