Merge pull request #11243 from edx/hasnain-naveed/HOL-37-proxy-rss
HOL-12 HOL-29 rss_proxy djangoapp
This commit is contained in:
0
lms/djangoapps/rss_proxy/__init__.py
Normal file
0
lms/djangoapps/rss_proxy/__init__.py
Normal file
7
lms/djangoapps/rss_proxy/admin.py
Normal file
7
lms/djangoapps/rss_proxy/admin.py
Normal file
@@ -0,0 +1,7 @@
|
||||
"""
|
||||
Admin module for the rss_proxy djangoapp.
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from rss_proxy.models import WhitelistedRssUrl
|
||||
|
||||
admin.site.register(WhitelistedRssUrl)
|
||||
24
lms/djangoapps/rss_proxy/migrations/0001_initial.py
Normal file
24
lms/djangoapps/rss_proxy/migrations/0001_initial.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='WhitelistedRssUrl',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
|
||||
('url', models.CharField(unique=True, max_length=255, db_index=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
0
lms/djangoapps/rss_proxy/migrations/__init__.py
Normal file
0
lms/djangoapps/rss_proxy/migrations/__init__.py
Normal file
20
lms/djangoapps/rss_proxy/models.py
Normal file
20
lms/djangoapps/rss_proxy/models.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
Models for the rss_proxy djangoapp.
|
||||
"""
|
||||
from django.db import models
|
||||
from model_utils.models import TimeStampedModel
|
||||
|
||||
|
||||
class WhitelistedRssUrl(TimeStampedModel):
|
||||
"""
|
||||
Model for persisting RSS feed URLs which are whitelisted
|
||||
for proxying via this rss_proxy djangoapp.
|
||||
"""
|
||||
url = models.CharField(max_length=255, unique=True, db_index=True)
|
||||
|
||||
class Meta(object):
|
||||
""" Meta class for this Django model """
|
||||
app_label = "rss_proxy"
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.url)
|
||||
0
lms/djangoapps/rss_proxy/tests/__init__.py
Normal file
0
lms/djangoapps/rss_proxy/tests/__init__.py
Normal file
19
lms/djangoapps/rss_proxy/tests/test_models.py
Normal file
19
lms/djangoapps/rss_proxy/tests/test_models.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""
|
||||
Tests for the rss_proxy models
|
||||
"""
|
||||
from django.test import TestCase
|
||||
from rss_proxy.models import WhitelistedRssUrl
|
||||
|
||||
|
||||
class WhitelistedRssUrlTests(TestCase):
|
||||
""" Tests for the rss_proxy.WhitelistedRssUrl model """
|
||||
|
||||
def setUp(self):
|
||||
super(WhitelistedRssUrlTests, self).setUp()
|
||||
self.whitelisted_rss_url = WhitelistedRssUrl.objects.create(url='http://www.example.com')
|
||||
|
||||
def test_unicode(self):
|
||||
"""
|
||||
Test the unicode function returns the url
|
||||
"""
|
||||
self.assertEqual(unicode(self.whitelisted_rss_url), self.whitelisted_rss_url.url)
|
||||
69
lms/djangoapps/rss_proxy/tests/test_views.py
Normal file
69
lms/djangoapps/rss_proxy/tests/test_views.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Tests for the rss_proxy views
|
||||
"""
|
||||
from django.test import TestCase
|
||||
from django.core.urlresolvers import reverse
|
||||
from mock import patch, Mock
|
||||
from rss_proxy.models import WhitelistedRssUrl
|
||||
|
||||
|
||||
class RssProxyViewTests(TestCase):
|
||||
""" Tests for the rss_proxy views """
|
||||
|
||||
def setUp(self):
|
||||
super(RssProxyViewTests, self).setUp()
|
||||
|
||||
self.whitelisted_url1 = 'http://www.example.com'
|
||||
self.whitelisted_url2 = 'http://www.example.org'
|
||||
self.non_whitelisted_url = 'http://www.example.net'
|
||||
self.rss = '''
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title></title>
|
||||
<link>http://www.example.com/rss</link>
|
||||
<description></description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>Example</title>
|
||||
<link>http://www.example.com/rss/item</link>
|
||||
<description>Example item description</description>
|
||||
<pubDate>Fri, 13 May 1977 00:00:00 +0000</pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
'''
|
||||
WhitelistedRssUrl.objects.create(url=self.whitelisted_url1)
|
||||
WhitelistedRssUrl.objects.create(url=self.whitelisted_url2)
|
||||
|
||||
@patch('rss_proxy.views.requests.get')
|
||||
def test_proxy_with_whitelisted_url(self, mock_requests_get):
|
||||
"""
|
||||
Test the proxy view with a whitelisted URL
|
||||
"""
|
||||
mock_requests_get.return_value = Mock(status_code=200, content=self.rss)
|
||||
resp = self.client.get('%s?url=%s' % (reverse('rss_proxy:proxy'), self.whitelisted_url1))
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp['Content-Type'], 'application/xml')
|
||||
self.assertEqual(resp.content, self.rss)
|
||||
|
||||
@patch('rss_proxy.views.requests.get')
|
||||
def test_proxy_with_whitelisted_url_404(self, mock_requests_get):
|
||||
"""
|
||||
Test the proxy view with a whitelisted URL that is not found
|
||||
"""
|
||||
mock_requests_get.return_value = Mock(status_code=404)
|
||||
resp = self.client.get('%s?url=%s' % (reverse('rss_proxy:proxy'), self.whitelisted_url2))
|
||||
print resp.status_code
|
||||
print resp.content
|
||||
print resp['Content-Type']
|
||||
self.assertEqual(resp.status_code, 404)
|
||||
self.assertEqual(resp['Content-Type'], 'application/xml')
|
||||
self.assertEqual(resp.content, '')
|
||||
|
||||
def test_proxy_with_non_whitelisted_url(self):
|
||||
"""
|
||||
Test the proxy view with a non-whitelisted URL
|
||||
"""
|
||||
resp = self.client.get('%s?url=%s' % (reverse('rss_proxy:proxy'), self.non_whitelisted_url))
|
||||
self.assertEqual(resp.status_code, 404)
|
||||
9
lms/djangoapps/rss_proxy/urls.py
Normal file
9
lms/djangoapps/rss_proxy/urls.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
URLs for the rss_proxy djangoapp.
|
||||
"""
|
||||
from django.conf.urls import url
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^$", "rss_proxy.views.proxy", name="proxy"),
|
||||
]
|
||||
38
lms/djangoapps/rss_proxy/views.py
Normal file
38
lms/djangoapps/rss_proxy/views.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Views for the rss_proxy djangoapp.
|
||||
"""
|
||||
import requests
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponse, HttpResponseNotFound
|
||||
from rss_proxy.models import WhitelistedRssUrl
|
||||
|
||||
|
||||
CACHE_KEY_RSS = "rss_proxy.{url}"
|
||||
|
||||
|
||||
def proxy(request):
|
||||
"""
|
||||
Proxy requests for the given RSS url if it has been whitelisted.
|
||||
"""
|
||||
|
||||
url = request.GET.get('url')
|
||||
if url and WhitelistedRssUrl.objects.filter(url=url).exists():
|
||||
# Check cache for RSS if the given url is whitelisted
|
||||
cache_key = CACHE_KEY_RSS.format(url=url)
|
||||
status_code = 200
|
||||
rss = cache.get(cache_key, '')
|
||||
print cache_key
|
||||
print 'Cached rss: %s' % rss
|
||||
if not rss:
|
||||
# Go get the RSS from the URL if it was not cached
|
||||
resp = requests.get(url)
|
||||
status_code = resp.status_code
|
||||
if status_code == 200:
|
||||
# Cache RSS
|
||||
rss = resp.content
|
||||
cache.set(cache_key, rss, settings.RSS_PROXY_CACHE_TIMEOUT)
|
||||
return HttpResponse(rss, status=status_code, content_type='application/xml')
|
||||
|
||||
return HttpResponseNotFound()
|
||||
@@ -1860,6 +1860,9 @@ INSTALLED_APPS = (
|
||||
# Microsite configuration
|
||||
'microsite_configuration',
|
||||
|
||||
# RSS Proxy
|
||||
'rss_proxy',
|
||||
|
||||
# Student Identity Reverification
|
||||
'reverification',
|
||||
|
||||
@@ -2656,6 +2659,9 @@ MICROSITE_TEMPLATE_BACKEND = 'microsite_configuration.backends.filebased.Filebas
|
||||
# TTL for microsite database template cache
|
||||
MICROSITE_DATABASE_TEMPLATE_CACHE_TTL = 5 * 60
|
||||
|
||||
################################ Settings for rss_proxy ################################
|
||||
|
||||
RSS_PROXY_CACHE_TIMEOUT = 3600 # The length of time we cache RSS retrieved from remote URLs in seconds
|
||||
|
||||
#### PROCTORING CONFIGURATION DEFAULTS
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ urlpatterns = (
|
||||
|
||||
url(r'^api/commerce/', include('commerce.api.urls', namespace='commerce_api')),
|
||||
url(r'^api/credit/', include('openedx.core.djangoapps.credit.urls', app_name="credit", namespace='credit')),
|
||||
url(r'^rss_proxy/', include('rss_proxy.urls', namespace='rss_proxy')),
|
||||
)
|
||||
|
||||
if settings.FEATURES["ENABLE_COMBINED_LOGIN_REGISTRATION"]:
|
||||
|
||||
Reference in New Issue
Block a user