Skip to content

Commit c1982fc

Browse files
authored
Include large API keys in the JSON body instead of as a header #83
* If the API key is sufficiently long, include it as part of the body of the request instead of as a header - only set the api key header when the api key length is not too long - Added some test cases - Pop off the api key header when a new API key is being set that is too long - Fixed indentation - Fixed typo - Added test cases * Use PYTHON_INTEGRATION_TESTS app on Travis * Fix test_index for python 2.6
1 parent 7c5d27b commit c1982fc

File tree

5 files changed

+65
-12
lines changed

5 files changed

+65
-12
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ env:
2222
- TOXENV=coveralls-py3
2323
- TOXENV=py27 APPENGINE_RUNTIME=python27
2424
global:
25-
- secure: S/H779PQk4yKOmP3HbcsrdJjls5cDQDekYhvW0nvlsSkw7L+nqEhV92Lk+JMIPOYeug66NmBSqCIhLC6NHp6TK3Z6y7wNO1JeVdtl+X7b7acRNAkMz9GqkZgLP05LyB1kGUpKfzEejxvKcKQ4iAkEVVu4N5IXcO92Y/IIMuKOe4=
26-
- secure: Xtw10xjgdPiWrG6BZ+2B1UlkCBEtpVoHwttXj1nmroWqpIGOLDiAHVxgORe+mt4lIvDe2+cWJRRIeuY8f1xkbkR/FjNMf7iGbNJiARvcUe3ivX29cwOCyghN7IliyikHLwhntQcx2UFBDlMyYH5DqZYVzo22IyUFmPBMS58WqO4=
27-
- secure: SLDv4lN/C6xVfd99YgNGl2vdYy95YNMd/Uqk0HjiO7TwavXPAsx7cegH6I+Q/j7XyLxFQFq4OAEWeVlnO8cebtSmu5cB1tcesf//r2lNQjrz4F7cI0bqmqbf4YzlyzPIAjSxWzELJD9l9jFbNdFMd1U8UzLt+obsLyp6AbLyqYs=
25+
- secure: BGg68g6mf+VktQNzz+WQ+fbiiuzaLNHqJeXsvuN/JP8BttFVpiRQe4CYQrBIyhyqyDg07l+QGOV/5T1SuzCiRh92YNotem+RbUGvQPc9/kzfYXSmTpwe+d31qlKJ2Gwymlbi6ZTckoDGHtfh29sbHs7mfzTPfQb8untXY0p5w9o= # ALGOLIA_APPLICATION_ID
26+
- secure: CAoqGDpJIREeeGieVPVvdEnDNPohZl95BEkhH0BHjYX3SLKCf9ZGw1DRcfGEPAwej3EpaUFSk4i1cHrItWll4zuZ6LQ8R/gUmsCrev3vPyFWk2DUTGxInHgPcYKpLTbQF/stgXo3YVSMBZtSky73++shbkS99KJRMGOJCLyvWp4= # ALGOLIA_API_KEY
27+
- secure: ZL+IUM4D7pJX3yP2lSEaHZpxt+utEbH+wrQ8RwXAvnkwLw5WgU3lP+yS2VEkVH+3b9LZA/b/mbXKZg9Ct/j8CIdbZyRmHhCr9qF5uHrPtLHg+Rono8I8PKyHe1QidLvqo0KQvYRHnGqooVx8nZYi9ue6KEfiAz0WNjpwupqYhow= # ALGOLIA_API_KEY_SEARCH

algoliasearch/client.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
from .helpers import urlify
4343

4444

45+
MAX_API_KEY_LENGTH = 500
46+
47+
4548
class Client(object):
4649
"""
4750
Entry point in the Python Client API.
@@ -76,15 +79,14 @@ def __init__(self, app_id, api_key, hosts=None, _transport=None):
7679
self._transport.write_hosts = hosts
7780

7881
self._transport.headers = {
79-
'X-Algolia-API-Key': api_key,
8082
'X-Algolia-Application-Id': app_id,
8183
'Content-Type': 'gzip',
8284
'Accept-Encoding': 'gzip',
8385
'User-Agent': 'Algolia for Python (%s)' % VERSION
8486
}
8587

8688
self._app_id = app_id
87-
self._api_key = api_key
89+
self.api_key = api_key
8890

8991
# Fix for AppEngine bug when using urlfetch_stub
9092
if 'google.appengine.api.apiproxy_stub_map' in sys.modules.keys():
@@ -117,7 +119,11 @@ def api_key(self):
117119
@api_key.setter
118120
def api_key(self, value):
119121
self._api_key = value
120-
self.set_extra_headers(**{'X-Algolia-API-Key': value})
122+
if len(value) > MAX_API_KEY_LENGTH:
123+
# If it was previously set, remove the header
124+
self.headers.pop('X-Algolia-API-Key', None)
125+
else:
126+
self.set_extra_headers(**{'X-Algolia-API-Key': value})
121127

122128
@deprecated
123129
def enableRateLimitForward(self, admin_api_key, end_user_ip,
@@ -489,4 +495,8 @@ def generate_secured_api_key(self, private_api_key, queryParameters,
489495
return str(base64.b64encode(("%s%s" % (securedKey, queryParameters)).encode('utf-8')).decode('utf-8'))
490496

491497
def _req(self, is_search, path, meth, params=None, data=None):
498+
if len(self.api_key) > MAX_API_KEY_LENGTH:
499+
if data is None:
500+
data = {}
501+
data['apiKey'] = self.api_key
492502
return self._transport.req(is_search, path, meth, params, data)

tests/test_client.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
except ImportError:
1212
import unittest
1313

14-
from algoliasearch.client import Client
14+
from algoliasearch.client import Client, MAX_API_KEY_LENGTH
1515

1616
from .helpers import safe_index_name
1717
from .helpers import get_api_client
@@ -88,6 +88,20 @@ def test_change_api_key(self):
8888
self.assertEqual(client._api_key, 'your_api_key')
8989
self.assertEqual(client.headers['X-Algolia-API-Key'], 'your_api_key')
9090

91+
def test_change_api_key_too_long(self):
92+
client = get_api_client()
93+
api_key = 'a' * (MAX_API_KEY_LENGTH + 1)
94+
client.api_key = api_key
95+
self.assertEqual(client._api_key, api_key)
96+
self.assertFalse('X-Algolia-API-Key' in client.headers)
97+
98+
def test_change_api_key_max_length(self):
99+
client = get_api_client()
100+
api_key = 'a' * MAX_API_KEY_LENGTH
101+
client.api_key = api_key
102+
self.assertEqual(client._api_key, api_key)
103+
self.assertEqual(client.headers['X-Algolia-API-Key'], api_key)
104+
91105
def test_subclassing_client(self):
92106
class SubClient(Client):
93107
def __init__(self, user_name, *args, **kwargs):

tests/test_index.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import unicode_literals
44

5+
import os
56
import time
67
from random import randint
78
from decimal import Decimal
@@ -12,6 +13,7 @@
1213
except ImportError:
1314
import unittest
1415

16+
from algoliasearch.client import MAX_API_KEY_LENGTH
1517
from algoliasearch.helpers import AlgoliaException
1618

1719
from .helpers import safe_index_name
@@ -277,6 +279,33 @@ def test_search(self):
277279
res_ids = [elt['objectID'] for elt in res['hits']]
278280
self.assertIn(self.objectIDs[2], res_ids)
279281

282+
def test_search_with_short_secured_api_key(self):
283+
old_key = self.client.api_key
284+
285+
secured_api_key = self.client.generate_secured_api_key(
286+
os.environ['ALGOLIA_API_KEY_SEARCH'],
287+
dict(filters=''),
288+
)
289+
assert len(secured_api_key) < MAX_API_KEY_LENGTH
290+
self.client.api_key = secured_api_key
291+
res = self.index.search('')
292+
self.assertEqual(res['nbHits'], 5)
293+
self.client.api_key = old_key
294+
295+
def test_search_with_long_secured_api_key(self):
296+
old_key = self.client.api_key
297+
298+
tags = set('x{0}'.format(100000 + i) for i in range(1000))
299+
secured_api_key = self.client.generate_secured_api_key(
300+
os.environ['ALGOLIA_API_KEY_SEARCH'],
301+
dict(filters=' OR '.join(tags)),
302+
)
303+
assert len(secured_api_key) > MAX_API_KEY_LENGTH
304+
self.client.api_key = secured_api_key
305+
res = self.index.search('')
306+
self.assertEqual(res['nbHits'], 0)
307+
self.client.api_key = old_key
308+
280309

281310
class IndexWithModifiableDataTest(IndexTest):
282311
"""Tests that use one index with initial data and modify it."""

tests/test_old.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ def test_wrong_app_id(self):
5959
pass
6060

6161
def test_retry(self):
62-
try:
63-
client = algoliasearch.Client(os.environ['ALGOLIA_APPLICATION_ID'], os.environ['ALGOLIA_API_KEY'], ["fakeapp-1.algolianet.com", "fakeapp-2.algolianet.com", os.environ['ALGOLIA_APPLICATION_ID'] + ".algolianet.com"])
64-
client.listIndexes
65-
except algoliasearch.AlgoliaException as e:
66-
self.assertTrue(false)
62+
try:
63+
client = algoliasearch.Client(os.environ['ALGOLIA_APPLICATION_ID'], os.environ['ALGOLIA_API_KEY'], ["fakeapp-1.algolianet.com", "fakeapp-2.algolianet.com", os.environ['ALGOLIA_APPLICATION_ID'] + ".algolianet.com"])
64+
client.listIndexes
65+
except algoliasearch.AlgoliaException as e:
66+
self.assertTrue(False)
6767

6868
def test_network(self):
6969
batch = []

0 commit comments

Comments
 (0)