Prevent URL encoding that is removing equals signs from URL - django

Working on a Django/React app. I have some verification emails links that look like the following:
https://test.example.com/auth/security_questions/f=ru&i=101083&k=7014c315f3056243534741610545c8067d64d747a981de22fe75b78a03d16c92
In dev env this works fine, but now that I am getting it ready for production, it isn't working. When I click on it, it converts it to:
https://test.example.com/auth/security_questions/f%3Dru&i%3D101083&k%3D7014c315f3056243534741610545c8067d64d747a981de22fe75b78a03d16c92/
This prevents react-router-dom from matching the correct URL, so a portion of the web application does not load properly.
The link is constructed using the following.
link = '%s/auth/security_questions/f=%s&i=%s&k=%s' % \
('https://test.example.com', 'ru', user.id, user.key)
Also, here is the url() that is catching the route:
url(r'^(?:.*)/$', TemplateView.as_view(template_name='index.html')),

These variables are supposed to be query parameters in a GET request. When you construct the link, you'll need to have a question mark in there somewhere separating the URL from the query string:
https://test.example.com/auth/security_questions/?f=ru&i=101083&k=7014c315...
^
|___ here
The conversion of = to url-encoded %3D etc is correct, and equivalent. Sometimes variables are part of the URL directly, but webapps don't use &-separated key/value pairs in that case.

Related

How to use variable at start of django url to return to view?

I am trying to pass the first part of a django url to a view, so I can filter my results by the term in the url.
Looking at the documentation, it seems quite straightforward.
However, I have the following urls.py
url('<colcat>/collection/(?P<name>[\w\-]+)$', views.collection_detail, name='collection_detail'),
url('<colcat>/', views.collection_view, name='collection_view'),
In this case, I want to be able to go to /living and have living be passed to my view so that I can use it to filter by.
When trying this however, no matter what url I put it isn't being matched, and I get an error saying the address I put in could not be matched to any urls.
What am I missing?
<colcat> is not a valid regex. You need to use the same format as you have for name.
url('(?P<colcat>[\w\-]+)/collection/(?P<name>[\w\-]+)$', views.collection_detail, name='collection_detail'),
url('(?P<colcat>[\w\-]+)/$', views.collection_view, name='collection_view'),
Alternatively, use the new path form which will be much simpler:
path('<str:colcat>/collection/<str:name>', views.collection_detail, name='collection_detail'),
path('<str:colcat>/', views.collection_view, name='collection_view'),

Django missed slash in url

I created a url like 'api/personal/'. Everything went right when I did local test using './manage.py runserver'. But when I used factoryboy to create a client and try to get the detail by 'self.user_client.get('api/personal/')', the response showed 404 NOTFOUND because the url had changed to apipersonal/. Does anyone know why did it happen?
Use named urls for avoiding this kind of confusions. Define the url like this:
path('api/personal/', your_view, name='api_personal') # added keyword argument name
and use it in the tests with reverse like this:
self.client.get(reverse('api_personal'))

Prevent escaping slashes in url helpers (specifically when called using .send() to url_helpers)

Perhaps the title of this question is cryptic, but the problem is real, I've just upgraded an application from Rails 3 to 4 and encountered the following issue (on both Ruby 2.0 and 2.1):
I have a method which calls several url helpers in a loop, using send(), like this:
class Sitemap
include Rails.application.routes.url_helpers
#...
# regions = [:city, :county, :zip]
regions.each do |region|
url_params = ... # [name, additional_id]
send("#{region}_url", url_params)
end
In Rails 3 the above resulted in urls like http://example.com/cities/atlanta/2
In Rails 4 I get http://example.com/cities/atlanta%2f2
slash gets CGI escaped, I don't want this. I use it in generating sitemap XML for my site and it seems to work even if the forward slash is escaped, but it looks ugly and I don't know if it will work correctly for all bots or clients.
UPDATE: after some debugging I've found out that the CGI escaping occurs somewhere in ActionDispatch::Journey::Visitors::Formatter
Router::Utils.escape_segment() # method call somewhere in
ActionDispatch::Journey::Visitors::Formatter # during
Visitors::Formatter.new(path_options).accept(path.spec) # in
#set.formatter.generate(:path_info, named_route, options, recall, PARAMETERIZE) # in a call to
ActionDispatch::Routing::RouteSet::Generator#generate
I was able to fix the issue with escaping slashes when generating the URL, here's the change:
# from:
send(region_url, url_params)
# to:
send(region_url, { id: url_params[0], market_id: url_params[1]})
# sometimes url_params is a one element array
The key is to provide a hash of parameters with explicitly assigned keys and values.
I use send to dynamically call method (xxx_url) from url_helpers module which is included in my model. url_params array looks like ['some-slug', 12]

Mapping urls in routes.py

I am using web2py and builing a REST api and have one of my URLs set up like this:
routes_in (
('/myapp/something/{?P<id>.*)/myfunction', /myapp/default/myfunction/\g<id>')
)
routes_out = (
('/myapp/default/myfunction/\g<id>', '/myapp/something/{?P<id>.*)/myfunction')
)
If my app is setup this way my function is not even entered into and I get an invalid request if I remove the id argument from the url that my url is being mapped to i.e. remove g<id> from above, I enter my function but the argument is not being captured.
I cannot change the structure of the URL as per my requirements and I am not sure how to go about this.
I would appreciate any pointers.
Thanks,
nav
The above does work in web2py I found that some other area of my code was breaking.

Django: # in url as a character?

I've made a Django application that uses tags. When i use tag 'c#' and try to redirect to mysiteaddress/tags/c# on server it redirects to ../tags/c and shows me stuff connected to 'c' tag, but when I do the same on my local development machine it redirects me to c%23 and works correctly. What should I change to make it work on production server?
Without more code I can't be too specific, but '#' corresponds to the character escape sequence %23 and something in your code may need to explicitly escape 'c#' before putting it in the url.
Here is a django-snippet that uses url-quoting:
http://www.djangosnippets.org/snippets/1159/
The solution to your problem might look like this:
from django.utils.http import urlquote
...
tag = urlquote(tag)
tag_url = base + "tags/" + tag
...