Skip to content

Commit

Permalink
Warns user to URL encode query parameters
Browse files Browse the repository at this point in the history
When making a request with a filter that uses the ``like`` operator, the
user will likely provide an argument of the form ``%somestring%``. If
not properly URL encoded, this will be interpreted on the server side as
an unintended string.

This fixes #331 and #415.
  • Loading branch information
jfinkels committed Mar 5, 2015
1 parent ec8beb3 commit 97a6827
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -20,6 +20,9 @@ Version 0.17.1-dev

Not yet released.

- #331, #415: documents the importance of URL encoding when using the ``like``
operator to filter results.

Version 0.17.0
--------------

Expand Down
11 changes: 10 additions & 1 deletion docs/searchformat.rst
Expand Up @@ -157,13 +157,22 @@ The operator strings recognized by the API incude:
* ``>=``, ``ge``, ``gte``, ``geq``, ``<=``, ``le``, ``lte``, ``leq``
* ``in``, ``not_in``
* ``is_null``, ``is_not_null``
* ``like``
* ``like``, ``ilike``
* ``has``
* ``any``

These correspond to SQLAlchemy column operators as defined `here
<http://docs.sqlalchemy.org/en/latest/core/expression_api.html#sqlalchemy.sql.operators.ColumnOperators>`_.

.. warning::

If you use a percent sign in the argument to the ``like`` operator (for
example, ``%somestring%``), make sure it is `URL encoded`_, otherwise the
server may interpret the first few characters of that argument as a
percent-encoded character when attempting to decode the URL.

.. _URL encoded: https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_the_percent_character

Examples
--------

Expand Down
13 changes: 13 additions & 0 deletions tests/test_views.py
Expand Up @@ -15,6 +15,7 @@
from datetime import datetime
from datetime import timedelta
import math
from urllib.parse import quote as urlquote

import dateutil
from flask import json
Expand Down Expand Up @@ -1951,6 +1952,18 @@ def test_search_bad_arguments(self):
resp = self.app.search('/api/person', dumps(d))
assert resp.status_code == 400

def test_like(self):
"""Tests for the like operator."""
person1 = self.Person(name='foo')
person2 = self.Person(name='bar')
self.session.add_all([person1, person2])
self.session.commit()
data = dict(filters=[dict(name='name', op='like', val='%bar%')])
response = self.app.search('/api/person', urlquote(dumps(data)))
data = loads(response.data)
people = data['objects']
assert ['bar'] == sorted(person['name'] for person in people)


class TestAssociationProxy(ManagerTestBase):
"""Unit tests for models which have a relationship involving an association
Expand Down

0 comments on commit 97a6827

Please sign in to comment.