Sorry, I didn't explain my situation clearly enough. I want the "testname"
in the example to actually be considered as a single URL segment. These
strings come from a database and represent a single resource, and I can't
control what they contain. Normally they don't have slashes in, but
occasionally they do, and I want the system to continue to work whether or
not they contain slashes.
For what it's worth, I've worked around the problem with a custom request
subclass that does the extra escaping. It only works for my specific usage,
but that's good enough for me :-). A proper fix (assuming it really is a
bug) would probably involve changing pyramid.traversal.quote_path_segment
to handle this case. This would also be necessary for traversal if a
resource's __name__ contained a slash.
from pyramid.request import Request
from pyramid.events import subscriber
class MyRequest(Request):
def route_url(self, *args, **kwargs):
result = super(MyRequest, self).route_url(*args, **kwargs)
# Escape %2F (slash) by percent-encoding the percent.
# When the URL is followed, the outer layer of escaping will be
# removed, leaving %2F in the matchdict.
return result.replace('%2F', '%252F')
def fixmatchdict(self):
matchdict = self.matchdict
if matchdict:
for key, value in matchdict.items():
if isinstance(value, basestring):
matchdict[key] = value.replace('%2F', '/')
# The ContextFound event fires after the URL has been processed
# but before any view code runs, so is a convenient place for us
# to unescape slashes in the matchdict
@subscriber('pyramid.events.ContextFound')
def contextfound(event):
event.request.fixmatchdict()
While reading the source, I noticed the documentation for
pyramid.traversal.quote_path_segment which says:
The return value for each segment passed to this
function is cached in a module-scope dictionary for
speed: the cached version is returned when possible
rather than recomputing the quoted version. No cache
emptying is ever done for the lifetime of an
application, however. If you pass arbitrary
user-supplied strings to this function (as opposed to
some bounded set of values from a 'working set' known to
your application), it may become a memory leak.
https://github.com/Pylons/pyramid/blob/1.4/pyramid/traversal.py#L549
As far as I can tell, if you are generating URLs based on strings from a
database, whether with traversal or url dispatch, that cache will end up
containing every string from your database that ever gets used during URL
generation. I know the docstring for quote_path_segment warns about this,
but I don't think that warning ever makes it as far as the main docs...
(Also, URL generation using strings from a database seems like a fairly
reasonable thing to want to do)
Simon
On Thursday, February 21, 2013 3:29:02 PM UTC, Blaise Laflamme wrote:
> The {pattern} notation represents a segment in a URL which is separated by
> slashes. If you want to use multiple segments you should define them
> separately, ie /{one}/{two} or use the /path/to/*remainder notation to
> catch everything remaining. To generate a URL you can provide a tuple or a
> string, i.e.: request.route_url('test', testname='path/to/resource') or
> request.route_url('test', testname=('path', 'to', 'resource')). Any value
> you pass in your patterns will be url-quoted.
>
> On Thursday, 21 February 2013 08:11:28 UTC-5, Simon King wrote:
>>
>> Hi all,
>>
>> I'm not sure if this would be considered a bug, but I'm having trouble
>> generating URLs using request.route_url, when my replacement values
>> themselves contain slashes. For example, if I had the following route
>> defined:
>>
>> config.add_route('test', '/tests/{testname}/')
>>
>> and I generate a route like this:
>>
>> request.route_url('test', testname='one/two')
>>
>> ...the resulting URL will look something like:
>>
>> http://localhost/tests/one%2Ftwo/
>>
>> However, if I try to visit this URL, it is treated exactly the same as:
>>
>> http://localhost/tests/one/two/
>>
>> ...so the route doesn't match. I suspect that as far as HTTP is concerned
>> those 2 URLs are equivalent, so my workaround will have to be escaping my
>> replacement values before creating URLs, and unescaping them in my views.
>>
>> Could this be considered a bug in route_url, that it generates URLs that
>> don't roundtrip correctly? And could it be fixed by adding special handling
>> of the "/" character in the generator and the matcher?
>>
>> Thanks,
>>
>> Simon
>>
>
--
You received this message because you are subscribed to the Google Groups
"pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.