Fix #1056 - Add flag to accept URLs without a trailing slash
authorJessica Tallon <jessica@megworld.co.uk>
Fri, 12 Dec 2014 13:55:14 +0000 (13:55 +0000)
committerJessica Tallon <jessica@megworld.co.uk>
Fri, 12 Dec 2014 14:33:15 +0000 (14:33 +0000)
mediagoblin/federation/routing.py
mediagoblin/tests/test_api.py
mediagoblin/tools/routing.py

index dddb5df5baddb2d711719f1bc4cbf5015a90bab5..b585750b2859fc5d5bc95d03b679b21a65ba45b6 100644 (file)
@@ -20,74 +20,87 @@ from mediagoblin.tools.routing import add_route
 add_route(
     "mediagoblin.federation.user",
     "/api/user/<string:username>/",
-    "mediagoblin.federation.views:user_endpoint"
+    "mediagoblin.federation.views:user_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.user.profile",
-    "/api/user/<string:username>/profile",
-    "mediagoblin.federation.views:profile_endpoint"
+    "/api/user/<string:username>/profile/",
+    "mediagoblin.federation.views:profile_endpoint",
+    match_slash=False
 )
 
 # Inbox and Outbox (feed)
 add_route(
     "mediagoblin.federation.feed",
-    "/api/user/<string:username>/feed",
-    "mediagoblin.federation.views:feed_endpoint"
+    "/api/user/<string:username>/feed/",
+    "mediagoblin.federation.views:feed_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.user.uploads",
-    "/api/user/<string:username>/uploads",
-    "mediagoblin.federation.views:uploads_endpoint"
+    "/api/user/<string:username>/uploads/",
+    "mediagoblin.federation.views:uploads_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox",
-    "/api/user/<string:username>/inbox",
-    "mediagoblin.federation.views:inbox_endpoint"
+    "/api/user/<string:username>/inbox/",
+    "mediagoblin.federation.views:inbox_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox_minor",
-    "/api/user/<string:username>/inbox/minor",
-    "mediagoblin.federation.views:inbox_minor_endpoint"
+    "/api/user/<string:username>/inbox/minor/",
+    "mediagoblin.federation.views:inbox_minor_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox_major",
-    "/api/user/<string:username>/inbox/major",
-    "mediagoblin.federation.views:inbox_major_endpoint"
+    "/api/user/<string:username>/inbox/major/",
+    "mediagoblin.federation.views:inbox_major_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox_direct",
-    "/api/user/<string:username>/inbox/direct",
-    "mediagoblin.federation.views:inbox_endpoint"
+    "/api/user/<string:username>/inbox/direct/",
+    "mediagoblin.federation.views:inbox_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox_direct_minor",
     "/api/user/<string:username>/inbox/direct/minor",
-    "mediagoblin.federation.views:inbox_minor_endpoint"
+    "mediagoblin.federation.views:inbox_minor_endpoint",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.inbox_direct_major",
     "/api/user/<string:username>/inbox/direct/major",
-    "mediagoblin.federation.views:inbox_major_endpoint"
+    "mediagoblin.federation.views:inbox_major_endpoint",
+    match_slash=False
 )
 
 # object endpoints
 add_route(
     "mediagoblin.federation.object",
-    "/api/<string:object_type>/<string:id>",
-    "mediagoblin.federation.views:object_endpoint"
-    )
+    "/api/<string:object_type>/<string:id>/",
+    "mediagoblin.federation.views:object_endpoint",
+    match_slash=False
+)
+
 add_route(
     "mediagoblin.federation.object.comments",
-    "/api/<string:object_type>/<string:id>/comments",
-    "mediagoblin.federation.views:object_comments"
+    "/api/<string:object_type>/<string:id>/comments/",
+    "mediagoblin.federation.views:object_comments",
+    match_slash=False
 )
 
 add_route(
@@ -104,18 +117,21 @@ add_route(
 
 add_route(
     "mediagoblin.webfinger.well-known.webfinger",
-    "/.well-known/webfinger",
-    "mediagoblin.federation.views:lrdd_lookup"
+    "/.well-known/webfinger/",
+    "mediagoblin.federation.views:lrdd_lookup",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.webfinger.whoami",
-    "/api/whoami",
-    "mediagoblin.federation.views:whoami"
+    "/api/whoami/",
+    "mediagoblin.federation.views:whoami",
+    match_slash=False
 )
 
 add_route(
     "mediagoblin.federation.activity_view",
-    "/<string:username>/activity/<string:id>",
-    "mediagoblin.federation.views:activity_view"
+    "/<string:username>/activity/<string:id>/",
+    "mediagoblin.federation.views:activity_view",
+    match_slash=False
 )
index 698b1f0ddff4b096a6f1906a2d6af32409157c03..83857d39f7e7010b723d6b75f8f1199b87ddd7d2 100644 (file)
@@ -188,7 +188,7 @@ class TestAPI(object):
         # Lets change the image uploader to be self.other_user, this is easier
         # than uploading the image as someone else as the way self.mocked_oauth_required
         # and self._upload_image.
-        id = int(data["object"]["id"].split("/")[-1])
+        id = int(data["object"]["id"].split("/")[-2])
         media = MediaEntry.query.filter_by(id=id).first()
         media.uploader = self.other_user.id
         media.save()
@@ -232,14 +232,14 @@ class TestAPI(object):
         image = json.loads(response.body.decode())["object"]
 
         # Check everything has been set on the media correctly
-        id = int(image["id"].split("/")[-1])
+        id = int(image["id"].split("/")[-2])
         media = MediaEntry.query.filter_by(id=id).first()
         assert media.title == title
         assert media.description == description
         assert media.license == license
 
         # Check we're being given back everything we should on an update
-        assert int(image["id"].split("/")[-1]) == media.id
+        assert int(image["id"].split("/")[-2]) == media.id
         assert image["displayName"] == title
         assert image["content"] == description
         assert image["license"] == license
@@ -288,7 +288,7 @@ class TestAPI(object):
             request = test_app.get(object_uri)
 
         image = json.loads(request.body.decode())
-        entry_id = int(image["id"].split("/")[-1])
+        entry_id = int(image["id"].split("/")[-2])
         entry = MediaEntry.query.filter_by(id=entry_id).first()
 
         assert request.status_code == 200
@@ -319,7 +319,7 @@ class TestAPI(object):
         assert response.status_code == 200
 
         # Find the objects in the database
-        media_id = int(data["object"]["id"].split("/")[-1])
+        media_id = int(data["object"]["id"].split("/")[-2])
         media = MediaEntry.query.filter_by(id=media_id).first()
         comment = media.get_comments()[0]
 
@@ -382,7 +382,7 @@ class TestAPI(object):
         response, comment_data = self._activity_to_feed(test_app, activity)
 
         # change who uploaded the comment as it's easier than changing
-        comment_id = int(comment_data["object"]["id"].split("/")[-1])
+        comment_id = int(comment_data["object"]["id"].split("/")[-2])
         comment = MediaComment.query.filter_by(id=comment_id).first()
         comment.author = self.other_user.id
         comment.save()
index 2ff003b72913cd1116ca4d6eeb2390e24adf713e..ae7c7154460751a88e4f6e376794f6f2d5da2db0 100644 (file)
@@ -28,15 +28,22 @@ url_map = Map()
 
 
 class MGRoute(Rule):
-    def __init__(self, endpoint, url, controller):
+    def __init__(self, endpoint, url, controller, match_slash=True):
         Rule.__init__(self, url, endpoint=endpoint)
         self.gmg_controller = controller
+        self.match_slash = match_slash
 
     def empty(self):
         new_rule = Rule.empty(self)
         new_rule.gmg_controller = self.gmg_controller
         return new_rule
 
+    def match(self, path, *args, **kwargs):
+        if not (self.match_slash or path.endswith("/")):
+            path = path + "/"
+
+        return super(MGRoute, self).match(path, *args, **kwargs)
+
 
 def endpoint_to_controller(rule):
     endpoint = rule.endpoint
@@ -52,11 +59,11 @@ def endpoint_to_controller(rule):
     return view_func
 
 
-def add_route(endpoint, url, controller):
+def add_route(endpoint, url, controller, *args, **kwargs):
     """
     Add a route to the url mapping
     """
-    url_map.add(MGRoute(endpoint, url, controller))
+    url_map.add(MGRoute(endpoint, url, controller, *args, **kwargs))
 
 
 def mount(mountpoint, routes):