diff options
| author | Mark Rawlings <Mark.Rawlings@hp.com> | 2015-03-03 18:03:58 +0000 |
|---|---|---|
| committer | Mark Rawlings <Mark.Rawlings@hp.com> | 2015-03-09 16:37:49 +0000 |
| commit | 4b6ed760d4303744907feefd81e60f38ae3750ef (patch) | |
| tree | d8019d0bcaacda66a10c7ae3ce13184f8c3aae8b | |
| parent | c964a12e01b115afcab40849ea72aa0eddc9b3dc (diff) | |
Reinstate Max URI length checking to V2_0 Client
A previous commit 799e288f48e5d99731dedbfb94808a8cbe01c05c
has broken the ability to recognise long URIs (>8192) and
raise an exception used to prevent the excessive URI being sent
to the server. This impacts the commands net-list and
security-group-rule-list.
The previous edit removed one of the duplicate _check_uri_length functions.
This edit 'swaps' the removal and updates the unit test stubbing accordingly.
The capability to split excessive URIs into managable chunks remained in
the code, but no longer executed because this exception was not raised.
It should be noted that as a side effect of recognising the
long URI, data is returned with the exception that indicates
'how excessive' the URI length was. This allows the URI to be
broken into chunks that will be supported.
Restore the capability to recognise that an excessive URI has
been provided and to raise the expected exception with
related data.
Closes-Bug: #1422736
Change-Id: I1b719bed406b83c5f2deac06e127798a91f51ad7
Notes
Notes (review):
Verified+2: Jenkins
Code-Review+2: Kyle Mestery <mestery@mestery.com>
Workflow+1: Kyle Mestery <mestery@mestery.com>
Code-Review+1: Brian Haley <brian.haley@hp.com>
Code-Review+2: Carl Baldwin <carl@ecbaldwin.net>
Submitted-by: Jenkins
Submitted-at: Wed, 11 Mar 2015 06:24:32 +0000
Reviewed-on: https://review.openstack.org/160923
Project: openstack/python-neutronclient
Branch: refs/heads/master
| -rw-r--r-- | neutronclient/client.py | 10 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_cli20.py | 11 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_cli20_network.py | 6 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_cli20_securitygroup.py | 6 | ||||
| -rw-r--r-- | neutronclient/v2_0/client.py | 11 |
5 files changed, 28 insertions, 16 deletions
diff --git a/neutronclient/client.py b/neutronclient/client.py index 0a68ff0..bc645f1 100644 --- a/neutronclient/client.py +++ b/neutronclient/client.py | |||
| @@ -48,9 +48,6 @@ class HTTPClient(object): | |||
| 48 | USER_AGENT = 'python-neutronclient' | 48 | USER_AGENT = 'python-neutronclient' |
| 49 | CONTENT_TYPE = 'application/json' | 49 | CONTENT_TYPE = 'application/json' |
| 50 | 50 | ||
| 51 | # 8192 Is the default max URI len for eventlet.wsgi.server | ||
| 52 | MAX_URI_LEN = 8192 | ||
| 53 | |||
| 54 | def __init__(self, username=None, user_id=None, | 51 | def __init__(self, username=None, user_id=None, |
| 55 | tenant_name=None, tenant_id=None, | 52 | tenant_name=None, tenant_id=None, |
| 56 | password=None, auth_url=None, | 53 | password=None, auth_url=None, |
| @@ -149,16 +146,9 @@ class HTTPClient(object): | |||
| 149 | 146 | ||
| 150 | return resp, resp.text | 147 | return resp, resp.text |
| 151 | 148 | ||
| 152 | def _check_uri_length(self, action): | ||
| 153 | uri_len = len(self.endpoint_url) + len(action) | ||
| 154 | if uri_len > self.MAX_URI_LEN: | ||
| 155 | raise exceptions.RequestURITooLong( | ||
| 156 | excess=uri_len - self.MAX_URI_LEN) | ||
| 157 | |||
| 158 | def do_request(self, url, method, **kwargs): | 149 | def do_request(self, url, method, **kwargs): |
| 159 | # Ensure client always has correct uri - do not guesstimate anything | 150 | # Ensure client always has correct uri - do not guesstimate anything |
| 160 | self.authenticate_and_fetch_endpoint_url() | 151 | self.authenticate_and_fetch_endpoint_url() |
| 161 | self._check_uri_length(url) | ||
| 162 | 152 | ||
| 163 | # Perform the request once. If we get a 401 back then it | 153 | # Perform the request once. If we get a 401 back then it |
| 164 | # might be because the auth token expired, so try to | 154 | # might be because the auth token expired, so try to |
diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py index 86c79b4..3f360c7 100644 --- a/neutronclient/tests/unit/test_cli20.py +++ b/neutronclient/tests/unit/test_cli20.py | |||
| @@ -618,6 +618,17 @@ class ClientV2TestJson(CLITestV20Base): | |||
| 618 | self.mox.VerifyAll() | 618 | self.mox.VerifyAll() |
| 619 | self.mox.UnsetStubs() | 619 | self.mox.UnsetStubs() |
| 620 | 620 | ||
| 621 | def test_do_request_with_long_uri_exception(self): | ||
| 622 | long_string = 'x' * 8200 # 8200 > MAX_URI_LEN:8192 | ||
| 623 | params = {'id': long_string} | ||
| 624 | |||
| 625 | try: | ||
| 626 | self.client.do_request('GET', '/test', body='', params=params) | ||
| 627 | except exceptions.RequestURITooLong as cm: | ||
| 628 | self.assertNotEqual(cm.excess, 0) | ||
| 629 | else: | ||
| 630 | self.fail('Expected exception NOT raised') | ||
| 631 | |||
| 621 | 632 | ||
| 622 | class ClientV2UnicodeTestXML(ClientV2TestJson): | 633 | class ClientV2UnicodeTestXML(ClientV2TestJson): |
| 623 | format = 'xml' | 634 | format = 'xml' |
diff --git a/neutronclient/tests/unit/test_cli20_network.py b/neutronclient/tests/unit/test_cli20_network.py index 1ac49b6..31754be 100644 --- a/neutronclient/tests/unit/test_cli20_network.py +++ b/neutronclient/tests/unit/test_cli20_network.py | |||
| @@ -551,14 +551,14 @@ class CLITestV20NetworkJSON(test_cli20.CLITestV20Base): | |||
| 551 | filters, response = self._build_test_data(data) | 551 | filters, response = self._build_test_data(data) |
| 552 | 552 | ||
| 553 | # 1 char of extra URI len will cause a split in 2 requests | 553 | # 1 char of extra URI len will cause a split in 2 requests |
| 554 | self.mox.StubOutWithMock(self.client.httpclient, | 554 | self.mox.StubOutWithMock(self.client, |
| 555 | "_check_uri_length") | 555 | "_check_uri_length") |
| 556 | self.client.httpclient._check_uri_length(mox.IgnoreArg()).AndRaise( | 556 | self.client._check_uri_length(mox.IgnoreArg()).AndRaise( |
| 557 | exceptions.RequestURITooLong(excess=1)) | 557 | exceptions.RequestURITooLong(excess=1)) |
| 558 | 558 | ||
| 559 | for data in sub_data_lists: | 559 | for data in sub_data_lists: |
| 560 | filters, response = self._build_test_data(data) | 560 | filters, response = self._build_test_data(data) |
| 561 | self.client.httpclient._check_uri_length( | 561 | self.client._check_uri_length( |
| 562 | mox.IgnoreArg()).AndReturn(None) | 562 | mox.IgnoreArg()).AndReturn(None) |
| 563 | self.client.httpclient.request( | 563 | self.client.httpclient.request( |
| 564 | test_cli20.MyUrlComparator( | 564 | test_cli20.MyUrlComparator( |
diff --git a/neutronclient/tests/unit/test_cli20_securitygroup.py b/neutronclient/tests/unit/test_cli20_securitygroup.py index ec18fb8..8032e03 100644 --- a/neutronclient/tests/unit/test_cli20_securitygroup.py +++ b/neutronclient/tests/unit/test_cli20_securitygroup.py | |||
| @@ -265,14 +265,14 @@ class CLITestV20SecurityGroupsJSON(test_cli20.CLITestV20Base): | |||
| 265 | def test_extend_list_exceed_max_uri_len(self): | 265 | def test_extend_list_exceed_max_uri_len(self): |
| 266 | def mox_calls(path, data): | 266 | def mox_calls(path, data): |
| 267 | # 1 char of extra URI len will cause a split in 2 requests | 267 | # 1 char of extra URI len will cause a split in 2 requests |
| 268 | self.mox.StubOutWithMock(self.client.httpclient, | 268 | self.mox.StubOutWithMock(self.client, |
| 269 | '_check_uri_length') | 269 | '_check_uri_length') |
| 270 | self.client.httpclient._check_uri_length(mox.IgnoreArg()).AndRaise( | 270 | self.client._check_uri_length(mox.IgnoreArg()).AndRaise( |
| 271 | exceptions.RequestURITooLong(excess=1)) | 271 | exceptions.RequestURITooLong(excess=1)) |
| 272 | responses = self._build_test_data(data, excess=1) | 272 | responses = self._build_test_data(data, excess=1) |
| 273 | 273 | ||
| 274 | for item in responses: | 274 | for item in responses: |
| 275 | self.client.httpclient._check_uri_length( | 275 | self.client._check_uri_length( |
| 276 | mox.IgnoreArg()).AndReturn(None) | 276 | mox.IgnoreArg()).AndReturn(None) |
| 277 | self.client.httpclient.request( | 277 | self.client.httpclient.request( |
| 278 | test_cli20.end_url(path, item['filter']), | 278 | test_cli20.end_url(path, item['filter']), |
diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 0feac68..2e63bb2 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py | |||
| @@ -184,6 +184,12 @@ class ClientBase(object): | |||
| 184 | # Raise the appropriate exception | 184 | # Raise the appropriate exception |
| 185 | exception_handler_v20(status_code, des_error_body) | 185 | exception_handler_v20(status_code, des_error_body) |
| 186 | 186 | ||
| 187 | def _check_uri_length(self, action): | ||
| 188 | uri_len = len(self.httpclient.endpoint_url) + len(action) | ||
| 189 | if uri_len > self.MAX_URI_LEN: | ||
| 190 | raise exceptions.RequestURITooLong( | ||
| 191 | excess=uri_len - self.MAX_URI_LEN) | ||
| 192 | |||
| 187 | def do_request(self, method, action, body=None, headers=None, params=None): | 193 | def do_request(self, method, action, body=None, headers=None, params=None): |
| 188 | # Add format and tenant_id | 194 | # Add format and tenant_id |
| 189 | action += ".%s" % self.format | 195 | action += ".%s" % self.format |
| @@ -192,6 +198,8 @@ class ClientBase(object): | |||
| 192 | params = utils.safe_encode_dict(params) | 198 | params = utils.safe_encode_dict(params) |
| 193 | action += '?' + urlparse.urlencode(params, doseq=1) | 199 | action += '?' + urlparse.urlencode(params, doseq=1) |
| 194 | 200 | ||
| 201 | self._check_uri_length(action) | ||
| 202 | |||
| 195 | if body: | 203 | if body: |
| 196 | body = self.serialize(body) | 204 | body = self.serialize(body) |
| 197 | 205 | ||
| @@ -456,6 +464,9 @@ class Client(ClientBase): | |||
| 456 | 'healthmonitors': 'healthmonitor', | 464 | 'healthmonitors': 'healthmonitor', |
| 457 | } | 465 | } |
| 458 | 466 | ||
| 467 | # 8192 Is the default max URI len for eventlet.wsgi.server | ||
| 468 | MAX_URI_LEN = 8192 | ||
| 469 | |||
| 459 | @APIParamsCall | 470 | @APIParamsCall |
| 460 | def list_ext(self, path, **_params): | 471 | def list_ext(self, path, **_params): |
| 461 | """Client extension hook for lists. | 472 | """Client extension hook for lists. |