Switched most stuff over from Routes
Removed the Routes routing functionality and replaced it with werkzeug.routes. Most views are functional. Known issues: - Translation integration with the request object is not yet figured out. This breaks 404 pages.
This commit is contained in:
parent
a817fb76b1
commit
7742dcc1fb
@ -18,11 +18,12 @@ import os
|
||||
import urllib
|
||||
import logging
|
||||
|
||||
import routes
|
||||
from webob import exc
|
||||
from werkzeug.wrappers import Request
|
||||
from mediagoblin.routing import url_map, view_functions, add_route
|
||||
|
||||
from mediagoblin import routing, meddleware, __version__
|
||||
from werkzeug.wrappers import Request
|
||||
from werkzeug.exceptions import HTTPException, NotFound
|
||||
|
||||
from mediagoblin import meddleware, __version__
|
||||
from mediagoblin.tools import common, translate, template
|
||||
from mediagoblin.tools.response import render_404
|
||||
from mediagoblin.tools.theme import register_themes
|
||||
@ -90,7 +91,10 @@ class MediaGoblinApp(object):
|
||||
self.public_store, self.queue_store = setup_storage()
|
||||
|
||||
# set up routing
|
||||
self.routing = routing.get_mapper(PluginManager().get_routes())
|
||||
self.url_map = url_map
|
||||
|
||||
for route in PluginManager().get_routes():
|
||||
add_route(*route)
|
||||
|
||||
# set up staticdirector tool
|
||||
self.staticdirector = get_staticdirector(app_config)
|
||||
@ -135,7 +139,7 @@ class MediaGoblinApp(object):
|
||||
|
||||
## Routing / controller loading stuff
|
||||
path_info = request.path
|
||||
route_match = self.routing.match(path_info)
|
||||
map_adapter = self.url_map.bind_to_environ(request.environ)
|
||||
|
||||
# By using fcgi, mediagoblin can run under a base path
|
||||
# like /mediagoblin/. request.path_info contains the
|
||||
@ -154,47 +158,52 @@ class MediaGoblinApp(object):
|
||||
environ.pop('HTTPS')
|
||||
|
||||
## Attach utilities to the request object
|
||||
request.matchdict = route_match
|
||||
request.urlgen = routes.URLGenerator(self.routing, environ)
|
||||
# Do we really want to load this via middleware? Maybe?
|
||||
request.session = request.environ['beaker.session']
|
||||
# Attach self as request.app
|
||||
# Also attach a few utilities from request.app for convenience?
|
||||
request.app = self
|
||||
request.locale = translate.get_locale_from_request(request)
|
||||
|
||||
request.template_env = template.get_jinja_env(
|
||||
self.template_loader, request.locale)
|
||||
request.db = self.db
|
||||
request.staticdirect = self.staticdirector
|
||||
|
||||
mg_request.setup_user_in_request(request)
|
||||
|
||||
# No matching page?
|
||||
if route_match is None:
|
||||
# Try to do see if we have a match with a trailing slash
|
||||
# added and if so, redirect
|
||||
if not path_info.endswith('/') \
|
||||
and request.method == 'GET' \
|
||||
and self.routing.match(path_info + '/'):
|
||||
new_path_info = path_info + '/'
|
||||
if request.GET:
|
||||
new_path_info = '%s?%s' % (
|
||||
new_path_info, urllib.urlencode(request.GET))
|
||||
redirect = exc.HTTPFound(location=new_path_info)
|
||||
return request.get_response(redirect)(environ, start_response)
|
||||
try:
|
||||
endpoint, url_values = map_adapter.match()
|
||||
request.matchdict = url_values
|
||||
|
||||
# Okay, no matches. 404 time!
|
||||
request.matchdict = {} # in case our template expects it
|
||||
request.locale = translate.get_locale_from_request(request)
|
||||
request.template_env = template.get_jinja_env(
|
||||
self.template_loader, request.locale)
|
||||
except NotFound as exc:
|
||||
return NotImplemented
|
||||
return render_404(request)(environ, start_response)
|
||||
except HTTPException as exc:
|
||||
# Support legacy webob.exc responses
|
||||
return exc(environ, start_response)
|
||||
|
||||
# import the controller, or if it's already a callable, call that
|
||||
route_controller = route_match['controller']
|
||||
if isinstance(route_controller, unicode) \
|
||||
or isinstance(route_controller, str):
|
||||
controller = common.import_component(route_match['controller'])
|
||||
def build_proxy(endpoint, **kw):
|
||||
try:
|
||||
qualified = kw.pop('qualified')
|
||||
except KeyError:
|
||||
qualified = False
|
||||
|
||||
return map_adapter.build(
|
||||
endpoint,
|
||||
values=dict(**kw),
|
||||
force_external=qualified)
|
||||
|
||||
request.urlgen = build_proxy
|
||||
|
||||
view_func = view_functions[endpoint]
|
||||
|
||||
# import the endpoint, or if it's already a callable, call that
|
||||
if isinstance(view_func, unicode) \
|
||||
or isinstance(view_func, str):
|
||||
controller = common.import_component(view_func)
|
||||
else:
|
||||
controller = route_match['controller']
|
||||
controller = view_func
|
||||
|
||||
# pass the request through our meddleware classes
|
||||
for m in self.meddleware:
|
||||
|
@ -14,25 +14,36 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from routes.route import Route
|
||||
from routes.route import add_route
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
auth_routes = [
|
||||
Route('mediagoblin.auth.register', '/register/',
|
||||
controller='mediagoblin.auth.views:register'),
|
||||
Route('mediagoblin.auth.login', '/login/',
|
||||
controller='mediagoblin.auth.views:login'),
|
||||
Route('mediagoblin.auth.logout', '/logout/',
|
||||
controller='mediagoblin.auth.views:logout'),
|
||||
Route('mediagoblin.auth.verify_email', '/verify_email/',
|
||||
controller='mediagoblin.auth.views:verify_email'),
|
||||
Route('mediagoblin.auth.resend_verification', '/resend_verification/',
|
||||
controller='mediagoblin.auth.views:resend_activation'),
|
||||
Route('mediagoblin.auth.resend_verification_success',
|
||||
'/resend_verification_success/',
|
||||
template='mediagoblin/auth/resent_verification_email.html',
|
||||
controller='mediagoblin.views:simple_template_render'),
|
||||
Route('mediagoblin.auth.forgot_password', '/forgot_password/',
|
||||
controller='mediagoblin.auth.views:forgot_password'),
|
||||
Route('mediagoblin.auth.verify_forgot_password',
|
||||
'/forgot_password/verify/',
|
||||
controller='mediagoblin.auth.views:verify_forgot_password')]
|
||||
add_route('mediagoblin.auth.logout',
|
||||
'/auth/logout/', 'mediagoblin.auth.views:logout')
|
||||
|
||||
|
||||
add_route('mediagoblin.auth.register', '/register/',
|
||||
'mediagoblin.auth.views:register')
|
||||
|
||||
add_route('mediagoblin.auth.login', '/login/',
|
||||
'mediagoblin.auth.views:login')
|
||||
|
||||
add_route('mediagoblin.auth.logout', '/logout/',
|
||||
'mediagoblin.auth.views:logout')
|
||||
|
||||
add_route('mediagoblin.auth.verify_email', '/verify_email/',
|
||||
'mediagoblin.auth.views:verify_email')
|
||||
|
||||
add_route('mediagoblin.auth.resend_verification', '/resend_verification/',
|
||||
'mediagoblin.auth.views:resend_activation')
|
||||
|
||||
add_route('mediagoblin.auth.resend_verification_success',
|
||||
'/resend_verification_success/',
|
||||
template='mediagoblin/auth/resent_verification_email.html',
|
||||
'mediagoblin.views:simple_template_render')
|
||||
|
||||
add_route('mediagoblin.auth.forgot_password', '/forgot_password/',
|
||||
'mediagoblin.auth.views:forgot_password')
|
||||
|
||||
add_route('mediagoblin.auth.verify_forgot_password',
|
||||
'/forgot_password/verify/',
|
||||
'mediagoblin.auth.views:verify_forgot_password')
|
||||
|
@ -14,13 +14,9 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
from routes.route import Route
|
||||
|
||||
edit_routes = [
|
||||
# Media editing view handled in user_pages/routing.py
|
||||
Route('mediagoblin.edit.profile', '/profile/',
|
||||
controller="mediagoblin.edit.views:edit_profile"),
|
||||
Route('mediagoblin.edit.account', '/account/',
|
||||
controller="mediagoblin.edit.views:edit_account"),
|
||||
]
|
||||
add_route('mediagoblin.edit.profile', '/edit/profile/',
|
||||
'mediagoblin.edit.views:edit_profile')
|
||||
add_route('mediagoblin.edit.account', '/edit/account/',
|
||||
'mediagoblin.edit.views:edit_account')
|
||||
|
@ -14,14 +14,10 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
from routes.route import Route
|
||||
|
||||
tag_routes = [
|
||||
# Route('mediagoblin.listings.tags_home', "/",
|
||||
# controller="mediagoblin.listings.views:tags_home"),
|
||||
Route('mediagoblin.listings.tags_listing', "/{tag}/",
|
||||
controller="mediagoblin.listings.views:tag_listing"),
|
||||
Route('mediagoblin.listings.tag_atom_feed', "/{tag}/atom/",
|
||||
controller="mediagoblin.listings.views:tag_atom_feed"),
|
||||
]
|
||||
add_route('mediagoblin.listings.tags_listing',
|
||||
"/tag/<string:tag>/",
|
||||
"mediagoblin.listings.views:tag_listing")
|
||||
add_route('mediagoblin.listings.tag_atom_feed', "/tag/<string:tag>/atom/",
|
||||
"mediagoblin.listings.views:tag_atom_feed")
|
||||
|
@ -33,12 +33,12 @@ def setup_plugin():
|
||||
_log.debug('API config: {0}'.format(config))
|
||||
|
||||
routes = [
|
||||
Route('mediagoblin.plugins.api.test', '/api/test',
|
||||
controller='mediagoblin.plugins.api.views:api_test'),
|
||||
Route('mediagoblin.plugins.api.entries', '/api/entries',
|
||||
controller='mediagoblin.plugins.api.views:get_entries'),
|
||||
Route('mediagoblin.plugins.api.post_entry', '/api/submit',
|
||||
controller='mediagoblin.plugins.api.views:post_entry')]
|
||||
('mediagoblin.plugins.api.test', '/api/test',
|
||||
'mediagoblin.plugins.api.views:api_test'),
|
||||
('mediagoblin.plugins.api.entries', '/api/entries',
|
||||
'mediagoblin.plugins.api.views:get_entries'),
|
||||
('mediagoblin.plugins.api.post_entry', '/api/submit',
|
||||
'mediagoblin.plugins.api.views:post_entry')]
|
||||
|
||||
pluginapi.register_routes(routes)
|
||||
|
||||
|
@ -36,21 +36,21 @@ def setup_plugin():
|
||||
_log.debug('OAuth config: {0}'.format(config))
|
||||
|
||||
routes = [
|
||||
Route('mediagoblin.plugins.oauth.authorize', '/oauth/authorize',
|
||||
controller='mediagoblin.plugins.oauth.views:authorize'),
|
||||
Route('mediagoblin.plugins.oauth.authorize_client', '/oauth/client/authorize',
|
||||
controller='mediagoblin.plugins.oauth.views:authorize_client'),
|
||||
Route('mediagoblin.plugins.oauth.access_token', '/oauth/access_token',
|
||||
controller='mediagoblin.plugins.oauth.views:access_token'),
|
||||
Route('mediagoblin.plugins.oauth.access_token',
|
||||
('mediagoblin.plugins.oauth.authorize', '/oauth/authorize',
|
||||
'mediagoblin.plugins.oauth.views:authorize'),
|
||||
('mediagoblin.plugins.oauth.authorize_client', '/oauth/client/authorize',
|
||||
'mediagoblin.plugins.oauth.views:authorize_client'),
|
||||
('mediagoblin.plugins.oauth.access_token', '/oauth/access_token',
|
||||
'mediagoblin.plugins.oauth.views:access_token'),
|
||||
('mediagoblin.plugins.oauth.access_token',
|
||||
'/oauth/client/connections',
|
||||
controller='mediagoblin.plugins.oauth.views:list_connections'),
|
||||
Route('mediagoblin.plugins.oauth.register_client',
|
||||
'mediagoblin.plugins.oauth.views:list_connections'),
|
||||
('mediagoblin.plugins.oauth.register_client',
|
||||
'/oauth/client/register',
|
||||
controller='mediagoblin.plugins.oauth.views:register_client'),
|
||||
Route('mediagoblin.plugins.oauth.list_clients',
|
||||
'mediagoblin.plugins.oauth.views:register_client'),
|
||||
('mediagoblin.plugins.oauth.list_clients',
|
||||
'/oauth/client/list',
|
||||
controller='mediagoblin.plugins.oauth.views:list_clients')]
|
||||
'mediagoblin.plugins.oauth.views:list_clients')]
|
||||
|
||||
pluginapi.register_routes(routes)
|
||||
pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
|
||||
|
@ -14,36 +14,22 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from routes import Mapper
|
||||
from werkzeug.routing import Map, Rule
|
||||
|
||||
from mediagoblin.auth.routing import auth_routes
|
||||
from mediagoblin.submit.routing import submit_routes
|
||||
from mediagoblin.user_pages.routing import user_routes
|
||||
from mediagoblin.edit.routing import edit_routes
|
||||
from mediagoblin.listings.routing import tag_routes
|
||||
from mediagoblin.webfinger.routing import webfinger_well_known_routes, \
|
||||
webfinger_routes
|
||||
from mediagoblin.admin.routing import admin_routes
|
||||
url_map = Map()
|
||||
|
||||
view_functions = {'index': 'mediagoblin.views:index'}
|
||||
|
||||
def get_mapper(plugin_routes):
|
||||
mapping = Mapper()
|
||||
mapping.minimization = False
|
||||
def add_route(endpoint, url, controller):
|
||||
view_functions.update({endpoint: controller})
|
||||
|
||||
# Plugin routes go first so they can override default routes.
|
||||
mapping.extend(plugin_routes)
|
||||
url_map.add(Rule(url, endpoint=endpoint))
|
||||
|
||||
mapping.connect(
|
||||
"index", "/",
|
||||
controller="mediagoblin.views:root_view")
|
||||
add_route('index', '/', 'mediagoblin.views:root_view')
|
||||
|
||||
mapping.extend(auth_routes, '/auth')
|
||||
mapping.extend(submit_routes, '/submit')
|
||||
mapping.extend(user_routes, '/u')
|
||||
mapping.extend(edit_routes, '/edit')
|
||||
mapping.extend(tag_routes, '/tag')
|
||||
mapping.extend(webfinger_well_known_routes, '/.well-known')
|
||||
mapping.extend(webfinger_routes, '/api/webfinger')
|
||||
mapping.extend(admin_routes, '/a')
|
||||
|
||||
return mapping
|
||||
import mediagoblin.submit.routing
|
||||
import mediagoblin.user_pages.routing
|
||||
import mediagoblin.auth.routing
|
||||
import mediagoblin.edit.routing
|
||||
import mediagoblin.webfinger.routing
|
||||
import mediagoblin.listings.routing
|
||||
|
@ -14,11 +14,8 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from routes.route import Route
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
submit_routes = [
|
||||
Route('mediagoblin.submit.start', '/',
|
||||
controller='mediagoblin.submit.views:submit_start'),
|
||||
Route('mediagoblin.submit.collection', '/collection',
|
||||
controller='mediagoblin.submit.views:add_collection'),
|
||||
]
|
||||
add_route('mediagoblin.submit.start',
|
||||
'/submit/', 'mediagoblin.submit.views:submit_start')
|
||||
add_route('collection_home', '/submit/collection', 'mediagoblin.submit.views:add_collection')
|
||||
|
@ -162,7 +162,7 @@ def register_routes(routes):
|
||||
Be careful when designing your route urls. If they clash with
|
||||
core urls, then it could result in DISASTER!
|
||||
"""
|
||||
if isinstance(routes, (tuple, list)):
|
||||
if isinstance(routes, list):
|
||||
for route in routes:
|
||||
PluginManager().register_route(route)
|
||||
else:
|
||||
|
@ -14,48 +14,68 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from routes.route import Route
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
user_routes = [
|
||||
Route('mediagoblin.user_pages.user_home', "/{user}/",
|
||||
controller="mediagoblin.user_pages.views:user_home"),
|
||||
Route('mediagoblin.user_pages.user_gallery', "/{user}/gallery/",
|
||||
controller="mediagoblin.user_pages.views:user_gallery"),
|
||||
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
|
||||
requirements=dict(m_id="[0-9a-fA-F]{24}"),
|
||||
controller="mediagoblin.user_pages.views:media_home"),
|
||||
Route('mediagoblin.user_pages.media_home.view_comment',
|
||||
'/{user}/m/{media}/c/{comment}/',
|
||||
controller="mediagoblin.user_pages.views:media_home"),
|
||||
Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
|
||||
controller="mediagoblin.edit.views:edit_media"),
|
||||
Route('mediagoblin.edit.attachments',
|
||||
'/{user}/m/{media}/attachments/',
|
||||
controller="mediagoblin.edit.views:edit_attachments"),
|
||||
Route('mediagoblin.user_pages.media_confirm_delete',
|
||||
"/{user}/m/{media}/confirm-delete/",
|
||||
controller="mediagoblin.user_pages.views:media_confirm_delete"),
|
||||
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
|
||||
controller="mediagoblin.user_pages.views:atom_feed"),
|
||||
Route('mediagoblin.user_pages.media_post_comment',
|
||||
'/{user}/m/{media}/comment/add/',
|
||||
controller="mediagoblin.user_pages.views:media_post_comment"),
|
||||
Route('mediagoblin.user_pages.media_collect',
|
||||
"/{user}/m/{media}/collect/",
|
||||
controller="mediagoblin.user_pages.views:media_collect"),
|
||||
Route('mediagoblin.user_pages.user_collection', "/{user}/collection/{collection}/",
|
||||
controller="mediagoblin.user_pages.views:user_collection"),
|
||||
Route('mediagoblin.edit.edit_collection', "/{user}/c/{collection}/edit/",
|
||||
controller="mediagoblin.edit.views:edit_collection"),
|
||||
Route('mediagoblin.user_pages.collection_confirm_delete',
|
||||
"/{user}/c/{collection}/confirm-delete/",
|
||||
controller="mediagoblin.user_pages.views:collection_confirm_delete"),
|
||||
Route('mediagoblin.user_pages.collection_item_confirm_remove',
|
||||
"/{user}/collection/{collection}/{collection_item}/confirm_remove/",
|
||||
controller="mediagoblin.user_pages.views:collection_item_confirm_remove"),
|
||||
Route('mediagoblin.user_pages.collection_atom_feed', '/{user}/collection/{collection}/atom/',
|
||||
controller="mediagoblin.user_pages.views:collection_atom_feed"),
|
||||
Route('mediagoblin.user_pages.processing_panel',
|
||||
'/{user}/panel/',
|
||||
controller="mediagoblin.user_pages.views:processing_panel"),
|
||||
]
|
||||
add_route('mediagoblin.user_pages.user_home',
|
||||
'/u/<string:user>/', 'mediagoblin.user_pages.views:user_home')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_home',
|
||||
'/u/<string:user>/m/<string:media>/',
|
||||
'mediagoblin.user_pages.views:media_home')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_confirm_delete',
|
||||
'/u/<string:user>/m/<string:media>/confirm-delete/',
|
||||
'mediagoblin.user_pages.views:media_confirm_delete')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_post_comment',
|
||||
'/u/<string:user>/m/<string:media>/comment/add/',
|
||||
'mediagoblin.user_pages.views:media_post_comment')
|
||||
|
||||
add_route('mediagoblin.user_pages.user_gallery',
|
||||
'/u/<string:user>/gallery/',
|
||||
'mediagoblin.user_pages.views:user_gallery')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_home.view_comment',
|
||||
'/u/<string:user>/m/<string:media>/c/<string:comment>/',
|
||||
'mediagoblin.user_pages.views:media_home')
|
||||
|
||||
add_route('mediagoblin.user_pages.atom_feed',
|
||||
'/u/<string:user>/atom/',
|
||||
'mediagoblin.user_pages.views:atom_feed')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_collect',
|
||||
'/u/<string:user>/m/<string:media>/collect/',
|
||||
'mediagoblin.user_pages.views:media_collect')
|
||||
|
||||
add_route('mediagoblin.user_pages.user_collection',
|
||||
'/u/<string:user>/collection/<string:collection>/',
|
||||
'mediagoblin.user_pages.views:user_collection')
|
||||
|
||||
add_route('mediagoblin.edit.edit_collection',
|
||||
'/u/<string:user>/c/<string:collection>/edit/',
|
||||
'mediagoblin.edit.views:edit_collection')
|
||||
|
||||
add_route('mediagoblin.user_pages.collection_confirm_delete',
|
||||
'/u/<string:user>/c/<string:collection>/confirm-delete/',
|
||||
'mediagoblin.user_pages.views:collection_confirm_delete')
|
||||
|
||||
add_route('mediagoblin.user_pages.collection_item_confirm_remove',
|
||||
'/u/<string:user>/collection/<string:collection>/<string:collection_item>/confirm_remove/',
|
||||
'mediagoblin.user_pages.views:collection_item_confirm_remove')
|
||||
|
||||
add_route('mediagoblin.user_pages.collection_atom_feed',
|
||||
'/u/<string:user>/collection/<string:collection>/atom/',
|
||||
'mediagoblin.user_pages.views:collection_atom_feed')
|
||||
|
||||
add_route('mediagoblin.user_pages.processing_panel',
|
||||
'/u/<string:user>/panel/',
|
||||
'mediagoblin.user_pages.views:processing_panel')
|
||||
|
||||
# Stray edit routes
|
||||
add_route('mediagoblin.edit.edit_media',
|
||||
'/u/<string:user>/m/<string:media>/edit/',
|
||||
'mediagoblin.user_pages.views:edit_media')
|
||||
|
||||
add_route('mediagoblin.edit.attachments',
|
||||
'/u/<string:user>/m/<string:media>/attachments/',
|
||||
'mediagoblin.user_pages.views:edit_attachments')
|
||||
|
@ -14,12 +14,10 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from routes.route import Route
|
||||
from mediagoblin.routing import add_route
|
||||
|
||||
webfinger_well_known_routes = [
|
||||
Route('mediagoblin.webfinger.host_meta', '/host-meta',
|
||||
controller='mediagoblin.webfinger.views:host_meta')]
|
||||
add_route('mediagoblin.webfinger.host_meta', '/.well-known/host-meta',
|
||||
'mediagoblin.webfinger.views:host_meta')
|
||||
|
||||
webfinger_routes = [
|
||||
Route('mediagoblin.webfinger.xrd', '/xrd',
|
||||
controller='mediagoblin.webfinger.views:xrd')]
|
||||
add_route('mediagoblin.webfinger.xrd', '/webfinger/xrd',
|
||||
'mediagoblin.webfinger.views:xrd')
|
||||
|
Loading…
x
Reference in New Issue
Block a user