Opened 9 years ago

Closed 9 years ago

#1056 closed defect (fixed)

endpoints redirect to trailing / endpoint if missing

Reported by: Jessica Tallon Owned by:
Priority: minor Milestone: 0.8.0
Component: programming Keywords: federation, api
Cc: JanKusanagi, Jessica Tallon Parent Tickets:

Description (last modified by Jessica Tallon)

When you request a URL without a tailing / at the end a redirection rather than the content you requested. This should work with or without the / e.g.

https://my.gmg.instance/api/user/Tsyesika/feed should resolve to the same endpoint as https://my.gmg.instance/api/user/Tsyesika/feed/

Change History (8)

comment:1 by Jessica Tallon, 9 years ago

Description: modified (diff)
Summary: endpoints 404 if missing trailing /endpoints redirect to trailing / endpoint if missing

comment:2 by Christopher Allan Webber, 9 years ago

This is very intentional... I originally set up the slash redirection to model two things:

  1. the concept that there is only one canonical URL per resource
  2. the way Django does the "append slash" stuff.

I think we shouldn't change this without considering the above. Consider the importance of well designed URLs, and preserving them!

If it's *really true* that for API compatibility that we should provide both, there is an easy solution, which is to provide two routes, both for one with and without the slash.

comment:3 by Christopher Allan Webber, 9 years ago

(Keep in mind though if duplicate routing is added that this might somewhat affect the URLgen procedures!)

comment:4 by JanKusanagi, 9 years ago

Is it much extra effort and code to provide 2 routes for the same thing?

And /feed is OK without the trailing slash, btw.

comment:5 by Christopher Allan Webber, 9 years ago

In a certain sense, it isn't so bad, but the main challenge is the "symbolic identifiers" that most routes have. For example, here is one route:

add_route('mediagoblin.edit.profile', '/u/<string:user>/edit/',
    'mediagoblin.edit.views:edit_profile')

The first parameter is the symbolic identifier, the second is the URL, the third is the actual view that the user accesses. So, we might think that we might do:

add_route('mediagoblin.edit.profile', '/u/<string:user>/edit',
    'mediagoblin.edit.views:edit_profile')
add_route('mediagoblin.edit.profile', '/u/<string:user>/edit/',
    'mediagoblin.edit.views:edit_profile')

This will make it so that both end up resolving to the same URL just fine, no redirects (I expect). The problem is, if you try to generate the path to that view:

request.urlgen("mediagoblin.edit.profile", user="wilma")

Previously, you were guaranteed to get back /u/wilma/edit/ ... now you might get that or /u/wilma/edit ... who knows! This might not sound bad, but it violates the "one resource" rule, and makes the function less "functional".

So, maybe you think you can do this instead:

add_route('mediagoblin.edit.profile-noslash', '/u/<string:user>/edit',
    'mediagoblin.edit.views:edit_profile')
add_route('mediagoblin.edit.profile', '/u/<string:user>/edit/',
    'mediagoblin.edit.views:edit_profile')

Nobody will ever use the -noslash in their urlgen, so the other one will stay canonical... however, we have some plugin tools where users can hook into template rendering depending on the symbolic name of the routing. Which means that some plugins might not run if you just go to /u/wilma/edit!

Which means, as much as it would mean adding another hack, the best result would be supporting the following:

add_route(
    'mediagoblin.edit.profile', '/u/<string:user>/edit/',
    'mediagoblin.edit.views:edit_profile',
    handle_noslash_without_redirect=True)

which would require altering our routing handling code, but would be the cleanest solution in the long run.

comment:6 by Christopher Allan Webber, 9 years ago

Cc: JanKusanagi Jessica Tallon added

cc'ing jankusanagi & Tsyesika

comment:7 by Jessica Tallon, 9 years ago

Owner: set to Jessica Tallon
Status: newin_progress

comment:8 by Jessica Tallon, 9 years ago

Owner: Jessica Tallon removed
Resolution: fixed
Status: in_progressclosed

This is fixed as of c7c26b1. Any URL defined in mediagoblin's routing can now be configured to respond to be slashless and slashed rather than a redirect by setting match_slash=False on the mediagoblin.tools.routing.add_route function.

Note: See TracTickets for help on using tickets.