From 45f38ddf814ddabe333e3a373df877c6989f456f Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Fri, 6 Sep 2013 10:56:41 -0400 Subject: [PATCH 1/7] Update `requests` library to 1.2.3 --- common/djangoapps/terrain/browser.py | 10 +++++----- common/lib/capa/capa/xqueue_interface.py | 3 ++- common/lib/sample-post.py | 2 +- .../grading_service_module.py | 2 +- docs/shared/requirements.txt | 2 +- .../mock_youtube_server/mock_youtube_server.py | 1 - lms/djangoapps/instructor/tests/test_api.py | 3 ++- lms/djangoapps/instructor/views/api.py | 1 - requirements/edx/base.txt | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/common/djangoapps/terrain/browser.py b/common/djangoapps/terrain/browser.py index 498197b590..a554a34f19 100644 --- a/common/djangoapps/terrain/browser.py +++ b/common/djangoapps/terrain/browser.py @@ -12,7 +12,7 @@ from django.core.management import call_command from django.conf import settings from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.desired_capabilities import DesiredCapabilities -from requests import put +import requests from base64 import encodestring from json import dumps @@ -54,12 +54,12 @@ def set_job_status(jobid, passed=True): """ Sets the job status on sauce labs """ - body_content = dumps({"passed": passed}) config = get_username_and_key() + url = 'http://saucelabs.com/rest/v1/{}/jobs/{}'.format(config['username'], world.jobid) + body_content = dumps({"passed": passed}) base64string = encodestring('{}:{}'.format(config['username'], config['access-key']))[:-1] - result = put('http://saucelabs.com/rest/v1/{}/jobs/{}'.format(config['username'], world.jobid), - data=body_content, - headers={"Authorization": "Basic {}".format(base64string)}) + headers = {"Authorization": "Basic {}".format(base64string)} + result = requests.put(url, data=body_content, headers=headers) return result.status_code == 200 diff --git a/common/lib/capa/capa/xqueue_interface.py b/common/lib/capa/capa/xqueue_interface.py index 4da8e11d53..81a221961d 100644 --- a/common/lib/capa/capa/xqueue_interface.py +++ b/common/lib/capa/capa/xqueue_interface.py @@ -64,7 +64,8 @@ class XQueueInterface(object): def __init__(self, url, django_auth, requests_auth=None): self.url = url self.auth = django_auth - self.session = requests.session(auth=requests_auth) + self.session = requests.Session() + self.session.auth = requests_auth def send_to_queue(self, header, body, files_to_upload=None): """ diff --git a/common/lib/sample-post.py b/common/lib/sample-post.py index a4985689bf..d035d40709 100644 --- a/common/lib/sample-post.py +++ b/common/lib/sample-post.py @@ -39,7 +39,7 @@ username = prompt('username on server', 'victor@edx.org') password = prompt('password', 'abc123', safe=True) print "get csrf cookie" -session = requests.session() +session = requests.Session() r = session.get(server + '/') r.raise_for_status() diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py index 4c6a79a5f1..3a107d51c1 100644 --- a/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py +++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py @@ -25,7 +25,7 @@ class GradingService(object): def __init__(self, config): self.username = config['username'] self.password = config['password'] - self.session = requests.session() + self.session = requests.Session() self.system = config['system'] def _login(self): diff --git a/docs/shared/requirements.txt b/docs/shared/requirements.txt index 7dc7da8a75..6504319c0d 100644 --- a/docs/shared/requirements.txt +++ b/docs/shared/requirements.txt @@ -48,7 +48,7 @@ python-memcached==1.48 python-openid==2.2.5 pytz==2012h PyYAML==3.10 -requests==0.14.2 +requests==1.2.3 Shapely==1.2.16 sorl-thumbnail==11.12 South==0.7.6 diff --git a/lms/djangoapps/courseware/mock_youtube_server/mock_youtube_server.py b/lms/djangoapps/courseware/mock_youtube_server/mock_youtube_server.py index 46b269dda6..16ab36b6f7 100644 --- a/lms/djangoapps/courseware/mock_youtube_server/mock_youtube_server.py +++ b/lms/djangoapps/courseware/mock_youtube_server/mock_youtube_server.py @@ -1,6 +1,5 @@ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler import urlparse -from requests.packages.oauthlib.oauth1.rfc5849 import signature import mock import threading import json diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 7d55b001d0..cd0b230423 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -4,6 +4,7 @@ Unit tests for instructor.api methods. # pylint: disable=E1111 import unittest import json +import requests from urllib import quote from django.conf import settings from django.test import TestCase @@ -756,7 +757,7 @@ class TestInstructorAPIAnalyticsProxy(ModuleStoreTestCase, LoginEnrollmentTestCa class FakeProxyResponse(object): """ Fake successful requests response object. """ def __init__(self): - self.status_code = instructor.views.api.codes.OK + self.status_code = requests.status_codes.codes.OK self.content = '{"test_content": "robot test content"}' class FakeBadProxyResponse(object): diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index e5498585a3..2fcc953e52 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -9,7 +9,6 @@ Many of these GETs may become PUTs in the future. import re import logging import requests -from requests.status_codes import codes from collections import OrderedDict from django.conf import settings from django_future.csrf import ensure_csrf_cookie diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 77fbe40ecc..61c98bf419 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -53,7 +53,7 @@ python-memcached==1.48 python-openid==2.2.5 pytz==2012h PyYAML==3.10 -requests==0.14.2 +requests==1.2.3 scipy==0.11.0 Shapely==1.2.16 sorl-thumbnail==11.12 From a1d3899a4d93c2beb18388e0ea85d19617d71251 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Tue, 10 Sep 2013 11:02:30 -0400 Subject: [PATCH 2/7] Use oauthlib directly for LTI module --- common/lib/xmodule/xmodule/lti_module.py | 11 ++++------- docs/shared/requirements.txt | 1 + .../courseware/mock_lti_server/mock_lti_server.py | 2 +- lms/djangoapps/courseware/tests/test_lti.py | 9 +++++---- requirements/edx/base.txt | 1 + 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index bc07cea97e..6a9adba929 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -1,15 +1,12 @@ """ Module that allows to insert LTI tools to page. -Module uses current edx-platform 0.14.2 version of requests (oauth part). -Please update code when upgrading requests. - Protocol is oauth1, LTI version is 1.1.1: http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html """ import logging -import requests +import oauthlib import urllib from xmodule.editing_module import MetadataOnlyEditingDescriptor @@ -192,7 +189,7 @@ class LTIModule(LTIFields, XModule): Also *anonymous student id* is passed to template and therefore to LTI provider. """ - client = requests.auth.Client( + client = oauthlib.oauth1.Client( client_key=unicode(client_key), client_secret=unicode(client_secret) ) @@ -230,8 +227,8 @@ class LTIModule(LTIFields, XModule): params[u'oauth_nonce'] = params[u'OAuth oauth_nonce'] del params[u'OAuth oauth_nonce'] - # 0.14.2 (current) version of requests oauth library encodes signature, - # with 'Content-Type': 'application/x-www-form-urlencoded' + # oauthlib encodes signature with + # 'Content-Type': 'application/x-www-form-urlencoded' # so '='' becomes '%3D'. # We send form via browser, so browser will encode it again, # So we need to decode signature back: diff --git a/docs/shared/requirements.txt b/docs/shared/requirements.txt index 6504319c0d..74c05d6d53 100644 --- a/docs/shared/requirements.txt +++ b/docs/shared/requirements.txt @@ -36,6 +36,7 @@ mako==0.7.3 Markdown==2.2.1 networkx==1.7 nltk==2.0.4 +oauthlib==0.5.1 paramiko==1.9.0 path.py==3.0.1 Pillow==1.7.8 diff --git a/lms/djangoapps/courseware/mock_lti_server/mock_lti_server.py b/lms/djangoapps/courseware/mock_lti_server/mock_lti_server.py index ba9cea84d6..833df3a1c3 100644 --- a/lms/djangoapps/courseware/mock_lti_server/mock_lti_server.py +++ b/lms/djangoapps/courseware/mock_lti_server/mock_lti_server.py @@ -1,6 +1,6 @@ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler import urlparse -from requests.packages.oauthlib.oauth1.rfc5849 import signature +from oauthlib.oauth1.rfc5849 import signature import mock from logging import getLogger logger = getLogger(__name__) diff --git a/lms/djangoapps/courseware/tests/test_lti.py b/lms/djangoapps/courseware/tests/test_lti.py index d2b4ea6867..71b5a1c3bb 100644 --- a/lms/djangoapps/courseware/tests/test_lti.py +++ b/lms/djangoapps/courseware/tests/test_lti.py @@ -1,6 +1,6 @@ """LTI integration tests""" -import requests +import oauthlib from . import BaseTestXmodule from collections import OrderedDict import mock @@ -11,7 +11,8 @@ class TestLTI(BaseTestXmodule): Integration test for lti xmodule. It checks overall code, by assuring that context that goes to template is correct. - As part of that, checks oauth signature generation by mocking signing function of `requests` library. + As part of that, checks oauth signature generation by mocking signing function + of `oauthlib` library. """ CATEGORY = "lti" @@ -43,7 +44,7 @@ class TestLTI(BaseTestXmodule): u'oauth_signature': mocked_decoded_signature } - saved_sign = requests.auth.Client.sign + saved_sign = oauthlib.oauth1.Client.sign def mocked_sign(self, *args, **kwargs): """ @@ -60,7 +61,7 @@ class TestLTI(BaseTestXmodule): headers[u'Authorization'] = ', '.join([k+'="'+v+'"' for k, v in old_parsed.items()]) return None, headers, None - patcher = mock.patch.object(requests.auth.Client, "sign", mocked_sign) + patcher = mock.patch.object(oauthlib.oauth1.Client, "sign", mocked_sign) patcher.start() self.addCleanup(patcher.stop) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 61c98bf419..44ab122c94 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -39,6 +39,7 @@ mako==0.7.3 Markdown==2.2.1 networkx==1.7 nltk==2.0.4 +oauthlib==0.5.1 paramiko==1.9.0 path.py==3.0.1 Pillow==1.7.8 From 871ad7d69483099c96bc7d4e9105cb1287d31853 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Tue, 10 Sep 2013 14:21:56 -0400 Subject: [PATCH 3/7] Pass hostname to LTI XModule Necessary for RFC compliance with oauthlib --- common/lib/capa/capa/tests/__init__.py | 1 + common/lib/xmodule/xmodule/lti_module.py | 9 ++++++--- common/lib/xmodule/xmodule/tests/__init__.py | 1 + common/lib/xmodule/xmodule/x_module.py | 3 ++- lms/djangoapps/courseware/module_render.py | 3 ++- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/common/lib/capa/capa/tests/__init__.py b/common/lib/capa/capa/tests/__init__.py index ac81ff66c4..a1f75b0e92 100644 --- a/common/lib/capa/capa/tests/__init__.py +++ b/common/lib/capa/capa/tests/__init__.py @@ -36,6 +36,7 @@ def test_system(): user=Mock(), filestore=fs.osfs.OSFS(os.path.join(TEST_DIR, "test_files")), debug=True, + hostname="edx.org", xqueue={'interface': xqueue_interface, 'construct_callback': calledback_url, 'default_queuename': 'testqueue', 'waittime': 10}, node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"), anonymous_student_id='student', diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index 6a9adba929..939190840a 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -6,7 +6,7 @@ http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html """ import logging -import oauthlib +import oauthlib.oauth1 import urllib from xmodule.editing_module import MetadataOnlyEditingDescriptor @@ -212,8 +212,11 @@ class LTIModule(LTIFields, XModule): # appending custom parameter for signing body.update(custom_parameters) - # This is needed for body encoding: - headers = {'Content-Type': 'application/x-www-form-urlencoded'} + headers = { + 'Host': self.system.HOSTNAME, + # This is needed for body encoding: + 'Content-Type': 'application/x-www-form-urlencoded', + } __, headers, __ = client.sign( unicode(self.launch_url), diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index b7e5ea8435..7f838aa242 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -62,6 +62,7 @@ def get_test_system(course_id=''): user=Mock(is_staff=False), filestore=Mock(), debug=True, + hostname="edx.org", xqueue={'interface': None, 'callback_url': '/', 'default_queuename': 'testqueue', 'waittime': 10, 'construct_callback' : Mock(side_effect="/")}, node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"), xblock_field_data=lambda descriptor: descriptor._field_data, diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 02feebea1b..edb9e7f640 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -833,7 +833,7 @@ class ModuleSystem(Runtime): def __init__( self, ajax_url, track_function, get_module, render_template, replace_urls, xblock_field_data, user=None, filestore=None, - debug=False, xqueue=None, publish=None, node_path="", + debug=False, hostname="", xqueue=None, publish=None, node_path="", anonymous_student_id='', course_id=None, open_ended_grading_interface=None, s3_interface=None, cache=None, can_execute_unsafe_code=None, replace_course_urls=None, @@ -897,6 +897,7 @@ class ModuleSystem(Runtime): self.get_module = get_module self.render_template = render_template self.DEBUG = self.debug = debug + self.HOSTNAME = self.hostname = hostname self.seed = user.id if user is not None else 0 self.replace_urls = replace_urls self.node_path = node_path diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 53f9c57f38..b6d22fbf57 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -347,6 +347,8 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours filestore=descriptor.system.resources_fs, get_module=inner_get_module, user=user, + debug=settings.DEBUG, + hostname=settings.SITE_NAME, # TODO (cpennington): This should be removed when all html from # a module is coming through get_html and is therefore covered # by the replace_static_urls code below @@ -380,7 +382,6 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours # pass position specified in URL to module through ModuleSystem system.set('position', position) - system.set('DEBUG', settings.DEBUG) if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'): system.set( 'psychometrics_handler', # set callback for updating PsychometricsData From 6a8546801c1e3d85c088dfe608bcf25a519ffa14 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Wed, 11 Sep 2013 10:18:00 -0400 Subject: [PATCH 4/7] Response.json is now a callable --- .../open_ended_grading_classes/grading_service_module.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py index 3a107d51c1..6248c63091 100644 --- a/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py +++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py @@ -42,7 +42,7 @@ class GradingService(object): response.raise_for_status() - return response.json + return response.json() def post(self, url, data, allow_redirects=False): """ @@ -88,9 +88,10 @@ class GradingService(object): Returns the result of operation(). Does not catch exceptions. """ response = operation() - if (response.json - and response.json.get('success') is False - and response.json.get('error') == 'login_required'): + resp_json = response.json() + if (resp_json + and resp_json.get('success') is False + and resp_json.get('error') == 'login_required'): # apparrently we aren't logged in. Try to fix that. r = self._login() if r and not r.get('success'): From 68409f0c7afadba6a2a6646d4d408b9fab9a709c Mon Sep 17 00:00:00 2001 From: Alexander Kryklia Date: Wed, 11 Sep 2013 19:16:46 +0300 Subject: [PATCH 5/7] Add default launch url for lti. --- common/lib/xmodule/xmodule/js/src/lti/lti.js | 4 ++-- common/lib/xmodule/xmodule/lti_module.py | 6 ++++-- lms/djangoapps/courseware/tests/test_lti.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/lti/lti.js b/common/lib/xmodule/xmodule/js/src/lti/lti.js index e5b6885e1b..7d5b183f21 100644 --- a/common/lib/xmodule/xmodule/js/src/lti/lti.js +++ b/common/lib/xmodule/xmodule/js/src/lti/lti.js @@ -16,9 +16,9 @@ window.LTI = (function () { // If the Form's action attribute is set (i.e. we can perform a normal // submit), then we submit the form and make the frame shown. - if (form.attr('action')) { + if (form.attr('action') && form.attr('action') !== 'http://www.example.com') { form.submit(); - element.find('.lti').addClass('rendered') + element.find('.lti').addClass('rendered'); } } diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index 939190840a..0144071a19 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -38,9 +38,12 @@ class LTIFields(object): vbid=put_book_id_here book_location=page/put_page_number_here + Default non-empty url for `launch_url` is needed due to oauthlib demand (url scheme should be presented):: + + https://github.com/idan/oauthlib/blob/master/oauthlib/oauth1/rfc5849/signature.py#L136 """ lti_id = String(help="Id of the tool", default='', scope=Scope.settings) - launch_url = String(help="URL of the tool", default='', scope=Scope.settings) + launch_url = String(help="URL of the tool", default='http://www.example.com', scope=Scope.settings) custom_parameters = List(help="Custom parameters (vbid, book_location, etc..)", scope=Scope.settings) @@ -213,7 +216,6 @@ class LTIModule(LTIFields, XModule): body.update(custom_parameters) headers = { - 'Host': self.system.HOSTNAME, # This is needed for body encoding: 'Content-Type': 'application/x-www-form-urlencoded', } diff --git a/lms/djangoapps/courseware/tests/test_lti.py b/lms/djangoapps/courseware/tests/test_lti.py index 71b5a1c3bb..596ec2dd9a 100644 --- a/lms/djangoapps/courseware/tests/test_lti.py +++ b/lms/djangoapps/courseware/tests/test_lti.py @@ -75,6 +75,6 @@ class TestLTI(BaseTestXmodule): 'input_fields': self.correct_headers, 'element_class': self.item_module.location.category, 'element_id': self.item_module.location.html_id(), - 'launch_url': '', # default value + 'launch_url': 'http://www.example.com', # default value } self.assertDictEqual(generated_context, expected_context) From 4621952a5512a3e96e1d729d560537143a2de07a Mon Sep 17 00:00:00 2001 From: Alexander Kryklia Date: Wed, 11 Sep 2013 19:32:06 +0300 Subject: [PATCH 6/7] Stub headers if scheme not provided. --- common/lib/xmodule/xmodule/lti_module.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index 0144071a19..e2c4832251 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -220,11 +220,21 @@ class LTIModule(LTIFields, XModule): 'Content-Type': 'application/x-www-form-urlencoded', } - __, headers, __ = client.sign( - unicode(self.launch_url), - http_method=u'POST', - body=body, - headers=headers) + try: + __, headers, __ = client.sign( + unicode(self.launch_url), + http_method=u'POST', + body=body, + headers=headers) + except ValueError: # scheme not in url + #https://github.com/idan/oauthlib/blob/master/oauthlib/oauth1/rfc5849/signature.py#L136 + #Stubbing headers for now: + headers = { + u'Content-Type': u'application/x-www-form-urlencoded', + u'Authorization': u'OAuth oauth_nonce="80966668944732164491378916897", \ +oauth_timestamp="1378916897", oauth_version="1.0", oauth_signature_method="HMAC-SHA1", \ +oauth_consumer_key="", oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"'} + params = headers['Authorization'] # parse headers to pass to template as part of context: params = dict([param.strip().replace('"', '').split('=') for param in params.split(',')]) From acd23ad933664400fc6d81c67bfab168e4bad339 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Wed, 11 Sep 2013 13:26:17 -0400 Subject: [PATCH 7/7] reformat for readability --- common/lib/xmodule/xmodule/lti_module.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index e2c4832251..a7ccb728d0 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -227,13 +227,17 @@ class LTIModule(LTIFields, XModule): body=body, headers=headers) except ValueError: # scheme not in url - #https://github.com/idan/oauthlib/blob/master/oauthlib/oauth1/rfc5849/signature.py#L136 - #Stubbing headers for now: + # Stubbing headers for now: headers = { u'Content-Type': u'application/x-www-form-urlencoded', - u'Authorization': u'OAuth oauth_nonce="80966668944732164491378916897", \ -oauth_timestamp="1378916897", oauth_version="1.0", oauth_signature_method="HMAC-SHA1", \ -oauth_consumer_key="", oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"'} + u'Authorization': u'oAuth ' # cont.. + u'oauth_nonce="80966668944732164491378916897", ' # cont.. + u'oauth_timestamp="1378916897", ' # cont.. + u'oauth_version="1.0", ' # cont.. + u'oauth_signature_method="HMAC-SHA1", ' # cont.. + u'oauth_consumer_key="", ' # cont.. + u'oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"', + } params = headers['Authorization'] # parse headers to pass to template as part of context: