##// END OF EJS Templates
rss: use permalinks without slashes for feeds. Fixes #5557
marcink -
r3810:d0cfe4e5 stable
parent child
Show More
@@ -485,13 +485,21 def includeme(config):
485 name='edit_repo_audit_logs',
485 name='edit_repo_audit_logs',
486 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
486 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
487
487
488 # ATOM/RSS Feed
488 # ATOM/RSS Feed, shouldn't contain slashes for outlook compatibility
489 config.add_route(
489 config.add_route(
490 name='rss_feed_home',
490 name='rss_feed_home',
491 pattern='/{repo_name:.*?[^/]}/feed-rss', repo_route=True)
492
493 config.add_route(
494 name='atom_feed_home',
495 pattern='/{repo_name:.*?[^/]}/feed-atom', repo_route=True)
496
497 config.add_route(
498 name='rss_feed_home_old',
491 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
499 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
492
500
493 config.add_route(
501 config.add_route(
494 name='atom_feed_home',
502 name='atom_feed_home_old',
495 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
503 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
496
504
497 # NOTE(marcink): needs to be at the end for catch-all
505 # NOTE(marcink): needs to be at the end for catch-all
@@ -27,8 +27,10 def route_path(name, params=None, **kwar
27 import urllib
27 import urllib
28
28
29 base_url = {
29 base_url = {
30 'rss_feed_home': '/{repo_name}/feed/rss',
30 'rss_feed_home': '/{repo_name}/feed-rss',
31 'atom_feed_home': '/{repo_name}/feed/atom',
31 'atom_feed_home': '/{repo_name}/feed-atom',
32 'rss_feed_home_old': '/{repo_name}/feed/rss',
33 'atom_feed_home_old': '/{repo_name}/feed/atom',
32 }[name].format(**kwargs)
34 }[name].format(**kwargs)
33
35
34 if params:
36 if params:
@@ -73,6 +75,42 class TestFeedView(TestController):
73
75
74 assert response.content_type == content_type
76 assert response.content_type == content_type
75
77
78 @pytest.mark.parametrize("feed_type, content_type", [
79 ('rss', "application/rss+xml"),
80 ('atom', "application/atom+xml")
81 ])
82 def test_feed_with_auth_token_by_uid(
83 self, backend, user_admin, feed_type, content_type):
84 auth_token = user_admin.feed_token
85 assert auth_token != ''
86
87 response = self.app.get(
88 route_path(
89 '{}_feed_home'.format(feed_type),
90 repo_name='_{}'.format(backend.repo.repo_id),
91 params=dict(auth_token=auth_token)),
92 status=200)
93
94 assert response.content_type == content_type
95
96 @pytest.mark.parametrize("feed_type, content_type", [
97 ('rss', "application/rss+xml"),
98 ('atom', "application/atom+xml")
99 ])
100 def test_feed_old_urls_with_auth_token(
101 self, backend, user_admin, feed_type, content_type):
102 auth_token = user_admin.feed_token
103 assert auth_token != ''
104
105 response = self.app.get(
106 route_path(
107 '{}_feed_home_old'.format(feed_type),
108 repo_name=backend.repo_name,
109 params=dict(auth_token=auth_token)),
110 status=200)
111
112 assert response.content_type == content_type
113
76 @pytest.mark.parametrize("feed_type", ['rss', 'atom'])
114 @pytest.mark.parametrize("feed_type", ['rss', 'atom'])
77 def test_feed_with_auth_token_of_wrong_type(
115 def test_feed_with_auth_token_of_wrong_type(
78 self, backend, user_util, feed_type):
116 self, backend, user_util, feed_type):
@@ -40,8 +40,6 log = logging.getLogger(__name__)
40 class RepoFeedView(RepoAppView):
40 class RepoFeedView(RepoAppView):
41 def load_default_context(self):
41 def load_default_context(self):
42 c = self._get_local_tmpl_context()
42 c = self._get_local_tmpl_context()
43
44
45 self._load_defaults()
43 self._load_defaults()
46 return c
44 return c
47
45
@@ -117,6 +115,9 class RepoFeedView(RepoAppView):
117 @view_config(
115 @view_config(
118 route_name='atom_feed_home', request_method='GET',
116 route_name='atom_feed_home', request_method='GET',
119 renderer=None)
117 renderer=None)
118 @view_config(
119 route_name='atom_feed_home_old', request_method='GET',
120 renderer=None)
120 def atom(self):
121 def atom(self):
121 """
122 """
122 Produce an atom-1.0 feed via feedgenerator module
123 Produce an atom-1.0 feed via feedgenerator module
@@ -181,6 +182,9 class RepoFeedView(RepoAppView):
181 @view_config(
182 @view_config(
182 route_name='rss_feed_home', request_method='GET',
183 route_name='rss_feed_home', request_method='GET',
183 renderer=None)
184 renderer=None)
185 @view_config(
186 route_name='rss_feed_home_old', request_method='GET',
187 renderer=None)
184 def rss(self):
188 def rss(self):
185 """
189 """
186 Produce an rss2 feed via feedgenerator module
190 Produce an rss2 feed via feedgenerator module
@@ -1841,6 +1841,10 class Repository(Base, BaseModel):
1841 return q.all()
1841 return q.all()
1842
1842
1843 @property
1843 @property
1844 def repo_uid(self):
1845 return '_{}'.format(self.repo_id)
1846
1847 @property
1844 def forks(self):
1848 def forks(self):
1845 """
1849 """
1846 Return forks of this repo
1850 Return forks of this repo
@@ -263,8 +263,10 function registerRCRoutes() {
263 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
263 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
264 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
264 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
265 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
265 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
266 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed/rss', ['repo_name']);
266 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']);
267 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed/atom', ['repo_name']);
267 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']);
268 pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']);
269 pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']);
268 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
270 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
269 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
271 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
270 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
272 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
@@ -217,7 +217,7
217 ## Context Actions
217 ## Context Actions
218 <div class="pull-right">
218 <div class="pull-right">
219 %if c.rhodecode_user.username != h.DEFAULT_USER:
219 %if c.rhodecode_user.username != h.DEFAULT_USER:
220 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
220 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
221
221
222 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
222 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
223 % if c.repository_is_user_following:
223 % if c.repository_is_user_following:
@@ -228,7 +228,7
228
228
229 </a>
229 </a>
230 %else:
230 %else:
231 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
231 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
232 %endif
232 %endif
233 </div>
233 </div>
234
234
@@ -2,7 +2,7
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ## represents page title
4 ## represents page title
5 ${_('%s Summary') % c.repo_name}
5 ${_('{} Summary').format(c.repo_name)}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
@@ -10,8 +10,8
10
10
11
11
12 <%def name="head_extra()">
12 <%def name="head_extra()">
13 <link href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s ATOM feed') % c.repo_name)}" type="application/atom+xml" />
13 <link href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s ATOM feed') % c.repo_name)}" type="application/atom+xml" />
14 <link href="${h.route_path('rss_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s RSS feed') % c.repo_name)}" type="application/rss+xml" />
14 <link href="${h.route_path('rss_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s RSS feed') % c.repo_name)}" type="application/rss+xml" />
15 </%def>
15 </%def>
16
16
17
17
General Comments 0
You need to be logged in to leave comments. Login now