Quote variable values in url_for()

This commit is contained in:
Kovid Goyal 2015-06-14 20:03:11 +05:30
parent 33e47e424c
commit dc7cf2cfdc
2 changed files with 14 additions and 0 deletions

View File

@ -7,6 +7,7 @@ __license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
import httplib, sys, inspect, re, time, numbers, json as jsonlib import httplib, sys, inspect, re, time, numbers, json as jsonlib
from urllib import quote as urlquote
from itertools import izip from itertools import izip
from operator import attrgetter from operator import attrgetter
@ -144,6 +145,13 @@ class Route(object):
raise RouteError('The required variable(s) %s were not specified for the route: %s' % (','.join(not_spec), self.endpoint.route)) raise RouteError('The required variable(s) %s were not specified for the route: %s' % (','.join(not_spec), self.endpoint.route))
args = self.defaults.copy() args = self.defaults.copy()
args.update(kwargs) args.update(kwargs)
def quoted(x):
if not isinstance(x, unicode) and not isinstance(x, bytes):
x = unicode(x)
if isinstance(x, unicode):
x = x.encode('utf-8')
return urlquote(x, '')
args = {k:quoted(v) for k, v in args.iteritems()}
route = self.var_pat.sub(lambda m:'{%s}' % m.group(1).partition('=')[0].lstrip('+'), self.endpoint.route) route = self.var_pat.sub(lambda m:'{%s}' % m.group(1).partition('=')[0].lstrip('+'), self.endpoint.route)
return route.format(**args) return route.format(**args)

View File

@ -64,6 +64,10 @@ class TestRouter(BaseTest):
def soak_opt(ctx, dest, rest): def soak_opt(ctx, dest, rest):
pass pass
@endpoint('/needs quoting/{x}')
def quoting(ctx, dest, x):
pass
for x in locals().itervalues(): for x in locals().itervalues():
if getattr(x, 'is_endpoint', False): if getattr(x, 'is_endpoint', False):
router.add(x) router.add(x)
@ -91,3 +95,5 @@ class TestRouter(BaseTest):
self.ae(ep, soak_opt), self.ae(args, ['xxx']) self.ae(ep, soak_opt), self.ae(args, ['xxx'])
ep, args = find('/soak_opt/a/b') ep, args = find('/soak_opt/a/b')
self.ae(ep, soak_opt), self.ae(args, ['a/b']) self.ae(ep, soak_opt), self.ae(args, ['a/b'])
self.ae(router.url_for('/needs quoting', x='a/b c'), '/needs quoting/a%2Fb%20c')